← Index
NYTProf Performance Profile   « line view »
For ./view
  Run on Fri Jul 31 19:05:14 2015
Reported on Fri Jul 31 19:08:08 2015

Filename/var/www/foswiki11/lib/Foswiki.pm
StatementsExecuted 979141 statements in 1.48s
Subroutines
Calls P F Exclusive
Time
Inclusive
Time
Subroutine
819181311924ms993msFoswiki::::normalizeWebTopicNameFoswiki::normalizeWebTopicName
46261109598ms3.15sFoswiki::::topicExistsFoswiki::topicExists
175636444.0ms49.6msFoswiki::::searchFoswiki::search
4542120.7ms59.1sFoswiki::::_expandMacroOnTopicRenderingFoswiki::_expandMacroOnTopicRendering (recurses: max depth 3, inclusive time 17.4s)
862115.2ms59.1sFoswiki::::_processMacrosFoswiki::_processMacros (recurses: max depth 5, inclusive time 26.7s)
11113.2ms14.7msFoswiki::::BEGIN@630Foswiki::BEGIN@630
144411.5ms12.9msFoswiki::::rendererFoswiki::renderer
11110.0ms16.9msFoswiki::::BEGIN@49Foswiki::BEGIN@49
15154197.13ms7.13msFoswiki::::isTrueFoswiki::isTrue
1116.47ms27.8msFoswiki::::writeCompletePageFoswiki::writeCompletePage
1114.53ms35.5msFoswiki::::BEGIN@137Foswiki::BEGIN@137
1114.45ms8.93msFoswiki::::BEGIN@47Foswiki::BEGIN@47
48333.51ms4.67msFoswiki::::i18nFoswiki::i18n
168742.83ms3.14msFoswiki::::templatesFoswiki::templates
1112.68ms8.05msFoswiki::::BEGIN@636Foswiki::BEGIN@636
3322.55ms2.96msFoswiki::::loggerFoswiki::logger
1112.45ms14.6msFoswiki::::BEGIN@631Foswiki::BEGIN@631
1112.32ms12.5msFoswiki::::finishFoswiki::finish
1112.25ms2.33msFoswiki::::BEGIN@632Foswiki::BEGIN@632
1112.25ms2.36msFoswiki::::attachFoswiki::attach
1112.02ms2.21msFoswiki::::BEGIN@48Foswiki::BEGIN@48
49632.01ms59.1sFoswiki::::innerExpandMacrosFoswiki::innerExpandMacros (recurses: max depth 3, inclusive time 17.4s)
106732.00ms2.00msFoswiki::::takeOutBlocksFoswiki::takeOutBlocks
1111.97ms3.16msFoswiki::::BEGIN@171Foswiki::BEGIN@171
2111.90ms8.35sFoswiki::::deepWebListFoswiki::deepWebList
1111.81ms4.42msFoswiki::::BEGIN@633Foswiki::BEGIN@633
1111.77ms5.61msFoswiki::::BEGIN@634Foswiki::BEGIN@634
177441.68ms14.4msFoswiki::::webExistsFoswiki::webExists
1111.67ms1.74msFoswiki::::BEGIN@51Foswiki::BEGIN@51
45321.65ms6.67msFoswiki::::getSkinFoswiki::getSkin
182111.16ms1.16msFoswiki::::isValidWebNameFoswiki::isValidWebName
1111.15ms4.33msFoswiki::::BEGIN@46Foswiki::BEGIN@46
96761.06ms1.06msFoswiki::::expandStandardEscapesFoswiki::expandStandardEscapes
4864995µs1.75msFoswiki::::getScriptUrlFoswiki::getScriptUrl
111989µs1.34msFoswiki::::BEGIN@50Foswiki::BEGIN@50
9963795µs830µsFoswiki::::putBackBlocksFoswiki::putBackBlocks
711638µs59.1sFoswiki::::expandMacrosFoswiki::expandMacros
221556µs20.8msFoswiki::::_renderZoneFoswiki::_renderZone
111531µs1.72sFoswiki::::newFoswiki::new
111442µs634µsFoswiki::::BEGIN@635Foswiki::BEGIN@635
3632386µs518µsFoswiki::::getPubUrlFoswiki::getPubUrl
1622358µs358µsFoswiki::::addToZoneFoswiki::addToZone
4321302µs302µsFoswiki::::_visitZoneIDFoswiki::_visitZoneID (recurses: max depth 3, inclusive time 163µs)
97124264µs264µsFoswiki::::inContextFoswiki::inContext
111236µs308µsFoswiki::::BEGIN@629Foswiki::BEGIN@629
2311206µs241µsFoswiki::::_make_paramsFoswiki::_make_params
55124185µs185µsFoswiki::::registerTagHandlerFoswiki::registerTagHandler
4274182µs182µsFoswiki::::enterContextFoswiki::enterContext
3311182µs590µsFoswiki::::__ANON__[:241]Foswiki::__ANON__[:241]
111177µs21.0msFoswiki::::_renderZonesFoswiki::_renderZones
5652175µs175µsFoswiki::::urlEncodeFoswiki::urlEncode
611158µs158µsFoswiki::::parseSectionsFoswiki::parseSections
4111113µs113µsFoswiki::::__ANON__[:368]Foswiki::__ANON__[:368]
5131111µs111µsFoswiki::::SINGLE_SINGLETONSFoswiki::SINGLE_SINGLETONS
1611105µs342µsFoswiki::::__ANON__[:270]Foswiki::__ANON__[:270]
922104µs104µsFoswiki::::isValidTopicNameFoswiki::isValidTopicName
21188µs88µsFoswiki::::spaceOutWikiWordFoswiki::spaceOutWikiWord
11177µs225µsFoswiki::::generateHTTPHeadersFoswiki::generateHTTPHeaders
91174µs161µsFoswiki::::__ANON__[:268]Foswiki::__ANON__[:268]
105473µs108µsFoswiki::::getLoginManagerFoswiki::getLoginManager
51155µs296µsFoswiki::::__ANON__[:211]Foswiki::__ANON__[:211]
11148µs450µsFoswiki::::logEventFoswiki::logEvent
141145µs45µsFoswiki::::__ANON__[:372]Foswiki::__ANON__[:372]
21137µs37µsFoswiki::::__ANON__[:417]Foswiki::__ANON__[:417]
44232µs32µsFoswiki::::leaveContextFoswiki::leaveContext
41126µs26µsFoswiki::::__ANON__[:361]Foswiki::__ANON__[:361]
11125µs111µsFoswiki::::getWorkAreaFoswiki::getWorkArea
11124µs48µsFoswiki::::BEGIN@44Foswiki::BEGIN@44
11121µs28µsFoswiki::::urlEncodeAttachmentFoswiki::urlEncodeAttachment
11116µs77µsFoswiki::::__ANON__[:283]Foswiki::__ANON__[:283]
11115µs15µsFoswiki::::_getLibDirFoswiki::_getLibDir
11115µs25µsFoswiki::::BEGIN@45Foswiki::BEGIN@45
11114µs79µsFoswiki::::__ANON__[:279]Foswiki::__ANON__[:279]
21113µs25µsFoswiki::::__ANON__[:240]Foswiki::__ANON__[:240]
11113µs22µsFoswiki::::__ANON__[:267]Foswiki::__ANON__[:267]
22112µs12µsFoswiki::::UTF82SiteCharSetFoswiki::UTF82SiteCharSet
11112µs42µsFoswiki::::getCGISessionFoswiki::getCGISession
1119µs93µsFoswiki::::__ANON__[:244]Foswiki::__ANON__[:244]
1118µs8µsFoswiki::::__ANON__[:404]Foswiki::__ANON__[:404]
2216µs6µsFoswiki::::SINGLE_SINGLETONS_TRACEFoswiki::SINGLE_SINGLETONS_TRACE
1115µs5µsFoswiki::::BEGIN@627Foswiki::BEGIN@627
1113µs3µsFoswiki::::BEGIN@628Foswiki::BEGIN@628
1113µs3µsFoswiki::::__ANON__[:366]Foswiki::__ANON__[:366]
2212µs2µsFoswiki::::__ANON__Foswiki::__ANON__ (xsub)
0000s0sFoswiki::::__ANON__[:152]Foswiki::__ANON__[:152]
0000s0sFoswiki::::__ANON__[:184]Foswiki::__ANON__[:184]
0000s0sFoswiki::::__ANON__[:186]Foswiki::__ANON__[:186]
0000s0sFoswiki::::__ANON__[:188]Foswiki::__ANON__[:188]
0000s0sFoswiki::::__ANON__[:195]Foswiki::__ANON__[:195]
0000s0sFoswiki::::__ANON__[:202]Foswiki::__ANON__[:202]
0000s0sFoswiki::::__ANON__[:217]Foswiki::__ANON__[:217]
0000s0sFoswiki::::__ANON__[:226]Foswiki::__ANON__[:226]
0000s0sFoswiki::::__ANON__[:236]Foswiki::__ANON__[:236]
0000s0sFoswiki::::__ANON__[:239]Foswiki::__ANON__[:239]
0000s0sFoswiki::::__ANON__[:250]Foswiki::__ANON__[:250]
0000s0sFoswiki::::__ANON__[:258]Foswiki::__ANON__[:258]
0000s0sFoswiki::::__ANON__[:262]Foswiki::__ANON__[:262]
0000s0sFoswiki::::__ANON__[:275]Foswiki::__ANON__[:275]
0000s0sFoswiki::::__ANON__[:297]Foswiki::__ANON__[:297]
0000s0sFoswiki::::__ANON__[:298]Foswiki::__ANON__[:298]
0000s0sFoswiki::::__ANON__[:299]Foswiki::__ANON__[:299]
0000s0sFoswiki::::__ANON__[:300]Foswiki::__ANON__[:300]
0000s0sFoswiki::::__ANON__[:301]Foswiki::__ANON__[:301]
0000s0sFoswiki::::__ANON__[:302]Foswiki::__ANON__[:302]
0000s0sFoswiki::::__ANON__[:3141]Foswiki::__ANON__[:3141]
0000s0sFoswiki::::__ANON__[:341]Foswiki::__ANON__[:341]
0000s0sFoswiki::::__ANON__[:358]Foswiki::__ANON__[:358]
0000s0sFoswiki::::__ANON__[:359]Foswiki::__ANON__[:359]
0000s0sFoswiki::::__ANON__[:360]Foswiki::__ANON__[:360]
0000s0sFoswiki::::__ANON__[:362]Foswiki::__ANON__[:362]
0000s0sFoswiki::::__ANON__[:364]Foswiki::__ANON__[:364]
0000s0sFoswiki::::__ANON__[:365]Foswiki::__ANON__[:365]
0000s0sFoswiki::::__ANON__[:367]Foswiki::__ANON__[:367]
0000s0sFoswiki::::__ANON__[:369]Foswiki::__ANON__[:369]
0000s0sFoswiki::::__ANON__[:370]Foswiki::__ANON__[:370]
0000s0sFoswiki::::__ANON__[:371]Foswiki::__ANON__[:371]
0000s0sFoswiki::::__ANON__[:373]Foswiki::__ANON__[:373]
0000s0sFoswiki::::__ANON__[:374]Foswiki::__ANON__[:374]
0000s0sFoswiki::::__ANON__[:375]Foswiki::__ANON__[:375]
0000s0sFoswiki::::__ANON__[:376]Foswiki::__ANON__[:376]
0000s0sFoswiki::::__ANON__[:377]Foswiki::__ANON__[:377]
0000s0sFoswiki::::_expandMacroOnTopicCreationFoswiki::_expandMacroOnTopicCreation
0000s0sFoswiki::::_isRedirectSafeFoswiki::_isRedirectSafe
0000s0sFoswiki::::_renderZoneByIdFoswiki::_renderZoneById
0000s0sFoswiki::::cacheQueryFoswiki::cacheQuery
0000s0sFoswiki::::entityDecodeFoswiki::entityDecode
0000s0sFoswiki::::entityEncodeFoswiki::entityEncode
0000s0sFoswiki::::expandMacrosOnTopicCreationFoswiki::expandMacrosOnTopicCreation
0000s0sFoswiki::::getApproxRevTimeFoswiki::getApproxRevTime
0000s0sFoswiki::::inlineAlertFoswiki::inlineAlert
0000s0sFoswiki::::isValidEmailAddressFoswiki::isValidEmailAddress
0000s0sFoswiki::::isValidWikiWordFoswiki::isValidWikiWord
0000s0sFoswiki::::netFoswiki::net
0000s0sFoswiki::::readFileFoswiki::readFile
0000s0sFoswiki::::redirectFoswiki::redirect
0000s0sFoswiki::::redirecttoFoswiki::redirectto
0000s0sFoswiki::::splitAnchorFromUrlFoswiki::splitAnchorFromUrl
0000s0sFoswiki::::urlDecodeFoswiki::urlDecode
0000s0sFoswiki::::validatePatternFoswiki::validatePattern
Call graph for these subroutines as a Graphviz dot language file.
Line State
ments
Time
on line
Calls Time
in subs
Code
1# See bottom of file for license and copyright information
2package Foswiki;
3
4=begin TML
5
6---+ package Foswiki
7
8Foswiki operates by creating a singleton object (known as the Session
9object) that acts as a point of reference for all the different
10modules in the system. This package is the class for this singleton,
11and also contains the vast bulk of the basic constants and the per-
12site configuration mechanisms.
13
14Global variables are avoided wherever possible to avoid problems
15with CGI accelerators such as mod_perl.
16
17---++ Public Data members
18 * =request= Pointer to the Foswiki::Request
19 * =response= Pointer to the Foswiki::Response
20 * =context= Hash of context ids
21 * =plugins= Foswiki::Plugins singleton
22 * =prefs= Foswiki::Prefs singleton
23 * =remoteUser= Login ID when using ApacheLogin. Maintained for
24 compatibility only, do not use.
25 * =requestedWebName= Name of web found in URL path or =web= URL parameter
26 * =scriptUrlPath= URL path to the current script. May be dynamically
27 extracted from the URL path if {GetScriptUrlFromCgi}.
28 Only required to support {GetScriptUrlFromCgi} and
29 not consistently used. Avoid.
30 * =security= Foswiki::Access singleton
31 * =store= Foswiki::Store singleton
32 * =topicName= Name of topic found in URL path or =topic= URL
33 parameter
34 * =urlHost= Host part of the URL (including the protocol)
35 determined during intialisation and defaulting to
36 {DefaultUrlHost}
37 * =user= Unique user ID of logged-in user
38 * =users= Foswiki::Users singleton
39 * =webName= Name of web found in URL path, or =web= URL parameter,
40 or {UsersWebName}
41
42=cut
43
44247µs272µs
# spent 48µs (24+24) within Foswiki::BEGIN@44 which was called: # once (24µs+24µs) by main::BEGIN@22 at line 44
use strict;
# spent 48µs making 1 call to Foswiki::BEGIN@44 # spent 24µs making 1 call to strict::import
45240µs235µs
# spent 25µs (15+10) within Foswiki::BEGIN@45 which was called: # once (15µs+10µs) by main::BEGIN@22 at line 45
use warnings;
# spent 25µs making 1 call to Foswiki::BEGIN@45 # spent 10µs making 1 call to warnings::import
462172µs24.35ms
# spent 4.33ms (1.15+3.18) within Foswiki::BEGIN@46 which was called: # once (1.15ms+3.18ms) by main::BEGIN@22 at line 46
use Assert;
# spent 4.33ms making 1 call to Foswiki::BEGIN@46 # spent 20µs making 1 call to Assert::import
472193µs29.13ms
# spent 8.93ms (4.45+4.48) within Foswiki::BEGIN@47 which was called: # once (4.45ms+4.48ms) by main::BEGIN@22 at line 47
use Error qw( :try );
# spent 8.93ms making 1 call to Foswiki::BEGIN@47 # spent 198µs making 1 call to Error::import
482176µs12.21ms
# spent 2.21ms (2.02+188µs) within Foswiki::BEGIN@48 which was called: # once (2.02ms+188µs) by main::BEGIN@22 at line 48
use Monitor ();
# spent 2.21ms making 1 call to Foswiki::BEGIN@48
492164µs116.9ms
# spent 16.9ms (10.0+6.85) within Foswiki::BEGIN@49 which was called: # once (10.0ms+6.85ms) by main::BEGIN@22 at line 49
use CGI (); # Always required to get html generation tags;
# spent 16.9ms making 1 call to Foswiki::BEGIN@49
502148µs11.34ms
# spent 1.34ms (989µs+347µs) within Foswiki::BEGIN@50 which was called: # once (989µs+347µs) by main::BEGIN@22 at line 50
use Digest::MD5 (); # For passthru and validation
# spent 1.34ms making 1 call to Foswiki::BEGIN@50
512765µs11.74ms
# spent 1.74ms (1.67+67µs) within Foswiki::BEGIN@51 which was called: # once (1.67ms+67µs) by main::BEGIN@22 at line 51
use Foswiki::Configure::Load ();
# spent 1.74ms making 1 call to Foswiki::BEGIN@51
52
53112µsrequire 5.005; # For regex objects and internationalisation
54
55# Site configuration constants
561400nsour %cfg;
57
58# Other computed constants
591200nsour $foswikiLibDir;
601200nsour %regex;
611100nsour %macros;
621100nsour %contextFreeSyntax;
631300nsour $VERSION;
641200nsour $RELEASE;
651300nsour $TRUE = 1;
661100nsour $FALSE = 0;
671100nsour $engine;
681700nsour $TranslationToken = "\0"; # Do not deprecate - used in many plugins
69
70# Note: the following marker is used in text to mark RENDERZONE
71# macros that have been hoisted from the source text of a page. It is
72# carefully chosen so that it is (1) not normally present in written
73# text (2) does not combine with other characters to form valid
74# wide-byte characters and (3) does not conflict with other markers used
75# by Foswiki/Render.pm
761200nsour $RENDERZONE_MARKER = "\3";
77
78# Used by takeOut/putBack blocks
791100nsour $BLOCKID = 0;
801200nsour $OC = "<!--\0";
811300nsour $CC = "\0-->";
82
83# This variable is set if Foswiki is running in unit test mode.
84# It is provided so that modules can detect unit test mode to avoid
85# corrupting data spaces.
861200nsour $inUnitTestMode = 0;
87
8851153µs
# spent 111µs within Foswiki::SINGLE_SINGLETONS which was called 51 times, avg 2µs/call: # 49 times (108µs+0s) by Foswiki::innerExpandMacros at line 2819, avg 2µs/call # once (2µs+0s) by Foswiki::new at line 1729 # once (2µs+0s) by Foswiki::finish at line 2205
sub SINGLE_SINGLETONS { 0 }
8928µs
# spent 6µs within Foswiki::SINGLE_SINGLETONS_TRACE which was called 2 times, avg 3µs/call: # once (4µs+0s) by Foswiki::finish at line 2200 # once (2µs+0s) by Foswiki::new at line 1716
sub SINGLE_SINGLETONS_TRACE { 0 }
90
91# Returns the full path of the directory containing Foswiki.pm
92
# spent 15µs within Foswiki::_getLibDir which was called: # once (15µs+0s) by Foswiki::BEGIN@137 at line 611
sub _getLibDir {
931300ns return $foswikiLibDir if $foswikiLibDir;
94
951800ns $foswikiLibDir = $INC{'Foswiki.pm'};
96
97 # fix path relative to location of called script
981700ns if ( $foswikiLibDir =~ /^\./ ) {
99 print STDERR
100"WARNING: Foswiki lib path $foswikiLibDir is relative; you should make it absolute, otherwise some scripts may not run from the command line.";
101 my $bin;
102
103 # SMELL : Should not assume environment variables; get data from request
104 if ( $ENV{SCRIPT_FILENAME}
105 && $ENV{SCRIPT_FILENAME} =~ m#^(.+)/.+?$# )
106 {
107
108 # CGI script name
109 # implicit untaint OK, because of use of $SCRIPT_FILENAME
110 $bin = $1;
111 }
112 elsif ( $0 =~ m#^(.*)/.*?$# ) {
113
114 # program name
115 # implicit untaint OK, because of use of $PROGRAM_NAME ($0)
116 $bin = $1;
117 }
118 else {
119
120 # last ditch; relative to current directory.
121 require Cwd;
122 $bin = Cwd::cwd();
123 }
124 $foswikiLibDir = "$bin/$foswikiLibDir/";
125
126 # normalize "/../" and "/./"
127 while ( $foswikiLibDir =~ s|([\\/])[^\\/]+[\\/]\.\.[\\/]|$1| ) {
128 }
129 $foswikiLibDir =~ s|([\\/])\.[\\/]|$1|g;
130 }
131110µs $foswikiLibDir =~ s|([\\/])[\\/]*|$1|g; # reduce "//" to "/"
13211µs $foswikiLibDir =~ s|[\\/]$||; # cut trailing "/"
133
13416µs return $foswikiLibDir;
135}
136
137
# spent 35.5ms (4.53+31.0) within Foswiki::BEGIN@137 which was called: # once (4.53ms+31.0ms) by main::BEGIN@22 at line 624
BEGIN {
138
139 #Monitor::MARK("Start of BEGIN block in Foswiki.pm");
14012µs12µs if (DEBUG) {
# spent 2µs making 1 call to Assert::ASSERTS_OFF
141 if ( not $Assert::soft ) {
142
143 # If ASSERTs are on (and not soft), then warnings are errors.
144 # Paranoid, but the only way to be sure we eliminate them all.
145 # Look out also for $cfg{WarningsAreErrors}, below, which
146 # is another way to install this handler without enabling
147 # ASSERTs
148 # ASSERTS are turned on by defining the environment variable
149 # FOSWIKI_ASSERTS. If ASSERTs are off, this is assumed to be a
150 # production environment, and no stack traces or paths are
151 # output to the browser.
152 $SIG{'__WARN__'} = sub { die @_ };
153 $Error::Debug = 1; # verbose stack traces, please
154 }
155 else {
156
157 # ASSERTs are soft, so warnings are not errors
158 # but ASSERTs are enabled. This is useful for tracking down
159 # problems that only manifest on production servers.
160 # Consequently, this is only useful when
161 # $cfg{WarningsAreErrors} is NOT enabled
162 $Error::Debug = 0; # no verbose stack traces
163 }
164 }
165 else {
1661500ns $Error::Debug = 0; # no verbose stack traces
167 }
168
169 # DO NOT CHANGE THE FORMAT OF $VERSION.
170 # Use $RELEASE for a descriptive version.
17143.40ms43.32ms
# spent 3.16ms (1.97+1.19) within Foswiki::BEGIN@171 which was called: # once (1.97ms+1.19ms) by main::BEGIN@22 at line 171
use version 0.77; $VERSION = version->declare('v1.1.9');
# spent 3.16ms making 1 call to Foswiki::BEGIN@171 # spent 66µs making 1 call to version::vxs::declare # spent 65µs making 1 call to UNIVERSAL::VERSION # spent 27µs making 1 call to version::import
1721500ns $RELEASE = 'Foswiki-1.1.9';
173
174 # Default handlers for different %TAGS%
175 # Where an entry is set as 'undef', the tag will be demand-loaded
176 # from Foswiki::Macros, if it is used. This tactic is used to reduce
177 # the load time of this module, especially when it is used from
178 # REST handlers.
179 %macros = (
180 ADDTOHEAD => undef,
181
182 # deprecated, use ADDTOZONE instead
183 ADDTOZONE => undef,
184 ALLVARIABLES => sub { $_[0]->{prefs}->stringify() },
185 ATTACHURL =>
186 sub { return $_[0]->getPubUrl( 1, $_[2]->web, $_[2]->topic ); },
187 ATTACHURLPATH =>
188 sub { return $_[0]->getPubUrl( 0, $_[2]->web, $_[2]->topic ); },
189 DATE => sub {
190 Foswiki::Time::formatTime(
191 time(),
192 $Foswiki::cfg{DefaultDateFormat},
193 $Foswiki::cfg{DisplayTimeValues}
194 );
195 },
196 DISPLAYTIME => sub {
197 Foswiki::Time::formatTime(
198 time(),
199 $_[1]->{_DEFAULT} || '',
200 $Foswiki::cfg{DisplayTimeValues}
201 );
202 },
203 ENCODE => undef,
204 ENV => undef,
205 EXPAND => undef,
206 FORMAT => undef,
207 FORMFIELD => undef,
208
# spent 296µs (55+241) within Foswiki::__ANON__[/var/www/foswiki11/lib/Foswiki.pm:211] which was called 5 times, avg 59µs/call: # 5 times (55µs+241µs) by Foswiki::_expandMacroOnTopicRendering at line 3160, avg 59µs/call
GMTIME => sub {
209547µs5241µs Foswiki::Time::formatTime( time(), $_[1]->{_DEFAULT} || '',
# spent 241µs making 5 calls to Foswiki::Time::formatTime, avg 48µs/call
210 'gmtime' );
211 },
212 GROUPINFO => undef,
213 GROUPS => undef,
214 HTTP_HOST =>
215
216 #deprecated functionality, now implemented using %ENV%
217 sub { $_[0]->{request}->header('Host') || '' },
218 HTTP => undef,
219 HTTPS => undef,
220 ICON => undef,
221 ICONURL => undef,
222 ICONURLPATH => undef,
223 IF => undef,
224 INCLUDE => undef,
225 INTURLENCODE => undef,
226 LANGUAGE => sub { $_[0]->i18n->language(); },
227 LANGUAGES => undef,
228 MAKETEXT => undef,
229 META => undef, # deprecated
230 METASEARCH => undef, # deprecated
231 NOP =>
232
233 # Remove NOP tag in template topics but show content.
234 # Used in template _topics_ (not templates, per se, but
235 # topics used as templates for new topics)
236 sub { $_[1]->{_RAW} ? $_[1]->{_RAW} : '<nop>' },
237 PLUGINVERSION => sub {
238 $_[0]->{plugins}->getPluginVersion( $_[1]->{_DEFAULT} );
239 },
240210µs211µs
# spent 25µs (13+11) within Foswiki::__ANON__[/var/www/foswiki11/lib/Foswiki.pm:240] which was called 2 times, avg 12µs/call: # 2 times (13µs+11µs) by Foswiki::_expandMacroOnTopicRendering at line 3160, avg 12µs/call
PUBURL => sub { $_[0]->getPubUrl(1) },
# spent 11µs making 2 calls to Foswiki::getPubUrl, avg 6µs/call
24133145µs33408µs
# spent 590µs (182+408) within Foswiki::__ANON__[/var/www/foswiki11/lib/Foswiki.pm:241] which was called 33 times, avg 18µs/call: # 33 times (182µs+408µs) by Foswiki::_expandMacroOnTopicRendering at line 3160, avg 18µs/call
PUBURLPATH => sub { $_[0]->getPubUrl(0) },
# spent 408µs making 33 calls to Foswiki::getPubUrl, avg 12µs/call
242 QUERY => undef,
243 QUERYPARAMS => undef,
244110µs184µs
# spent 93µs (9+84) within Foswiki::__ANON__[/var/www/foswiki11/lib/Foswiki.pm:244] which was called: # once (9µs+84µs) by Foswiki::_expandMacroOnTopicRendering at line 3160
QUERYSTRING => sub { $_[0]->{request}->queryString() },
# spent 84µs making 1 call to Foswiki::Request::queryString
245 RELATIVETOPICPATH => undef,
246 REMOTE_ADDR =>
247
248 # DEPRECATED, now implemented using %ENV%
249 #move to compatibility plugin in Foswiki 2.0
250 sub { $_[0]->{request}->remoteAddress() || ''; },
251 REMOTE_PORT =>
252
253 # DEPRECATED
254 # CGI/1.1 (RFC 3875) doesn't specify REMOTE_PORT,
255 # but some webservers implement it. However, since
256 # it's not RFC compliant, Foswiki should not rely on
257 # it. So we get more portability.
258 sub { '' },
259 REMOTE_USER =>
260
261 # DEPRECATED
262 sub { $_[0]->{request}->remoteUser() || '' },
263 RENDERZONE => undef,
264 REVINFO => undef,
265 REVTITLE => undef,
266 REVARG => undef,
267115µs19µs
# spent 22µs (13+9) within Foswiki::__ANON__[/var/www/foswiki11/lib/Foswiki.pm:267] which was called: # once (13µs+9µs) by Foswiki::_expandMacroOnTopicRendering at line 3160
SCRIPTNAME => sub { $_[0]->{request}->action() },
# spent 9µs making 1 call to Foswiki::Request::action
268961µs987µs
# spent 161µs (74+87) within Foswiki::__ANON__[/var/www/foswiki11/lib/Foswiki.pm:268] which was called 9 times, avg 18µs/call: # 9 times (74µs+87µs) by Foswiki::_expandMacroOnTopicRendering at line 3160, avg 18µs/call
SCRIPTURL => sub { $_[0]->getScriptUrl( 1, $_[1]->{_DEFAULT} || '' ) },
# spent 87µs making 9 calls to Foswiki::getScriptUrl, avg 10µs/call
269 SCRIPTURLPATH =>
2701683µs16238µs
# spent 342µs (105+238) within Foswiki::__ANON__[/var/www/foswiki11/lib/Foswiki.pm:270] which was called 16 times, avg 21µs/call: # 16 times (105µs+238µs) by Foswiki::_expandMacroOnTopicRendering at line 3160, avg 21µs/call
sub { $_[0]->getScriptUrl( 0, $_[1]->{_DEFAULT} || '' ) },
# spent 238µs making 16 calls to Foswiki::getScriptUrl, avg 15µs/call
271 SEARCH => undef,
272 SEP =>
273
274 # Shortcut to %TMPL:P{"sep"}%
275 sub { $_[0]->templates->expandTemplate('sep') },
276
# spent 79µs (14+65) within Foswiki::__ANON__[/var/www/foswiki11/lib/Foswiki.pm:279] which was called: # once (14µs+65µs) by Foswiki::_expandMacroOnTopicRendering at line 3160
SERVERTIME => sub {
27719µs165µs Foswiki::Time::formatTime( time(), $_[1]->{_DEFAULT} || '',
# spent 65µs making 1 call to Foswiki::Time::formatTime
278 'servertime' );
279 },
280 SHOWPREFERENCE => undef,
281 SPACEDTOPIC => undef,
282 SPACEOUT => undef,
283115µs261µs
# spent 77µs (16+61) within Foswiki::__ANON__[/var/www/foswiki11/lib/Foswiki.pm:283] which was called: # once (16µs+61µs) by Foswiki::_expandMacroOnTopicRendering at line 3160
'TMPL:P' => sub { $_[0]->templates->tmplP( $_[1] ) },
# spent 55µs making 1 call to Foswiki::Templates::tmplP # spent 6µs making 1 call to Foswiki::templates
284 TOPICLIST => undef,
285 URLENCODE => undef,
286 URLPARAM => undef,
287 USERINFO => undef,
288 USERNAME => undef,
289 VAR => undef,
290 WEBLIST => undef,
291 WIKINAME => undef,
292 WIKIUSERNAME => undef,
293 DISPLAYDEPENDENCIES => undef,
294
295 # Constant tag strings _not_ dependent on config. These get nicely
296 # optimised by the compiler.
297 ENDSECTION => sub { '' },
298 WIKIVERSION => sub { $VERSION },
299 WIKIRELEASE => sub { $RELEASE },
300 STARTSECTION => sub { '' },
301 STARTINCLUDE => sub { '' },
302 STOPINCLUDE => sub { '' },
303175µs );
30411µs $contextFreeSyntax{IF} = 1;
305
30612µs unless ( ( $Foswiki::cfg{DetailedOS} = $^O ) ) {
307 require Config;
308 $Foswiki::cfg{DetailedOS} = $Config::Config{'osname'};
309 }
3101600ns $Foswiki::cfg{OS} = 'UNIX';
31115µs if ( $Foswiki::cfg{DetailedOS} =~ /darwin/i ) { # MacOS X
312 $Foswiki::cfg{OS} = 'UNIX';
313 }
314 elsif ( $Foswiki::cfg{DetailedOS} =~ /Win/i ) {
315 $Foswiki::cfg{OS} = 'WINDOWS';
316 }
317 elsif ( $Foswiki::cfg{DetailedOS} =~ /vms/i ) {
318 $Foswiki::cfg{OS} = 'VMS';
319 }
320 elsif ( $Foswiki::cfg{DetailedOS} =~ /bsdos/i ) {
321 $Foswiki::cfg{OS} = 'UNIX';
322 }
323 elsif ( $Foswiki::cfg{DetailedOS} =~ /dos/i ) {
324 $Foswiki::cfg{OS} = 'DOS';
325 }
326 elsif ( $Foswiki::cfg{DetailedOS} =~ /^MacOS$/i ) { # MacOS 9 or earlier
327 $Foswiki::cfg{OS} = 'MACINTOSH';
328 }
329 elsif ( $Foswiki::cfg{DetailedOS} =~ /os2/i ) {
330 $Foswiki::cfg{OS} = 'OS2';
331 }
332
333 # readConfig is defined in Foswiki::Configure::Load to allow overriding it
33413µs113.2ms if ( Foswiki::Configure::Load::readConfig() ) {
# spent 13.2ms making 1 call to Foswiki::Configure::Load::readConfig
335 $Foswiki::cfg{isVALID} = 1;
336 }
337
3381400ns if ( $Foswiki::cfg{WarningsAreErrors} ) {
339
340 # Note: Warnings are always errors if ASSERTs are enabled
341 $SIG{'__WARN__'} = sub { die @_ };
342 }
343
3441600ns if ( $Foswiki::cfg{UseLocale} ) {
3451600ns require locale;
34615µs16µs import locale();
# spent 6µs making 1 call to locale::import
347 }
348
349 # If not set, default to strikeone validation
3501800ns $Foswiki::cfg{Validation}{Method} ||= 'strikeone';
3511500ns $Foswiki::cfg{Validation}{ValidForTime} = $Foswiki::cfg{LeaseLength}
352 unless defined $Foswiki::cfg{Validation}{ValidForTime};
3531900ns $Foswiki::cfg{Validation}{MaxKeys} = 1000
354 unless defined $Foswiki::cfg{Validation}{MaxKeys};
355
356 # Constant tags dependent on the config
357 $macros{ALLOWLOGINNAME} =
35813µs sub { $Foswiki::cfg{Register}{AllowLoginName} || 0 };
35912µs $macros{AUTHREALM} = sub { $Foswiki::cfg{AuthRealm} };
36011µs $macros{DEFAULTURLHOST} = sub { $Foswiki::cfg{DefaultUrlHost} };
361527µs
# spent 26µs within Foswiki::__ANON__[/var/www/foswiki11/lib/Foswiki.pm:361] which was called 4 times, avg 6µs/call: # 4 times (26µs+0s) by Foswiki::_expandMacroOnTopicRendering at line 3160, avg 6µs/call
$macros{HOMETOPIC} = sub { $Foswiki::cfg{HomeTopicName} };
36211µs $macros{LOCALSITEPREFS} = sub { $Foswiki::cfg{LocalSitePreferences} };
363 $macros{NOFOLLOW} =
36412µs sub { $Foswiki::cfg{NoFollow} ? 'rel=' . $Foswiki::cfg{NoFollow} : '' };
36511µs $macros{NOTIFYTOPIC} = sub { $Foswiki::cfg{NotifyTopicName} };
366217µs
# spent 3µs within Foswiki::__ANON__[/var/www/foswiki11/lib/Foswiki.pm:366] which was called: # once (3µs+0s) by Foswiki::_expandMacroOnTopicRendering at line 3160
$macros{SCRIPTSUFFIX} = sub { $Foswiki::cfg{ScriptSuffix} };
36712µs $macros{STATISTICSTOPIC} = sub { $Foswiki::cfg{Stats}{TopicName} };
36842157µs
# spent 113µs within Foswiki::__ANON__[/var/www/foswiki11/lib/Foswiki.pm:368] which was called 41 times, avg 3µs/call: # 41 times (113µs+0s) by Foswiki::_expandMacroOnTopicRendering at line 3160, avg 3µs/call
$macros{SYSTEMWEB} = sub { $Foswiki::cfg{SystemWebName} };
36911µs $macros{TRASHWEB} = sub { $Foswiki::cfg{TrashWebName} };
37011µs $macros{SANDBOXWEB} = sub { $Foswiki::cfg{SandboxWebName} };
37111µs $macros{WIKIADMINLOGIN} = sub { $Foswiki::cfg{AdminUserLogin} };
3721548µs
# spent 45µs within Foswiki::__ANON__[/var/www/foswiki11/lib/Foswiki.pm:372] which was called 14 times, avg 3µs/call: # 14 times (45µs+0s) by Foswiki::_expandMacroOnTopicRendering at line 3160, avg 3µs/call
$macros{USERSWEB} = sub { $Foswiki::cfg{UsersWebName} };
37311µs $macros{WEBPREFSTOPIC} = sub { $Foswiki::cfg{WebPrefsTopicName} };
37412µs $macros{WIKIPREFSTOPIC} = sub { $Foswiki::cfg{SitePrefsTopicName} };
37511µs $macros{WIKIUSERSTOPIC} = sub { $Foswiki::cfg{UsersTopicName} };
37611µs $macros{WIKIWEBMASTER} = sub { $Foswiki::cfg{WebMasterEmail} };
37711µs $macros{WIKIWEBMASTERNAME} = sub { $Foswiki::cfg{WebMasterName} };
378
379 # locale setup
380 #
381 #
382 # Note that 'use locale' must be done in BEGIN block for regexes and
383 # sorting to work properly, although regexes can still work without
384 # this in 'non-locale regexes' mode.
385
3861700ns if ( $Foswiki::cfg{UseLocale} ) {
387
388 # Set environment variables for grep
38915µs $ENV{LC_CTYPE} = $Foswiki::cfg{Site}{Locale};
390
391 # Load POSIX for I18N support.
3921109µs require POSIX;
39314µs11.14ms import POSIX qw( locale_h LC_CTYPE LC_COLLATE );
# spent 1.14ms making 1 call to POSIX::import
394
395 # SMELL: mod_perl compatibility note: If Foswiki is running under Apache,
396 # won't this play with the Apache process's locale settings too?
397 # What effects would this have?
398148µs235µs setlocale( &LC_CTYPE, $Foswiki::cfg{Site}{Locale} );
# spent 33µs making 1 call to POSIX::setlocale # spent 1µs making 1 call to Foswiki::__ANON__
399116µs29µs setlocale( &LC_COLLATE, $Foswiki::cfg{Site}{Locale} );
# spent 8µs making 1 call to POSIX::setlocale # spent 900ns making 1 call to Foswiki::__ANON__
400 }
401
402
# spent 8µs within Foswiki::__ANON__[/var/www/foswiki11/lib/Foswiki.pm:404] which was called: # once (8µs+0s) by Foswiki::_expandMacroOnTopicRendering at line 3160
$macros{CHARSET} = sub {
403111µs $Foswiki::cfg{Site}{CharSet} || CGI::charset();
40414µs };
405
406
# spent 37µs within Foswiki::__ANON__[/var/www/foswiki11/lib/Foswiki.pm:417] which was called 2 times, avg 19µs/call: # 2 times (37µs+0s) by Foswiki::_expandMacroOnTopicRendering at line 3160, avg 19µs/call
$macros{LANG} = sub {
40722µs my $lang = 'en'; # the default
408224µs if ( $Foswiki::cfg{UseLocale}
409 && $Foswiki::cfg{Site}{Locale} =~ m/^([a-z]+)(?:_([a-z]+))?/i )
410 {
411
412# Locale identifiers use _ as the separator in the language, but a minus sign is required
413# for HTML (see http://www.ietf.org/rfc/rfc1766.txt)
414 $lang = $1 . ( $2 ? "-$2" : '' );
415 }
416216µs return $lang;
41716µs };
418
419 # Set up pre-compiled regexes for use in rendering. All regexes with
420 # unchanging variables in match should use the '/o' option.
421 # In the regex hash, all precompiled REs have "Regex" at the
422 # end of the name. Anything else is a string, either intended
423 # for use as a character class, or as a sub-expression in
424 # another compiled RE.
425
426 # Build up character class components for use in regexes.
427 # Depends on locale mode and Perl version, and finally on
428 # whether locale-based regexes are turned off.
42913µs if ( not $Foswiki::cfg{UseLocale}
430 or $] < 5.006
431 or not $Foswiki::cfg{Site}{LocaleRegexes} )
432 {
433
434 # No locales needed/working, or Perl 5.005, so just use
435 # any additional national characters defined in LocalSite.cfg
436 $regex{upperAlpha} = 'A-Z' . $Foswiki::cfg{UpperNational};
437 $regex{lowerAlpha} = 'a-z' . $Foswiki::cfg{LowerNational};
438 $regex{numeric} = '\d';
439 $regex{mixedAlpha} = $regex{upperAlpha} . $regex{lowerAlpha};
440 }
441 else {
442
443 # Perl 5.006 or higher with working locales
44411µs $regex{upperAlpha} = '[:upper:]';
4451500ns $regex{lowerAlpha} = '[:lower:]';
4461500ns $regex{numeric} = '[:digit:]';
4471600ns $regex{mixedAlpha} = '[:alpha:]';
448 }
44912µs $regex{mixedAlphaNum} = $regex{mixedAlpha} . $regex{numeric};
4501900ns $regex{lowerAlphaNum} = $regex{lowerAlpha} . $regex{numeric};
4511900ns $regex{upperAlphaNum} = $regex{upperAlpha} . $regex{numeric};
452
453 # Compile regexes for efficiency and ease of use
454 # Note: qr// locks in regex modes (i.e. '-xism' here) - see Friedl
455 # book at http://regex.info/.
456
45711µs $regex{linkProtocolPattern} = $Foswiki::cfg{LinkProtocolPattern};
458
459 # Header patterns based on '+++'. The '###' are reserved for numbered
460 # headers
461 # '---++ Header', '---## Header'
46213µs $regex{headerPatternDa} = qr/^---+(\++|\#+)(.*)$/m;
463
464 # '<h6>Header</h6>
46511µs $regex{headerPatternHt} = qr/^<h([1-6])>(.+?)<\/h\1>/mi;
466
467 # '---++!! Header' or '---++ Header %NOTOC% ^top'
4681500ns $regex{headerPatternNoTOC} = '(\!\!+|%NOTOC%)';
469
470 # Foswiki concept regexes
471130µs $regex{wikiWordRegex} = qr(
472 [$regex{upperAlpha}]+
473 [$regex{lowerAlphaNum}]+
474 [$regex{upperAlpha}]+
475 [$regex{mixedAlphaNum}]*
476 )xo;
477112µs $regex{webNameBaseRegex} =
478 qr/[$regex{upperAlpha}]+[$regex{mixedAlphaNum}_]*/o;
4791600ns if ( $Foswiki::cfg{EnableHierarchicalWebs} ) {
480128µs $regex{webNameRegex} = qr(
481 $regex{webNameBaseRegex}
482 (?:(?:[\.\/]$regex{webNameBaseRegex})+)*
483 )xo;
484 }
485 else {
486 $regex{webNameRegex} = $regex{webNameBaseRegex};
487 }
488111µs $regex{defaultWebNameRegex} = qr/_[$regex{mixedAlphaNum}_]+/o;
489110µs $regex{anchorRegex} = qr/\#[$regex{mixedAlphaNum}:._]+/o;
490110µs $regex{abbrevRegex} = qr/[$regex{upperAlpha}]{3,}s?\b/o;
491
492129µs $regex{topicNameRegex} =
493 qr/(?:(?:$regex{wikiWordRegex})|(?:$regex{abbrevRegex}))/o;
494
495 # Email regex, e.g. for WebNotify processing and email matching
496 # during rendering.
497
49819µs my $emailAtom = qr([A-Z0-9\Q!#\$%&'*+-/=?^_`{|}~\E])i; # Per RFC 5322 ]
499
500 # Valid TLD's at http://data.iana.org/TLD/tlds-alpha-by-domain.txt
501 # Version 2012022300, Last Updated Thu Feb 23 15:07:02 2012 UTC
50211µs my $validTLD = $Foswiki::cfg{Email}{ValidTLD};
503
504218µs unless ( eval { qr/$validTLD/ } ) {
505 $validTLD =
506qr(AERO|ARPA|ASIA|BIZ|CAT|COM|COOP|EDU|GOV|INFO|INT|JOBS|MIL|MOBI|MUSEUM|NAME|NET|ORG|PRO|TEL|TRAVEL|XXX)i;
507
508# Too early to log, should do something here other than die (which prevents fixing)
509# warn is trapped and turned into a die...
510#warn( "{Email}{ValidTLD} does not compile, using default" );
511 }
512
513159µs $regex{emailAddrRegex} = qr(
514 (?: # LEFT Side of Email address
515 (?:$emailAtom+ # Valid characters left side of email address
516 (?:\.$emailAtom+)* # And 0 or more dotted atoms
517 )
518 |
519 (?:"[\x21\x23-\x5B\x5D-\x7E\s]+?") # or a quoted string per RFC 5322
520 )
521 @
522 (?: # RIGHT side of Email address
523 (?: # FQDN
524 [a-z0-9-]+ # hostname part
525 (?:\.[a-z0-9-]+)* # 0 or more alphanumeric domains following a dot.
526 \.(?: # TLD
527 (?:[a-z]{2,2}) # 2 character TLD
528 |
529 $validTLD # TLD's longer than 2 characters
530 )
531 )
532 |
533 (?:\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\]) # dotted triplets IP Address
534 )
535 )oxi;
536
537 # Item11185: This is how things were before we began Operation Unicode:
538 #
539 # $regex{filenameInvalidCharRegex} = qr/[^$regex{mixedAlphaNum}\. _-]/o;
540 #
541 # It was only used in Foswiki::Sandbox::sanitizeAttachmentName(), which now
542 # uses $Foswiki::cfg{NameFilter} instead.
543 # See RobustnessTests::test_sanitizeAttachmentName
544 #
545 # Actually, this is used in GenPDFPrincePlugin; let's copy NameFilter
5461800ns $regex{filenameInvalidCharRegex} = $Foswiki::cfg{NameFilter};
547
548 # Multi-character alpha-based regexes
549112µs $regex{mixedAlphaNumRegex} = qr/[$regex{mixedAlphaNum}]*/o;
550
551 # %TAG% name
55212µs $regex{tagNameRegex} =
553 '[' . $regex{mixedAlpha} . '][' . $regex{mixedAlphaNum} . '_:]*';
554
555 # Set statement in a topic
5561500ns $regex{bulletRegex} = '^(?:\t| )+\*';
55711µs $regex{setRegex} = $regex{bulletRegex} . '\s+(Set|Local)\s+';
55811µs $regex{setVarRegex} =
559 $regex{setRegex} . '(' . $regex{tagNameRegex} . ')\s*=\s*(.*)$';
560
561 # Character encoding regexes
562
563 # 7-bit ASCII only
56411µs $regex{validAsciiStringRegex} = qr/^[\x00-\x7F]+$/o;
565
566 # Regex to match only a valid UTF-8 character, taking care to avoid
567 # security holes due to overlong encodings by excluding the relevant
568 # gaps in UTF-8 encoding space - see 'perldoc perlunicode', Unicode
569 # Encodings section. Tested against Markus Kuhn's UTF-8 test file
570 # at http://www.cl.cam.ac.uk/~mgk25/ucs/examples/UTF-8-test.txt.
57111µs $regex{validUtf8CharRegex} = qr{
572 # Single byte - ASCII
573 [\x00-\x7F]
574 |
575
576 # 2 bytes
577 [\xC2-\xDF][\x80-\xBF]
578 |
579
580 # 3 bytes
581
582 # Avoid illegal codepoints - negative lookahead
583 (?!\xEF\xBF[\xBE\xBF])
584
585 # Match valid codepoints
586 (?:
587 ([\xE0][\xA0-\xBF])|
588 ([\xE1-\xEC\xEE-\xEF][\x80-\xBF])|
589 ([\xED][\x80-\x9F])
590 )
591 [\x80-\xBF]
592 |
593
594 # 4 bytes
595 (?:
596 ([\xF0][\x90-\xBF])|
597 ([\xF1-\xF3][\x80-\xBF])|
598 ([\xF4][\x80-\x8F])
599 )
600 [\x80-\xBF][\x80-\xBF]
601 }xo;
602
603138µs $regex{validUtf8StringRegex} = qr/^(?:$regex{validUtf8CharRegex})+$/o;
604
605 # Check for unsafe search regex mode (affects filtering in) - default
606 # to safe mode
6071500ns $Foswiki::cfg{ForceUnsafeRegexes} = 0
608 unless defined $Foswiki::cfg{ForceUnsafeRegexes};
609
610 # initialize lib directory early because of later 'cd's
61112µs115µs _getLibDir();
# spent 15µs making 1 call to Foswiki::_getLibDir
612
613 # initialize the runtime engine
6141500ns if ( !defined $Foswiki::cfg{Engine} ) {
615
616 # Caller did not define an engine; try and work it out (mainly for
617 # the benefit of pre-1.0 CGI scripts)
618 $Foswiki::cfg{Engine} = 'Foswiki::Engine::Legacy';
619 }
620146µs $engine = eval qq(use $Foswiki::cfg{Engine}; $Foswiki::cfg{Engine}->new);
# spent 406µs executing statements in string eval
# includes 1.10ms spent executing 1 call to 1 sub defined therein.
62115µs die $@ if $@;
622
623 #Monitor::MARK('End of BEGIN block in Foswiki.pm');
624125µs135.5ms}
# spent 35.5ms making 1 call to Foswiki::BEGIN@137
625
626# Components that all requests need
627223µs15µs
# spent 5µs within Foswiki::BEGIN@627 which was called: # once (5µs+0s) by main::BEGIN@22 at line 627
use Foswiki::Response ();
# spent 5µs making 1 call to Foswiki::BEGIN@627
6282183µs13µs
# spent 3µs within Foswiki::BEGIN@628 which was called: # once (3µs+0s) by main::BEGIN@22 at line 628
use Foswiki::Request ();
# spent 3µs making 1 call to Foswiki::BEGIN@628
629298µs1308µs
# spent 308µs (236+73) within Foswiki::BEGIN@629 which was called: # once (236µs+73µs) by main::BEGIN@22 at line 629
use Foswiki::Logger ();
# spent 308µs making 1 call to Foswiki::BEGIN@629
6302154µs114.7ms
# spent 14.7ms (13.2+1.44) within Foswiki::BEGIN@630 which was called: # once (13.2ms+1.44ms) by main::BEGIN@22 at line 630
use Foswiki::Meta ();
# spent 14.7ms making 1 call to Foswiki::BEGIN@630
6312129µs114.6ms
# spent 14.6ms (2.45+12.2) within Foswiki::BEGIN@631 which was called: # once (2.45ms+12.2ms) by main::BEGIN@22 at line 631
use Foswiki::Sandbox ();
# spent 14.6ms making 1 call to Foswiki::BEGIN@631
6322113µs12.33ms
# spent 2.33ms (2.25+73µs) within Foswiki::BEGIN@632 which was called: # once (2.25ms+73µs) by main::BEGIN@22 at line 632
use Foswiki::Time ();
# spent 2.33ms making 1 call to Foswiki::BEGIN@632
633296µs14.42ms
# spent 4.42ms (1.81+2.61) within Foswiki::BEGIN@633 which was called: # once (1.81ms+2.61ms) by main::BEGIN@22 at line 633
use Foswiki::Prefs ();
# spent 4.42ms making 1 call to Foswiki::BEGIN@633
6342105µs15.61ms
# spent 5.61ms (1.77+3.84) within Foswiki::BEGIN@634 which was called: # once (1.77ms+3.84ms) by main::BEGIN@22 at line 634
use Foswiki::Plugins ();
# spent 5.61ms making 1 call to Foswiki::BEGIN@634
6352112µs1634µs
# spent 634µs (442+192) within Foswiki::BEGIN@635 which was called: # once (442µs+192µs) by main::BEGIN@22 at line 635
use Foswiki::Store ();
# spent 634µs making 1 call to Foswiki::BEGIN@635
63629.72ms18.05ms
# spent 8.05ms (2.68+5.37) within Foswiki::BEGIN@636 which was called: # once (2.68ms+5.37ms) by main::BEGIN@22 at line 636
use Foswiki::Users ();
# spent 8.05ms making 1 call to Foswiki::BEGIN@636
637
638
# spent 12µs within Foswiki::UTF82SiteCharSet which was called 2 times, avg 6µs/call: # once (8µs+0s) by Foswiki::new at line 1884 # once (5µs+0s) by Foswiki::new at line 1923
sub UTF82SiteCharSet {
63922µs my ( $this, $text ) = @_;
640
64122µs return $text unless ( defined $Foswiki::cfg{Site}{CharSet} );
642
643 # Detect character encoding of the full topic name from URL
644213µs return if ( $text =~ $regex{validAsciiStringRegex} );
645
646 # SMELL: all this regex stuff should go away.
647 # If not UTF-8 - assume in site character set, no conversion required
648 if ( $^O eq 'darwin' ) {
649
650 #this is a gross over-generalisation - as not all darwins are apple's
651 # and not all darwins use apple's perl
652 my $trial = $text;
653 $trial =~ s/$regex{validUtf8CharRegex}//g;
654 return unless ( length($trial) == 0 );
655 }
656 else {
657
658 #SMELL: this seg faults on OSX leopard. (and possibly others)
659 return unless ( $text =~ $regex{validUtf8StringRegex} );
660 }
661
662 # If site charset is already UTF-8, there is no need to convert anything:
663 if ( $Foswiki::cfg{Site}{CharSet} =~ /^utf-?8$/i ) {
664
665 # warn if using Perl older than 5.8
666 if ( $] < 5.008 ) {
667 $this->logger->log( 'warning',
668 'UTF-8 not remotely supported on Perl '
669 . $]
670 . ' - use Perl 5.8 or higher..' );
671 }
672
673 # We still don't have Codev.UnicodeSupport
674 $this->logger->log( 'warning',
675 'UTF-8 not yet supported as site charset -'
676 . 'Foswiki is likely to have problems' );
677 return $text;
678 }
679
680 # Convert into ISO-8859-1 if it is the site charset. This conversion
681 # is *not valid for ISO-8859-15*.
682 if ( $Foswiki::cfg{Site}{CharSet} =~ /^iso-?8859-?1$/i ) {
683
684 # ISO-8859-1 maps onto first 256 codepoints of Unicode
685 # (conversion from 'perldoc perluniintro')
686 $text =~ s/ ([\xC2\xC3]) ([\x80-\xBF]) /
687 chr( ord($1) << 6 & 0xC0 | ord($2) & 0x3F )
688 /egx;
689 }
690 else {
691
692 # Convert from UTF-8 into some other site charset
693 if ( $] >= 5.008 ) {
694 require Encode;
695 import Encode qw(:fallbacks);
696
697 # Map $Foswiki::cfg{Site}{CharSet} into real encoding name
698 my $charEncoding =
699 Encode::resolve_alias( $Foswiki::cfg{Site}{CharSet} );
700 if ( not $charEncoding ) {
701 $this->logger->log( 'warning',
702 'Conversion to "'
703 . $Foswiki::cfg{Site}{CharSet}
704 . '" not supported, or name not recognised - check '
705 . '"perldoc Encode::Supported"' );
706 }
707 else {
708
709 # Convert text using Encode:
710 # - first, convert from UTF8 bytes into internal
711 # (UTF-8) characters
712 $text = Encode::decode( 'utf8', $text );
713
714 # - then convert into site charset from internal UTF-8,
715 # inserting \x{NNNN} for characters that can't be converted
716 $text = Encode::encode( $charEncoding, $text, &FB_PERLQQ() );
717 }
718 }
719 else {
720 require Unicode::MapUTF8; # Pre-5.8 Perl versions
721 my $charEncoding = $Foswiki::cfg{Site}{CharSet};
722 if ( not Unicode::MapUTF8::utf8_supported_charset($charEncoding) ) {
723 $this->logger->log( 'warning',
724 'Conversion to "'
725 . $Foswiki::cfg{Site}{CharSet}
726 . '" not supported, or name not recognised - check '
727 . '"perldoc Unicode::MapUTF8"' );
728 }
729 else {
730
731 # Convert text
732 $text = Unicode::MapUTF8::from_utf8(
733 {
734 -string => $text,
735 -charset => $charEncoding
736 }
737 );
738
739 # FIXME: Check for failed conversion?
740 }
741 }
742 }
743 return $text;
744}
745
746=begin TML
747
748---++ ObjectMethod writeCompletePage( $text, $pageType, $contentType )
749
750Write a complete HTML page with basic header to the browser.
751 * =$text= is the text of the page script (&lt;html&gt; to &lt;/html&gt; if it's HTML)
752 * =$pageType= - May be "edit", which will cause headers to be generated that force
753 caching for 24 hours, to prevent Codev.BackFromPreviewLosesText bug, which caused
754 data loss with IE5 and IE6.
755 * =$contentType= - page content type | text/html
756
757This method removes noautolink and nop tags before outputting the page unless
758$contentType is text/plain.
759
760=cut
761
762
# spent 27.8ms (6.47+21.4) within Foswiki::writeCompletePage which was called: # once (6.47ms+21.4ms) by Foswiki::UI::View::view at line 405 of /var/www/foswiki11/lib/Foswiki/UI/View.pm
sub writeCompletePage {
763118µs my ( $this, $text, $pageType, $contentType ) = @_;
7641500ns $contentType ||= 'text/html';
765
76613µs142µs my $cgis = $this->getCGISession();
# spent 42µs making 1 call to Foswiki::getCGISession
7671400ns if ( $cgis
768 && $contentType eq 'text/html'
769 && $Foswiki::cfg{Validation}{Method} ne 'none' )
770 {
771
772 # Don't expire the validation key through login, or when
773 # endpoint is an error.
774 Foswiki::Validation::expireValidationKeys($cgis)
775 unless ( $this->{request}->action() eq 'login'
776 or ( $ENV{REDIRECT_STATUS} || 0 ) >= 400 );
777
778 my $usingStrikeOne = 0;
779 if (
780 $Foswiki::cfg{Validation}{Method} eq 'strikeone'
781
782 # Add the onsubmit handler to the form
783 && $text =~ s/(<form[^>]*method=['"]POST['"][^>]*>)/
784 Foswiki::Validation::addOnSubmit($1)/gei
785 )
786 {
787
788 # At least one form has been touched; add the validation
789 # cookie
790 my $valCookie = Foswiki::Validation::getCookie($cgis);
791 $valCookie->secure( $this->{request}->secure );
792 $this->{response}
793 ->cookies( [ $this->{response}->cookies, $valCookie ] );
794
795 # Add the JS module to the page. Note that this is *not*
796 # incorporated into the foswikilib.js because that module
797 # is conditionally loaded under the control of the
798 # templates, and we have to be *sure* it gets loaded.
799 my $src = $this->{prefs}->getPreference('FWSRC') || '';
800 $this->addToZone( 'script', 'JavascriptFiles/strikeone', <<JS );
801<script type="text/javascript" src="$Foswiki::cfg{PubUrlPath}/$Foswiki::cfg{SystemWebName}/JavascriptFiles/strikeone$src.js"></script>
802JS
803 $usingStrikeOne = 1;
804 }
805
806 # Inject validation key in HTML forms
807 my $context =
808 $this->{request}->url( -full => 1, -path => 1, -query => 1 ) . time();
809 $text =~ s/(<form[^>]*method=['"]POST['"][^>]*>)/
810 $1 . Foswiki::Validation::addValidationKey(
811 $cgis, $context, $usingStrikeOne )/gei;
812 }
813
81414µs121.0ms if ( $contentType ne 'text/plain' ) {
# spent 21.0ms making 1 call to Foswiki::_renderZones
815
816 $text = $this->_renderZones($text);
817 }
818
819 # SMELL: can't compute; faking content-type for backwards compatibility;
820 # any other information might become bogus later anyway
821 # Validate format of content-type (defined in rfc2616)
82214µs my $tch = qr/[^\[\]()<>@,;:\\"\/?={}\s]/o;
823136µs if ( $contentType =~ /($tch+\/$tch+(\s*;\s*$tch+=($tch+|"[^"]*"))*)$/oi ) {
824 $contentType = $1;
825 }
826 else {
827 $contentType = "text/plain;contenttype=invalid";
828 }
82913µs my $hdr = "Content-type: " . $1 . "\r\n";
830
831 # Call final handler
83214µs16µs $this->{plugins}->dispatch( 'completePageHandler', $text, $hdr );
# spent 6µs making 1 call to Foswiki::Plugins::dispatch
833
834 # cache final page, but only view
8351200ns my $cachedPage;
83611µs if ( $contentType ne 'text/plain' ) {
83712µs if ( $Foswiki::cfg{Cache}{Enabled}
838 && ( $this->inContext('view') || $this->inContext('rest') ) )
839 {
840 $cachedPage = $this->{cache}->cachePage( $contentType, $text );
841 $this->{cache}->renderDirtyAreas( \$text )
842 if $cachedPage->{isDirty};
843 }
844 else {
845
846 # remove <dirtyarea> tags
847125µs $text =~ s/<\/?dirtyarea[^>]*>//go;
848 }
849
850 # Remove <nop> and <noautolink> tags
85116.33ms $text =~ s/([\t ]?)[ \t]*<\/?(nop|noautolink)\/?>/$1/gis;
852
853 # Check that the templates specified clean HTML
85412µs12µs if (DEBUG) {
# spent 2µs making 1 call to Assert::ASSERTS_OFF
855
856 # When tracing is enabled in Foswiki::Templates, then there will
857 # always be a <!--bodyend--> after </html>. So we need to disable
858 # this check.
859 require Foswiki::Templates;
860 if ( !Foswiki::Templates->TRACE
861 && $contentType =~ m#text/html#
862 && $text =~ m#</html>(.*?\S.*)$#s )
863 {
864 ASSERT( 0, <<BOGUS );
865Junk after </html>: $1. Templates may be bogus
866- Check for excess blank lines at ends of .tmpl files
867- or newlines after %TMPL:INCLUDE
868- You can enable TRACE in Foswiki::Templates to help debug
869BOGUS
870 }
871 }
872 }
873
87414µs1225µs $this->generateHTTPHeaders( $pageType, $contentType, $text, $cachedPage );
# spent 225µs making 1 call to Foswiki::generateHTTPHeaders
875
876 # SMELL: null operation. the http headers are written out
877 # during Foswiki::Engine::finalize
878 # $hdr = $this->{response}->printHeaders;
879
880111µs190µs $this->{response}->print($text);
# spent 90µs making 1 call to Foswiki::Response::print
881}
882
883=begin TML
884
885---++ ObjectMethod generateHTTPHeaders( $pageType, $contentType, $text, $cachedPage )
886
887All parameters are optional.
888
889 * =$pageType= - May be "edit", which will cause headers to be generated that force caching for 24 hours, to prevent Codev.BackFromPreviewLosesText bug, which caused data loss with IE5 and IE6.
890 * =$contentType= - page content type | text/html
891 * =$text= - page content
892 * =$cachedPage= - a pointer to the page container as fetched from the page cache
893
894=cut
895
896
# spent 225µs (77+148) within Foswiki::generateHTTPHeaders which was called: # once (77µs+148µs) by Foswiki::writeCompletePage at line 874
sub generateHTTPHeaders {
897119µs my ( $this, $pageType, $contentType, $text, $cachedPage ) = @_;
898
89911µs my $hopts = {};
900
901 # Handle Edit pages - future versions will extend to caching
902 # of other types of page, with expiry time driven by page type.
90311µs if ( $pageType && $pageType eq 'edit' ) {
904
905 # Get time now in HTTP header format
906 my $lastModifiedString =
907 Foswiki::Time::formatTime( time, '$http', 'gmtime' );
908
909 # Expiry time is set high to avoid any data loss. Each instance of
910 # Edit page has a unique URL with time-string suffix (fix for
911 # RefreshEditPage), so this long expiry time simply means that the
912 # browser Back button always works. The next Edit on this page
913 # will use another URL and therefore won't use any cached
914 # version of this Edit page.
915 my $expireHours = 24;
916 my $expireSeconds = $expireHours * 60 * 60;
917
918 # and cache control headers, to ensure edit page
919 # is cached until required expiry time.
920 $hopts->{'last-modified'} = $lastModifiedString;
921 $hopts->{expires} = "+${expireHours}h";
922 $hopts->{'cache-control'} = "max-age=$expireSeconds";
923 }
924
925 # DEPRECATED plugins header handler. Plugins should use
926 # modifyHeaderHandler instead.
92715µs16µs my $pluginHeaders =
# spent 6µs making 1 call to Foswiki::Plugins::dispatch
928 $this->{plugins}->dispatch( 'writeHeaderHandler', $this->{request} )
929 || '';
9301200ns if ($pluginHeaders) {
931 foreach ( split /\r?\n/, $pluginHeaders ) {
932
933 # Implicit untaint OK; data from plugin handler
934 if (m/^([\-a-z]+): (.*)$/i) {
935 $hopts->{$1} = $2;
936 }
937 }
938 }
939
9401300ns $contentType = 'text/html' unless $contentType;
94119µs $contentType .= '; charset=' . $Foswiki::cfg{Site}{CharSet}
942 if $contentType ne ''
943 && $contentType =~ m!^text/!
944 && $contentType !~ /\bcharset\b/
945 && $Foswiki::cfg{Site}{CharSet};
946
947 # use our version of the content type
94812µs $hopts->{'Content-Type'} = $contentType;
949
950 # New (since 1.026)
95113µs182µs $this->{plugins}
# spent 82µs making 1 call to Foswiki::Plugins::dispatch
952 ->dispatch( 'modifyHeaderHandler', $hopts, $this->{request} );
953
954 # add http compression and conditional cache controls
95513µs13µs if ( !$this->inContext('command_line') && $text ) {
# spent 3µs making 1 call to Foswiki::inContext
956
957 if ( $Foswiki::cfg{HttpCompress}
958 && $ENV{'HTTP_ACCEPT_ENCODING'}
959 && $ENV{'HTTP_ACCEPT_ENCODING'} =~ /(x-gzip|gzip)/i )
960 {
961 my $encoding = $1;
962 $hopts->{'Content-Encoding'} = $encoding;
963 $hopts->{'Vary'} = 'Accept-Encoding';
964
965 # check if we take the version from the cache
966 if ( $cachedPage && !$cachedPage->{isDirty} ) {
967 $text = $cachedPage->{text};
968 }
969 else {
970 require Compress::Zlib;
971 $text = Compress::Zlib::memGzip($text);
972 }
973 }
974 elsif ($cachedPage
975 && !$cachedPage->{isDirty}
976 && $Foswiki::cfg{HttpCompress} )
977 {
978
979 # Outch, we need to uncompressed pages from cache again
980 # Note, this is effort to avoid under any circumstances as
981 # the page has been compressed when it has been created and now
982 # is uncompressed again to get back the original. For now the
983 # only know situation this can happen is for older browsers like IE6
984 # which does not understand gzip'ed http encodings
985 require Compress::Zlib;
986 $text = Compress::Zlib::memGunzip($text);
987 }
988
989 # we need to force the browser into a check on every
990 # request; let the server decide on an 304 as below
991 $hopts->{'Cache-Control'} = 'max-age=0';
992
993 # check etag and last modification time
994 # if we have a cached page on the server side
995 if ($cachedPage) {
996 my $etag = $cachedPage->{etag};
997 my $lastModified = $cachedPage->{lastModified};
998
999 $hopts->{'ETag'} = $etag;
1000 $hopts->{'Last-Modified'} = $lastModified if $lastModified;
1001
1002 # only send a 304 if both criteria are true
1003 my $etagFlag = 1;
1004 my $lastModifiedFlag = 1;
1005
1006 # check etag
1007 unless ( $ENV{'HTTP_IF_NONE_MATCH'}
1008 && $etag eq $ENV{'HTTP_IF_NONE_MATCH'} )
1009 {
1010 $etagFlag = 0;
1011 }
1012
1013 # check last-modified
1014 unless ( $ENV{'HTTP_IF_MODIFIED_SINCE'}
1015 && $lastModified eq $ENV{'HTTP_IF_MODIFIED_SINCE'} )
1016 {
1017 $lastModifiedFlag = 0;
1018 }
1019
1020 # finally decide on a 304 reply
1021 if ( $etagFlag && $lastModified ) {
1022 $hopts->{'Status'} = '304 Not Modified';
1023 $text = '';
1024
1025 #print STDERR "NOT modified\n";
1026 }
1027 }
1028
1029 # write back to text
1030 $_[3] = $text;
1031 }
1032
103319µs18µs $hopts->{"X-FoswikiAction"} = $this->{request}->action;
# spent 8µs making 1 call to Foswiki::Request::action
103415µs14µs $hopts->{"X-FoswikiURI"} = $this->{request}->uri;
# spent 4µs making 1 call to Foswiki::Request::uri
1035
1036 # The headers method resets all headers to what we pass
1037 # what we want is simply ensure our headers are there
1038112µs146µs $this->{response}->setDefaultHeaders($hopts);
# spent 46µs making 1 call to Foswiki::Response::setDefaultHeaders
1039}
1040
1041# Tests if the $redirect is an external URL, returning false if
1042# AllowRedirectUrl is denied
1043sub _isRedirectSafe {
1044 my $redirect = shift;
1045
1046 return 1 if ( $Foswiki::cfg{AllowRedirectUrl} );
1047 return 1 if $redirect =~ m#^/#; # relative URL - OK
1048
1049 #TODO: this should really use URI
1050 # Compare protocol, host name and port number
1051 if ( $redirect =~ m!^(.*?://[^/?#]*)! ) {
1052
1053 # implicit untaints OK because result not used. uc retaints
1054 # if use locale anyway.
1055 my $target = uc($1);
1056
1057 $Foswiki::cfg{DefaultUrlHost} =~ m!^(.*?://[^/]*)!;
1058 return 1 if ( $target eq uc($1) );
1059
1060 if ( $Foswiki::cfg{PermittedRedirectHostUrls} ) {
1061 foreach my $red (
1062 split( /\s*,\s*/, $Foswiki::cfg{PermittedRedirectHostUrls} ) )
1063 {
1064 $red =~ m!^(.*?://[^/]*)!;
1065 return 1 if ( $target eq uc($1) );
1066 }
1067 }
1068 }
1069 return 0;
1070}
1071
1072=begin TML
1073
1074---++ ObjectMethod redirectto($url) -> $url
1075
1076If the CGI parameter 'redirectto' is present on the query, then will validate
1077that it is a legal redirection target (url or topic name). If 'redirectto'
1078is not present on the query, performs the same steps on $url.
1079
1080Returns undef if the target is not valid, and the target URL otherwise.
1081
1082=cut
1083
1084sub redirectto {
1085 my ( $this, $url ) = @_;
1086
1087 my $redirecturl = $this->{request}->param('redirectto');
1088 $redirecturl = $url unless $redirecturl;
1089
1090 return unless $redirecturl;
1091
1092 if ( $redirecturl =~ m#^$regex{linkProtocolPattern}://#o ) {
1093
1094 # assuming URL
1095 return $redirecturl if _isRedirectSafe($redirecturl);
1096 return;
1097 }
1098
1099 # assuming 'web.topic' or 'topic'
1100 my ( $w, $t ) =
1101 $this->normalizeWebTopicName( $this->{webName}, $redirecturl );
1102
1103 # capture anchor
1104 my ( $topic, $anchor ) = split( '#', $t, 2 );
1105 $t = $topic if $topic;
1106 my @attrs = ();
1107 push( @attrs, '#' => $anchor ) if $anchor;
1108
1109 return $this->getScriptUrl( 0, 'view', $w, $t, @attrs );
1110}
1111
1112=begin TML
1113
1114---++ StaticMethod splitAnchorFromUrl( $url ) -> ( $url, $anchor )
1115
1116Takes a full url (including possible query string) and splits off the anchor.
1117The anchor includes the # sign. Returns an empty string if not found in the url.
1118
1119=cut
1120
1121sub splitAnchorFromUrl {
1122 my ($url) = @_;
1123
1124 ( $url, my $anchor ) = $url =~ m/^(.*?)(#(.*?))*$/;
1125 return ( $url, $anchor );
1126}
1127
1128=begin TML
1129
1130---++ ObjectMethod redirect( $url, $passthrough )
1131
1132 * $url - url or topic to redirect to
1133 * $passthrough - (optional) parameter to pass through current query
1134 parameters (see below)
1135
1136Redirects the request to =$url=, *unless*
1137 1 It is overridden by a plugin declaring a =redirectCgiQueryHandler=
1138 (a dangerous, deprecated handler!)
1139 1 =$session->{request}= is =undef= or
1140Thus a redirect is only generated when in a CGI context.
1141
1142Normally this method will ignore parameters to the current query. Sometimes,
1143for example when redirecting to a login page during authentication (and then
1144again from the login page to the original requested URL), you want to make
1145sure all parameters are passed on, and for this $passthrough should be set to
1146true. In this case it will pass all parameters that were passed to the
1147current query on to the redirect target. If the request_method for the
1148current query was GET, then all parameters will be passed by encoding them
1149in the URL (after ?). If the request_method was POST, then there is a risk the
1150URL would be too big for the receiver, so it caches the form data and passes
1151over a cache reference in the redirect GET.
1152
1153NOTE: Passthrough is only meaningful if the redirect target is on the same
1154server.
1155
1156=cut
1157
1158sub redirect {
1159 my ( $this, $url, $passthru ) = @_;
1160 ASSERT( defined $url ) if DEBUG;
1161
1162 return unless $this->{request};
1163
1164 ( $url, my $anchor ) = splitAnchorFromUrl($url);
1165
1166 if ( $passthru && defined $this->{request}->method() ) {
1167 my $existing = '';
1168 if ( $url =~ s/\?(.*)$// ) {
1169 $existing = $1; # implicit untaint OK; recombined later
1170 }
1171 if ( uc( $this->{request}->method() ) eq 'POST' ) {
1172
1173 # Redirecting from a post to a get
1174 my $cache = $this->cacheQuery();
1175 if ($cache) {
1176 if ( $url eq '/' ) {
1177 $url = $this->getScriptUrl( 1, 'view' );
1178 }
1179 $url .= $cache;
1180 }
1181 }
1182 else {
1183
1184 # Redirecting a get to a get; no need to use passthru
1185 if ( $this->{request}->query_string() ) {
1186 $url .= '?' . $this->{request}->query_string();
1187 }
1188 if ($existing) {
1189 if ( $url =~ /\?/ ) {
1190 $url .= ';';
1191 }
1192 else {
1193 $url .= '?';
1194 }
1195 $url .= $existing;
1196 }
1197 }
1198 }
1199
1200 # prevent phishing by only allowing redirect to configured host
1201 # do this check as late as possible to catch _any_ last minute hacks
1202 # TODO: this should really use URI
1203 if ( !_isRedirectSafe($url) ) {
1204
1205 # goto oops if URL is trying to take us somewhere dangerous
1206 $url = $this->getScriptUrl(
1207 1, 'oops',
1208 $this->{webName} || $Foswiki::cfg{UsersWebName},
1209 $this->{topicName} || $Foswiki::cfg{HomeTopicName},
1210 template => 'oopsredirectdenied',
1211 def => 'redirect_denied',
1212 param1 => "$url",
1213 param2 => "$Foswiki::cfg{DefaultUrlHost}",
1214 );
1215 }
1216
1217 $url .= $anchor if $anchor;
1218
1219 # Dangerous, deprecated handler! Might work, probably won't.
1220 return
1221 if ( $this->{plugins}
1222 ->dispatch( 'redirectCgiQueryHandler', $this->{response}, $url ) );
1223
1224 $url = $this->getLoginManager()->rewriteRedirectUrl($url);
1225
1226 # Foswiki::Response::redirect doesn't automatically pass on the cookies
1227 # for us, so we have to do it explicitly; otherwise the session cookie
1228 # won't get passed on.
1229 $this->{response}
1230 ->redirect( -url => $url, -cookies => $this->{response}->cookies() );
1231}
1232
1233=begin TML
1234
1235---++ ObjectMethod cacheQuery() -> $queryString
1236
1237Caches the current query in the params cache, and returns a rewritten
1238query string for the cache to be picked up again on the other side of a
1239redirect.
1240
1241We can't encode post params into a redirect, because they may exceed the
1242size of the GET request. So we cache the params, and reload them when the
1243redirect target is reached.
1244
1245=cut
1246
1247sub cacheQuery {
1248 my $this = shift;
1249 my $query = $this->{request};
1250
1251 return '' unless ( scalar( $query->param() ) );
1252
1253 # Don't double-cache
1254 return '' if ( $query->param('foswiki_redirect_cache') );
1255
1256 require Foswiki::Request::Cache;
1257 my $uid = Foswiki::Request::Cache->new()->save($query);
1258 if ( $Foswiki::cfg{UsePathForRedirectCache} ) {
1259 return '/foswiki_redirect_cache/' . $uid;
1260 }
1261 else {
1262 return '?foswiki_redirect_cache=' . $uid;
1263 }
1264}
1265
1266=begin TML
1267
1268---++ ObjectMethod getCGISession() -> $cgisession
1269
1270Get the CGI::Session object associated with this session, if there is
1271one. May return undef.
1272
1273=cut
1274
1275
# spent 42µs (12+30) within Foswiki::getCGISession which was called: # once (12µs+30µs) by Foswiki::writeCompletePage at line 766
sub getCGISession {
127619µs130µs $_[0]->{users}->getCGISession();
# spent 30µs making 1 call to Foswiki::Users::getCGISession
1277}
1278
1279=begin TML
1280
1281---++ ObjectMethod getLoginManager() -> $loginManager
1282
1283Get the Foswiki::LoginManager object associated with this session, if there is
1284one. May return undef.
1285
1286=cut
1287
1288
# spent 108µs (73+35) within Foswiki::getLoginManager which was called 10 times, avg 11µs/call: # 5 times (36µs+19µs) by Foswiki::Render::getRenderedVersion at line 1464 of /var/www/foswiki11/lib/Foswiki/Render.pm, avg 11µs/call # 2 times (16µs+7µs) by Foswiki::LoginManager::_LOGIN at line 1150 of /var/www/foswiki11/lib/Foswiki/LoginManager.pm, avg 12µs/call # once (11µs+6µs) by Foswiki::Func::setSessionValue at line 377 of /var/www/foswiki11/lib/Foswiki/Func.pm # once (5µs+2µs) by Foswiki::Func::clearSessionValue at line 394 of /var/www/foswiki11/lib/Foswiki/Func.pm # once (5µs+2µs) by Foswiki::UI::__ANON__[/var/www/foswiki11/lib/Foswiki/UI.pm:318] at line 315 of /var/www/foswiki11/lib/Foswiki/UI.pm
sub getLoginManager {
12891066µs1035µs $_[0]->{users}->getLoginManager();
# spent 35µs making 10 calls to Foswiki::Users::getLoginManager, avg 4µs/call
1290}
1291
1292=begin TML
1293
1294---++ StaticMethod isValidWikiWord( $name ) -> $boolean
1295
1296Check for a valid WikiWord or WikiName
1297
1298=cut
1299
1300sub isValidWikiWord {
1301 my $name = shift || '';
1302 return ( $name =~ m/^$regex{wikiWordRegex}$/o );
1303}
1304
1305=begin TML
1306
1307---++ StaticMethod isValidTopicName( $name [, $nonww] ) -> $boolean
1308
1309Check for a valid topic =$name=. If =$nonww=, then accept non wiki-words
1310(though they must still be composed of only valid, unfiltered characters)
1311
1312=cut
1313
1314# Note: must work on tainted names.
1315
# spent 104µs within Foswiki::isValidTopicName which was called 9 times, avg 12µs/call: # 7 times (57µs+0s) by Foswiki::INCLUDE at line 176 of /var/www/foswiki11/lib/Foswiki/Macros/INCLUDE.pm, avg 8µs/call # 2 times (47µs+0s) by Foswiki::Sandbox::validateTopicName at line 160 of /var/www/foswiki11/lib/Foswiki/Sandbox.pm, avg 23µs/call
sub isValidTopicName {
131697µs my ( $name, $nonww ) = @_;
1317
131897µs return 0 unless defined $name && $name ne '';
1319978µs return 1 if ( $name =~ m/^$regex{topicNameRegex}$/o );
13202500ns return 0 unless $nonww;
1321213µs return 0 if $name =~ /$cfg{NameFilter}/o;
132227µs return 1;
1323}
1324
1325=begin TML
1326
1327---++ StaticMethod isValidWebName( $name, $system ) -> $boolean
1328
1329STATIC Check for a valid web name. If $system is true, then
1330system web names are considered valid (names starting with _)
1331otherwise only user web names are valid
1332
1333If $Foswiki::cfg{EnableHierarchicalWebs} is off, it will also return false
1334when a nested web name is passed to it.
1335
1336=cut
1337
1338# Note: must work on tainted names.
1339
# spent 1.16ms within Foswiki::isValidWebName which was called 182 times, avg 6µs/call: # 182 times (1.16ms+0s) by Foswiki::Sandbox::validateWebName at line 145 of /var/www/foswiki11/lib/Foswiki/Sandbox.pm, avg 6µs/call
sub isValidWebName {
134018292µs my $name = shift || '';
134118243µs my $sys = shift;
1342182262µs return 1 if ( $sys && $name =~ m/^$regex{defaultWebNameRegex}$/o );
13431791.11ms return ( $name =~ m/^$regex{webNameRegex}$/o );
1344}
1345
1346=begin TML
1347
1348---++ StaticMethod isValidEmailAddress( $name ) -> $boolean
1349
1350STATIC Check for a valid email address name.
1351
1352=cut
1353
1354# Note: must work on tainted names.
1355sub isValidEmailAddress {
1356 my $name = shift || '';
1357 return $name =~ /^$regex{emailAddrRegex}$/o;
1358}
1359
1360=begin TML
1361
1362---++ ObjectMethod getSkin () -> $string
1363
1364Get the currently requested skin path
1365
1366=cut
1367
1368
# spent 6.67ms (1.65+5.02) within Foswiki::getSkin which was called 45 times, avg 148µs/call: # 42 times (1.52ms+4.65ms) by Foswiki::Templates::readTemplate at line 230 of /var/www/foswiki11/lib/Foswiki/Templates.pm, avg 147µs/call # 2 times (87µs+265µs) by Foswiki::UI::View::view at line 326 of /var/www/foswiki11/lib/Foswiki/UI/View.pm, avg 176µs/call # once (36µs+103µs) by Foswiki::UI::View::view at line 349 of /var/www/foswiki11/lib/Foswiki/UI/View.pm
sub getSkin {
13694525µs my $this = shift;
1370
1371458µs my @skinpath;
13724513µs my $skins;
1373
13744553µs if ( $this->{request} ) {
137545290µs451.96ms $skins = $this->{request}->param('cover');
# spent 1.96ms making 45 calls to Foswiki::Request::param, avg 44µs/call
13764521µs if ( defined $skins
1377 && $skins =~ /([$regex{mixedAlphaNum}.,\s]+)/o )
1378 {
1379
1380 # Implicit untaint ok - validated
1381 $skins = $1;
1382 push( @skinpath, split( /,\s]+/, $skins ) );
1383 }
1384 }
1385
138645324µs452.30ms $skins = $this->{prefs}->getPreference('COVER');
# spent 2.30ms making 45 calls to Foswiki::Prefs::getPreference, avg 51µs/call
13874517µs if ( defined $skins
1388 && $skins =~ /([$regex{mixedAlphaNum}.,\s]+)/o )
1389 {
1390
1391 # Implicit untaint ok - validated
1392 $skins = $1;
1393 push( @skinpath, split( /[,\s]+/, $skins ) );
1394 }
1395
139645161µs45763µs $skins = $this->{request} ? $this->{request}->param('skin') : undef;
# spent 763µs making 45 calls to Foswiki::Request::param, avg 17µs/call
13974512µs $skins = $this->{prefs}->getPreference('SKIN') unless $skins;
1398
139945323µs if ( defined $skins && $skins =~ /([$regex{mixedAlphaNum}.,\s]+)/o ) {
1400
1401 # Implicit untaint ok - validated
14024551µs $skins = $1;
140345189µs push( @skinpath, split( /[,\s]+/, $skins ) );
1404 }
1405
140645252µs return join( ',', @skinpath );
1407}
1408
1409=begin TML
1410
1411---++ ObjectMethod getScriptUrl( $absolute, $script, $web, $topic, ... ) -> $scriptURL
1412
1413Returns the URL to a Foswiki script, providing the web and topic as
1414"path info" parameters. The result looks something like this:
1415"http://host/foswiki/bin/$script/$web/$topic".
1416 * =...= - an arbitrary number of name,value parameter pairs that will be url-encoded and added to the url. The special parameter name '#' is reserved for specifying an anchor. e.g. <tt>getScriptUrl('x','y','view','#'=>'XXX',a=>1,b=>2)</tt> will give <tt>.../view/x/y?a=1&b=2#XXX</tt>
1417
1418If $absolute is set, generates an absolute URL. $absolute is advisory only;
1419Foswiki can decide to generate absolute URLs (for example when run from the
1420command-line) even when relative URLs have been requested.
1421
1422The default script url is taken from {ScriptUrlPath}, unless there is
1423an exception defined for the given script in {ScriptUrlPaths}. Both
1424{ScriptUrlPath} and {ScriptUrlPaths} may be absolute or relative URIs. If
1425they are absolute, then they will always generate absolute URLs. if they
1426are relative, then they will be converted to absolute when required (e.g.
1427when running from the command line, or when generating rss). If
1428$script is not given, absolute URLs will always be generated.
1429
1430If either the web or the topic is defined, will generate a full url (including web and topic). Otherwise will generate only up to the script name. An undefined web will default to the main web name.
1431
1432=cut
1433
1434
# spent 1.75ms (995µs+751µs) within Foswiki::getScriptUrl which was called 48 times, avg 36µs/call: # 17 times (444µs+391µs) by Foswiki::Render::_renderExistingWikiWord at line 677 of /var/www/foswiki11/lib/Foswiki/Render.pm, avg 49µs/call # 16 times (198µs+39µs) by Foswiki::__ANON__[/var/www/foswiki11/lib/Foswiki.pm:270] at line 270, avg 15µs/call # 9 times (87µs+0s) by Foswiki::__ANON__[/var/www/foswiki11/lib/Foswiki.pm:268] at line 268, avg 10µs/call # 2 times (110µs+170µs) by Foswiki::UI::View::revisionsAround at line 492 of /var/www/foswiki11/lib/Foswiki/UI/View.pm, avg 140µs/call # 2 times (66µs+93µs) by Foswiki::UI::View::revisionsAround at line 480 of /var/www/foswiki11/lib/Foswiki/UI/View.pm, avg 80µs/call # 2 times (89µs+58µs) by Foswiki::LoginManager::ApacheLogin::loginUrl at line 102 of /var/www/foswiki11/lib/Foswiki/LoginManager/ApacheLogin.pm, avg 74µs/call
sub getScriptUrl {
14354881µs my ( $this, $absolute, $script, $web, $topic, @params ) = @_;
1436
14374882µs39110µs $absolute ||=
# spent 110µs making 39 calls to Foswiki::inContext, avg 3µs/call
1438 ( $this->inContext('command_line')
1439 || $this->inContext('rss')
1440 || $this->inContext('absolute_urls') );
1441
1442 # SMELL: topics and webs that contain spaces?
1443
1444489µs my $url;
14454868µs if ( defined $Foswiki::cfg{ScriptUrlPaths} && $script ) {
1446 $url = $Foswiki::cfg{ScriptUrlPaths}{$script};
1447 }
14484813µs unless ( defined($url) ) {
14491413µs $url = $Foswiki::cfg{ScriptUrlPath};
1450146µs if ($script) {
14511214µs $url .= '/' unless $url =~ /\/$/;
1452125µs $url .= $script;
14531228µs if (
1454 rindex( $url, $Foswiki::cfg{ScriptSuffix} ) !=
1455 ( length($url) - length( $Foswiki::cfg{ScriptSuffix} ) ) )
1456 {
1457 $url .= $Foswiki::cfg{ScriptSuffix} if $script;
1458 }
1459 }
1460 }
1461
146248111µs if ( $absolute && $url !~ /^[a-z]+:/ ) {
1463
1464 # See http://www.ietf.org/rfc/rfc2396.txt for the definition of
1465 # "absolute URI". Foswiki bastardises this definition by assuming
1466 # that all relative URLs lack the <authority> component as well.
1467 $url = $this->{urlHost} . $url;
1468 }
1469
14704823µs if ( $web || $topic ) {
14712388µs23311µs ( $web, $topic ) = $this->normalizeWebTopicName( $web, $topic );
# spent 311µs making 23 calls to Foswiki::normalizeWebTopicName, avg 14µs/call
1472
14732391µs2389µs $url .= urlEncode( '/' . $web . '/' . $topic );
# spent 89µs making 23 calls to Foswiki::urlEncode, avg 4µs/call
1474
14752360µs23241µs $url .= _make_params( 0, @params );
# spent 241µs making 23 calls to Foswiki::_make_params, avg 10µs/call
1476 }
1477
147848186µs return $url;
1479}
1480
1481
# spent 241µs (206+35) within Foswiki::_make_params which was called 23 times, avg 10µs/call: # 23 times (206µs+35µs) by Foswiki::getScriptUrl at line 1475, avg 10µs/call
sub _make_params {
14822310µs my $notfirst = shift;
14832310µs my $url = '';
1484235µs my $ps = '';
1485236µs my $anchor = '';
14862335µs while ( my $p = shift @_ ) {
148765µs if ( $p eq '#' ) {
1488 $anchor = '#' . urlEncode( shift(@_) );
1489 }
1490 else {
149163µs my $v = shift(@_);
149262µs $v = '' unless defined $v;
1493627µs1236µs $ps .= ';' . urlEncode($p) . '=' . urlEncode($v);
# spent 36µs making 12 calls to Foswiki::urlEncode, avg 3µs/call
1494 }
1495 }
1496237µs if ($ps) {
1497415µs $ps =~ s/^;/?/ unless $notfirst;
149842µs $url .= $ps;
1499 }
15002392µs return $url . $anchor;
1501}
1502
1503=begin TML
1504
1505---++ ObjectMethod getPubUrl($absolute, $web, $topic, $attachment) -> $url
1506
1507Composes a pub url. If $absolute is set, returns an absolute URL.
1508If $absolute is set, generates an absolute URL. $absolute is advisory only;
1509Foswiki can decide to generate absolute URLs (for example when run from the
1510command-line) even when relative URLs have been requested.
1511
1512$web, $topic and $attachment are optional. A partial URL path will be
1513generated if one or all is not given.
1514
1515=cut
1516
1517
# spent 518µs (386+132) within Foswiki::getPubUrl which was called 36 times, avg 14µs/call: # 33 times (333µs+75µs) by Foswiki::__ANON__[/var/www/foswiki11/lib/Foswiki.pm:241] at line 241, avg 12µs/call # 2 times (11µs+0s) by Foswiki::__ANON__[/var/www/foswiki11/lib/Foswiki.pm:240] at line 240, avg 6µs/call # once (42µs+58µs) by Foswiki::_getIconUrl at line 134 of /var/www/foswiki11/lib/Foswiki/Macros/ICON.pm
sub getPubUrl {
15183634µs my ( $this, $absolute, $web, $topic, $attachment ) = @_;
1519
15203656µs3375µs $absolute ||=
# spent 75µs making 33 calls to Foswiki::inContext, avg 2µs/call
1521 ( $this->inContext('command_line')
1522 || $this->inContext('rss')
1523 || $this->inContext('absolute_urls') );
1524
15253616µs my $url = '';
15263627µs $url .= $Foswiki::cfg{PubUrlPath};
15273674µs if ( $absolute && $url !~ /^[a-z]+:/ ) {
1528
1529 # See http://www.ietf.org/rfc/rfc2396.txt for the definition of
1530 # "absolute URI". Foswiki bastardises this definition by assuming
1531 # that all relative URLs lack the <authority> component as well.
1532 $url = $this->{urlHost} . $url;
1533 }
15343615µs if ( $web || $topic || $attachment ) {
153515µs130µs ( $web, $topic ) = $this->normalizeWebTopicName( $web, $topic );
# spent 30µs making 1 call to Foswiki::normalizeWebTopicName
1536
153712µs my $path = '/' . $web . '/' . $topic;
153811µs if ($attachment) {
15391900ns $path .= '/' . $attachment;
1540
1541 # Attachments are served directly by web server, need to handle
1542 # URL encoding specially
154316µs128µs $url .= urlEncodeAttachment($path);
# spent 28µs making 1 call to Foswiki::urlEncodeAttachment
1544 }
1545 else {
1546 $url .= urlEncode($path);
1547 }
1548 }
1549
155036136µs return $url;
1551}
1552
1553=begin TML
1554
1555---++ ObjectMethod deepWebList($filter, $web) -> @list
1556
1557Deep list subwebs of the named web. $filter is a Foswiki::WebFilter
1558object that is used to filter the list. The listing of subwebs is
1559dependent on $Foswiki::cfg{EnableHierarchicalWebs} being true.
1560
1561Webs are returned as absolute web pathnames.
1562
1563=cut
1564
1565
# spent 8.35s (1.90ms+8.35) within Foswiki::deepWebList which was called 2 times, avg 4.18s/call: # 2 times (1.90ms+8.35s) by Foswiki::Func::getListOfWebs at line 1477 of /var/www/foswiki11/lib/Foswiki/Func.pm, avg 4.18s/call
sub deepWebList {
156624µs my ( $this, $filter, $rootWeb ) = @_;
15672600ns my @list;
1568211µs267µs my $webObject = new Foswiki::Meta( $this, $rootWeb );
# spent 67µs making 2 calls to Foswiki::Meta::new, avg 33µs/call
1569214µs292.1ms my $it = $webObject->eachWeb( $Foswiki::cfg{EnableHierarchicalWebs} );
# spent 92.1ms making 2 calls to Foswiki::Meta::eachWeb, avg 46.0ms/call
157021µs return $it->all() unless $filter;
157127µs219µs while ( $it->hasNext() ) {
# spent 19µs making 2 calls to Foswiki::ListIterator::hasNext, avg 10µs/call
157210076µs my $w = $rootWeb || '';
157310022µs $w .= '/' if $w;
1574100263µs100946µs $w .= $it->next();
# spent 946µs making 100 calls to Foswiki::ListIterator::next, avg 9µs/call
1575100680µs2008.26s if ( $filter->ok( $this, $w ) ) {
# spent 8.26s making 100 calls to Foswiki::WebFilter::ok, avg 82.6ms/call # spent 891µs making 100 calls to Foswiki::ListIterator::hasNext, avg 9µs/call
1576 push( @list, $w );
1577 }
1578 }
15792347µs return @list;
1580}
1581
1582=begin TML
1583
1584---++ ObjectMethod normalizeWebTopicName( $web, $topic ) -> ( $web, $topic )
1585
1586Normalize a Web<nop>.<nop>TopicName
1587
1588See =Foswiki::Func= for a full specification of the expansion (not duplicated
1589here)
1590
1591*WARNING* if there is no web specification (in the web or topic parameters)
1592the web defaults to $Foswiki::cfg{UsersWebName}. If there is no topic
1593specification, or the topic is '0', the topic defaults to the web home topic
1594name.
1595
1596*WARNING* if the input topic name is tainted, then the output web and
1597topic names will be tainted.
1598
1599=cut
1600
1601
# spent 993ms (924+68.8) within Foswiki::normalizeWebTopicName which was called 81918 times, avg 12µs/call: # 81336 times (918ms+68.1ms) by Foswiki::Func::normalizeWebTopicName at line 2834 of /var/www/foswiki11/lib/Foswiki/Func.pm, avg 12µs/call # 377 times (3.90ms+316µs) by Foswiki::Users::getCanonicalUserID at line 504 of /var/www/foswiki11/lib/Foswiki/Users.pm, avg 11µs/call # 98 times (1.20ms+151µs) by Foswiki::Templates::_readTemplateFile at line 459 of /var/www/foswiki11/lib/Foswiki/Templates.pm, avg 14µs/call # 42 times (441µs+56µs) by Foswiki::VAR at line 15 of /var/www/foswiki11/lib/Foswiki/Macros/VAR.pm, avg 12µs/call # 23 times (277µs+34µs) by Foswiki::getScriptUrl at line 1471, avg 14µs/call # 17 times (222µs+25µs) by Foswiki::Render::_handleSquareBracketedLink at line 902 of /var/www/foswiki11/lib/Foswiki/Render.pm, avg 15µs/call # 7 times (117µs+16µs) by Foswiki::INCLUDE at line 172 of /var/www/foswiki11/lib/Foswiki/Macros/INCLUDE.pm, avg 19µs/call # 7 times (99µs+10µs) by Foswiki::If::OP_istopic::evaluate at line 33 of /var/www/foswiki11/lib/Foswiki/If/OP_istopic.pm, avg 16µs/call # 5 times (54µs+4µs) by Foswiki::Func::_checkWTA at line 73 of /var/www/foswiki11/lib/Foswiki/Func.pm, avg 11µs/call # 3 times (27µs+3µs) by Foswiki::REVINFO at line 20 of /var/www/foswiki11/lib/Foswiki/Macros/REVINFO.pm, avg 10µs/call # once (52µs+87µs) by Foswiki::_lookupIcon at line 29 of /var/www/foswiki11/lib/Foswiki/Macros/ICON.pm # once (56µs+4µs) by Foswiki::Prefs::loadSitePreferences at line 376 of /var/www/foswiki11/lib/Foswiki/Prefs.pm # once (26µs+3µs) by Foswiki::getPubUrl at line 1535
sub normalizeWebTopicName {
16028191854.9ms my ( $this, $web, $topic ) = @_;
1603
16048191867.1ms8191854.6ms ASSERT( defined $topic ) if DEBUG;
# spent 54.6ms making 81918 calls to Assert::ASSERTS_OFF, avg 667ns/call
1605
160681918242ms if ( $topic =~ m|^(.*)[./](.*?)$| ) {
16071772516.7ms $web = $1;
1608177255.61ms $topic = $2;
1609
16101772519.1ms1772514.1ms if ( DEBUG && !UNTAINTED( $_[2] ) ) {
# spent 14.1ms making 17725 calls to Assert::ASSERTS_OFF, avg 794ns/call
1611
1612 # retaint data untainted by RE above
1613 $web = TAINT($web);
1614 $topic = TAINT($topic);
1615 }
1616 }
16178191813.2ms $web ||= $cfg{UsersWebName};
1618819188.90ms $topic ||= $cfg{HomeTopicName};
1619
1620 # MAINWEB and TWIKIWEB expanded for compatibility reasons
16218191872.2ms while (
1622 $web =~ s/%((MAIN|TWIKI|USERS|SYSTEM|DOC)WEB)%/
1623217µs271µs $this->_expandMacroOnTopicRendering( $1 ) || ''/e
# spent 155µs making 2 calls to Foswiki::_expandMacroOnTopicRendering, avg 77µs/call, recursion: max depth 3, sum of overlapping time 84µs
1624 )
1625 {
1626 }
1627
1628 # Normalize web name to use / and not . as a subweb separator
16298191825.0ms $web =~ s#\.#/#g;
1630
163181918431ms return ( $web, $topic );
1632}
1633
1634=begin TML
1635
1636---++ ClassMethod new( $defaultUser, $query, \%initialContext )
1637
1638Constructs a new Foswiki session object. A unique session object exists for
1639ever transaction with Foswiki, for example every browser request, or every
1640script run. Session objects do not persist between mod_perl runs.
1641
1642 * =$defaultUser= is the username (*not* the wikiname) of the default
1643 user you want to be logged-in, if none is available from a session
1644 or browser. Used mainly for unit tests and debugging, it is typically
1645 undef, in which case the default user is taken from
1646 $Foswiki::cfg{DefaultUserName}.
1647 * =$query= the Foswiki::Request query (may be undef, in which case an
1648 empty query is used)
1649 * =\%initialContext= - reference to a hash containing context
1650 name=value pairs to be pre-installed in the context hash. May be undef.
1651
1652=cut
1653
1654
# spent 1.72s (531µs+1.72) within Foswiki::new which was called: # once (531µs+1.72s) by Foswiki::UI::__ANON__[/var/www/foswiki11/lib/Foswiki/UI.pm:318] at line 306 of /var/www/foswiki11/lib/Foswiki/UI.pm
sub new {
16551900ns my ( $class, $defaultUser, $query, $initialContext ) = @_;
165612µs12µs Monitor::MARK("Static init over; make Foswiki object");
165711µs11µs ASSERT( !$query || UNIVERSAL::isa( $query, 'Foswiki::Request' ) ) if DEBUG;
# spent 1µs making 1 call to Assert::ASSERTS_OFF
1658
1659 # Compatibility; not used except maybe in plugins
1660 # Note, this returns in Foswiki 1.2
166112µs $Foswiki::cfg{TempfileDir} = "$Foswiki::cfg{WorkingDir}/tmp"
1662 unless defined( $Foswiki::cfg{TempfileDir} );
1663
166411µs if ( $Foswiki::cfg{WarningFileName}
1665 && $Foswiki::cfg{Log}{Implementation} eq 'Foswiki::Logger::PlainFile' )
1666 {
1667
1668 # Admin has already expressed a preference for where they want their
1669 # logfiles to go, and has obviously not re-run configure yet.
1670 $Foswiki::cfg{Log}{Implementation} = 'Foswiki::Logger::Compatibility';
1671
1672#print STDERR "WARNING: Foswiki is using the compatibility logger. Please re-run configure and check your logfiles settings\n";
1673 }
1674
1675 # Make sure LogFielname is defined for use in old plugins,
1676 # but don't overwrite the setting from configure, if there is one.
1677 # This is especially important when the admin has *chosen*
1678 # to use the compatibility logger. (Some old TWiki heritage
1679 # plugins write directly to the configured LogFileName
16801500ns if ( not $Foswiki::cfg{LogFileName} ) {
168111µs if ( $Foswiki::cfg{Log}{Implementation} eq
1682 'Foswiki::Logger::Compatibility' )
1683 {
1684 my $stamp =
1685 Foswiki::Time::formatTime( time(), '$year$mo', 'servertime' );
1686 my $defaultLogDir = "$Foswiki::cfg{DataDir}";
1687 $Foswiki::cfg{LogFileName} = $defaultLogDir . "/log$stamp.txt";
1688
1689#print STDERR "Overrode LogFileName to $Foswiki::cfg{LogFileName} for CompatibilityLogger\n"
1690 }
1691 else {
169212µs $Foswiki::cfg{LogFileName} = "$Foswiki::cfg{Log}{Dir}/events.log";
1693
1694#print STDERR "Overrode LogFileName to $Foswiki::cfg{LogFileName} for PlainFileLogger\n"
1695 }
1696 }
1697
1698 # Set command_line context if there is no query
16991200ns $initialContext ||= defined($query) ? {} : { command_line => 1 };
1700
17011100ns $query ||= new Foswiki::Request();
170216µs my $this = bless( { sandbox => 'Foswiki::Sandbox' }, $class );
1703
170413µs12.80ms if ( defined $Foswiki::cfg{Site}{CharSet} ) {
# spent 2.80ms making 1 call to CGI::charset
1705
1706 # Ensure the auto-encoding in CGI uses the correct character set.
1707 # CGI defaults to iso-8859-1, and has a special exception for
1708 # iso-8859-1 and windows1252 in CGI::escapeHTML which breaks
1709 # UTF-8 content. See Item758. Get this wrong, and CGI will
1710 # fail to encode certain UTF-8 characters correctly.
1711 # Note we cannot call CGI::charset in begin block. We must have
1712 # the CGI object created because otherwise Perl 5.8 versions of
1713 # CGI will lose things like its temp files.
1714 CGI::charset( $Foswiki::cfg{Site}{CharSet} );
1715 }
171612µs12µs if (SINGLE_SINGLETONS_TRACE) {
# spent 2µs making 1 call to Foswiki::SINGLE_SINGLETONS_TRACE
1717 require Data::Dumper;
1718 print STDERR "new $this: "
1719 . Data::Dumper->Dump( [ [caller], [ caller(1) ] ] );
1720 }
1721
17221400ns $this->{request} = $query;
17231300ns $this->{cgiQuery} = $query; # for backwards compatibility in contribs
172414µs113µs $this->{response} = new Foswiki::Response();
# spent 13µs making 1 call to Foswiki::Response::new
1725117µs111µs $this->{digester} = new Digest::MD5();
# spent 11µs making 1 call to Digest::MD5::new
1726
1727 # This is required in case we get an exception during
1728 # initialisation, so that we have a session to handle it with.
172912µs12µs ASSERT( !$Foswiki::Plugins::SESSION ) if SINGLE_SINGLETONS;
# spent 2µs making 1 call to Foswiki::SINGLE_SINGLETONS
17301300ns $Foswiki::Plugins::SESSION = $this;
173111µs1800ns ASSERT( $Foswiki::Plugins::SESSION->isa('Foswiki') ) if DEBUG;
# spent 800ns making 1 call to Assert::ASSERTS_OFF
1732
1733 # Tell Foswiki::Response which charset we are using if not default
173418µs if ( defined $Foswiki::cfg{Site}{CharSet}
1735 && $Foswiki::cfg{Site}{CharSet} !~ /^iso-?8859-?1$/io )
1736 {
1737 $this->{response}->charset( $Foswiki::cfg{Site}{CharSet} );
1738 }
1739
1740 # hash of zone records
17411600ns $this->{_zones} = ();
1742
1743 # hash of occurences of RENDERZONE
17441200ns $this->{_renderZonePlaceholder} = ();
1745
174611µs $this->{context} = $initialContext;
1747
174812µs if ( $Foswiki::cfg{Cache}{Enabled} ) {
1749 require Foswiki::PageCache;
1750 $this->{cache} = new Foswiki::PageCache($this);
1751 }
175214µs11.00ms my $prefs = new Foswiki::Prefs($this);
# spent 1.00ms making 1 call to Foswiki::Prefs::new
17531700ns $this->{prefs} = $prefs;
175415µs129µs $this->{plugins} = new Foswiki::Plugins($this);
# spent 29µs making 1 call to Foswiki::Plugins::new
1755
1756121µs eval "require $Foswiki::cfg{Store}{Implementation}";
# spent 66µs executing statements in string eval
175712µs12µs ASSERT( !$@, $@ ) if DEBUG;
# spent 2µs making 1 call to Assert::ASSERTS_OFF
175818µs110µs $this->{store} = $Foswiki::cfg{Store}{Implementation}->new();
# spent 10µs making 1 call to Foswiki::Store::new
1759
1760 #Monitor::MARK("Created store");
1761
176214µs119.3ms $this->{users} = new Foswiki::Users($this);
# spent 19.3ms making 1 call to Foswiki::Users::new
1763
1764 #Monitor::MARK("Created users object");
1765
1766 #{urlHost} is needed by loadSession..
176714µs1157µs my $url = $query->url();
# spent 157µs making 1 call to Foswiki::Request::url
176815µs if ( $url
1769 && !$Foswiki::cfg{ForceDefaultUrlHost}
1770 && $url =~ m{^([^:]*://[^/]*).*$} )
1771 {
177212µs $this->{urlHost} = $1;
1773
17741700ns if ( $Foswiki::cfg{RemovePortNumber} ) {
1775 $this->{urlHost} =~ s/\:[0-9]+$//;
1776 }
1777
1778 # If the urlHost in the url is localhost, this is a lot less
1779 # useful than the default url host. This is because new CGI("")
1780 # assigns this host by default - it's a default setting, used
1781 # when there is nothing better available.
178213µs if ( $this->{urlHost} =~ /^(https?:\/\/)localhost$/i ) {
1783 my $protocol = $1;
1784
1785#only replace localhost _if_ the protocol matches the one specified in the DefaultUrlHost
1786 if ( $Foswiki::cfg{DefaultUrlHost} =~ /^$protocol/i ) {
1787 $this->{urlHost} = $Foswiki::cfg{DefaultUrlHost};
1788 }
1789 }
1790 }
1791 else {
1792 $this->{urlHost} = $Foswiki::cfg{DefaultUrlHost};
1793 }
179412µs11µs ASSERT( $this->{urlHost} ) if DEBUG;
# spent 1µs making 1 call to Assert::ASSERTS_OFF
1795
1796 # Load (or create) the CGI session
179714µs139.0ms $this->{remoteUser} = $this->{users}->loadSession($defaultUser);
# spent 39.0ms making 1 call to Foswiki::Users::loadSession
1798
1799 # Make %ENV safer, preventing hijack of the search path. The
1800 # environment is set per-query, so this can't be done in a BEGIN.
1801 # TWikibug:Item4382: Default $ENV{PATH} must be untainted because
1802 # Foswiki runs with use strict and calling external programs that
1803 # writes on the disk will fail unless Perl seens it as set to safe value.
180414µs if ( $Foswiki::cfg{SafeEnvPath} ) {
1805 $ENV{PATH} = $Foswiki::cfg{SafeEnvPath};
1806 }
1807 else {
1808
1809 # SMELL: how can we validate the PATH?
1810 $ENV{PATH} = Foswiki::Sandbox::untaintUnchecked( $ENV{PATH} );
1811 }
181218µs delete @ENV{qw( IFS CDPATH ENV BASH_ENV )};
1813
181411µs if ( $Foswiki::cfg{GetScriptUrlFromCgi}
1815 && $url
1816 && $url =~ m{^[^:]*://[^/]*(.*)/.*$}
1817 && $1 )
1818 {
1819
1820 # SMELL: this is a really dangerous hack. It will fail
1821 # spectacularly with mod_perl.
1822 # SMELL: why not just use $query->script_name?
1823 # SMELL: unchecked implicit untaint?
1824 $this->{scriptUrlPath} = $1;
1825 }
1826
18271500ns my $web = '';
182812µs119µs my $topic = $query->param('topic');
# spent 19µs making 1 call to Foswiki::Request::param
18291800ns if ($topic) {
1830126µs if ( $topic =~ m#^$regex{linkProtocolPattern}://#o
1831 && $this->{request} )
1832 {
1833
1834 # SMELL: this is a result of Codev.GoBoxUnderstandsURLs,
1835 # an unrequested, undocumented, and AFAICT pretty useless
1836 #"feature". It should be deprecated (or silently removed; I
1837 # really, really doubt anyone is using it)
1838 $this->{webName} = '';
1839 $this->redirect($topic);
1840 return $this;
1841 }
1842 elsif ( $topic =~ m#^(.*)[./](.*?)$# ) {
1843
1844 # is '?topic=Webname.SomeTopic'
1845 # implicit untaint OK - validated later
184611µs $web = $1;
18471900ns $topic = $2;
184812µs $web =~ s/\./\//g;
1849
1850 # jump to WebHome if 'bin/script?topic=Webname.'
18511400ns $topic = $Foswiki::cfg{HomeTopicName} if ( $web && !$topic );
1852 }
1853
1854 # otherwise assume 'bin/script/Webname?topic=SomeTopic'
1855 }
1856 else {
1857 $topic = '';
1858 }
1859
186012µs13µs my $pathInfo = $query->path_info();
# spent 3µs making 1 call to Foswiki::Request::pathInfo
1861
1862 # Truncate the path_info at any quote
18631800ns if ( $pathInfo =~ m/['"]/g ) {
1864 $pathInfo = substr( $pathInfo, 0, ( ( pos $pathInfo ) - 1 ) );
1865 }
1866
18671500ns $pathInfo =~ s|//+|/|g; # multiple //'s are illogical
1868
1869 # Get the web and topic names from PATH_INFO
18701900ns if ( $pathInfo =~ m#^/(.*)[./](.*?)$# ) {
1871
1872 # is '/Webname/SomeTopic' or '/Webname'
1873 # implicit untaint OK - validated later
1874 $web = $1 unless $web;
1875 $topic = $2 unless $topic;
1876 $web =~ s/\./\//g;
1877 }
1878 elsif ( $pathInfo =~ m#^/(.*?)$# ) {
1879
1880 # is 'bin/script/Webname' or 'bin/script/'
1881 # implicit untaint OK - validated later
1882 $web = $1 unless $web;
1883 }
188413µs18µs my $topicNameTemp = $this->UTF82SiteCharSet($topic);
# spent 8µs making 1 call to Foswiki::UTF82SiteCharSet
18851400ns if ($topicNameTemp) {
1886 $topic = $topicNameTemp;
1887 }
1888
1889 # Item3270 - here's the appropriate place to enforce spec
1890 # http://develop.twiki.org/~twiki4/cgi-bin/view/Bugs/Item3270
189112µs $topic = ucfirst($topic);
1892
1893 # Validate and untaint topic name from path info
189414µs160µs $this->{topicName} = Foswiki::Sandbox::untaint( $topic,
# spent 60µs making 1 call to Foswiki::Sandbox::untaint
1895 \&Foswiki::Sandbox::validateTopicName );
1896
1897 # Set the requestedWebName before applying defaults - used by statistics
1898 # generation. Note: This is validated using Topic name rules to permit
1899 # names beginning with lower case.
190013µs125µs $this->{requestedWebName} =
# spent 25µs making 1 call to Foswiki::Sandbox::untaint
1901 Foswiki::Sandbox::untaint( $web, \&Foswiki::Sandbox::validateTopicName );
1902
1903 # Validate web name from path info
190414µs152µs $this->{webName} =
# spent 52µs making 1 call to Foswiki::Sandbox::untaint
1905 Foswiki::Sandbox::untaint( $web, \&Foswiki::Sandbox::validateWebName );
1906
19071700ns if ( !defined $this->{webName} && !defined $this->{topicName} ) {
1908 $this->{webName} = $Foswiki::cfg{UsersWebName};
1909 $this->{topicName} = $Foswiki::cfg{HomeTopicName};
1910 }
1911
19121600ns $this->{webName} = ''
1913 unless ( defined $this->{webName} );
1914
19151700ns $this->{topicName} = $Foswiki::cfg{HomeTopicName}
1916 unless ( defined $this->{topicName} );
1917
1918 # Convert UTF-8 web and topic name from URL into site charset if
1919 # necessary
1920 # SMELL: merge these two cases, browsers just don't mix two encodings
1921 # in one URL - can also simplify into 2 lines by making function
1922 # return unprocessed text if no conversion
192312µs15µs my $webNameTemp = $this->UTF82SiteCharSet( $this->{webName} );
# spent 5µs making 1 call to Foswiki::UTF82SiteCharSet
19241300ns if ($webNameTemp) {
1925 $this->{webName} = $webNameTemp;
1926 }
1927
192812µs $this->{scriptUrlPath} = $Foswiki::cfg{ScriptUrlPath};
1929
1930 # Form definition cache
19311800ns $this->{forms} = {};
1932
1933 # Push global preferences from %SYSTEMWEB%.DefaultPreferences
193413µs1175ms $prefs->loadDefaultPreferences();
# spent 175ms making 1 call to Foswiki::Prefs::loadDefaultPreferences
1935
1936 #Monitor::MARK("Loaded default prefs");
1937
1938 # SMELL: what happens if we move this into the Foswiki::Users::new?
1939110µs198.2ms $this->{user} = $this->{users}->initialiseUser( $this->{remoteUser} );
# spent 98.2ms making 1 call to Foswiki::Users::initialiseUser
1940
1941 #Monitor::MARK("Initialised user");
1942
1943 # Static session variables that can be expanded in topics when they
1944 # are enclosed in % signs
1945 # SMELL: should collapse these into one. The duplication is pretty
1946 # pointless.
194717µs118µs $prefs->setInternalPreferences(
# spent 18µs making 1 call to Foswiki::Prefs::setInternalPreferences
1948 BASEWEB => $this->{webName},
1949 BASETOPIC => $this->{topicName},
1950 INCLUDINGTOPIC => $this->{topicName},
1951 INCLUDINGWEB => $this->{webName}
1952 );
1953
1954 # Push plugin settings
195514µs11.30s $this->{plugins}->settings();
# spent 1.30s making 1 call to Foswiki::Plugins::settings
1956
1957 # Now the rest of the preferences
195818µs117.7ms $prefs->loadSitePreferences();
# spent 17.7ms making 1 call to Foswiki::Prefs::loadSitePreferences
1959
1960 # User preferences only available if we can get to a valid wikiname,
1961 # which depends on the user mapper.
196218µs19µs my $wn = $this->{users}->getWikiName( $this->{user} );
# spent 9µs making 1 call to Foswiki::Users::getWikiName
196313µs1145µs if ($wn) {
# spent 145µs making 1 call to Foswiki::Prefs::setUserPreferences
1964 $prefs->setUserPreferences($wn);
1965 }
1966
196716µs14.53ms $prefs->pushTopicContext( $this->{webName}, $this->{topicName} );
# spent 4.53ms making 1 call to Foswiki::Prefs::pushTopicContext
1968
1969 #Monitor::MARK("Preferences all set up");
1970
197118µs12.49ms if ( $this->{users}->isAdmin( $this->{user} ) ) {
# spent 2.49ms making 1 call to Foswiki::Users::isAdmin
1972 $this->{context}{isadmin} = 1;
1973 }
1974
1975 # Finish plugin initialization - register handlers
197615µs149.9ms $this->{plugins}->enable();
# spent 49.9ms making 1 call to Foswiki::Plugins::enable
1977
197816µs15µs Monitor::MARK("Foswiki object created");
1979
1980111µs return $this;
1981}
1982
1983=begin TML
1984
1985---++ ObjectMethod renderer()
1986Get a reference to the renderer object. Done lazily because not everyone
1987needs the renderer.
1988
1989=cut
1990
1991
# spent 12.9ms (11.5+1.41) within Foswiki::renderer which was called 14 times, avg 922µs/call: # 5 times (29µs+0s) by Foswiki::__ANON__[/var/www/foswiki11/lib/Foswiki/Macros/INCLUDE.pm:331] at line 317 of /var/www/foswiki11/lib/Foswiki/Macros/INCLUDE.pm, avg 6µs/call # 5 times (16µs+0s) by Foswiki::Meta::renderTML at line 3117 of /var/www/foswiki11/lib/Foswiki/Meta.pm, avg 3µs/call # 3 times (6µs+0s) by Foswiki::REVINFO at line 38 of /var/www/foswiki11/lib/Foswiki/Macros/REVINFO.pm, avg 2µs/call # once (11.5ms+1.41ms) by Foswiki::META at line 19 of /var/www/foswiki11/lib/Foswiki/Macros/META.pm
sub renderer {
19921410µs my ($this) = @_;
1993
19941410µs unless ( $this->{renderer} ) {
19951100µs require Foswiki::Render;
199617µs112µs $this->{renderer} = new Foswiki::Render($this);
# spent 12µs making 1 call to Foswiki::Render::new
1997 }
19981450µs return $this->{renderer};
1999}
2000
2001=begin TML
2002
2003---++ ObjectMethod attach()
2004Get a reference to the attach object. Done lazily because not everyone
2005needs the attach.
2006
2007=cut
2008
2009
# spent 2.36ms (2.25+104µs) within Foswiki::attach which was called: # once (2.25ms+104µs) by Foswiki::META at line 19 of /var/www/foswiki11/lib/Foswiki/Macros/META.pm
sub attach {
20101700ns my ($this) = @_;
2011
201211µs unless ( $this->{attach} ) {
2013176µs require Foswiki::Attach;
201418µs114µs $this->{attach} = new Foswiki::Attach($this);
# spent 14µs making 1 call to Foswiki::Attach::new
2015 }
201615µs return $this->{attach};
2017}
2018
2019=begin TML
2020
2021---++ ObjectMethod templates()
2022Get a reference to the templates object. Done lazily because not everyone
2023needs the templates.
2024
2025=cut
2026
2027
# spent 3.14ms (2.83+310µs) within Foswiki::templates which was called 168 times, avg 19µs/call: # 41 times (213µs+0s) by Foswiki::Search::loadTemplates at line 508 of /var/www/foswiki11/lib/Foswiki/Search.pm, avg 5µs/call # 41 times (104µs+0s) by Foswiki::Search::loadTemplates at line 523 of /var/www/foswiki11/lib/Foswiki/Search.pm, avg 3µs/call # 41 times (75µs+0s) by Foswiki::Search::loadTemplates at line 524 of /var/www/foswiki11/lib/Foswiki/Search.pm, avg 2µs/call # 41 times (73µs+0s) by Foswiki::Search::loadTemplates at line 535 of /var/www/foswiki11/lib/Foswiki/Search.pm, avg 2µs/call # 2 times (10µs+0s) by Foswiki::LoginManager::_LOGIN at line 1156 of /var/www/foswiki11/lib/Foswiki/LoginManager.pm, avg 5µs/call # once (2.35ms+310µs) by Foswiki::UI::View::view at line 239 of /var/www/foswiki11/lib/Foswiki/UI/View.pm # once (6µs+0s) by Foswiki::__ANON__[/var/www/foswiki11/lib/Foswiki.pm:283] at line 283
sub templates {
202816873µs my ($this) = @_;
2029
203016881µs unless ( $this->{templates} ) {
20311142µs require Foswiki::Templates;
203217µs113µs $this->{templates} = new Foswiki::Templates($this);
# spent 13µs making 1 call to Foswiki::Templates::new
2033 }
2034168551µs return $this->{templates};
2035}
2036
2037=begin TML
2038
2039---++ ObjectMethod i18n()
2040Get a reference to the i18n object. Done lazily because not everyone
2041needs the i18ner.
2042
2043=cut
2044
2045
# spent 4.67ms (3.51+1.16) within Foswiki::i18n which was called 48 times, avg 97µs/call: # 33 times (3.45ms+1.16ms) by Foswiki::MAKETEXT at line 50 of /var/www/foswiki11/lib/Foswiki/Macros/MAKETEXT.pm, avg 140µs/call # 12 times (44µs+0s) by Foswiki::Search::formatResult at line 1195 of /var/www/foswiki11/lib/Foswiki/Search.pm, avg 4µs/call # 3 times (12µs+0s) by Foswiki::Meta::haveAccess at line 1812 of /var/www/foswiki11/lib/Foswiki/Meta.pm, avg 4µs/call
sub i18n {
20464826µs my ($this) = @_;
2047
20484829µs unless ( $this->{i18n} ) {
20491161µs require Foswiki::I18N;
2050
2051 # language information; must be loaded after
2052 # *all possible preferences sources* are available
2053111µs11.00ms $this->{i18n} = new Foswiki::I18N($this);
# spent 1.00ms making 1 call to Foswiki::I18N::new
2054 }
205548176µs return $this->{i18n};
2056}
2057
2058=begin TML
2059
2060---++ ObjectMethod logger()
2061
2062=cut
2063
2064
# spent 2.96ms (2.55+416µs) within Foswiki::logger which was called 3 times, avg 988µs/call: # once (2.53ms+416µs) by Foswiki::Plugins::load at line 205 of /var/www/foswiki11/lib/Foswiki/Plugins.pm # once (10µs+0s) by Foswiki::Plugins::enable at line 272 of /var/www/foswiki11/lib/Foswiki/Plugins.pm # once (8µs+0s) by Foswiki::logEvent at line 2269
sub logger {
206534µs my $this = shift;
2066
206733µs unless ( $this->{logger} ) {
206812µs if ( $Foswiki::cfg{Log}{Implementation} eq 'none' ) {
2069 $this->{logger} = Foswiki::Logger->new();
2070 }
2071 else {
2072127µs eval "require $Foswiki::cfg{Log}{Implementation}";
# spent 65µs executing statements in string eval
207312µs if ($@) {
2074 print STDERR "Logger load failed: $@";
2075 $this->{logger} = Foswiki::Logger->new();
2076 }
2077 else {
207818µs19µs $this->{logger} = $Foswiki::cfg{Log}{Implementation}->new();
# spent 9µs making 1 call to Foswiki::Logger::PlainFile::new
2079 }
2080 }
2081 }
2082
2083320µs return $this->{logger};
2084}
2085
2086=begin TML
2087
2088---++ ObjectMethod search()
2089Get a reference to the search object. Done lazily because not everyone
2090needs the searcher.
2091
2092=cut
2093
2094
# spent 49.6ms (44.0+5.65) within Foswiki::search which was called 17563 times, avg 3µs/call: # 8760 times (19.6ms+0s) by Foswiki::Search::InfoCache::addTopic at line 99 of /var/www/foswiki11/lib/Foswiki/Search/InfoCache.pm, avg 2µs/call # 8760 times (19.1ms+0s) by Foswiki::Store::QueryAlgorithms::BruteForce::_webQuery at line 230 of /var/www/foswiki11/lib/Foswiki/Store/QueryAlgorithms/BruteForce.pm, avg 2µs/call # 40 times (5.32ms+5.65ms) by Foswiki::__ANON__[/var/www/foswiki11/lib/Foswiki/Macros/SEARCH.pm:33] at line 32 of /var/www/foswiki11/lib/Foswiki/Macros/SEARCH.pm, avg 274µs/call # once (8µs+0s) by Foswiki::Users::TopicUserMapping::_getListOfGroups at line 1630 of /var/www/foswiki11/lib/Foswiki/Users/TopicUserMapping.pm # once (2µs+0s) by Foswiki::Store::QueryAlgorithms::BruteForce::_webQuery at line 114 of /var/www/foswiki11/lib/Foswiki/Store/QueryAlgorithms/BruteForce.pm # once (2µs+0s) by Foswiki::Users::TopicUserMapping::_getListOfGroups at line 1636 of /var/www/foswiki11/lib/Foswiki/Users/TopicUserMapping.pm
sub search {
2095175637.01ms my ($this) = @_;
2096
2097175638.18ms unless ( $this->{search} ) {
2098173µs require Foswiki::Search;
209916µs110µs $this->{search} = new Foswiki::Search($this);
# spent 10µs making 1 call to Foswiki::Search::new
2100 }
21011756391.2ms return $this->{search};
2102}
2103
2104=begin TML
2105
2106---++ ObjectMethod net()
2107Get a reference to the net object. Done lazily because not everyone
2108needs the net.
2109
2110=cut
2111
2112sub net {
2113 my ($this) = @_;
2114
2115 unless ( $this->{net} ) {
2116 require Foswiki::Net;
2117 $this->{net} = new Foswiki::Net($this);
2118 }
2119 return $this->{net};
2120}
2121
2122=begin TML
2123
2124---++ ObjectMethod DESTROY()
2125
2126called by Perl when the Foswiki object goes out of scope
2127(maybe should be used kist to ASSERT that finish() was called..
2128
2129=cut
2130
2131#sub DESTROY {
2132# my $this = shift;
2133# $this->finish();
2134#}
2135
2136=begin TML
2137
2138---++ ObjectMethod finish()
2139Break circular references.
2140
2141=cut
2142
2143# Note to developers; please undef *all* fields in the object explicitly,
2144# whether they are references or not. That way this method is "golden
2145# documentation" of the live fields in the object.
2146
# spent 12.5ms (2.32+10.2) within Foswiki::finish which was called: # once (2.32ms+10.2ms) by Foswiki::UI::_execute at line 436 of /var/www/foswiki11/lib/Foswiki/UI.pm
sub finish {
21471800ns my $this = shift;
2148
2149 # Print any macros that are never loaded
2150 #print STDERR "NEVER USED\n";
2151 #for my $i (keys %macros) {
2152 # print STDERR "\t$i\n" unless defined $macros{$i};
2153 #}
215415µs $_->finish() foreach values %{ $this->{forms} };
215511µs undef $this->{forms};
215613µs foreach my $key (
2157 qw(plugins users prefs templates renderer net
2158 store search attach access security i18n cache)
2159 )
2160 {
2161 next
21621316µs unless ref( $this->{$key} );
21639100µs910.2ms $this->{$key}->finish();
# spent 4.10ms making 1 call to Foswiki::Prefs::finish # spent 2.87ms making 1 call to Foswiki::Search::finish # spent 1.79ms making 1 call to Foswiki::Users::finish # spent 668µs making 1 call to Foswiki::Plugins::finish # spent 659µs making 1 call to Foswiki::Templates::finish # spent 40µs making 1 call to Foswiki::I18N::Fallback::finish # spent 35µs making 1 call to Foswiki::Store::VC::Store::finish # spent 8µs making 1 call to Foswiki::Render::finish # spent 5µs making 1 call to Foswiki::Attach::finish
216492.11ms undef $this->{$key};
2165 }
2166
2167 #TODO: the logger doesn't seem to have a finish...
2168 # $this->{logger}->finish() if $this->{logger};
216919µs undef $this->{logger};
2170
217111µs undef $this->{_zones};
21721400ns undef $this->{_renderZonePlaceholder};
2173
21741400ns undef $this->{request};
217511µs undef $this->{cgiQuery};
2176
2177130µs undef $this->{digester};
217812µs19µs undef $this->{urlHost};
# spent 9µs making 1 call to Digest::MD5::DESTROY
217914µs undef $this->{web};
21801300ns undef $this->{topic};
21811600ns undef $this->{webName};
21821300ns undef $this->{topicName};
218317µs undef $this->{_ICONSPACE};
21841600ns undef $this->{_EXT2ICON};
21851900ns undef $this->{_KNOWNICON};
21861500ns undef $this->{_ICONSTEMPLATE};
21871400ns undef $this->{context};
21881500ns undef $this->{remoteUser};
218911µs undef $this->{requestedWebName}; # Web name before renaming
21901300ns undef $this->{scriptUrlPath};
21911500ns undef $this->{user};
21921800ns undef $this->{_INCLUDES};
21931300ns undef $this->{response};
219411µs undef $this->{evaluating_if};
219511µs undef $this->{_addedToHEAD};
219611µs undef $this->{sandbox};
21971900ns undef $this->{evaluatingEval};
2198
21991500ns undef $this->{DebugVerificationCode}; # from Foswiki::UI::Register
220014µs14µs if (SINGLE_SINGLETONS_TRACE) {
# spent 4µs making 1 call to Foswiki::SINGLE_SINGLETONS_TRACE
2201 require Data::Dumper;
2202 print STDERR "finish $this: "
2203 . Data::Dumper->Dump( [ [caller], [ caller(1) ] ] );
2204 }
220512µs12µs if (SINGLE_SINGLETONS) {
# spent 2µs making 1 call to Foswiki::SINGLE_SINGLETONS
2206 ASSERT( defined $Foswiki::Plugins::SESSION );
2207 ASSERT( $Foswiki::Plugins::SESSION == $this );
2208 ASSERT( $Foswiki::Plugins::SESSION->isa('Foswiki') );
2209 }
22101400ns undef $Foswiki::Plugins::SESSION;
2211
221218µs12µs if (DEBUG) {
# spent 2µs making 1 call to Assert::ASSERTS_OFF
2213 my $remaining = join ',', grep { defined $this->{$_} } keys %$this;
2214 ASSERT( 0,
2215 "Fields with defined values in "
2216 . ref($this)
2217 . "->finish(): "
2218 . $remaining )
2219 if $remaining;
2220 }
2221}
2222
2223=begin TML
2224
2225---++ ObjectMethod logEvent( $action, $webTopic, $extra, $user )
2226 * =$action= - what happened, e.g. view, save, rename
2227 * =$webTopic= - what it happened to
2228 * =$extra= - extra info, such as minor flag
2229 * =$user= - login name of user - default current user,
2230 or failing that the user agent
2231
2232Write the log for an event to the logfile
2233
2234=cut
2235
2236
# spent 450µs (48+402) within Foswiki::logEvent which was called: # once (48µs+402µs) by Foswiki::UI::View::view at line 213 of /var/www/foswiki11/lib/Foswiki/UI/View.pm
sub logEvent {
223712µs my $this = shift;
2238
22391500ns my $action = shift || '';
22401500ns my $webTopic = shift || '';
224111µs my $extra = shift || '';
22421400ns my $user = shift;
2243
2244 return
224514µs if ( defined $Foswiki::cfg{Log}{Action}{$action}
2246 && !$Foswiki::cfg{Log}{Action}{$action} );
2247
224811µs $user ||= $this->{user};
224918µs110µs $user = ( $this->{users}->getLoginName($user) || 'unknown' )
# spent 10µs making 1 call to Foswiki::Users::getLoginName
2250 if ( $this->{users} );
2251
225212µs my $cgiQuery = $this->{request};
22531500ns if ($cgiQuery) {
225414µs135µs my $agent = $cgiQuery->user_agent();
# spent 35µs making 1 call to Foswiki::Request::userAgent
22551400ns if ($agent) {
2256 $extra .= ' ' if $extra;
2257 if ( $agent =~ /(MSIE 6|MSIE 7|Firefox|Opera|Konqueror|Safari)/ ) {
2258 $extra .= $1;
2259 }
2260 else {
2261 $agent =~ m/([\w]+)/;
2262 $extra .= $1;
2263 }
2264 }
2265 }
2266
226716µs17µs my $remoteAddr = $this->{request}->remoteAddress() || '';
# spent 7µs making 1 call to Foswiki::Request::remoteAddress
2268
2269118µs2350µs $this->logger->log( 'info', $user, $action, $webTopic, $extra,
# spent 342µs making 1 call to Foswiki::Logger::PlainFile::log # spent 8µs making 1 call to Foswiki::logger
2270 $remoteAddr );
2271}
2272
2273=begin TML
2274
2275---++ StaticMethod validatePattern( $pattern ) -> $pattern
2276
2277Validate a pattern provided in a parameter to $pattern so that
2278dangerous chars (interpolation and execution) are disabled.
2279
2280=cut
2281
2282sub validatePattern {
2283 my $pattern = shift;
2284
2285 # Escape unescaped $ and @ characters that might interpolate
2286 # an internal variable.
2287 # There is no need to defuse (??{ and (?{ as perl won't allow
2288 # it anyway, unless one uses re 'eval' which we won't do
2289 $pattern =~ s/(^|[^\\])([\$\@])/$1\\$2/g;
2290 return $pattern;
2291}
2292
2293=begin TML
2294
2295---++ ObjectMethod inlineAlert($template, $def, ... ) -> $string
2296
2297Format an error for inline inclusion in rendered output. The message string
2298is obtained from the template 'oops'.$template, and the DEF $def is
2299selected. The parameters (...) are used to populate %PARAM1%..%PARAMn%
2300
2301=cut
2302
2303sub inlineAlert {
2304 my $this = shift;
2305 my $template = shift;
2306 my $def = shift;
2307
2308 # web and topic can be anything; they are not used
2309 my $topicObject =
2310 Foswiki::Meta->new( $this, $this->{webName}, $this->{topicName} );
2311 my $text = $this->templates->readTemplate( 'oops' . $template );
2312 if ($text) {
2313 my $blah = $this->templates->expandTemplate($def);
2314 $text =~ s/%INSTANTIATE%/$blah/;
2315
2316 $text = $topicObject->expandMacros($text);
2317 my $n = 1;
2318 while ( defined( my $param = shift ) ) {
2319 $text =~ s/%PARAM$n%/$param/g;
2320 $n++;
2321 }
2322
2323 # Suppress missing params
2324 $text =~ s/%PARAM\d+%//g;
2325
2326 # Suppress missing params
2327 $text =~ s/%PARAM\d+%//g;
2328 }
2329 else {
2330
2331 # Error in the template system.
2332 $text = $topicObject->renderTML(<<MESSAGE);
2333---+ Foswiki Installation Error
2334Template 'oops$template' not found or returned no text, expanding $def.
2335
2336Check your configuration settings for {TemplateDir} and {TemplatePath}
2337or check for syntax errors in templates, or a missing TMPL:END.
2338MESSAGE
2339 }
2340
2341 return $text;
2342}
2343
2344=begin TML
2345
2346---++ StaticMethod parseSections($text) -> ($string,$sectionlistref)
2347
2348Generic parser for sections within a topic. Sections are delimited
2349by STARTSECTION and ENDSECTION, which may be nested, overlapped or
2350otherwise abused. The parser builds an array of sections, which is
2351ordered by the order of the STARTSECTION within the topic. It also
2352removes all the SECTION tags from the text, and returns the text
2353and the array of sections.
2354
2355Each section is a =Foswiki::Attrs= object, which contains the attributes
2356{type, name, start, end}
2357where start and end are character offsets in the
2358string *after all section tags have been removed*. All sections
2359are required to be uniquely named; if a section is unnamed, it
2360will be given a generated name. Sections may overlap or nest.
2361
2362See test/unit/Fn_SECTION.pm for detailed testcases that
2363round out the spec.
2364
2365=cut
2366
2367
# spent 158µs within Foswiki::parseSections which was called 6 times, avg 26µs/call: # 6 times (158µs+0s) by Foswiki::__ANON__[/var/www/foswiki11/lib/Foswiki/Macros/INCLUDE.pm:331] at line 251 of /var/www/foswiki11/lib/Foswiki/Macros/INCLUDE.pm, avg 26µs/call
sub parseSections {
2368
2369611µs my $text = shift;
2370
237162µs return ( '', [] ) unless defined $text;
2372
237361µs my %sections;
237464µs my @list = ();
2375
237662µs my $seq = 0;
237765µs my $ntext = '';
237862µs my $offset = 0;
2379647µs foreach my $bit ( split( /(%(?:START|END)SECTION(?:{.*?})?%)/, $text ) ) {
2380626µs if ( $bit =~ /^%STARTSECTION(?:{(.*)})?%$/ ) {
2381 require Foswiki::Attrs;
2382
2383 # SMELL: unchecked implicit untaint?
2384 my $attrs = new Foswiki::Attrs($1);
2385 $attrs->{type} ||= 'section';
2386 $attrs->{name} =
2387 $attrs->{_DEFAULT}
2388 || $attrs->{name}
2389 || '_SECTION' . $seq++;
2390 delete $attrs->{_DEFAULT};
2391 my $id = $attrs->{type} . ':' . $attrs->{name};
2392 if ( $sections{$id} ) {
2393
2394 # error, this named section already defined, ignore
2395 next;
2396 }
2397
2398 # close open unnamed sections of the same type
2399 foreach my $s (@list) {
2400 if ( $s->{end} < 0
2401 && $s->{type} eq $attrs->{type}
2402 && $s->{name} =~ /^_SECTION\d+$/ )
2403 {
2404 $s->{end} = $offset;
2405 }
2406 }
2407 $attrs->{start} = $offset;
2408 $attrs->{end} = -1; # open section
2409 $sections{$id} = $attrs;
2410 push( @list, $attrs );
2411 }
2412 elsif ( $bit =~ /^%ENDSECTION(?:{(.*)})?%$/ ) {
2413 require Foswiki::Attrs;
2414
2415 # SMELL: unchecked implicit untaint?
2416 my $attrs = new Foswiki::Attrs($1);
2417 $attrs->{type} ||= 'section';
2418 $attrs->{name} = $attrs->{_DEFAULT} || $attrs->{name} || '';
2419 delete $attrs->{_DEFAULT};
2420 unless ( $attrs->{name} ) {
2421
2422 # find the last open unnamed section of this type
2423 foreach my $s ( reverse @list ) {
2424 if ( $s->{end} == -1
2425 && $s->{type} eq $attrs->{type}
2426 && $s->{name} =~ /^_SECTION\d+$/ )
2427 {
2428 $attrs->{name} = $s->{name};
2429 last;
2430 }
2431 }
2432
2433 # ignore it if no matching START found
2434 next unless $attrs->{name};
2435 }
2436 my $id = $attrs->{type} . ':' . $attrs->{name};
2437 if ( !$sections{$id} || $sections{$id}->{end} >= 0 ) {
2438
2439 # error, no such open section, ignore
2440 next;
2441 }
2442 $sections{$id}->{end} = $offset;
2443 }
2444 else {
244568µs $ntext .= $bit;
244664µs $offset = length($ntext);
2447 }
2448 }
2449
2450 # close open sections
245167µs foreach my $s (@list) {
2452 $s->{end} = $offset if $s->{end} < 0;
2453 }
2454
2455641µs return ( $ntext, \@list );
2456}
2457
2458=begin TML
2459
2460---++ ObjectMethod expandMacrosOnTopicCreation ( $topicObject )
2461
2462 * =$topicObject= - the topic
2463
2464Expand only that subset of Foswiki variables that are
2465expanded during topic creation, in the body text and
2466PREFERENCE meta only. The expansion is in-place inside
2467the topic object.
2468
2469# SMELL: no plugin handler
2470
2471=cut
2472
2473sub expandMacrosOnTopicCreation {
2474 my ( $this, $topicObject ) = @_;
2475
2476 # Make sure func works, for registered tag handlers
2477 if (SINGLE_SINGLETONS) {
2478 ASSERT( defined $Foswiki::Plugins::SESSION );
2479 ASSERT( $Foswiki::Plugins::SESSION == $this );
2480 }
2481 local $Foswiki::Plugins::SESSION = $this;
2482 ASSERT( $Foswiki::Plugins::SESSION->isa('Foswiki') ) if DEBUG;
2483
2484 my $text = $topicObject->text();
2485 if ($text) {
2486
2487 # Chop out templateonly sections
2488 my ( $ntext, $sections ) = parseSections($text);
2489 if ( scalar(@$sections) ) {
2490
2491 # Note that if named templateonly sections overlap,
2492 # the behaviour is undefined.
2493 foreach my $s ( reverse @$sections ) {
2494 if ( $s->{type} eq 'templateonly' ) {
2495 $ntext =
2496 substr( $ntext, 0, $s->{start} )
2497 . substr( $ntext, $s->{end}, length($ntext) );
2498 }
2499 else {
2500
2501 # put back non-templateonly sections
2502 my $start = $s->remove('start');
2503 my $end = $s->remove('end');
2504 $ntext =
2505 substr( $ntext, 0, $start )
2506 . '%STARTSECTION{'
2507 . $s->stringify() . '}%'
2508 . substr( $ntext, $start, $end - $start )
2509 . '%ENDSECTION{'
2510 . $s->stringify() . '}%'
2511 . substr( $ntext, $end, length($ntext) );
2512 }
2513 }
2514 $text = $ntext;
2515 }
2516
2517 $text = _processMacros( $this, $text, \&_expandMacroOnTopicCreation,
2518 $topicObject, 16 );
2519
2520 # expand all variables for type="expandvariables" sections
2521 ( $ntext, $sections ) = parseSections($text);
2522 if ( scalar(@$sections) ) {
2523 foreach my $s ( reverse @$sections ) {
2524 if ( $s->{type} eq 'expandvariables' ) {
2525 my $etext =
2526 substr( $ntext, $s->{start}, $s->{end} - $s->{start} );
2527 $this->innerExpandMacros( \$etext, $topicObject );
2528 $ntext =
2529 substr( $ntext, 0, $s->{start} )
2530 . $etext
2531 . substr( $ntext, $s->{end}, length($ntext) );
2532 }
2533 else {
2534
2535 # put back non-expandvariables sections
2536 my $start = $s->remove('start');
2537 my $end = $s->remove('end');
2538 $ntext =
2539 substr( $ntext, 0, $start )
2540 . '%STARTSECTION{'
2541 . $s->stringify() . '}%'
2542 . substr( $ntext, $start, $end - $start )
2543 . '%ENDSECTION{'
2544 . $s->stringify() . '}%'
2545 . substr( $ntext, $end, length($ntext) );
2546 }
2547 }
2548 $text = $ntext;
2549 }
2550
2551 # kill markers used to prevent variable expansion
2552 $text =~ s/%NOP%//g;
2553 $topicObject->text($text);
2554 }
2555
2556 # Expand preferences
2557 my @prefs = $topicObject->find('PREFERENCE');
2558 foreach my $p (@prefs) {
2559 $p->{value} =
2560 _processMacros( $this, $p->{value}, \&_expandMacroOnTopicCreation,
2561 $topicObject, 16 );
2562
2563 # kill markers used to prevent variable expansion
2564 $p->{value} =~ s/%NOP%//g;
2565
2566 }
2567}
2568
2569=begin TML
2570
2571---++ StaticMethod entityEncode( $text, $extras ) -> $encodedText
2572
2573Escape special characters to HTML numeric entities. This is *not* a generic
2574encoding, it is tuned specifically for use in Foswiki.
2575
2576HTML4.0 spec:
2577"Certain characters in HTML are reserved for use as markup and must be
2578escaped to appear literally. The "&lt;" character may be represented with
2579an <em>entity</em>, <strong class=html>&amp;lt;</strong>. Similarly, "&gt;"
2580is escaped as <strong class=html>&amp;gt;</strong>, and "&amp;" is escaped
2581as <strong class=html>&amp;amp;</strong>. If an attribute value contains a
2582double quotation mark and is delimited by double quotation marks, then the
2583quote should be escaped as <strong class=html>&amp;quot;</strong>.
2584
2585Other entities exist for special characters that cannot easily be entered
2586with some keyboards..."
2587
2588This method encodes HTML special and any non-printable ascii
2589characters (except for \n and \r) using numeric entities.
2590
2591FURTHER this method also encodes characters that are special in Foswiki
2592meta-language.
2593
2594$extras is an optional param that may be used to include *additional*
2595characters in the set of encoded characters. It should be a string
2596containing the additional chars.
2597
2598=cut
2599
2600sub entityEncode {
2601 my ( $text, $extra ) = @_;
2602 $extra ||= '';
2603
2604 # encode all non-printable 7-bit chars (< \x1f),
2605 # except \n (\xa) and \r (\xd)
2606 # encode HTML special characters '>', '<', '&', ''' and '"'.
2607 # encode TML special characters '%', '|', '[', ']', '@', '_',
2608 # '*', and '='
2609 $text =~
2610 s/([[\x01-\x09\x0b\x0c\x0e-\x1f"%&'*<=>@[_\|$extra])/'&#'.ord($1).';'/ge;
2611 return $text;
2612}
2613
2614=begin TML
2615
2616---++ StaticMethod entityDecode ( $encodedText ) -> $text
2617
2618Decodes all numeric entities (e.g. &amp;#123;). _Does not_ decode
2619named entities such as &amp;amp; (use HTML::Entities for that)
2620
2621=cut
2622
2623sub entityDecode {
2624 my $text = shift;
2625
2626 $text =~ s/&#(\d+);/chr($1)/ge;
2627 return $text;
2628}
2629
2630=begin TML
2631
2632---++ StaticMethod urlEncodeAttachment ( $text )
2633
2634For attachments, URL-encode specially to 'freeze' any characters >127 in the
2635site charset (e.g. ISO-8859-1 or KOI8-R), by doing URL encoding into native
2636charset ($siteCharset) - used when generating attachment URLs, to enable the
2637web server to serve attachments, including images, directly.
2638
2639This encoding is required to handle the cases of:
2640
2641 - browsers that generate UTF-8 URLs automatically from site charset URLs - now quite common
2642 - web servers that directly serve attachments, using the site charset for
2643 filenames, and cannot convert UTF-8 URLs into site charset filenames
2644
2645The aim is to prevent the browser from converting a site charset URL in the web
2646page to a UTF-8 URL, which is the default. Hence we 'freeze' the URL into the
2647site character set through URL encoding.
2648
2649In two cases, no URL encoding is needed: For EBCDIC mainframes, we assume that
2650site charset URLs will be translated (outbound and inbound) by the web server to/from an
2651EBCDIC character set. For sites running in UTF-8, there's no need for Foswiki to
2652do anything since all URLs and attachment filenames are already in UTF-8.
2653
2654=cut
2655
2656
# spent 28µs (21+6) within Foswiki::urlEncodeAttachment which was called: # once (21µs+6µs) by Foswiki::getPubUrl at line 1543
sub urlEncodeAttachment {
265711µs my ($text) = @_;
2658
265911µs my $usingEBCDIC = ( 'A' eq chr(193) ); # Only true on EBCDIC mainframes
2660
266116µs if (
2662 (
2663 defined( $Foswiki::cfg{Site}{CharSet} )
2664 and $Foswiki::cfg{Site}{CharSet} =~ /^utf-?8$/i
2665 )
2666 or $usingEBCDIC
2667 )
2668 {
2669
2670 # Just let browser do UTF-8 URL encoding
2671 return $text;
2672 }
2673
2674 # Freeze into site charset through URL encoding
2675112µs16µs return urlEncode($text);
# spent 6µs making 1 call to Foswiki::urlEncode
2676}
2677
2678=begin TML
2679
2680---++ StaticMethod urlEncode( $string ) -> encoded string
2681
2682Encode by converting characters that are illegal in URLs to
2683their %NN equivalents. This method is used for encoding
2684strings that must be embedded _verbatim_ in URLs; it cannot
2685be applied to URLs themselves, as it escapes reserved
2686characters such as = and ?.
2687
2688RFC 1738, Dec. '94:
2689 <verbatim>
2690 ...Only alphanumerics [0-9a-zA-Z], the special
2691 characters $-_.+!*'(), and reserved characters used for their
2692 reserved purposes may be used unencoded within a URL.
2693 </verbatim>
2694
2695Reserved characters are $&+,/:;=?@ - these are _also_ encoded by
2696this method.
2697
2698This URL-encoding handles all character encodings including ISO-8859-*,
2699KOI8-R, EUC-* and UTF-8.
2700
2701This may not handle EBCDIC properly, as it generates an EBCDIC URL-encoded
2702URL, but mainframe web servers seem to translate this outbound before it hits browser
2703- see CGI::Util::escape for another approach.
2704
2705=cut
2706
2707
# spent 175µs within Foswiki::urlEncode which was called 56 times, avg 3µs/call: # 23 times (89µs+0s) by Foswiki::getScriptUrl at line 1473, avg 4µs/call # 12 times (36µs+0s) by Foswiki::_make_params at line 1493, avg 3µs/call # 10 times (27µs+0s) by Foswiki::Request::queryString at line 207 of /var/www/foswiki11/lib/Foswiki/Request.pm, avg 3µs/call # 10 times (17µs+0s) by Foswiki::Request::queryString at line 208 of /var/www/foswiki11/lib/Foswiki/Request.pm, avg 2µs/call # once (6µs+0s) by Foswiki::urlEncodeAttachment at line 2675
sub urlEncode {
27085627µs my $text = shift;
2709
27105653µs $text =~ s/([^0-9a-zA-Z-_.:~!*'\/])/'%'.sprintf('%02x',ord($1))/ge;
2711
271256179µs return $text;
2713}
2714
2715=begin TML
2716
2717---++ StaticMethod urlDecode( $string ) -> decoded string
2718
2719Reverses the encoding done in urlEncode.
2720
2721=cut
2722
2723sub urlDecode {
2724 my $text = shift;
2725
2726 $text =~ s/%([\da-f]{2})/chr(hex($1))/gei;
2727
2728 return $text;
2729}
2730
2731=begin TML
2732
2733---++ StaticMethod isTrue( $value, $default ) -> $boolean
2734
2735Returns 1 if =$value= is true, and 0 otherwise. "true" means set to
2736something with a Perl true value, with the special cases that "off",
2737"false" and "no" (case insensitive) are forced to false. Leading and
2738trailing spaces in =$value= are ignored.
2739
2740If the value is undef, then =$default= is returned. If =$default= is
2741not specified it is taken as 0.
2742
2743=cut
2744
2745
# spent 7.13ms within Foswiki::isTrue which was called 1515 times, avg 5µs/call: # 94 times (1.46ms+0s) by Foswiki::WebFilter::ok at line 39 of /var/www/foswiki11/lib/Foswiki/WebFilter.pm, avg 16µs/call # 81 times (598µs+0s) by Foswiki::Search::InfoCache::sortResults at line 138 of /var/www/foswiki11/lib/Foswiki/Search/InfoCache.pm, avg 7µs/call # 41 times (399µs+0s) by Foswiki::Search::searchWeb at line 400 of /var/www/foswiki11/lib/Foswiki/Search.pm, avg 10µs/call # 41 times (339µs+0s) by Foswiki::Search::InfoCache::_getListOfWebs at line 442 of /var/www/foswiki11/lib/Foswiki/Search/InfoCache.pm, avg 8µs/call # 41 times (313µs+0s) by Foswiki::Store::QueryAlgorithms::BruteForce::query at line 66 of /var/www/foswiki11/lib/Foswiki/Store/QueryAlgorithms/BruteForce.pm, avg 8µs/call # 41 times (305µs+0s) by Foswiki::Search::searchWeb at line 258 of /var/www/foswiki11/lib/Foswiki/Search.pm, avg 7µs/call # 41 times (238µs+0s) by Foswiki::Search::searchWeb at line 295 of /var/www/foswiki11/lib/Foswiki/Search.pm, avg 6µs/call # 41 times (219µs+0s) by Foswiki::Search::searchWeb at line 260 of /var/www/foswiki11/lib/Foswiki/Search.pm, avg 5µs/call # 41 times (215µs+0s) by Foswiki::Search::formatResults at line 601 of /var/www/foswiki11/lib/Foswiki/Search.pm, avg 5µs/call # 41 times (194µs+0s) by Foswiki::Search::formatResults at line 722 of /var/www/foswiki11/lib/Foswiki/Search.pm, avg 5µs/call # 41 times (182µs+0s) by Foswiki::Search::formatResults at line 723 of /var/www/foswiki11/lib/Foswiki/Search.pm, avg 4µs/call # 41 times (182µs+0s) by Foswiki::Search::formatResults at line 603 of /var/www/foswiki11/lib/Foswiki/Search.pm, avg 4µs/call # 41 times (120µs+0s) by Foswiki::Store::QueryAlgorithms::BruteForce::query at line 82 of /var/www/foswiki11/lib/Foswiki/Store/QueryAlgorithms/BruteForce.pm, avg 3µs/call # 41 times (92µs+0s) by Foswiki::Search::searchWeb at line 250 of /var/www/foswiki11/lib/Foswiki/Search.pm, avg 2µs/call # 41 times (80µs+0s) by Foswiki::Search::searchWeb at line 401 of /var/www/foswiki11/lib/Foswiki/Search.pm, avg 2µs/call # 41 times (80µs+0s) by Foswiki::Search::searchWeb at line 277 of /var/www/foswiki11/lib/Foswiki/Search.pm, avg 2µs/call # 41 times (77µs+0s) by Foswiki::Search::searchWeb at line 261 of /var/www/foswiki11/lib/Foswiki/Search.pm, avg 2µs/call # 41 times (72µs+0s) by Foswiki::Search::formatResults at line 602 of /var/www/foswiki11/lib/Foswiki/Search.pm, avg 2µs/call # 41 times (69µs+0s) by Foswiki::Search::searchWeb at line 293 of /var/www/foswiki11/lib/Foswiki/Search.pm, avg 2µs/call # 41 times (68µs+0s) by Foswiki::Search::searchWeb at line 299 of /var/www/foswiki11/lib/Foswiki/Search.pm, avg 2µs/call # 41 times (66µs+0s) by Foswiki::Search::formatResults at line 735 of /var/www/foswiki11/lib/Foswiki/Search.pm, avg 2µs/call # 41 times (66µs+0s) by Foswiki::Search::formatResults at line 600 of /var/www/foswiki11/lib/Foswiki/Search.pm, avg 2µs/call # 41 times (64µs+0s) by Foswiki::Search::formatResults at line 604 of /var/www/foswiki11/lib/Foswiki/Search.pm, avg 2µs/call # 41 times (62µs+0s) by Foswiki::Search::searchWeb at line 255 of /var/www/foswiki11/lib/Foswiki/Search.pm, avg 2µs/call # 41 times (61µs+0s) by Foswiki::Search::searchWeb at line 309 of /var/www/foswiki11/lib/Foswiki/Search.pm, avg 1µs/call # 41 times (57µs+0s) by Foswiki::Search::searchWeb at line 315 of /var/www/foswiki11/lib/Foswiki/Search.pm, avg 1µs/call # 41 times (55µs+0s) by Foswiki::Search::formatResults at line 738 of /var/www/foswiki11/lib/Foswiki/Search.pm, avg 1µs/call # 41 times (55µs+0s) by Foswiki::Search::formatResults at line 736 of /var/www/foswiki11/lib/Foswiki/Search.pm, avg 1µs/call # 41 times (54µs+0s) by Foswiki::Search::searchWeb at line 310 of /var/www/foswiki11/lib/Foswiki/Search.pm, avg 1µs/call # 41 times (53µs+0s) by Foswiki::Search::searchWeb at line 317 of /var/www/foswiki11/lib/Foswiki/Search.pm, avg 1µs/call # 40 times (320µs+0s) by Foswiki::Store::SearchAlgorithms::Forking::query at line 171 of /var/www/foswiki11/lib/Foswiki/Store/SearchAlgorithms/Forking.pm, avg 8µs/call # 40 times (278µs+0s) by Foswiki::Search::InfoCache::_getListOfWebs at line 488 of /var/www/foswiki11/lib/Foswiki/Search/InfoCache.pm, avg 7µs/call # 40 times (215µs+0s) by Foswiki::Store::SearchAlgorithms::Forking::query at line 187 of /var/www/foswiki11/lib/Foswiki/Store/SearchAlgorithms/Forking.pm, avg 5µs/call # 40 times (90µs+0s) by Foswiki::Search::searchWeb at line 460 of /var/www/foswiki11/lib/Foswiki/Search.pm, avg 2µs/call # 14 times (95µs+0s) by Foswiki::Func::getPreferencesFlag at line 819 of /var/www/foswiki11/lib/Foswiki/Func.pm, avg 7µs/call # 6 times (112µs+0s) by Foswiki::__ANON__[/var/www/foswiki11/lib/Foswiki/Macros/INCLUDE.pm:331] at line 291 of /var/www/foswiki11/lib/Foswiki/Macros/INCLUDE.pm, avg 19µs/call # 5 times (50µs+0s) by Foswiki::Render::getRenderedVersion at line 1428 of /var/www/foswiki11/lib/Foswiki/Render.pm, avg 10µs/call # 3 times (8µs+0s) by Foswiki::URLPARAM at line 20 of /var/www/foswiki11/lib/Foswiki/Macros/URLPARAM.pm, avg 3µs/call # 2 times (11µs+0s) by Foswiki::Func::isTrue at line 2966 of /var/www/foswiki11/lib/Foswiki/Func.pm, avg 5µs/call # once (54µs+0s) by Foswiki::_includeWarning at line 94 of /var/www/foswiki11/lib/Foswiki/Macros/INCLUDE.pm # once (2µs+0s) by Foswiki::Search::searchWeb at line 304 of /var/www/foswiki11/lib/Foswiki/Search.pm
sub isTrue {
274615151.02ms my ( $value, $default ) = @_;
2747
27481515417µs $default ||= 0;
2749
275015152.76ms return $default unless defined($value);
2751
27526073.07ms $value =~ s/^\s*(.*?)\s*$/$1/gi;
2753607152µs $value =~ s/off//gi;
2754607130µs $value =~ s/no//gi;
2755607115µs $value =~ s/false//gi;
27566075.77ms return ($value) ? 1 : 0;
2757}
2758
2759=begin TML
2760
2761---++ StaticMethod spaceOutWikiWord( $word, $sep ) -> $string
2762
2763Spaces out a wiki word by inserting a string (default: one space) between each word component.
2764With parameter $sep any string may be used as separator between the word components; if $sep is undefined it defaults to a space.
2765
2766=cut
2767
2768
# spent 88µs within Foswiki::spaceOutWikiWord which was called 2 times, avg 44µs/call: # 2 times (88µs+0s) by Foswiki::SPACEOUT at line 11 of /var/www/foswiki11/lib/Foswiki/Macros/SPACEOUT.pm, avg 44µs/call
sub spaceOutWikiWord {
276922µs my ( $word, $sep ) = @_;
2770
2771 # Both could have the value 0 so we cannot use simple = || ''
277221µs $word = defined($word) ? $word : '';
277322µs $sep = defined($sep) ? $sep : ' ';
2774252µs $word =~
2775s/([$regex{lowerAlpha}])([$regex{upperAlpha}$regex{numeric}]+)/$1$sep$2/go;
2776217µs $word =~ s/([$regex{numeric}])([$regex{upperAlpha}])/$1$sep$2/go;
2777215µs return $word;
2778}
2779
2780=begin TML
2781
2782---++ ObjectMethod innerExpandMacros(\$text, $topicObject)
2783Expands variables by replacing the variables with their
2784values. Some example variables: %<nop>TOPIC%, %<nop>SCRIPTURL%,
2785%<nop>WIKINAME%, etc.
2786$web and $incs are passed in for recursive include expansion. They can
2787safely be undef.
2788The rules for tag expansion are:
2789 1 Tags are expanded left to right, in the order they are encountered.
2790 1 Tags are recursively expanded as soon as they are encountered -
2791 the algorithm is inherently single-pass
2792 1 A tag is not "encountered" until the matching }% has been seen, by
2793 which time all tags in parameters will have been expanded
2794 1 Tag expansions that create new tags recursively are limited to a
2795 set number of hierarchical levels of expansion
2796
2797=cut
2798
2799
# spent 59.1s (2.01ms+59.1) within Foswiki::innerExpandMacros which was called 49 times, avg 1.21s/call: # 18 times (646µs+-646µs) by Foswiki::If::OP_dollar::evaluate at line 40 of /var/www/foswiki11/lib/Foswiki/If/OP_dollar.pm, avg 0s/call # 7 times (290µs+59.1s) by Foswiki::expandMacros at line 3342, avg 8.44s/call # 7 times (256µs+952µs) by Foswiki::expandMacros at line 3352, avg 173µs/call # 6 times (271µs+-271µs) by Foswiki::__ANON__[/var/www/foswiki11/lib/Foswiki/Macros/INCLUDE.pm:331] at line 310 of /var/www/foswiki11/lib/Foswiki/Macros/INCLUDE.pm, avg 0s/call # 6 times (356µs+-356µs) by Foswiki::__ANON__[/var/www/foswiki11/lib/Foswiki/Macros/INCLUDE.pm:331] at line 297 of /var/www/foswiki11/lib/Foswiki/Macros/INCLUDE.pm, avg 0s/call # 5 times (193µs+-193µs) by Foswiki::__ANON__[/var/www/foswiki11/lib/Foswiki/Macros/INCLUDE.pm:331] at line 328 of /var/www/foswiki11/lib/Foswiki/Macros/INCLUDE.pm, avg 0s/call
sub innerExpandMacros {
28004936µs my ( $this, $text, $topicObject ) = @_;
2801
2802 # push current context
280349102µs49377µs my $memTopic = $this->{prefs}->getPreference('TOPIC');
# spent 377µs making 49 calls to Foswiki::Prefs::getPreference, avg 8µs/call
28044996µs49297µs my $memWeb = $this->{prefs}->getPreference('WEB');
# spent 297µs making 49 calls to Foswiki::Prefs::getPreference, avg 6µs/call
2805
2806 # Historically this couldn't be called on web objects.
280749108µs49115µs my $webContext = $topicObject->web || $this->{webName};
# spent 115µs making 49 calls to Foswiki::Meta::web, avg 2µs/call
28084990µs49111µs my $topicContext = $topicObject->topic || $this->{topicName};
# spent 111µs making 49 calls to Foswiki::Meta::topic, avg 2µs/call
2809
28104988µs49401µs $this->{prefs}->setInternalPreferences(
# spent 401µs making 49 calls to Foswiki::Prefs::setInternalPreferences, avg 8µs/call
2811 TOPIC => $topicContext,
2812 WEB => $webContext
2813 );
2814
2815 # Escape ' !%VARIABLE%'
281649220µs $$text =~ s/(?<=\s)!%($regex{tagNameRegex})/&#37;$1/g;
2817
2818 # Make sure func works, for registered tag handlers
281949117µs49108µs if (SINGLE_SINGLETONS) {
# spent 108µs making 49 calls to Foswiki::SINGLE_SINGLETONS, avg 2µs/call
2820 ASSERT( defined $Foswiki::Plugins::SESSION );
2821 ASSERT( $Foswiki::Plugins::SESSION == $this );
2822 }
28234934µs local $Foswiki::Plugins::SESSION = $this;
28244967µs4953µs ASSERT( $Foswiki::Plugins::SESSION->isa('Foswiki') ) if DEBUG;
# spent 53µs making 49 calls to Assert::ASSERTS_OFF, avg 1µs/call
2825
2826 # NOTE TO DEBUGGERS
2827 # The depth parameter in the following call controls the maximum number
2828 # of levels of expansion. If it is set to 1 then only macros in the
2829 # topic will be expanded; macros that they in turn generate will be
2830 # left unexpanded. If it is set to 2 then the expansion will stop after
2831 # the first recursive inclusion, and so on. This is incredible useful
2832 # when debugging. The default, 16, was selected empirically.
283349164µs4959.1s $$text = _processMacros( $this, $$text, \&_expandMacroOnTopicRendering,
# spent 76.5s making 49 calls to Foswiki::_processMacros, avg 1.56s/call, recursion: max depth 4, sum of overlapping time 17.4s
2834 $topicObject, 16 );
2835
2836 # restore previous context
283749291µs49397µs $this->{prefs}->setInternalPreferences(
# spent 397µs making 49 calls to Foswiki::Prefs::setInternalPreferences, avg 8µs/call
2838 TOPIC => $memTopic,
2839 WEB => $memWeb
2840 );
2841}
2842
2843=begin TML
2844
2845---++ StaticMethod takeOutBlocks( \$text, $tag, \%map ) -> $text
2846 * =$text= - Text to process
2847 * =$tag= - XML-style tag.
2848 * =\%map= - Reference to a hash to contain the removed blocks
2849
2850Return value: $text with blocks removed
2851
2852Searches through $text and extracts blocks delimited by an XML-style tag,
2853storing the extracted block, and replacing with a token string which is
2854not affected by TML rendering. The text after these substitutions is
2855returned.
2856
2857=cut
2858
2859
# spent 2.00ms within Foswiki::takeOutBlocks which was called 106 times, avg 19µs/call: # 71 times (657µs+0s) by Foswiki::_processMacros at line 2988, avg 9µs/call # 7 times (188µs+0s) by Foswiki::expandMacros at line 3324, avg 27µs/call # 7 times (185µs+0s) by Foswiki::expandMacros at line 3344, avg 26µs/call # 6 times (169µs+0s) by Foswiki::__ANON__[/var/www/foswiki11/lib/Foswiki/Macros/INCLUDE.pm:331] at line 300 of /var/www/foswiki11/lib/Foswiki/Macros/INCLUDE.pm, avg 28µs/call # 5 times (485µs+0s) by Foswiki::Render::getRenderedVersion at line 1130 of /var/www/foswiki11/lib/Foswiki/Render.pm, avg 97µs/call # 5 times (169µs+0s) by Foswiki::Render::getRenderedVersion at line 1129 of /var/www/foswiki11/lib/Foswiki/Render.pm, avg 34µs/call # 5 times (145µs+0s) by Foswiki::Render::getRenderedVersion at line 1161 of /var/www/foswiki11/lib/Foswiki/Render.pm, avg 29µs/call
sub takeOutBlocks {
2860106144µs my ( $intext, $tag, $map ) = @_;
2861
28621061.75ms return $intext unless ( $intext =~ m/<$tag\b/i );
2863
28642900ns my $out = '';
28652400ns my $depth = 0;
28662300ns my $scoop;
28672400ns my $tagParams;
2868
2869263µs foreach my $token ( split( /(<\/?$tag[^>]*>)/i, $intext ) ) {
287058106µs if ( $token =~ /<$tag\b([^>]*)?>/i ) {
2871143µs $depth++;
2872146µs if ( $depth eq 1 ) {
28731410µs $tagParams = $1;
2874144µs next;
2875 }
2876 }
2877 elsif ( $token =~ /<\/$tag>/i ) {
2878143µs if ( $depth > 0 ) {
28791410µs $depth--;
2880144µs if ( $depth eq 0 ) {
2881147µs my $placeholder = "$tag$BLOCKID";
2882142µs $BLOCKID++;
28831425µs $map->{$placeholder}{text} = $scoop;
28841412µs $map->{$placeholder}{params} = $tagParams;
2885149µs $out .= "$OC$placeholder$CC";
2886142µs $scoop = '';
2887144µs next;
2888 }
2889 }
2890 }
28913017µs if ( $depth > 0 ) {
2892 $scoop .= $token;
2893 }
2894 else {
2895168µs $out .= $token;
2896 }
2897 }
2898
2899 # unmatched tags
290022µs if ( defined($scoop) && ( $scoop ne '' ) ) {
2901 my $placeholder = "$tag$BLOCKID";
2902 $BLOCKID++;
2903 $map->{$placeholder}{text} = $scoop;
2904 $map->{$placeholder}{params} = $tagParams;
2905 $out .= "$OC$placeholder$CC";
2906 }
2907
2908217µs return $out;
2909}
2910
2911=begin TML
2912
2913---++ StaticMethod putBackBlocks( \$text, \%map, $tag, $newtag, $callBack ) -> $text
2914
2915Return value: $text with blocks added back
2916 * =\$text= - reference to text to process
2917 * =\%map= - map placeholders to blocks removed by takeOutBlocks
2918 * =$tag= - Tag name processed by takeOutBlocks
2919 * =$newtag= - Tag name to use in output, in place of $tag.
2920 If undefined, uses $tag.
2921 * =$callback= - Reference to function to call on each block
2922 being inserted (optional)
2923
2924Reverses the actions of takeOutBlocks.
2925
2926Each replaced block is processed by the callback (if there is one) before
2927re-insertion.
2928
2929Parameters to the outermost cut block are replaced into the open tag,
2930even if that tag is changed. This allows things like =&lt;verbatim class=''>=
2931to be changed to =&lt;pre class=''>=
2932
2933If you set $newtag to '', replaces the taken-out block with the contents
2934of the block, not including the open/close. This is used for &lt;literal>,
2935for example.
2936
2937=cut
2938
2939
# spent 830µs (795+35) within Foswiki::putBackBlocks which was called 99 times, avg 8µs/call: # 71 times (354µs+0s) by Foswiki::_processMacros at line 3110, avg 5µs/call # 7 times (30µs+0s) by Foswiki::expandMacros at line 3377, avg 4µs/call # 6 times (29µs+0s) by Foswiki::__ANON__[/var/www/foswiki11/lib/Foswiki/Macros/INCLUDE.pm:331] at line 306 of /var/www/foswiki11/lib/Foswiki/Macros/INCLUDE.pm, avg 5µs/call # 5 times (276µs+35µs) by Foswiki::Render::getRenderedVersion at line 1456 of /var/www/foswiki11/lib/Foswiki/Render.pm, avg 62µs/call # 5 times (58µs+0s) by Foswiki::Render::getRenderedVersion at line 1445 of /var/www/foswiki11/lib/Foswiki/Render.pm, avg 12µs/call # 5 times (48µs+0s) by Foswiki::Render::getRenderedVersion at line 1451 of /var/www/foswiki11/lib/Foswiki/Render.pm, avg 10µs/call
sub putBackBlocks {
29409991µs my ( $text, $map, $tag, $newtag, $callback ) = @_;
2941
29429939µs $newtag = $tag if ( !defined($newtag) );
2943
294499482µs foreach my $placeholder ( keys %$map ) {
294572116µs if ( $placeholder =~ /^$tag\d+$/ ) {
29461412µs my $params = $map->{$placeholder}{params} || '';
2947147µs my $val = $map->{$placeholder}{text};
29481424µs1435µs $val = &$callback($val) if ( defined($callback) );
# spent 35µs making 14 calls to Foswiki::Render::_filterLiteral, avg 3µs/call
2949149µs if ( $newtag eq '' ) {
295014116µs $$text =~ s($OC$placeholder$CC)($val);
2951 }
2952 else {
2953 $$text =~ s($OC$placeholder$CC)
2954 (<$newtag$params>$val</$newtag>);
2955 }
29561419µs delete( $map->{$placeholder} );
2957 }
2958 }
2959}
2960
2961# Process Foswiki %TAGS{}% by parsing the input tokenised into
2962# % separated sections. The parser is a simple stack-based parse,
2963# sufficient to ensure nesting of tags is correct, but no more
2964# than that.
2965# $depth limits the number of recursive expansion steps that
2966# can be performed on expanded tags.
2967
# spent 59.1s (15.2ms+59.1) within Foswiki::_processMacros which was called 86 times, avg 687ms/call: # 49 times (11.3ms+59.1s) by Foswiki::innerExpandMacros at line 2833, avg 1.21s/call # 37 times (3.84ms+-3.84ms) by Foswiki::_processMacros at line 3054, avg 0s/call
sub _processMacros {
296886155µs my ( $this, $text, $tagf, $topicObject, $depth ) = @_;
29698626µs my $tell = 0;
2970
29718657µs return '' if ( ( !defined($text) )
2972 || ( $text eq '' ) );
2973
2974 #no tags to process
297586220µs return $text unless ( $text =~ /%/ );
2976
29777114µs unless ($depth) {
2978 my $mess = "Max recursive depth reached: $text";
2979 $this->logger->log( 'warning', $mess );
2980
2981 # prevent recursive expansion that just has been detected
2982 # from happening in the error message
2983 $text =~ s/%(.*?)%/$1/go;
2984 return $text;
2985 }
2986
29877146µs my $verbatim = {};
298871135µs71657µs $text = takeOutBlocks( $text, 'verbatim', $verbatim );
# spent 657µs making 71 calls to Foswiki::takeOutBlocks, avg 9µs/call
2989
29907133µs my $dirtyAreas = {};
29917165µs $text = takeOutBlocks( $text, 'dirtyarea', $dirtyAreas )
2992 if $Foswiki::cfg{Cache}{Enabled};
2993
2994711.24ms my @queue = split( /(%)/, $text );
29957112µs my @stack;
29967131µs my $stackTop = ''; # the top stack entry. Done this way instead of
2997 # referring to the top of the stack for efficiency. This var
2998 # should be considered to be $stack[$#stack]
2999
300071264µs while ( scalar(@queue) ) {
3001
3002 #print STDERR "QUEUE:".join("\n ", map { "'$_'" } @queue)."\n";
30031887791µs my $token = shift(@queue);
3004
3005 #print STDERR ' ' x $tell,"PROCESSING $token \n";
3006
3007 # each % sign either closes an existing stacked context, or
3008 # opens a new context.
300918871.13ms if ( $token eq '%' ) {
3010
3011 #print STDERR ' ' x $tell,"CONSIDER $stackTop\n";
3012 # If this is a closing }%, try to rejoin the previous
3013 # tokens until we get to a valid tag construct. This is
3014 # a bit of a hack, but it's hard to think of a better
3015 # way to do this without a full parse that takes % signs
3016 # in tag parameters into account.
3017923540µs if ( $stackTop =~ /}$/s ) {
3018231963µs while ( scalar(@stack)
3019 && $stackTop !~ /^%$regex{tagNameRegex}\{.*}$/so )
3020 {
3021187µs my $top = $stackTop;
3022
3023 #print STDERR ' ' x $tell,"COLLAPSE $top \n";
30241848µs $stackTop = pop(@stack) . $top;
3025 }
3026 }
3027
3028 # /s so you can have newlines in parameters
30299232.36ms if ( $stackTop =~ m/^%(($regex{tagNameRegex})(?:{(.*)})?)$/so ) {
3030
3031 # SMELL: unchecked implicit untaint?
3032452981µs my ( $expr, $tag, $args ) = ( $1, $2, $3 );
3033
3034 #print STDERR ' ' x $tell,"POP $tag\n";
3035 #Monitor::MARK("Before $tag");
30364521.06ms45259.1s my $e = &$tagf( $this, $tag, $args, $topicObject );
# spent 76.5s making 452 calls to Foswiki::_expandMacroOnTopicRendering, avg 169ms/call, recursion: max depth 3, sum of overlapping time 17.4s
3037
3038 #Monitor::MARK("After $tag");
3039
3040452171µs if ( defined($e) ) {
3041
3042 #print STDERR ' ' x $tell--,"EXPANDED $tag -> $e\n";
3043442367µs $stackTop = pop(@stack);
3044
3045 # Don't bother recursively expanding unless there are
3046 # unexpanded tags in the result.
3047442863µs unless ( $e =~ /%$regex{tagNameRegex}(?:{.*})?%/so ) {
3048405425µs $stackTop .= $e;
3049405317µs next;
3050 }
3051
3052 # Recursively expand tags in the expansion of $tag
3053 $stackTop .=
305437202µs370s $this->_processMacros( $e, $tagf, $topicObject,
# spent 9.34s making 37 calls to Foswiki::_processMacros, avg 252ms/call, recursion: max depth 5, sum of overlapping time 9.34s
3055 $depth - 1 );
3056 }
3057 else {
3058
3059 #print STDERR ' ' x $tell++,"EXPAND $tag FAILED\n";
3060 # To handle %NOP
3061 # correctly, we have to handle the %VAR% case differently
3062 # to the %VAR{}% case when a variable expansion fails.
3063 # This is so that recursively define variables e.g.
3064 # %A%B%D% expand correctly, but at the same time we ensure
3065 # that a mismatched }% can't accidentally close a context
3066 # that was left open when a tag expansion failed.
3067 # However TWiki didn't do this, so for compatibility
3068 # we have to accept that %NOP can never be fixed. if it
3069 # could, then we could uncomment the following:
3070
3071 #if( $stackTop =~ /}$/ ) {
3072 # # %VAR{...}% case
3073 # # We need to push the unexpanded expression back
3074 # # onto the stack, but we don't want it to match the
3075 # # tag expression again. So we protect the %'s
3076 # $stackTop = "&#37;$expr&#37;";
3077 #} else
3078 #{
3079
3080 # %VAR% case.
3081 # In this case we *do* want to match the tag expression
3082 # again, as an embedded %VAR% may have expanded to
3083 # create a valid outer expression. This is directly
3084 # at odds with the %VAR{...}% case.
3085107µs push( @stack, $stackTop );
3086103µs $stackTop = '%'; # open new context
3087 #}
3088 }
3089 }
3090 else {
3091471602µs push( @stack, $stackTop );
3092471164µs $stackTop = '%'; # push a new context
3093 #$tell++;
3094 }
3095 }
3096 else {
3097964499µs $stackTop .= $token;
3098 }
3099 }
3100
3101 # Run out of input. Gather up everything in the stack.
31027134µs while ( scalar(@stack) ) {
31032137µs my $expr = $stackTop;
31042112µs $stackTop = pop(@stack);
31052161µs $stackTop .= $expr;
3106 }
3107
31087151µs putBackBlocks( \$stackTop, $dirtyAreas, 'dirtyarea' )
3109 if $Foswiki::cfg{Cache}{Enabled};
311071145µs71354µs putBackBlocks( \$stackTop, $verbatim, 'verbatim' );
# spent 354µs making 71 calls to Foswiki::putBackBlocks, avg 5µs/call
3111
3112 #print STDERR "FINAL $stackTop\n";
3113
311471368µs return $stackTop;
3115}
3116
3117# Handle expansion of a tag during topic rendering
3118# $tag is the tag name
3119# $args is the bit in the {} (if there are any)
3120# $topicObject should be passed for dynamic tags (not needed for
3121# session or constant tags
3122
# spent 59.1s (20.7ms+59.1) within Foswiki::_expandMacroOnTopicRendering which was called 454 times, avg 130ms/call: # 452 times (20.7ms+59.1s) by Foswiki::_processMacros at line 3036, avg 131ms/call # 2 times (76µs+-5µs) by Foswiki::normalizeWebTopicName at line 1623, avg 36µs/call
sub _expandMacroOnTopicRendering {
3123454411µs my ( $this, $tag, $args, $topicObject ) = @_;
3124
3125454268µs require Foswiki::Attrs;
312645475µs my $attrs;
3127
3128454906µs45411.3ms my $e = $this->{prefs}->getPreference($tag);
# spent 11.3ms making 454 calls to Foswiki::Prefs::getPreference, avg 25µs/call
3129454463µs if ( defined $e ) {
313010132µs if ( $args && $args =~ /\S/ ) {
3131 $attrs = new Foswiki::Attrs( $args, 0 );
3132 $attrs->{DEFAULT} = $attrs->{_DEFAULT};
3133 $e = $this->_processMacros(
3134 $e,
3135 sub {
3136 my ( $this, $tag, $args, $topicObject ) = @_;
3137 return
3138 defined $attrs->{$tag}
3139 ? expandStandardEscapes( $attrs->{$tag} )
3140 : undef;
3141 },
3142 $topicObject,
3143 1
3144 );
3145 }
3146 }
3147 elsif ( exists( $macros{$tag} ) ) {
3148343179µs unless ( defined( $macros{$tag} ) ) {
3149
3150 # Demand-load the macro module
31511655µs die $tag unless $tag =~ /([A-Z_:]+)/i;
31521615µs $tag = $1;
315316826µs eval "require Foswiki::Macros::$tag";
# spent 206µs executing statements in string eval # spent 195µs executing statements in 2 string evals (merged) # spent 191µs executing statements in string eval # spent 168µs executing statements in string eval # spent 149µs executing statements in string eval # spent 138µs executing statements in string eval # spent 129µs executing statements in string eval # spent 118µs executing statements in string eval # spent 116µs executing statements in string eval # spent 110µs executing statements in string eval # spent 91µs executing statements in string eval # spent 83µs executing statements in string eval # spent 75µs executing statements in string eval # spent 73µs executing statements in string eval # spent 72µs executing statements in string eval
3154167µs die $@ if $@;
315516529µs $macros{$tag} = eval "\\&$tag";
# spent 7µs executing statements in 2 string evals (merged) # spent 5µs executing statements in string eval # spent 5µs executing statements in string eval # spent 4µs executing statements in string eval # spent 4µs executing statements in string eval # spent 4µs executing statements in string eval # spent 4µs executing statements in string eval # spent 4µs executing statements in string eval # spent 4µs executing statements in string eval # spent 3µs executing statements in string eval # spent 3µs executing statements in string eval # spent 3µs executing statements in string eval # spent 3µs executing statements in string eval # spent 2µs executing statements in string eval # spent 2µs executing statements in string eval
3156168µs die $@ if $@;
3157 }
3158
31593431.70ms3437.77ms $attrs = new Foswiki::Attrs( $args, $contextFreeSyntax{$tag} );
# spent 7.77ms making 343 calls to Foswiki::Attrs::new, avg 23µs/call
31603431.21ms34367.4s $e = &{ $macros{$tag} }( $this, $attrs, $topicObject );
# spent 49.6s making 40 calls to Foswiki::SEARCH, avg 1.24s/call # spent 18.3s making 7 calls to Foswiki::INCLUDE, avg 2.61s/call, recursion: max depth 2, sum of overlapping time 8.98s # spent 8.35s making 4 calls to Foswiki::Func::__ANON__[/var/www/foswiki11/lib/Foswiki/Func.pm:611], avg 2.09s/call # spent 77.0ms making 41 calls to Foswiki::IF, avg 1.88ms/call # spent 20.3ms making 3 calls to Foswiki::META, avg 6.76ms/call # spent 5.63ms making 33 calls to Foswiki::MAKETEXT, avg 171µs/call # spent 5.24ms making 42 calls to Foswiki::VAR, avg 125µs/call # spent 4.47ms making 3 calls to Foswiki::REVINFO, avg 1.49ms/call # spent 2.75ms making 1 call to Foswiki::QUERY # spent 859µs making 1 call to Foswiki::ICONURL # spent 673µs making 2 calls to Foswiki::LoginManager::_LOGIN, avg 337µs/call # spent 590µs making 33 calls to Foswiki::__ANON__[/var/www/foswiki11/lib/Foswiki.pm:241], avg 18µs/call # spent 482µs making 5 calls to Foswiki::WIKINAME, avg 96µs/call # spent 342µs making 16 calls to Foswiki::__ANON__[/var/www/foswiki11/lib/Foswiki.pm:270], avg 21µs/call # spent 337µs making 2 calls to Foswiki::WIKIUSERNAME, avg 168µs/call # spent 296µs making 5 calls to Foswiki::__ANON__[/var/www/foswiki11/lib/Foswiki.pm:211], avg 59µs/call # spent 224µs making 4 calls to Foswiki::ADDTOZONE, avg 56µs/call # spent 222µs making 2 calls to Foswiki::USERNAME, avg 111µs/call # spent 167µs making 3 calls to Foswiki::URLPARAM, avg 56µs/call # spent 161µs making 9 calls to Foswiki::__ANON__[/var/www/foswiki11/lib/Foswiki.pm:268], avg 18µs/call # spent 134µs making 15 calls to Foswiki::ENCODE, avg 9µs/call # spent 113µs making 41 calls to Foswiki::__ANON__[/var/www/foswiki11/lib/Foswiki.pm:368], avg 3µs/call # spent 112µs making 2 calls to Foswiki::SPACEOUT, avg 56µs/call # spent 93µs making 1 call to Foswiki::__ANON__[/var/www/foswiki11/lib/Foswiki.pm:244] # spent 79µs making 1 call to Foswiki::__ANON__[/var/www/foswiki11/lib/Foswiki.pm:279] # spent 77µs making 1 call to Foswiki::__ANON__[/var/www/foswiki11/lib/Foswiki.pm:283] # spent 45µs making 14 calls to Foswiki::__ANON__[/var/www/foswiki11/lib/Foswiki.pm:372], avg 3µs/call # spent 37µs making 2 calls to Foswiki::__ANON__[/var/www/foswiki11/lib/Foswiki.pm:417], avg 19µs/call # spent 26µs making 4 calls to Foswiki::__ANON__[/var/www/foswiki11/lib/Foswiki.pm:361], avg 6µs/call # spent 25µs making 2 calls to Foswiki::__ANON__[/var/www/foswiki11/lib/Foswiki.pm:240], avg 12µs/call # spent 22µs making 1 call to Foswiki::__ANON__[/var/www/foswiki11/lib/Foswiki.pm:267] # spent 9µs making 1 call to Foswiki::LoginManager::ApacheLogin::__ANON__[/var/www/foswiki11/lib/Foswiki/LoginManager/ApacheLogin.pm:46] # spent 8µs making 1 call to Foswiki::__ANON__[/var/www/foswiki11/lib/Foswiki.pm:404] # spent 3µs making 1 call to Foswiki::__ANON__[/var/www/foswiki11/lib/Foswiki.pm:366]
3161 }
3162 elsif ( $args && $args =~ /\S/ ) {
316313µs165µs $attrs = new Foswiki::Attrs($args);
# spent 65µs making 1 call to Foswiki::Attrs::new
31641700ns if ( defined $attrs->{default} ) {
3165 $e = expandStandardEscapes( $attrs->{default} );
3166 }
3167 }
31684542.15ms return $e;
3169}
3170
3171# Handle expansion of a tag during new topic creation. When creating a
3172# new topic from a template we only expand a subset of the available legal
3173# tags, and we expand %NOP% differently.
3174sub _expandMacroOnTopicCreation {
3175 my $this = shift;
3176
3177 # my( $tag, $args, $topicObject ) = @_;
3178
3179 # Required for Cairo compatibility. Ignore %NOP{...}%
3180 # %NOP% is *not* ignored until all variable expansion is complete,
3181 # otherwise them inside-out rule would remove it too early e.g.
3182 # %GM%NOP%TIME -> %GMTIME -> 12:00. So we ignore it here and scrape it
3183 # out later. We *have* to remove %NOP{...}% because it can foul up
3184 # brace-matching.
3185 return '' if $_[0] eq 'NOP' && defined $_[1];
3186
3187 # Only expand a subset of legal tags. Warning: $this->{user} may be
3188 # overridden during this call, when a new user topic is being created.
3189 # This is what we want to make sure new user templates are populated
3190 # correctly, but you need to think about this if you extend the set of
3191 # tags expanded here.
3192 return
3193 unless $_[0] =~
3194 /^(URLPARAM|DATE|(SERVER|GM)TIME|(USER|WIKI)NAME|WIKIUSERNAME|USERINFO)$/;
3195
3196 return $this->_expandMacroOnTopicRendering(@_);
3197}
3198
3199=begin TML
3200
3201---++ ObjectMethod enterContext( $id, $val )
3202
3203Add the context id $id into the set of active contexts. The $val
3204can be anything you like, but should always evaluate to boolean
3205TRUE.
3206
3207An example of the use of contexts is in the use of tag
3208expansion. The commonTagsHandler in plugins is called every
3209time tags need to be expanded, and the context of that expansion
3210is signalled by the expanding module using a context id. So the
3211forms module adds the context id "form" before invoking common
3212tags expansion.
3213
3214Contexts are not just useful for tag expansion; they are also
3215relevant when rendering.
3216
3217Contexts are intended for use mainly by plugins. Core modules can
3218use $session->inContext( $id ) to determine if a context is active.
3219
3220=cut
3221
3222
# spent 182µs within Foswiki::enterContext which was called 42 times, avg 4µs/call: # 36 times (154µs+0s) by Foswiki::Plugin::registerHandlers at line 285 of /var/www/foswiki11/lib/Foswiki/Plugin.pm, avg 4µs/call # once (12µs+0s) by Foswiki::UI::View::view at line 371 of /var/www/foswiki11/lib/Foswiki/UI/View.pm # once (4µs+0s) by Foswiki::UI::View::view at line 397 of /var/www/foswiki11/lib/Foswiki/UI/View.pm # once (4µs+0s) by Foswiki::LoginManager::ApacheLogin::new at line 43 of /var/www/foswiki11/lib/Foswiki/LoginManager/ApacheLogin.pm # once (4µs+0s) by Foswiki::UI::View::view at line 391 of /var/www/foswiki11/lib/Foswiki/UI/View.pm # once (3µs+0s) by Foswiki::Users::new at line 120 of /var/www/foswiki11/lib/Foswiki/Users.pm # once (2µs+0s) by Foswiki::Users::new at line 121 of /var/www/foswiki11/lib/Foswiki/Users.pm
sub enterContext {
32234232µs my ( $this, $id, $val ) = @_;
32244217µs $val ||= 1;
322542190µs $this->{context}->{$id} = $val;
3226}
3227
3228=begin TML
3229
3230---++ ObjectMethod leaveContext( $id )
3231
3232Remove the context id $id from the set of active contexts.
3233(see =enterContext= for more information on contexts)
3234
3235=cut
3236
3237
# spent 32µs within Foswiki::leaveContext which was called 4 times, avg 8µs/call: # once (12µs+0s) by Foswiki::UI::View::view at line 399 of /var/www/foswiki11/lib/Foswiki/UI/View.pm # once (9µs+0s) by Foswiki::UI::View::view at line 393 of /var/www/foswiki11/lib/Foswiki/UI/View.pm # once (6µs+0s) by Foswiki::UI::View::view at line 373 of /var/www/foswiki11/lib/Foswiki/UI/View.pm # once (5µs+0s) by Foswiki::LoginManager::new at line 165 of /var/www/foswiki11/lib/Foswiki/LoginManager.pm
sub leaveContext {
323846µs my ( $this, $id ) = @_;
323945µs my $res = $this->{context}->{$id};
324048µs delete $this->{context}->{$id};
3241423µs return $res;
3242}
3243
3244=begin TML
3245
3246---++ ObjectMethod inContext( $id )
3247
3248Return the value for the given context id
3249(see =enterContext= for more information on contexts)
3250
3251=cut
3252
3253
# spent 264µs within Foswiki::inContext which was called 97 times, avg 3µs/call: # 39 times (110µs+0s) by Foswiki::getScriptUrl at line 1437, avg 3µs/call # 33 times (75µs+0s) by Foswiki::getPubUrl at line 1520, avg 2µs/call # 8 times (30µs+0s) by Foswiki::If::OP_context::evaluate at line 36 of /var/www/foswiki11/lib/Foswiki/If/OP_context.pm, avg 4µs/call # 5 times (14µs+0s) by Foswiki::LoginManager::endRenderingHandler at line 890 of /var/www/foswiki11/lib/Foswiki/LoginManager.pm, avg 3µs/call # 4 times (12µs+0s) by Foswiki::Func::__ANON__[/var/www/foswiki11/lib/Foswiki/Func.pm:611] at line 598 of /var/www/foswiki11/lib/Foswiki/Func.pm, avg 3µs/call # 2 times (6µs+0s) by Foswiki::LoginManager::_LOGIN at line 1152 of /var/www/foswiki11/lib/Foswiki/LoginManager.pm, avg 3µs/call # once (6µs+0s) by Foswiki::LoginManager::checkAccess at line 589 of /var/www/foswiki11/lib/Foswiki/LoginManager.pm # once (3µs+0s) by Foswiki::LoginManager::makeLoginManager at line 91 of /var/www/foswiki11/lib/Foswiki/LoginManager.pm # once (3µs+0s) by Foswiki::generateHTTPHeaders at line 955 # once (2µs+0s) by Foswiki::LoginManager::userLoggedIn at line 699 of /var/www/foswiki11/lib/Foswiki/LoginManager.pm # once (2µs+0s) by Foswiki::LoginManager::loadSession at line 306 of /var/www/foswiki11/lib/Foswiki/LoginManager.pm # once (2µs+0s) by Foswiki::LoginManager::makeLoginManager at line 130 of /var/www/foswiki11/lib/Foswiki/LoginManager.pm
sub inContext {
32549757µs my ( $this, $id ) = @_;
325597413µs return $this->{context}->{$id};
3256}
3257
3258=begin TML
3259
3260---++ StaticMethod registerTagHandler( $tag, $fnref, $syntax )
3261
3262STATIC Add a tag handler to the function tag handlers.
3263 * =$tag= name of the tag e.g. MYTAG
3264 * =$fnref= Function to execute. Will be passed ($session, \%params, $web, $topic )
3265 * =$syntax= somewhat legacy - 'classic' or 'context-free' (context-free may be removed in future)
3266
3267
3268$syntax parameter:
3269Way back in prehistory, back when the dinosaur still roamed the earth,
3270Crawford tried to extend the tag syntax of macros such that they could be processed
3271by a context-free parser (hence the "context-free")
3272and bring them into line with HTML.
3273This work was banjaxed by one particular tyrranosaur,
3274who felt that the existing syntax was perfect.
3275However by that time Crawford had used it in a couple of places - most notable in the action tracker.
3276
3277The syntax isn't vastly different from what's there; the differences are:
3278 1 Use either type of quote for parameters
3279 2 Optional quotes on parameter values e.g. recurse=on
3280 3 Standardised use of \ for escapes
3281 4 Boolean (valueless) options (i.e. recurse instead of recurse="on"
3282
3283
3284=cut
3285
3286
# spent 185µs within Foswiki::registerTagHandler which was called 55 times, avg 3µs/call: # 44 times (162µs+0s) by Foswiki::Func::registerTagHandler at line 612 of /var/www/foswiki11/lib/Foswiki/Func.pm, avg 4µs/call # once (3µs+0s) by Foswiki::Plugins::new at line 74 of /var/www/foswiki11/lib/Foswiki/Plugins.pm # once (3µs+0s) by Foswiki::LoginManager::new at line 174 of /var/www/foswiki11/lib/Foswiki/LoginManager.pm # once (2µs+0s) by Foswiki::Plugins::new at line 76 of /var/www/foswiki11/lib/Foswiki/Plugins.pm # once (2µs+0s) by Foswiki::LoginManager::new at line 176 of /var/www/foswiki11/lib/Foswiki/LoginManager.pm # once (2µs+0s) by Foswiki::LoginManager::new at line 178 of /var/www/foswiki11/lib/Foswiki/LoginManager.pm # once (2µs+0s) by Foswiki::Plugins::new at line 78 of /var/www/foswiki11/lib/Foswiki/Plugins.pm # once (2µs+0s) by Foswiki::LoginManager::new at line 177 of /var/www/foswiki11/lib/Foswiki/LoginManager.pm # once (2µs+0s) by Foswiki::LoginManager::new at line 175 of /var/www/foswiki11/lib/Foswiki/LoginManager.pm # once (2µs+0s) by Foswiki::LoginManager::new at line 179 of /var/www/foswiki11/lib/Foswiki/LoginManager.pm # once (2µs+0s) by Foswiki::LoginManager::new at line 180 of /var/www/foswiki11/lib/Foswiki/LoginManager.pm # once (2µs+0s) by Foswiki::LoginManager::ApacheLogin::new at line 46 of /var/www/foswiki11/lib/Foswiki/LoginManager/ApacheLogin.pm
sub registerTagHandler {
32875537µs my ( $tag, $fnref, $syntax ) = @_;
32885578µs $macros{$tag} = $fnref;
328955165µs if ( $syntax && $syntax eq 'context-free' ) {
3290 $contextFreeSyntax{$tag} = 1;
3291 }
3292}
3293
3294=begin TML
3295
3296---++ ObjectMethod expandMacros( $text, $topicObject ) -> $text
3297
3298Processes %<nop>VARIABLE%, and %<nop>TOC% syntax; also includes
3299'commonTagsHandler' plugin hook.
3300
3301Returns the text of the topic, after file inclusion, variable substitution,
3302table-of-contents generation, and any plugin changes from commonTagsHandler.
3303
3304$topicObject may be undef when, for example, expanding templates, or one-off strings
3305at a time when meta isn't available.
3306
3307DO NOT CALL THIS DIRECTLY; use $topicObject->expandMacros instead.
3308
3309=cut
3310
3311
# spent 59.1s (638µs+59.1) within Foswiki::expandMacros which was called 7 times, avg 8.45s/call: # 7 times (638µs+59.1s) by Foswiki::Meta::expandMacros at line 3103 of /var/www/foswiki11/lib/Foswiki/Meta.pm, avg 8.45s/call
sub expandMacros {
3312716µs my ( $this, $text, $topicObject ) = @_;
3313
331472µs return '' unless defined $text;
3315
3316 # Plugin Hook (for cache Plugins only)
3317752µs21730µs $this->{plugins}
# spent 839µs making 7 calls to Foswiki::Plugins::dispatch, avg 120µs/call, recursion: max depth 1, sum of overlapping time 140µs # spent 17µs making 7 calls to Foswiki::Meta::topic, avg 2µs/call # spent 16µs making 7 calls to Foswiki::Meta::web, avg 2µs/call
3318 ->dispatch( 'beforeCommonTagsHandler', $text, $topicObject->topic,
3319 $topicObject->web, $topicObject );
3320
3321 #use a "global var", so included topics can extract and putback
3322 #their verbatim blocks safetly.
332375µs my $verbatim = {};
3324720µs7188µs $text = takeOutBlocks( $text, 'verbatim', $verbatim );
# spent 188µs making 7 calls to Foswiki::takeOutBlocks, avg 27µs/call
3325
3326 # take out dirty areas
332775µs my $dirtyAreas = {};
332879µs $text = takeOutBlocks( $text, 'dirtyarea', $dirtyAreas )
3329 if $Foswiki::cfg{Cache}{Enabled};
3330
3331 # Require defaults for plugin handlers :-(
3332718µs718µs my $webContext = $topicObject->web || $this->{webName};
# spent 18µs making 7 calls to Foswiki::Meta::web, avg 3µs/call
3333714µs719µs my $topicContext = $topicObject->topic || $this->{topicName};
# spent 19µs making 7 calls to Foswiki::Meta::topic, avg 3µs/call
3334
3335717µs721µs my $memW = $this->{prefs}->getPreference('INCLUDINGWEB');
# spent 21µs making 7 calls to Foswiki::Prefs::getPreference, avg 3µs/call
3336714µs716µs my $memT = $this->{prefs}->getPreference('INCLUDINGTOPIC');
# spent 16µs making 7 calls to Foswiki::Prefs::getPreference, avg 2µs/call
3337716µs778µs $this->{prefs}->setInternalPreferences(
# spent 78µs making 7 calls to Foswiki::Prefs::setInternalPreferences, avg 11µs/call
3338 INCLUDINGWEB => $webContext,
3339 INCLUDINGTOPIC => $topicContext
3340 );
3341
3342718µs759.1s $this->innerExpandMacros( \$text, $topicObject );
# spent 59.1s making 7 calls to Foswiki::innerExpandMacros, avg 8.44s/call
3343
3344719µs7185µs $text = takeOutBlocks( $text, 'verbatim', $verbatim );
# spent 185µs making 7 calls to Foswiki::takeOutBlocks, avg 26µs/call
3345
3346 # Plugin Hook
3347722µs77.43ms $this->{plugins}
# spent 7.84ms making 7 calls to Foswiki::Plugins::dispatch, avg 1.12ms/call, recursion: max depth 1, sum of overlapping time 417µs
3348 ->dispatch( 'commonTagsHandler', $text, $topicContext, $webContext, 0,
3349 $topicObject );
3350
3351 # process tags again because plugin hook may have added more in
3352719µs71.21ms $this->innerExpandMacros( \$text, $topicObject );
# spent 1.21ms making 7 calls to Foswiki::innerExpandMacros, avg 173µs/call
3353
3354718µs752µs $this->{prefs}->setInternalPreferences(
# spent 52µs making 7 calls to Foswiki::Prefs::setInternalPreferences, avg 7µs/call
3355 INCLUDINGWEB => $memW,
3356 INCLUDINGTOPIC => $memT
3357 );
3358
3359 # 'Special plugin tag' TOC hack, must be done after all other expansions
3360 # are complete, and has to reprocess the entire topic.
3361
3362760µs if ( $text =~ /%TOC(?:{.*})?%/ ) {
3363 require Foswiki::Macros::TOC;
3364 $text =~ s/%TOC(?:{(.*?)})?%/$this->TOC($text, $topicObject, $1)/ge;
3365 }
3366
3367 # Codev.FormattedSearchWithConditionalOutput: remove <nop> lines,
3368 # possibly introduced by SEARCHes with conditional CALC. This needs
3369 # to be done after CALC and before table rendering in order to join
3370 # table rows properly
3371754µs $text =~ s/^<nop>\r?\n//gm;
3372
3373 # restore dirty areas
337476µs putBackBlocks( \$text, $dirtyAreas, 'dirtyarea' )
3375 if $Foswiki::cfg{Cache}{Enabled};
3376
3377715µs730µs putBackBlocks( \$text, $verbatim, 'verbatim' );
# spent 30µs making 7 calls to Foswiki::putBackBlocks, avg 4µs/call
3378
3379 # Foswiki Plugin Hook (for cache Plugins only)
3380715µs7159µs $this->{plugins}
# spent 195µs making 7 calls to Foswiki::Plugins::dispatch, avg 28µs/call, recursion: max depth 1, sum of overlapping time 36µs
3381 ->dispatch( 'afterCommonTagsHandler', $text, $topicContext, $webContext,
3382 $topicObject );
3383
3384742µs return $text;
3385}
3386
3387=begin TML
3388
3389---++ ObjectMethod addToZone($zone, $id, $data, $requires)
3390
3391Add =$data= identified as =$id= to =$zone=, which will later be expanded (with
3392renderZone() - implements =%<nop>RENDERZONE%=). =$ids= are unique within
3393the zone that they are added - dependencies between =$ids= in different zones
3394will not be resolved, except for the special case of =head= and =script= zones
3395when ={MergeHeadAndScriptZones}= is enabled.
3396
3397In this case, they are treated as separate zones when adding to them, but as
3398one merged zone when rendering, i.e. a call to render either =head= or =script=
3399zones will actually render both zones in this one call. Both zones are undef'd
3400afterward to avoid double rendering of content from either zone, to support
3401proper behaviour when =head= and =script= are rendered with separate calls even
3402when ={MergeHeadAndScriptZones}= is set. See ZoneTests/explicit_RENDERZONE*.
3403
3404This behaviour allows an addToZone('head') call to require an id that has been
3405added to =script= only.
3406
3407 * =$zone= - name of the zone
3408 * =$id= - unique identifier
3409 * =$data= - content
3410 * =$requires= - optional, comma-separated string of =$id= identifiers
3411 that should precede the content
3412
3413<blockquote class="foswikiHelp">%X%
3414*Note:* Read the developer supplement at Foswiki:Development.AddToZoneFromPluginHandlers if you
3415are calling =addToZone()= from a rendering or macro/tag-related plugin handler
3416</blockquote>
3417
3418Implements =%<nop>ADDTOZONE%=.
3419
3420=cut
3421
3422
# spent 358µs within Foswiki::addToZone which was called 16 times, avg 22µs/call: # 12 times (234µs+0s) by Foswiki::Func::addToZone at line 2657 of /var/www/foswiki11/lib/Foswiki/Func.pm, avg 19µs/call # 4 times (124µs+0s) by Foswiki::ADDTOZONE at line 38 of /var/www/foswiki11/lib/Foswiki/Macros/ADDTOZONE.pm, avg 31µs/call
sub addToZone {
34231623µs my ( $this, $zone, $id, $data, $requires ) = @_;
3424
3425165µs $requires ||= '';
3426
3427 # get a random one
3428163µs unless ($id) {
3429 $id = int( rand(10000) ) + 1;
3430 }
3431
3432 # get zone, or create record
34331618µs my $thisZone = $this->{_zones}{$zone};
3434168µs unless ( defined $thisZone ) {
3435 $this->{_zones}{$zone} = $thisZone = {};
3436 }
3437
3438165µs my @requires;
34391684µs foreach my $req ( split( /\s*,\s*/, $requires ) ) {
34402335µs unless ( $thisZone->{$req} ) {
3441 $thisZone->{$req} = {
3442 id => $req,
3443 zone => $zone,
3444 requires => [],
3445 missingrequires => [],
3446 text => '',
3447 populated => 0
3448 };
3449 }
34502333µs push( @requires, $thisZone->{$req} );
3451 }
3452
3453 # store record within zone
34541610µs my $zoneID = $thisZone->{$id};
3455166µs unless ($zoneID) {
34561419µs $zoneID = { id => $id };
34571418µs $thisZone->{$id} = $zoneID;
3458 }
3459
3460 # override previous properties
34611611µs $zoneID->{zone} = $zone;
34621614µs $zoneID->{requires} = \@requires;
34631614µs $zoneID->{missingrequires} = [];
34641612µs $zoneID->{text} = $data;
3465168µs $zoneID->{populated} = 1;
3466
34671664µs return;
3468}
3469
3470sub _renderZoneById {
3471 my $this = shift;
3472 my $id = shift;
3473
3474 return '' unless defined $id;
3475
3476 my $renderZone = $this->{_renderZonePlaceholder}{$id};
3477
3478 return '' unless defined $renderZone;
3479
3480 my $params = $renderZone->{params};
3481 my $topicObject = $renderZone->{topicObject};
3482 my $zone = $params->{_DEFAULT} || $params->{zone};
3483
3484 return _renderZone( $this, $zone, $params, $topicObject );
3485}
3486
3487# This private function is used in ZoneTests
3488
# spent 20.8ms (556µs+20.3) within Foswiki::_renderZone which was called 2 times, avg 10.4ms/call: # once (337µs+17.7ms) by Foswiki::_renderZones at line 3661 # once (218µs+2.55ms) by Foswiki::_renderZones at line 3656
sub _renderZone {
348923µs my ( $this, $zone, $params, $topicObject ) = @_;
3490
3491 # Check the zone is defined and has not already been rendered
349224µs return '' unless $zone && $this->{_zones}{$zone};
3493
349423µs $params->{header} ||= '';
349522µs $params->{footer} ||= '';
34962800ns $params->{chomp} ||= 'off';
349722µs $params->{missingformat} = '$id: requires= missing ids: $missingids';
349822µs $params->{format} = '$item<!--<literal>$missing</literal>-->'
3499 unless defined $params->{format};
350022µs $params->{separator} = '$n()' unless defined $params->{separator};
3501
3502211µs254µs unless ( defined $topicObject ) {
# spent 54µs making 2 calls to Foswiki::Meta::new, avg 27µs/call
3503 $topicObject =
3504 Foswiki::Meta->new( $this, $this->{webName}, $this->{topicName} );
3505 }
3506
3507 # Loop through the vertices of the graph, in any order, initiating
3508 # a depth-first search for any vertex that has not already been
3509 # visited by a previous search. The desired topological sorting is
3510 # the reverse postorder of these searches. That is, we can construct
3511 # the ordering as a list of vertices, by adding each vertex to the
3512 # start of the list at the time when the depth-first search is
3513 # processing that vertex and has returned from processing all children
3514 # of that vertex. Since each edge and vertex is visited once, the
3515 # algorithm runs in linear time.
351622µs my %visited;
35172700ns my @total;
3518
3519 # When {MergeHeadAndScriptZones} is set, try to treat head and script
3520 # zones as merged for compatibility with ADDTOHEAD usage where requirements
3521 # have been moved to the script zone. See ZoneTests/Item9317
3522228µs if ( $Foswiki::cfg{MergeHeadAndScriptZones}
3523 and ( ( $zone eq 'head' ) or ( $zone eq 'script' ) ) )
3524 {
3525 my @zoneIDs = (
3526 values %{ $this->{_zones}{head} },
3527 values %{ $this->{_zones}{script} }
3528 );
3529
3530 foreach my $zoneID (@zoneIDs) {
3531 $this->_visitZoneID( $zoneID, \%visited, \@total );
3532 }
3533 undef $this->{_zones}{head};
3534 undef $this->{_zones}{script};
3535 }
3536 else {
3537219µs my @zoneIDs = values %{ $this->{_zones}{$zone} };
3538
353922µs foreach my $zoneID (@zoneIDs) {
35402045µs20302µs $this->_visitZoneID( $zoneID, \%visited, \@total );
# spent 302µs making 20 calls to Foswiki::_visitZoneID, avg 15µs/call
3541 }
3542
3543 # kill a zone once it has been rendered, to prevent it being
3544 # added twice (e.g. by duplicate %RENDERZONEs or by automatic
3545 # zone expansion in the head or script)
354624µs undef $this->{_zones}{$zone};
3547 }
3548
3549 # nothing rendered for a zone with no ADDTOZONE calls
355022µs return '' unless scalar(@total) > 0;
3551
355222µs my @result = ();
355322µs my $missingformat = $params->{missingformat};
355423µs foreach my $item (@total) {
35552015µs my $text = $item->{text};
35562015µs my @missingids = @{ $item->{missingrequires} };
35572016µs my $missingformat =
3558 ( scalar(@missingids) ) ? $params->{missingformat} : '';
3559
35602010µs if ( $params->{'chomp'} ) {
35612015µs $text =~ s/^\s+//g;
35622043µs $text =~ s/\s+$//g;
3563 }
3564
3565 # ASSERT($text, "No content for zone id $item->{id} in zone $zone")
3566 # if DEBUG;
3567
3568205µs next unless $text;
35691410µs my $id = $item->{id} || '';
3570145µs my $line = $params->{format};
3571149µs if ( scalar(@missingids) ) {
357226µs $line =~ s/\$missing\b/$missingformat/g;
3573210µs $line =~ s/\$missingids\b/join(', ', @missingids)/ge;
3574 }
3575 else {
35761228µs $line =~ s/\$missing\b/\$id/g;
3577 }
35781432µs $line =~ s/\$item\b/$text/g;
35791434µs $line =~ s/\$id\b/$id/g;
3580149µs $line =~ s/\$zone\b/$item->{zone}/g;
35811420µs push @result, $line if $line;
3582 }
3583219µs283µs my $result =
# spent 83µs making 2 calls to Foswiki::expandStandardEscapes, avg 42µs/call
3584 expandStandardEscapes( $params->{header}
3585 . join( $params->{separator}, @result )
3586 . $params->{footer} );
3587
3588 # delay rendering the zone until now
358926µs216.4ms $result = $topicObject->expandMacros($result);
# spent 16.4ms making 2 calls to Foswiki::Meta::expandMacros, avg 8.18ms/call
359024µs23.46ms $result = $topicObject->renderTML($result);
# spent 3.46ms making 2 calls to Foswiki::Meta::renderTML, avg 1.73ms/call
3591
3592269µs return $result;
3593}
3594
3595
# spent 302µs (302+0ns) within Foswiki::_visitZoneID which was called 43 times, avg 7µs/call: # 23 times (124µs+-124µs) by Foswiki::_visitZoneID at line 3628, avg 0s/call # 20 times (178µs+124µs) by Foswiki::_renderZone at line 3540, avg 15µs/call
sub _visitZoneID {
35964324µs my ( $this, $zoneID, $visited, $list ) = @_;
3597
35984383µs return if $visited->{$zoneID};
3599
36002030µs $visited->{$zoneID} = 1;
3601
36022035µs foreach my $requiredZoneID ( @{ $zoneID->{requires} } ) {
3603233µs my $zoneIDToVisit;
3604
36052311µs if ( $Foswiki::cfg{MergeHeadAndScriptZones}
3606 and not $requiredZoneID->{populated} )
3607 {
3608
3609 # Compatibility mode, where we are trying to treat head and script
3610 # zones as merged, and a required ZoneID isn't populated. Try
3611 # opposite zone to see if it exists there instead. Item9317
3612 if ( $requiredZoneID->{zone} eq 'head' ) {
3613 $zoneIDToVisit =
3614 $this->{_zones}{script}{ $requiredZoneID->{id} };
3615 }
3616 else {
3617 $zoneIDToVisit = $this->{_zones}{head}{ $requiredZoneID->{id} };
3618 }
3619 if ( not $zoneIDToVisit->{populated} ) {
3620
3621 # Oops, the required ZoneID doesn't exist there either; reset
3622 $zoneIDToVisit = $requiredZoneID;
3623 }
3624 }
3625 else {
3626237µs $zoneIDToVisit = $requiredZoneID;
3627 }
36282341µs230s $this->_visitZoneID( $zoneIDToVisit, $visited, $list );
# spent 163µs making 23 calls to Foswiki::_visitZoneID, avg 7µs/call, recursion: max depth 3, sum of overlapping time 163µs
3629
36302332µs if ( not $zoneIDToVisit->{populated} ) {
3631
3632 # Finally, we got to here and the required ZoneID just cannot be
3633 # found in either head or script (or other) zones, so record it for
3634 # diagnostic purposes ($missingids format token)
3635 push( @{ $zoneID->{missingrequires} }, $zoneIDToVisit->{id} );
3636 }
3637 }
3638209µs push( @{$list}, $zoneID );
3639
36402049µs return;
3641}
3642
3643# This private function is used in ZoneTests
3644
# spent 21.0ms (177µs+20.8) within Foswiki::_renderZones which was called: # once (177µs+20.8ms) by Foswiki::writeCompletePage at line 814
sub _renderZones {
3645119µs my ( $this, $text ) = @_;
3646
3647 # Render zones that were pulled out by Foswiki/Macros/RENDERZONE.pm
3648 # NOTE: once a zone has been rendered it is cleared, so cannot
3649 # be rendered again.
3650
3651127µs $text =~ s/${RENDERZONE_MARKER}RENDERZONE{(.*?)}${RENDERZONE_MARKER}/
3652 _renderZoneById($this, $1)/geo;
3653
3654 # get the head zone and insert it at the end of the </head>
3655 # *if it has not already been rendered*
3656110µs12.77ms my $headZone = _renderZone( $this, 'head', { chomp => "on" } );
# spent 2.77ms making 1 call to Foswiki::_renderZone
3657136µs $text =~ s!(</head>)!$headZone\n$1!i if $headZone;
3658
3659 # SMELL: Item9480 - can't trust that _renderzone(head) above has truly
3660 # flushed both script and head zones empty when {MergeHeadAndScriptZones} = 1.
366116µs118.1ms my $scriptZone = _renderZone( $this, 'script', { chomp => "on" } );
# spent 18.1ms making 1 call to Foswiki::_renderZone
3662153µs $text =~ s!(</head>)!$scriptZone\n$1!i if $scriptZone;
3663
366411µs chomp($text);
3665
3666121µs return $text;
3667}
3668
3669=begin TML
3670
3671---++ StaticMethod readFile( $filename ) -> $text
3672
3673Returns the entire contents of the given file, which can be specified in any
3674format acceptable to the Perl open() function. Fast, but inherently unsafe.
3675
3676WARNING: Never, ever use this for accessing topics or attachments! Use the
3677Store API for that. This is for global control files only, and should be
3678used *only* if there is *absolutely no alternative*.
3679
3680=cut
3681
3682sub readFile {
3683 my $name = shift;
3684 my $IN_FILE;
3685 open( $IN_FILE, "<$name" ) || return '';
3686 local $/ = undef;
3687 my $data = <$IN_FILE>;
3688 close($IN_FILE);
3689 $data = '' unless ( defined($data) );
3690 return $data;
3691}
3692
3693=begin TML
3694
3695---++ StaticMethod expandStandardEscapes($str) -> $unescapedStr
3696
3697Expands standard escapes used in parameter values to block evaluation. See
3698System.FormatTokens for a full list of supported tokens.
3699
3700=cut
3701
3702
# spent 1.06ms within Foswiki::expandStandardEscapes which was called 96 times, avg 11µs/call: # 40 times (508µs+0s) by Foswiki::Search::searchWeb at line 457 of /var/www/foswiki11/lib/Foswiki/Search.pm, avg 13µs/call # 21 times (136µs+0s) by Foswiki::__ANON__[/var/www/foswiki11/lib/Foswiki/Macros/IF.pm:43] at line 41 of /var/www/foswiki11/lib/Foswiki/Macros/IF.pm, avg 6µs/call # 20 times (215µs+0s) by Foswiki::__ANON__[/var/www/foswiki11/lib/Foswiki/Macros/IF.pm:43] at line 37 of /var/www/foswiki11/lib/Foswiki/Macros/IF.pm, avg 11µs/call # 9 times (76µs+0s) by Foswiki::USERINFO at line 126 of /var/www/foswiki11/lib/Foswiki/Macros/USERINFO.pm, avg 8µs/call # 3 times (37µs+0s) by Foswiki::Render::renderRevisionInfo at line 1737 of /var/www/foswiki11/lib/Foswiki/Render.pm, avg 12µs/call # 2 times (83µs+0s) by Foswiki::_renderZone at line 3583, avg 42µs/call # once (5µs+0s) by Foswiki::META at line 19 of /var/www/foswiki11/lib/Foswiki/Macros/META.pm
sub expandStandardEscapes {
37039663µs my $text = shift;
3704
3705 # expand '$n()' and $n! to new line
370696104µs $text =~ s/\$n\(\)/\n/gs;
370796180µs $text =~ s/\$n(?=[^$regex{mixedAlpha}]|$)/\n/gos;
3708
3709 # filler, useful for nested search
37109650µs $text =~ s/\$nop(\(\))?//gs;
3711
3712 # $quot -> "
37139689µs $text =~ s/\$quot(\(\))?/\"/gs;
3714
3715 # $comma -> ,
37169635µs $text =~ s/\$comma(\(\))?/,/gs;
3717
3718 # $percent -> %
37199675µs $text =~ s/\$perce?nt(\(\))?/\%/gs;
3720
3721 # $lt -> <
37229687µs $text =~ s/\$lt(\(\))?/\</gs;
3723
3724 # $gt -> >
37259635µs $text =~ s/\$gt(\(\))?/\>/gs;
3726
3727 # $amp -> &
37289633µs $text =~ s/\$amp(\(\))?/\&/gs;
3729
3730 # $dollar -> $, done last to avoid creating the above tokens
37319635µs $text =~ s/\$dollar(\(\))?/\$/gs;
3732
373396312µs return $text;
3734}
3735
3736=begin TML
3737
3738---++ ObjectMethod webExists( $web ) -> $boolean
3739
3740Test if web exists
3741 * =$web= - Web name, required, e.g. ='Sandbox'=
3742
3743A web _has_ to have a preferences topic to be a web.
3744
3745=cut
3746
3747
# spent 14.4ms (1.68+12.7) within Foswiki::webExists which was called 177 times, avg 81µs/call: # 95 times (982µs+9.03ms) by Foswiki::WebFilter::ok at line 36 of /var/www/foswiki11/lib/Foswiki/WebFilter.pm, avg 105µs/call # 41 times (453µs+1.99ms) by Foswiki::Store::QueryAlgorithms::BruteForce::query at line 63 of /var/www/foswiki11/lib/Foswiki/Store/QueryAlgorithms/BruteForce.pm, avg 59µs/call # 40 times (229µs+1.61ms) by Foswiki::Store::SearchAlgorithms::Forking::query at line 168 of /var/www/foswiki11/lib/Foswiki/Store/SearchAlgorithms/Forking.pm, avg 46µs/call # once (17µs+56µs) by Foswiki::UI::checkWebExists at line 488 of /var/www/foswiki11/lib/Foswiki/UI.pm
sub webExists {
3748177184µs my ( $this, $web ) = @_;
3749
3750177217µs177185µs ASSERT( UNTAINTED($web), 'web is tainted' ) if DEBUG;
# spent 185µs making 177 calls to Assert::ASSERTS_OFF, avg 1µs/call
37511771.02ms17712.5ms return $this->{store}->webExists($web);
# spent 12.5ms making 177 calls to Foswiki::Store::VC::Store::webExists, avg 71µs/call
3752}
3753
3754=begin TML
3755
3756---++ ObjectMethod topicExists( $web, $topic ) -> $boolean
3757
3758Test if topic exists
3759 * =$web= - Web name, optional, e.g. ='Main'=
3760 * =$topic= - Topic name, required, e.g. ='TokyoOffice'=, or ="Main.TokyoOffice"=
3761
3762=cut
3763
3764
# spent 3.15s (598ms+2.55) within Foswiki::topicExists which was called 46261 times, avg 68µs/call: # 46125 times (597ms+2.54s) by Foswiki::Search::InfoCache::__ANON__[/var/www/foswiki11/lib/Foswiki/Search/InfoCache.pm:579] at line 577 of /var/www/foswiki11/lib/Foswiki/Search/InfoCache.pm, avg 68µs/call # 98 times (1.06ms+5.18ms) by Foswiki::Templates::_readTemplateFile at line 462 of /var/www/foswiki11/lib/Foswiki/Templates.pm, avg 64µs/call # 17 times (195µs+1.35ms) by Foswiki::Render::_renderWikiWord at line 613 of /var/www/foswiki11/lib/Foswiki/Render.pm, avg 91µs/call # 7 times (74µs+484µs) by Foswiki::If::OP_istopic::evaluate at line 34 of /var/www/foswiki11/lib/Foswiki/If/OP_istopic.pm, avg 80µs/call # 7 times (78µs+438µs) by Foswiki::Plugin::topicWeb at line 374 of /var/www/foswiki11/lib/Foswiki/Plugin.pm, avg 74µs/call # 3 times (35µs+162µs) by Foswiki::Users::TopicUserMapping::eachGroupMember at line 698 of /var/www/foswiki11/lib/Foswiki/Users/TopicUserMapping.pm, avg 66µs/call # once (15µs+142µs) by Foswiki::_lookupIcon at line 31 of /var/www/foswiki11/lib/Foswiki/Macros/ICON.pm # once (16µs+89µs) by Foswiki::Users::TopicUserMapping::_loadMapping at line 1676 of /var/www/foswiki11/lib/Foswiki/Users/TopicUserMapping.pm # once (12µs+66µs) by Foswiki::Func::topicExists at line 1565 of /var/www/foswiki11/lib/Foswiki/Func.pm # once (9µs+42µs) by Foswiki::UI::View::view at line 121 of /var/www/foswiki11/lib/Foswiki/UI/View.pm
sub topicExists {
37654626129.8ms my ( $this, $web, $topic ) = @_;
37664626142.2ms4626140.5ms ASSERT( UNTAINTED($web), 'web is tainted' ) if DEBUG;
# spent 40.5ms making 46261 calls to Assert::ASSERTS_OFF, avg 876ns/call
37674626144.9ms4626135.3ms ASSERT( UNTAINTED($topic), 'topic is tainted' ) if DEBUG;
# spent 35.3ms making 46261 calls to Assert::ASSERTS_OFF, avg 762ns/call
376846261214ms462612.47s return $this->{store}->topicExists( $web, $topic );
# spent 2.47s making 46261 calls to Foswiki::Store::VC::Store::topicExists, avg 53µs/call
3769}
3770
3771=begin TML
3772
3773---+++ ObjectMethod getWorkArea( $key ) -> $directorypath
3774
3775Gets a private directory uniquely identified by $key. The directory is
3776intended as a work area for plugins etc. The directory will exist.
3777
3778=cut
3779
3780
# spent 111µs (25+86) within Foswiki::getWorkArea which was called: # once (25µs+86µs) by Foswiki::Func::getWorkArea at line 2745 of /var/www/foswiki11/lib/Foswiki/Func.pm
sub getWorkArea {
378111µs my ( $this, $key ) = @_;
3782122µs186µs return $this->{store}->getWorkArea($key);
# spent 86µs making 1 call to Foswiki::Store::getWorkArea
3783}
3784
3785=begin TML
3786
3787---++ ObjectMethod getApproxRevTime ( $web, $topic ) -> $epochSecs
3788
3789Get an approximate rev time for the latest rev of the topic. This method
3790is used to optimise searching. Needs to be as fast as possible.
3791
3792SMELL: is there a reason this is in Foswiki.pm, and not in Search?
3793
3794=cut
3795
3796sub getApproxRevTime {
3797 my ( $this, $web, $topic ) = @_;
3798
3799 my $metacache = $this->search->metacache;
3800 if ( $metacache->hasCached( $web, $topic ) ) {
3801
3802 #don't kill me - this should become a property on Meta
3803 return $metacache->get( $web, $topic )->{modified};
3804 }
3805
3806 return $this->{store}->getApproxRevTime( $web, $topic );
3807}
3808
380919µs1;
3810__END__
 
# spent 2µs within Foswiki::__ANON__ which was called 2 times, avg 1µs/call: # once (1µs+0s) by Foswiki::BEGIN@137 at line 398 # once (900ns+0s) by Foswiki::BEGIN@137 at line 399
sub Foswiki::__ANON__; # xsub