← Index
NYTProf Performance Profile   « block view • line view • sub view »
For /usr/local/src/github.com/foswiki/core/bin/view
  Run on Sun Dec 4 17:17:59 2011
Reported on Sun Dec 4 17:26:34 2011

Filename/usr/local/src/github.com/foswiki/core/lib/Foswiki/Func.pm
StatementsExecuted 109127 statements in 639ms
Subroutines
Calls P F Exclusive
Time
Inclusive
Time
Subroutine
1216411255ms4.28sFoswiki::Func::::eachGroupMemberFoswiki::Func::eachGroupMember
1225577207ms745msFoswiki::Func::::normalizeWebTopicNameFoswiki::Func::normalizeWebTopicName
1216732107ms194msFoswiki::Func::::isTrueFoswiki::Func::isTrue
10993135.9ms87.2msFoswiki::Func::::_checkWTAFoswiki::Func::_checkWTA
10943230.4ms1.25sFoswiki::Func::::expandCommonVariablesFoswiki::Func::expandCommonVariables
10962118.2ms105msFoswiki::Func::::_validateWTAFoswiki::Func::_validateWTA
11884413.1ms17.2msFoswiki::Func::::getContextFoswiki::Func::getContext
6632.60ms3.38msFoswiki::Func::::registerRESTHandlerFoswiki::Func::registerRESTHandler
262661.01ms1.51msFoswiki::Func::::registerTagHandlerFoswiki::Func::registerTagHandler
221510520µs2.49msFoswiki::Func::::getPreferencesValueFoswiki::Func::getPreferencesValue
1464281µs1.08msFoswiki::Func::::addToZoneFoswiki::Func::addToZone
311205µs176sFoswiki::Func::::__ANON__[:573]Foswiki::Func::__ANON__[:573]
222197µs20.3sFoswiki::Func::::readTopicTextFoswiki::Func::readTopicText
1811184µs5.18msFoswiki::Func::::__ANON__[:1252]Foswiki::Func::__ANON__[:1252]
1111170µs211µsFoswiki::Func::::getRequestObjectFoswiki::Func::getRequestObject
211136µs3.16sFoswiki::Func::::readTopicFoswiki::Func::readTopic
2611129µs129µsFoswiki::Func::::CORE:matchFoswiki::Func::CORE:match (opcode)
1176129µs340µsFoswiki::Func::::getCgiQueryFoswiki::Func::getCgiQuery
322126µs1.21msFoswiki::Func::::getScriptUrlFoswiki::Func::getScriptUrl
421123µs204µsFoswiki::Func::::getWikiNameFoswiki::Func::getWikiName
11195µs60.8sFoswiki::Func::::checkAccessPermissionFoswiki::Func::checkAccessPermission
33285µs924µsFoswiki::Func::::extractParametersFoswiki::Func::extractParameters
33184µs1.08msFoswiki::Func::::expandTemplateFoswiki::Func::expandTemplate
63174µs103µsFoswiki::Func::::getCanonicalUserIDFoswiki::Func::getCanonicalUserID
44271µs447µsFoswiki::Func::::getPreferencesFlagFoswiki::Func::getPreferencesFlag
11166µs430msFoswiki::Func::::loadTemplateFoswiki::Func::loadTemplate
21164µs681µsFoswiki::Func::::topicExistsFoswiki::Func::topicExists
72142µs42µsFoswiki::Func::::CORE:substFoswiki::Func::CORE:subst (opcode)
11141µs197µsFoswiki::Func::::getPluginPreferencesValueFoswiki::Func::getPluginPreferencesValue
11128µs57µsFoswiki::Func::::isAnAdminFoswiki::Func::isAnAdmin
33326µs26µsFoswiki::Func::::getPubUrlPathFoswiki::Func::getPubUrlPath
11124µs31µsFoswiki::Func::::BEGIN@55Foswiki::Func::BEGIN@55
11121µs62µsFoswiki::Func::::BEGIN@60Foswiki::Func::BEGIN@60
11118µs21µsFoswiki::Func::::getUrlHostFoswiki::Func::getUrlHost
11117µs68µsFoswiki::Func::::addToHEADFoswiki::Func::addToHEAD
11116µs378µsFoswiki::Func::::BEGIN@59Foswiki::Func::BEGIN@59
11116µs34µsFoswiki::Func::::BEGIN@56Foswiki::Func::BEGIN@56
11110µs10µsFoswiki::Func::::BEGIN@62Foswiki::Func::BEGIN@62
11110µs10µsFoswiki::Func::::BEGIN@57Foswiki::Func::BEGIN@57
1119µs9µsFoswiki::Func::::BEGIN@65Foswiki::Func::BEGIN@65
1119µs9µsFoswiki::Func::::BEGIN@64Foswiki::Func::BEGIN@64
1118µs8µsFoswiki::Func::::BEGIN@66Foswiki::Func::BEGIN@66
1118µs8µsFoswiki::Func::::BEGIN@63Foswiki::Func::BEGIN@63
0000s0sFoswiki::Func::::__ANON__[:1150]Foswiki::Func::__ANON__[:1150]
0000s0sFoswiki::Func::::__ANON__[:1702]Foswiki::Func::__ANON__[:1702]
0000s0sFoswiki::Func::::__ANON__[:1705]Foswiki::Func::__ANON__[:1705]
0000s0sFoswiki::Func::::__ANON__[:2317]Foswiki::Func::__ANON__[:2317]
0000s0sFoswiki::Func::::__ANON__[:3533]Foswiki::Func::__ANON__[:3533]
0000s0sFoswiki::Func::::__ANON__[:3541]Foswiki::Func::__ANON__[:3541]
0000s0sFoswiki::Func::::__ANON__[:668]Foswiki::Func::__ANON__[:668]
0000s0sFoswiki::Func::::addUserToGroupFoswiki::Func::addUserToGroup
0000s0sFoswiki::Func::::attachmentExistsFoswiki::Func::attachmentExists
0000s0sFoswiki::Func::::checkDependenciesFoswiki::Func::checkDependencies
0000s0sFoswiki::Func::::checkTopicEditLockFoswiki::Func::checkTopicEditLock
0000s0sFoswiki::Func::::clearSessionValueFoswiki::Func::clearSessionValue
0000s0sFoswiki::Func::::copyAttachmentFoswiki::Func::copyAttachment
0000s0sFoswiki::Func::::createWebFoswiki::Func::createWeb
0000s0sFoswiki::Func::::decodeFormatTokensFoswiki::Func::decodeFormatTokens
0000s0sFoswiki::Func::::eachChangeSinceFoswiki::Func::eachChangeSince
0000s0sFoswiki::Func::::eachEventSinceFoswiki::Func::eachEventSince
0000s0sFoswiki::Func::::eachGroupFoswiki::Func::eachGroup
0000s0sFoswiki::Func::::eachMembershipFoswiki::Func::eachMembership
0000s0sFoswiki::Func::::eachUserFoswiki::Func::eachUser
0000s0sFoswiki::Func::::emailToWikiNamesFoswiki::Func::emailToWikiNames
0000s0sFoswiki::Func::::expandVariablesOnTopicCreationFoswiki::Func::expandVariablesOnTopicCreation
0000s0sFoswiki::Func::::extractNameValuePairFoswiki::Func::extractNameValuePair
0000s0sFoswiki::Func::::formatGmTimeFoswiki::Func::formatGmTime
0000s0sFoswiki::Func::::formatTimeFoswiki::Func::formatTime
0000s0sFoswiki::Func::::getAttachmentListFoswiki::Func::getAttachmentList
0000s0sFoswiki::Func::::getDataDirFoswiki::Func::getDataDir
0000s0sFoswiki::Func::::getDefaultUserNameFoswiki::Func::getDefaultUserName
0000s0sFoswiki::Func::::getExternalResourceFoswiki::Func::getExternalResource
0000s0sFoswiki::Func::::getListOfWebsFoswiki::Func::getListOfWebs
0000s0sFoswiki::Func::::getMainWebnameFoswiki::Func::getMainWebname
0000s0sFoswiki::Func::::getOopsUrlFoswiki::Func::getOopsUrl
0000s0sFoswiki::Func::::getPluginPreferencesFlagFoswiki::Func::getPluginPreferencesFlag
0000s0sFoswiki::Func::::getPubDirFoswiki::Func::getPubDir
0000s0sFoswiki::Func::::getPublicWebListFoswiki::Func::getPublicWebList
0000s0sFoswiki::Func::::getRegularExpressionFoswiki::Func::getRegularExpression
0000s0sFoswiki::Func::::getRevisionAtTimeFoswiki::Func::getRevisionAtTime
0000s0sFoswiki::Func::::getRevisionInfoFoswiki::Func::getRevisionInfo
0000s0sFoswiki::Func::::getScriptUrlPathFoswiki::Func::getScriptUrlPath
0000s0sFoswiki::Func::::getSessionKeysFoswiki::Func::getSessionKeys
0000s0sFoswiki::Func::::getSessionValueFoswiki::Func::getSessionValue
0000s0sFoswiki::Func::::getSkinFoswiki::Func::getSkin
0000s0sFoswiki::Func::::getTopicListFoswiki::Func::getTopicList
0000s0sFoswiki::Func::::getTwikiWebnameFoswiki::Func::getTwikiWebname
0000s0sFoswiki::Func::::getViewUrlFoswiki::Func::getViewUrl
0000s0sFoswiki::Func::::getWikiToolNameFoswiki::Func::getWikiToolName
0000s0sFoswiki::Func::::getWikiUserNameFoswiki::Func::getWikiUserName
0000s0sFoswiki::Func::::getWorkAreaFoswiki::Func::getWorkArea
0000s0sFoswiki::Func::::internalLinkFoswiki::Func::internalLink
0000s0sFoswiki::Func::::isGroupFoswiki::Func::isGroup
0000s0sFoswiki::Func::::isGroupMemberFoswiki::Func::isGroupMember
0000s0sFoswiki::Func::::isGuestFoswiki::Func::isGuest
0000s0sFoswiki::Func::::isValidTopicNameFoswiki::Func::isValidTopicName
0000s0sFoswiki::Func::::isValidWebNameFoswiki::Func::isValidWebName
0000s0sFoswiki::Func::::isValidWikiWordFoswiki::Func::isValidWikiWord
0000s0sFoswiki::Func::::moveAttachmentFoswiki::Func::moveAttachment
0000s0sFoswiki::Func::::moveTopicFoswiki::Func::moveTopic
0000s0sFoswiki::Func::::moveWebFoswiki::Func::moveWeb
0000s0sFoswiki::Func::::permissionsSetFoswiki::Func::permissionsSet
0000s0sFoswiki::Func::::popTopicContextFoswiki::Func::popTopicContext
0000s0sFoswiki::Func::::pushTopicContextFoswiki::Func::pushTopicContext
0000s0sFoswiki::Func::::queryFoswiki::Func::query
0000s0sFoswiki::Func::::readAttachmentFoswiki::Func::readAttachment
0000s0sFoswiki::Func::::readFileFoswiki::Func::readFile
0000s0sFoswiki::Func::::readTemplateFoswiki::Func::readTemplate
0000s0sFoswiki::Func::::redirectCgiQueryFoswiki::Func::redirectCgiQuery
0000s0sFoswiki::Func::::registerMETAFoswiki::Func::registerMETA
0000s0sFoswiki::Func::::removeUserFromGroupFoswiki::Func::removeUserFromGroup
0000s0sFoswiki::Func::::renderTextFoswiki::Func::renderText
0000s0sFoswiki::Func::::sanitizeAttachmentNameFoswiki::Func::sanitizeAttachmentName
0000s0sFoswiki::Func::::saveAttachmentFoswiki::Func::saveAttachment
0000s0sFoswiki::Func::::saveFileFoswiki::Func::saveFile
0000s0sFoswiki::Func::::saveTopicFoswiki::Func::saveTopic
0000s0sFoswiki::Func::::saveTopicTextFoswiki::Func::saveTopicText
0000s0sFoswiki::Func::::searchInWebContentFoswiki::Func::searchInWebContent
0000s0sFoswiki::Func::::sendEmailFoswiki::Func::sendEmail
0000s0sFoswiki::Func::::setPreferencesValueFoswiki::Func::setPreferencesValue
0000s0sFoswiki::Func::::setSessionValueFoswiki::Func::setSessionValue
0000s0sFoswiki::Func::::setTopicEditLockFoswiki::Func::setTopicEditLock
0000s0sFoswiki::Func::::spaceOutWikiWordFoswiki::Func::spaceOutWikiWord
0000s0sFoswiki::Func::::summariseChangesFoswiki::Func::summariseChanges
0000s0sFoswiki::Func::::userToWikiNameFoswiki::Func::userToWikiName
0000s0sFoswiki::Func::::webExistsFoswiki::Func::webExists
0000s0sFoswiki::Func::::wikiToEmailFoswiki::Func::wikiToEmail
0000s0sFoswiki::Func::::wikiToUserNameFoswiki::Func::wikiToUserName
0000s0sFoswiki::Func::::wikinameToEmailsFoswiki::Func::wikinameToEmails
0000s0sFoswiki::Func::::writeDebugFoswiki::Func::writeDebug
0000s0sFoswiki::Func::::writeEventFoswiki::Func::writeEvent
0000s0sFoswiki::Func::::writeHeaderFoswiki::Func::writeHeader
0000s0sFoswiki::Func::::writeWarningFoswiki::Func::writeWarning
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
2
3=begin TML
4
5---+ package Foswiki::Func
6
7_Interface for Foswiki extensions developers_
8
9This module defines the main interfaces that extensions
10can use to interact with the Foswiki engine and content.
11
12Refer to =lib/Foswiki/Plugins/EmptyPlugin.pm= for a template Plugin
13and starter documentation on how to write a Plugin.
14
15Plugins should *only* call methods in packages documented in
16System.DevelopingPlugins. If you use
17functions in other Foswiki libraries you risk creating a security hole, and
18you will probably need to change your plugin when you upgrade Foswiki.
19
20API version $Date$ (revision $Rev$)
21
22*Since:* _date_ indicates where functions or parameters have been added since
23the baseline of the API (Foswiki 1.0.0). The _date_ indicates the
24earliest date of a Foswiki release that will support that function or
25parameter. See Foswiki:Download.ReleaseDates for version release dates.
26
27*Deprecated* _date_ indicates where a function or parameters has been
28[[http://en.wikipedia.org/wiki/Deprecation][deprecated]]. Deprecated
29functions will still work, though they should
30_not_ be called in new plugins and should be replaced in older plugins
31as soon as possible. Deprecated parameters are simply ignored in Foswiki
32releases after _date_.
33
34*Until* _date_ indicates where a function or parameter has been removed.
35The _date_ indicates the latest date at which Foswiki releases still supported
36the function or parameter.
37
38Note that the =Foswiki::Func= API should always be the first place extension
39authors look for methods. Certain other lower-level APIs are also exposed
40by the core, but those APIs should only be called if there is no alternative
41available through =Foswiki::Func=. The APIs in question are documented in
42System.DevelopingPlugins.
43
44=cut
45
46# THIS PACKAGE IS PART OF THE PUBLISHED API USED BY EXTENSION AUTHORS.
47# DO NOT CHANGE THE EXISTING APIS (well thought out extensions are OK)
48# AND ENSURE ALL POD DOCUMENTATION IS COMPLETE AND ACCURATE.
49#
50# Deprecated functions should not be removed, but should be moved to to the
51# deprecated functions section.
52
53package Foswiki::Func;
54
55245µs239µs
# spent 31µs (24+8) within Foswiki::Func::BEGIN@55 which was called: # once (24µs+8µs) by Foswiki::Users::TopicUserMapping::BEGIN@36 at line 55
use strict;
# spent 31µs making 1 call to Foswiki::Func::BEGIN@55 # spent 8µs making 1 call to strict::import
56242µs252µs
# spent 34µs (16+18) within Foswiki::Func::BEGIN@56 which was called: # once (16µs+18µs) by Foswiki::Users::TopicUserMapping::BEGIN@36 at line 56
use warnings;
# spent 34µs making 1 call to Foswiki::Func::BEGIN@56 # spent 18µs making 1 call to warnings::import
57242µs110µs
# spent 10µs within Foswiki::Func::BEGIN@57 which was called: # once (10µs+0s) by Foswiki::Users::TopicUserMapping::BEGIN@36 at line 57
use Scalar::Util ();
# spent 10µs making 1 call to Foswiki::Func::BEGIN@57
58
59254µs2739µs
# spent 378µs (16+362) within Foswiki::Func::BEGIN@59 which was called: # once (16µs+362µs) by Foswiki::Users::TopicUserMapping::BEGIN@36 at line 59
use Error qw( :try );
# spent 378µs making 1 call to Foswiki::Func::BEGIN@59 # spent 362µs making 1 call to Error::import
60249µs2103µs
# spent 62µs (21+41) within Foswiki::Func::BEGIN@60 which was called: # once (21µs+41µs) by Foswiki::Users::TopicUserMapping::BEGIN@36 at line 60
use Assert;
# spent 62µs making 1 call to Foswiki::Func::BEGIN@60 # spent 41µs making 1 call to Assert::import
61
62239µs110µs
# spent 10µs within Foswiki::Func::BEGIN@62 which was called: # once (10µs+0s) by Foswiki::Users::TopicUserMapping::BEGIN@36 at line 62
use Foswiki ();
# spent 10µs making 1 call to Foswiki::Func::BEGIN@62
63243µs18µs
# spent 8µs within Foswiki::Func::BEGIN@63 which was called: # once (8µs+0s) by Foswiki::Users::TopicUserMapping::BEGIN@36 at line 63
use Foswiki::Plugins ();
# spent 8µs making 1 call to Foswiki::Func::BEGIN@63
64237µs19µs
# spent 9µs within Foswiki::Func::BEGIN@64 which was called: # once (9µs+0s) by Foswiki::Users::TopicUserMapping::BEGIN@36 at line 64
use Foswiki::Meta ();
# spent 9µs making 1 call to Foswiki::Func::BEGIN@64
65236µs19µs
# spent 9µs within Foswiki::Func::BEGIN@65 which was called: # once (9µs+0s) by Foswiki::Users::TopicUserMapping::BEGIN@36 at line 65
use Foswiki::AccessControlException ();
# spent 9µs making 1 call to Foswiki::Func::BEGIN@65
66214.4ms18µs
# spent 8µs within Foswiki::Func::BEGIN@66 which was called: # once (8µs+0s) by Foswiki::Users::TopicUserMapping::BEGIN@36 at line 66
use Foswiki::Sandbox ();
# spent 8µs making 1 call to Foswiki::Func::BEGIN@66
67
68# Given $web, $web and $topic, or $web $topic and $attachment, validate
69# and untaint each of them and return. If any fails to validate it will
70# be returned as undef.
71
# spent 87.2ms (35.9+51.2) within Foswiki::Func::_checkWTA which was called 1099 times, avg 79µs/call: # 1096 times (35.8ms+51.1ms) by Foswiki::Func::_validateWTA at line 102, avg 79µs/call # 2 times (95µs+94µs) by Foswiki::Func::topicExists at line 1500, avg 95µs/call # once (45µs+54µs) by Foswiki::Func::checkAccessPermission at line 1346
sub _checkWTA {
72879239.1ms my ( $web, $topic, $attachment ) = @_;
73 if ( defined $topic ) {
7410993.39ms ASSERT($Foswiki::Plugins::SESSION) if DEBUG;
# spent 3.39ms making 1099 calls to Assert::ASSERTS_OFF, avg 3µs/call
75109943.0ms ( $web, $topic ) =
# spent 43.0ms making 1099 calls to Foswiki::normalizeWebTopicName, avg 39µs/call
76 $Foswiki::Plugins::SESSION->normalizeWebTopicName( $web, $topic );
77 }
7810992.90ms if ( Scalar::Util::tainted($web) ) {
# spent 2.90ms making 1099 calls to Scalar::Util::tainted, avg 3µs/call
79 $web = Foswiki::Sandbox::untaint( $web,
80 \&Foswiki::Sandbox::validateWebName );
81 }
82 return ($web) unless defined $web && defined $topic;
83
8410991.95ms if ( Scalar::Util::tainted($topic) ) {
# spent 1.95ms making 1099 calls to Scalar::Util::tainted, avg 2µs/call
85 $topic = Foswiki::Sandbox::untaint( $topic,
86 \&Foswiki::Sandbox::validateTopicName );
87 }
88 return ( $web, $topic ) unless defined $topic && defined $attachment;
89
90 if ( Scalar::Util::tainted($attachment) ) {
91 $attachment = Foswiki::Sandbox::untaint( $attachment,
92 \&Foswiki::Sandbox::validateAttachmentName );
93 }
94 return ( $web, $topic, $attachment );
95
96}
97
98# Validate a web.topic.attachment and throw an exception if the
99# validation fails
100
# spent 105ms (18.2+86.9) within Foswiki::Func::_validateWTA which was called 1096 times, avg 96µs/call: # 1094 times (18.1ms+86.7ms) by Foswiki::Func::expandCommonVariables at line 2468, avg 96µs/call # 2 times (45µs+168µs) by Foswiki::Func::readTopic at line 1528, avg 106µs/call
sub _validateWTA {
101657618.0ms my ( $web, $topic, $attachment ) = @_;
102109686.9ms my ( $w, $t, $a ) = _checkWTA( $web, $topic, $attachment );
# spent 86.9ms making 1096 calls to Foswiki::Func::_checkWTA, avg 79µs/call
103 die 'Invalid web' if ( defined $web && !defined $w );
104 die 'Invalid topic' if ( defined $topic && !defined $t );
105 die 'Invalid attachment' if ( defined $attachment && !defined $a );
106 return ( $w, $t, $a );
107}
108
109=begin TML
110
111---++ Environment
112
113=cut
114
115=begin TML
116
117---+++ getSkin( ) -> $skin
118
119Get the skin path, set by the =SKIN= and =COVER= preferences variables or the =skin= and =cover= CGI parameters
120
121Return: =$skin= Comma-separated list of skins, e.g. ='gnu,tartan'=. Empty string if none.
122
123=cut
124
125sub getSkin {
126 ASSERT($Foswiki::Plugins::SESSION) if DEBUG;
127
128 return $Foswiki::Plugins::SESSION->getSkin();
129}
130
131=begin TML
132
133---+++ getUrlHost( ) -> $host
134
135Get protocol, domain and optional port of script URL
136
137Return: =$host= URL host, e.g. ="http://example.com:80"=
138
139=cut
140
141
# spent 21µs (18+3) within Foswiki::Func::getUrlHost which was called: # once (18µs+3µs) by Foswiki::Plugins::RenderListPlugin::initPlugin at line 67 of /usr/local/src/github.com/foswiki/core/lib/Foswiki/Plugins/RenderListPlugin.pm
sub getUrlHost {
142215µs13µs ASSERT($Foswiki::Plugins::SESSION) if DEBUG;
# spent 3µs making 1 call to Assert::ASSERTS_OFF
143
144 return $Foswiki::Plugins::SESSION->{urlHost};
145}
146
147=begin TML
148
149---+++ getScriptUrl( $web, $topic, $script, ... ) -> $url
150
151Compose fully qualified URL
152 * =$web= - Web name, e.g. ='Main'=
153 * =$topic= - Topic name, e.g. ='WebNotify'=
154 * =$script= - Script name, e.g. ='view'=
155 * =...= - 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>
156
157Return: =$url= URL, e.g. ="http://example.com:80/cgi-bin/view.pl/Main/WebNotify"=
158
159=cut
160
161
# spent 1.21ms (126µs+1.09) within Foswiki::Func::getScriptUrl which was called 3 times, avg 404µs/call: # 2 times (86µs+895µs) by Foswiki::Plugins::SubscribePlugin::_SUBSCRIBE at line 86 of /usr/local/src/github.com/foswiki/core/lib/Foswiki/Plugins/SubscribePlugin.pm, avg 491µs/call # once (40µs+190µs) by Foswiki::Plugins::CommentPlugin::Comment::prompt at line 87 of /usr/local/src/github.com/foswiki/core/lib/Foswiki/Plugins/CommentPlugin/Comment.pm
sub getScriptUrl {
16215102µs my $web = shift;
163 my $topic = shift;
164 my $script = shift;
165315µs ASSERT($Foswiki::Plugins::SESSION) if DEBUG;
# spent 15µs making 3 calls to Assert::ASSERTS_OFF, avg 5µs/call
166
16731.07ms return $Foswiki::Plugins::SESSION->getScriptUrl( 1, $script, $web, $topic,
# spent 1.07ms making 3 calls to Foswiki::getScriptUrl, avg 357µs/call
168 @_ );
169}
170
171=begin TML
172
173---+++ getViewUrl( $web, $topic ) -> $url
174
175Compose fully qualified view URL
176 * =$web= - Web name, e.g. ='Main'=. The current web is taken if empty
177 * =$topic= - Topic name, e.g. ='WebNotify'=
178Return: =$url= URL, e.g. ="http://example.com:80/cgi-bin/view.pl/Main/WebNotify"=
179
180=cut
181
182sub getViewUrl {
183 my ( $web, $topic ) = @_;
184 ASSERT($Foswiki::Plugins::SESSION) if DEBUG;
185
186 $web ||= $Foswiki::Plugins::SESSION->{webName}
187 || $Foswiki::cfg{UsersWebName};
188 return getScriptUrl( $web, $topic, 'view' );
189}
190
191=begin TML
192
193---+++ getPubUrlPath( ) -> $path
194
195Get pub URL path
196
197Return: =$path= URL path of pub directory, e.g. ="/pub"=
198
199=cut
200
201
# spent 26µs within Foswiki::Func::getPubUrlPath which was called 3 times, avg 9µs/call: # once (12µs+0s) by Foswiki::Plugins::SmiliesPlugin::initPlugin at line 54 of /usr/local/src/github.com/foswiki/core/lib/Foswiki/Plugins/SmiliesPlugin.pm # once (8µs+0s) by Foswiki::Plugins::TablePlugin::BEGIN@1 at line 42 of /usr/local/src/github.com/foswiki/core/lib/Foswiki/Plugins/TablePlugin/Core.pm # once (6µs+0s) by Foswiki::Plugins::RenderListPlugin::initPlugin at line 67 of /usr/local/src/github.com/foswiki/core/lib/Foswiki/Plugins/RenderListPlugin.pm
sub getPubUrlPath {
202333µs return $Foswiki::cfg{PubUrlPath};
203}
204
205=begin TML
206
207---+++ getExternalResource( $url ) -> $response
208
209Get whatever is at the other end of a URL (using an HTTP GET request). Will
210only work for encrypted protocols such as =https= if the =LWP= CPAN module is
211installed.
212
213Note that the =$url= may have an optional user and password, as specified by
214the relevant RFC. Any proxy set in =configure= is honoured.
215
216The =$response= is an object that is known to implement the following subset of
217the methods of =LWP::Response=. It may in fact be an =LWP::Response= object,
218but it may also not be if =LWP= is not available, so callers may only assume
219the following subset of methods is available:
220| =code()= |
221| =message()= |
222| =header($field)= |
223| =content()= |
224| =is_error()= |
225| =is_redirect()= |
226
227Note that if LWP is *not* available, this function:
228 1 can only really be trusted for HTTP/1.0 urls. If HTTP/1.1 or another
229 protocol is required, you are *strongly* recommended to =require LWP=.
230 1 Will not parse multipart content
231
232In the event of the server returning an error, then =is_error()= will return
233true, =code()= will return a valid HTTP status code
234as specified in RFC 2616 and RFC 2518, and =message()= will return the
235message that was received from
236the server. In the event of a client-side error (e.g. an unparseable URL)
237then =is_error()= will return true and =message()= will return an explanatory
238message. =code()= will return 400 (BAD REQUEST).
239
240Note: Callers can easily check the availability of other HTTP::Response methods
241as follows:
242
243<verbatim>
244my $response = Foswiki::Func::getExternalResource($url);
245if (!$response->is_error() && $response->isa('HTTP::Response')) {
246 ... other methods of HTTP::Response may be called
247} else {
248 ... only the methods listed above may be called
249}
250</verbatim>
251
252=cut
253
254sub getExternalResource {
255 my ($url) = @_;
256 ASSERT($Foswiki::Plugins::SESSION) if DEBUG;
257 ASSERT( defined $url ) if DEBUG;
258
259 return $Foswiki::Plugins::SESSION->net->getExternalResource($url);
260}
261
262=begin TML
263
264---+++ getRequestObject( ) -> $query
265
266Get the request object. This is a subclass of =Foswiki::Request=. The request
267object can be used to get the parameters passed to the request, either
268via CGI or on the command ine (depending on how the script was called).
269
270A =Foswiki::Request= object is largely compatible with a CPAN:CGI object.
271Most of the time, documentation for that class applies directly to
272=Foswiki::Request= objects as well.
273
274Note that this method replaces =getCgiQuery= (which is a synonym for this
275method). Code that is expected to run with pre-1.1 versions of Foswiki
276can continue to call =getCgiQuery= for as long as necessary.
277
278*Since:* 31 Mar 2009
279
280=cut
281
282
# spent 211µs (170+41) within Foswiki::Func::getRequestObject which was called 11 times, avg 19µs/call: # 11 times (170µs+41µs) by Foswiki::Func::getCgiQuery at line 3415, avg 19µs/call
sub getRequestObject {
28322141µs1141µs ASSERT($Foswiki::Plugins::SESSION) if DEBUG;
# spent 41µs making 11 calls to Assert::ASSERTS_OFF, avg 4µs/call
284 return $Foswiki::Plugins::SESSION->{request};
285}
286
287=begin TML
288
289---+++ getSessionKeys() -> @keys
290Get a list of all the names of session variables. The list is unsorted.
291
292Session keys are stored and retrieved using =setSessionValue= and
293=getSessionValue=.
294
295=cut
296
297sub getSessionKeys {
298 ASSERT($Foswiki::Plugins::SESSION) if DEBUG;
299 my $hash =
300 $Foswiki::Plugins::SESSION->getLoginManager()->getSessionValues();
301 return keys %{$hash};
302}
303
304=begin TML
305
306---+++ getSessionValue( $key ) -> $value
307
308Get a session value from the client session module
309 * =$key= - Session key
310Return: =$value= Value associated with key; empty string if not set
311
312=cut
313
314sub getSessionValue {
315
316 # my( $key ) = @_;
317 ASSERT($Foswiki::Plugins::SESSION) if DEBUG;
318
319 return $Foswiki::Plugins::SESSION->getLoginManager()->getSessionValue(@_);
320}
321
322=begin TML
323
324---+++ setSessionValue( $key, $value ) -> $boolean
325
326Set a session value.
327 * =$key= - Session key
328 * =$value= - Value associated with key
329Return: true if function succeeded
330
331=cut
332
333sub setSessionValue {
334
335 # my( $key, $value ) = @_;
336 ASSERT($Foswiki::Plugins::SESSION) if DEBUG;
337
338 $Foswiki::Plugins::SESSION->getLoginManager()->setSessionValue(@_);
339}
340
341=begin TML
342
343---+++ clearSessionValue( $key ) -> $boolean
344
345Clear a session value that was set using =setSessionValue=.
346 * =$key= - name of value stored in session to be cleared. Note that
347 you *cannot* clear =AUTHUSER=.
348Return: true if the session value was cleared
349
350=cut
351
352sub clearSessionValue {
353 ASSERT($Foswiki::Plugins::SESSION) if DEBUG;
354
355 return $Foswiki::Plugins::SESSION->getLoginManager()->clearSessionValue(@_);
356}
357
358=begin TML
359
360---+++ getContext() -> \%hash
361
362Get a hash of context identifiers representing the currently active
363context.
364
365The context is a set of identifiers that are set
366during specific phases of processing. For example, each of
367the standard scripts in the 'bin' directory each has a context
368identifier - the view script has 'view', the edit script has 'edit'
369etc. So you can easily tell what 'type' of script your Plugin is
370being called within. The core context identifiers are listed
371in the %SYSTEMWEB%.IfStatements topic. Please be careful not to
372overwrite any of these identifiers!
373
374Context identifiers can be used to communicate between Plugins, and between
375Plugins and templates. For example, in FirstPlugin.pm, you might write:
376<verbatim>
377sub initPlugin {
378 Foswiki::Func::getContext()->{'MyID'} = 1;
379 ...
380</verbatim>
381This can be used in !SecondPlugin.pm like this:
382<verbatim>
383sub initPlugin {
384 if( Foswiki::Func::getContext()->{'MyID'} ) {
385 ...
386 }
387 ...
388</verbatim>
389or in a template, like this:
390<verbatim>
391%TMPL:DEF{"ON"}% Not off %TMPL:END%
392%TMPL:DEF{"OFF"}% Not on %TMPL:END%
393%TMPL:P{context="MyID" then="ON" else="OFF"}%
394</verbatim>
395or in a topic:
396<verbatim>
397%IF{"context MyID" then="MyID is ON" else="MyID is OFF"}%
398</verbatim>
399__Note__: *all* plugins have an *automatically generated* context identifier
400if they are installed and initialised. For example, if the FirstPlugin is
401working, the context ID 'FirstPlugin' will be set.
402
403=cut
404
405
# spent 17.2ms (13.1+4.15) within Foswiki::Func::getContext which was called 1188 times, avg 14µs/call: # 1131 times (12.2ms+3.91ms) by Foswiki::Plugins::WysiwygPlugin::beforeCommonTagsHandler at line 260 of /usr/local/src/github.com/foswiki/core/lib/Foswiki/Plugins/WysiwygPlugin.pm, avg 14µs/call # 55 times (864µs+232µs) by Foswiki::Plugins::JQueryPlugin::Plugins::registerPlugin at line 137 of /usr/local/src/github.com/foswiki/core/lib/Foswiki/Plugins/JQueryPlugin/Plugins.pm, avg 20µs/call # once (16µs+3µs) by Foswiki::Plugins::AutoViewTemplatePlugin::initPlugin at line 43 of /usr/local/src/github.com/foswiki/core/lib/Foswiki/Plugins/AutoViewTemplatePlugin.pm # once (10µs+3µs) by Foswiki::Plugins::CommentPlugin::_COMMENT at line 56 of /usr/local/src/github.com/foswiki/core/lib/Foswiki/Plugins/CommentPlugin.pm
sub getContext {
406237612.3ms11884.15ms ASSERT($Foswiki::Plugins::SESSION) if DEBUG;
# spent 4.15ms making 1188 calls to Assert::ASSERTS_OFF, avg 3µs/call
407 return $Foswiki::Plugins::SESSION->{context};
408}
409
410=begin TML
411
412---+++ pushTopicContext($web, $topic)
413 * =$web= - new web
414 * =$topic= - new topic
415Change the Foswiki context, adding the requested =$web.$topic= onto the
416preferences stack. Any preferences found in =$web.$topic= will be used
417in place of preferences previously set in the stack, provided that they
418were not finalized in a lower level. Preferences set in the prior
419=web.topic= are *not* cleared. =$web.$topic= replaces and adds to
420preferences but does not remove preferences that it does not set.
421
422Note that if the new topic is not readable by the logged in user due to
423access control considerations, there will *not* be an exception. It is the
424duty of the caller to check access permissions before changing the topic.
425All other errors will throw an exception.
426
427It is the duty of the caller to restore the original context by calling
428=popTopicContext=.
429
430Note that this call does *not* re-initialise plugins, so if you have used
431global variables to remember the web and topic in =initPlugin=, then those
432values will be unchanged.
433
434=cut
435
436sub pushTopicContext {
437 my $session = $Foswiki::Plugins::SESSION;
438 ASSERT($session) if DEBUG;
439 my ( $web, $topic ) = _validateWTA(@_);
440
441 $session->{prefs}->pushTopicContext( $web, $topic );
442 $session->{webName} = $web;
443 $session->{topicName} = $topic;
444 $session->{prefs}->setInternalPreferences(
445 BASEWEB => $web,
446 BASETOPIC => $topic,
447 INCLUDINGWEB => $web,
448 INCLUDINGTOPIC => $topic
449 );
450}
451
452=begin TML
453
454---+++ popTopicContext()
455
456Returns the Foswiki context to the state it was in before the
457=pushTopicContext= was called.
458
459=cut
460
461sub popTopicContext {
462 my $session = $Foswiki::Plugins::SESSION;
463 ASSERT($session) if DEBUG;
464 ( $session->{webName}, $session->{topicName} ) =
465 $session->{prefs}->popTopicContext();
466}
467
468=begin TML
469
470---++ Registering extensions
471
472Plugins work either by using handlers to manipulate the text being processed,
473or by registering extensions, such as new macros, scripts, or meta-data types.
474
475=cut
476
477=begin TML=
478
479---+++ registerTagHandler( $var, \&fn, $syntax )
480
481Should only be called from initPlugin.
482
483Register a function to handle a simple variable. Handles both %<nop>VAR% and
484%<nop>VAR{...}%. Registered variables are treated the same as internal macros,
485and are expanded at the same time. This is a _lot_ more efficient than using the =commonTagsHandler=.
486 * =$var= - The name of the variable, i.e. the 'MYVAR' part of %<nop>MYVAR%.
487 The variable name *must* match /^[A-Z][A-Z0-9_]*$/ or it won't work.
488 * =\&fn= - Reference to the handler function.
489 * =$syntax= can be 'classic' (the default) or 'context-free'. (context-free may be removed in future)
490 'classic' syntax is appropriate where you want the variable to support classic syntax
491 i.e. to accept the standard =%<nop>MYVAR{ "unnamed" param1="value1" param2="value2" }%= syntax,
492 as well as an unquoted default parameter, such as =%<nop>MYVAR{unquoted parameter}%=.
493 If your variable will only use named parameters, you can use 'context-free' syntax,
494 which supports a more relaxed syntax. For example,
495 %MYVAR{param1=value1, value 2, param3="value 3", param4='value 5"}%
496
497The variable handler function must be of the form:
498<verbatim>
499sub handler(\%session, \%params, $topic, $web, $topicObject)
500</verbatim>
501where:
502 * =\%session= - a reference to the session object (may be ignored)
503 * =\%params= - a reference to a Foswiki::Attrs object containing parameters. This can be used as a simple hash that maps parameter names to values, with _DEFAULT being the name for the default parameter.
504 * =$topic= - name of the topic in the query
505 * =$web= - name of the web in the query
506 * =$topicObject= - is the Foswiki::Meta object for the topic *Since* 2009-03-06
507for example, to execute an arbitrary command on the server, you might do this:
508<verbatim>
509sub initPlugin{
510 Foswiki::Func::registerTagHandler('EXEC', \&boo);
511}
512
513sub boo {
514 my( $session, $params, $topic, $web, $topicObject ) = @_;
515 my $cmd = $params->{_DEFAULT};
516
517 return "NO COMMAND SPECIFIED" unless $cmd;
518
519 my $result = `$cmd 2>&1`;
520 return $params->{silent} ? '' : $result;
521}
522</verbatim>
523would let you do this:
524=%<nop>EXEC{"ps -Af" silent="on"}%=
525
526Registered tags differ from tags implemented using the old approach (text substitution in =commonTagsHandler=) in the following ways:
527 * registered tags are evaluated at the same time as system tags, such as %SERVERTIME. =commonTagsHandler= is only called later, when all system tags have already been expanded (though they are expanded _again_ after =commonTagsHandler= returns).
528 * registered tag names can only contain alphanumerics and _ (underscore)
529 * registering a tag =FRED= defines both =%<nop>FRED{...}%= *and also* =%FRED%=.
530 * registered tag handlers *cannot* return another tag as their only result (e.g. =return '%<nop>SERVERTIME%';=). It won't work.
531
532=cut
533
534
# spent 1.51ms (1.01+498µs) within Foswiki::Func::registerTagHandler which was called 26 times, avg 58µs/call: # once (65µs+42µs) by Foswiki::Plugins::JQueryPlugin::initPlugin at line 43 of /usr/local/src/github.com/foswiki/core/lib/Foswiki/Plugins/JQueryPlugin.pm # once (62µs+25µs) by Foswiki::Plugins::CommentPlugin::initPlugin at line 30 of /usr/local/src/github.com/foswiki/core/lib/Foswiki/Plugins/CommentPlugin.pm # once (52µs+31µs) by Foswiki::Plugins::SubscribePlugin::initPlugin at line 22 of /usr/local/src/github.com/foswiki/core/lib/Foswiki/Plugins/SubscribePlugin.pm # once (52µs+29µs) by Foswiki::Plugins::JQueryPlugin::initPlugin at line 59 of /usr/local/src/github.com/foswiki/core/lib/Foswiki/Plugins/JQueryPlugin.pm # once (48µs+28µs) by Foswiki::Plugins::TwistyPlugin::initPlugin at line 50 of /usr/local/src/github.com/foswiki/core/lib/Foswiki/Plugins/TwistyPlugin.pm # once (57µs+17µs) by Foswiki::Plugins::JQueryPlugin::initPlugin at line 56 of /usr/local/src/github.com/foswiki/core/lib/Foswiki/Plugins/JQueryPlugin.pm # once (41µs+18µs) by Foswiki::Plugins::JQueryPlugin::initPlugin at line 44 of /usr/local/src/github.com/foswiki/core/lib/Foswiki/Plugins/JQueryPlugin.pm # once (39µs+18µs) by Foswiki::Plugins::JQueryPlugin::initPlugin at line 50 of /usr/local/src/github.com/foswiki/core/lib/Foswiki/Plugins/JQueryPlugin.pm # once (38µs+18µs) by Foswiki::Plugins::JQueryPlugin::initPlugin at line 47 of /usr/local/src/github.com/foswiki/core/lib/Foswiki/Plugins/JQueryPlugin.pm # once (38µs+18µs) by Foswiki::Plugins::JQueryPlugin::initPlugin at line 53 of /usr/local/src/github.com/foswiki/core/lib/Foswiki/Plugins/JQueryPlugin.pm # once (37µs+18µs) by Foswiki::Plugins::JQueryPlugin::initPlugin at line 51 of /usr/local/src/github.com/foswiki/core/lib/Foswiki/Plugins/JQueryPlugin.pm # once (37µs+18µs) by Foswiki::Plugins::JQueryPlugin::initPlugin at line 45 of /usr/local/src/github.com/foswiki/core/lib/Foswiki/Plugins/JQueryPlugin.pm # once (36µs+19µs) by Foswiki::Plugins::HistoryPlugin::initPlugin at line 29 of /usr/local/src/github.com/foswiki/core/lib/Foswiki/Plugins/HistoryPlugin.pm # once (37µs+18µs) by Foswiki::Plugins::JQueryPlugin::initPlugin at line 46 of /usr/local/src/github.com/foswiki/core/lib/Foswiki/Plugins/JQueryPlugin.pm # once (37µs+17µs) by Foswiki::Plugins::JQueryPlugin::initPlugin at line 52 of /usr/local/src/github.com/foswiki/core/lib/Foswiki/Plugins/JQueryPlugin.pm # once (32µs+17µs) by Foswiki::Plugins::WysiwygPlugin::initPlugin at line 57 of /usr/local/src/github.com/foswiki/core/lib/Foswiki/Plugins/WysiwygPlugin.pm # once (33µs+15µs) by Foswiki::Plugins::TwistyPlugin::initPlugin at line 51 of /usr/local/src/github.com/foswiki/core/lib/Foswiki/Plugins/TwistyPlugin.pm # once (31µs+16µs) by Foswiki::Plugins::TwistyPlugin::initPlugin at line 52 of /usr/local/src/github.com/foswiki/core/lib/Foswiki/Plugins/TwistyPlugin.pm # once (31µs+15µs) by Foswiki::Plugins::TwistyPlugin::initPlugin at line 54 of /usr/local/src/github.com/foswiki/core/lib/Foswiki/Plugins/TwistyPlugin.pm # once (31µs+15µs) by Foswiki::Plugins::WysiwygPlugin::initPlugin at line 59 of /usr/local/src/github.com/foswiki/core/lib/Foswiki/Plugins/WysiwygPlugin.pm # once (30µs+15µs) by Foswiki::Plugins::TwistyPlugin::initPlugin at line 53 of /usr/local/src/github.com/foswiki/core/lib/Foswiki/Plugins/TwistyPlugin.pm # once (31µs+14µs) by Foswiki::Plugins::WysiwygPlugin::initPlugin at line 61 of /usr/local/src/github.com/foswiki/core/lib/Foswiki/Plugins/WysiwygPlugin.pm # once (30µs+15µs) by Foswiki::Plugins::WysiwygPlugin::initPlugin at line 63 of /usr/local/src/github.com/foswiki/core/lib/Foswiki/Plugins/WysiwygPlugin.pm # once (30µs+14µs) by Foswiki::Plugins::TwistyPlugin::initPlugin at line 55 of /usr/local/src/github.com/foswiki/core/lib/Foswiki/Plugins/TwistyPlugin.pm # once (30µs+14µs) by Foswiki::Plugins::WysiwygPlugin::initPlugin at line 65 of /usr/local/src/github.com/foswiki/core/lib/Foswiki/Plugins/WysiwygPlugin.pm # once (30µs+14µs) by Foswiki::Plugins::TwistyPlugin::initPlugin at line 56 of /usr/local/src/github.com/foswiki/core/lib/Foswiki/Plugins/TwistyPlugin.pm
sub registerTagHandler {
5351561.10ms my ( $tag, $function, $syntax ) = @_;
5362697µs ASSERT($Foswiki::Plugins::SESSION) if DEBUG;
# spent 97µs making 26 calls to Assert::ASSERTS_OFF, avg 4µs/call
537
538 # $pluginContext is undefined if a contrib registers a tag handler.
539 my $pluginContext;
54026129µs if ( caller =~ m/^Foswiki::Plugins::(\w+)/ ) {
# spent 129µs making 26 calls to Foswiki::Func::CORE:match, avg 5µs/call
541 $pluginContext = $1 . 'Enabled';
542 }
543
544 # Use an anonymous function so it gets inlined at compile time.
545 # Make sure we don't mangle the session reference.
546 Foswiki::registerTagHandler(
547 $tag,
548
# spent 176s (205µs+176) within Foswiki::Func::__ANON__[/usr/local/src/github.com/foswiki/core/lib/Foswiki/Func.pm:573] which was called 3 times, avg 58.6s/call: # 3 times (205µs+176s) by Foswiki::_expandMacroOnTopicRendering at line 3066 of /usr/local/src/github.com/foswiki/core/lib/Foswiki.pm, avg 58.6s/call
sub {
54924178µs my ( $session, $params, $topicObject ) = @_;
550 my $record = $Foswiki::Plugins::SESSION;
551 $Foswiki::Plugins::SESSION = $_[0];
552
553 # $pluginContext is defined for all plugins
554 # but never defined for contribs.
555 # This is convenient, because contribs cannot be disabled
556 # at run-time, either.
557 if ( defined $pluginContext ) {
558
559 # Registered tag handlers should only be called if the plugin
560 # is enabled. Disabled plugins can still have tag handlers
561 # registered in persistent environments (e.g. modperl)
562 # and also for rest handlers that disable plugins.
563 # See Item1871
564326µs return unless $session->inContext($pluginContext);
# spent 26µs making 3 calls to Foswiki::inContext, avg 9µs/call
565 }
566
567 # Compatibility; expand $topicObject to the topic and web
5689176s my $result =
# spent 175s making 2 calls to Foswiki::Plugins::SubscribePlugin::_SUBSCRIBE, avg 87.7s/call # spent 442ms making 1 call to Foswiki::Plugins::CommentPlugin::_COMMENT # spent 26µs making 3 calls to Foswiki::Meta::topic, avg 9µs/call # spent 22µs making 3 calls to Foswiki::Meta::web, avg 7µs/call
569 &$function( $session, $params, $topicObject->topic,
570 $topicObject->web, $topicObject );
571 $Foswiki::Plugins::SESSION = $record;
572 return $result;
573 },
57426272µs $syntax
# spent 272µs making 26 calls to Foswiki::registerTagHandler, avg 10µs/call
575 );
576}
577
578=begin TML=
579
580---+++ registerRESTHandler( $alias, \&fn, %options )
581
582Should only be called from initPlugin.
583
584Adds a function to the dispatch table of the REST interface
585 * =$alias= - The name .
586 * =\&fn= - Reference to the function.
587 * =%options= - additional options affecting the handler
588The handler function must be of the form:
589<verbatim>
590sub handler(\%session)
591</verbatim>
592where:
593 * =\%session= - a reference to the Foswiki session object (may be ignored)
594
595From the REST interface, the name of the plugin must be used
596as the subject of the invokation.
597
598Additional options are set in the =%options= hash. These options are important
599to ensuring that requests to your handler can't be used in cross-scripting
600attacks, or used for phishing.
601 * =authenticate= - use this boolean option to require authentication for the
602 handler. If this is set, then an authenticated session must be in place
603 or the REST call will be rejected with a 401 (Unauthorized) status code.
604 By default, rest handlers do *not* require authentication.
605 * =validate= - use this boolean option to require validation of any requests
606 made to this handler. Validation is the process by which a secret key
607 is passed to the server so it can identify the origin of the request.
608 By default, requests made to REST handlers are not validated.
609 * =http_allow= use this option to specify that the HTTP methods that can
610 be used to invoke the handler. For example, =http_allow=>'POST,GET'= will
611 constrain the handler to be invoked using POST and GET, but not other
612 HTTP methods, such as DELETE. Normally you will use http_allow=>'POST'.
613 Together with authentication this is an important security tool.
614 Handlers that can be invoked using GET are vulnerable to being called
615 in the =src= parameter of =img= tags, a common method for cross-site
616 request forgery (CSRF) attacks. This option is set automatically if
617 =authenticate= is specified.
618
619---++++ Example
620
621The EmptyPlugin has the following call in the initPlugin handler:
622<verbatim>
623 Foswiki::Func::registerRESTHandler('example', \&restExample,
624 http_allow=>'GET,POST');
625</verbatim>
626
627This adds the =restExample= function to the REST dispatch table
628for the EmptyPlugin under the 'example' alias, and allows it
629to be invoked using the URL
630
631=http://server:port/bin/rest/EmptyPlugin/example=
632
633note that the URL
634
635=http://server:port/bin/rest/EmptyPlugin/restExample=
636
637(ie, with the name of the function instead of the alias) will not work.
638
639---++++ Calling REST handlers from the command-line
640The =rest= script allows handlers to be invoked from the command line. The
641script is invoked passing the parameters as described in CommandAndCGIScripts.
642If the handler requires authentication ( =authenticate=>1= ) then this can
643be passed in the username and =password= parameters.
644
645For example,
646
647=perl -wT rest /EmptyPlugin/example -username HughPugh -password trumpton=
648
649=cut
650
651
# spent 3.38ms (2.60+782µs) within Foswiki::Func::registerRESTHandler which was called 6 times, avg 563µs/call: # once (2.42ms+671µs) by Foswiki::Plugins::CommentPlugin::initPlugin at line 31 of /usr/local/src/github.com/foswiki/core/lib/Foswiki/Plugins/CommentPlugin.pm # once (41µs+30µs) by Foswiki::Plugins::WysiwygPlugin::initPlugin at line 68 of /usr/local/src/github.com/foswiki/core/lib/Foswiki/Plugins/WysiwygPlugin.pm # once (40µs+30µs) by Foswiki::Plugins::MailerContribPlugin::initPlugin at line 14 of /usr/local/src/github.com/foswiki/core/lib/Foswiki/Plugins/MailerContribPlugin.pm # once (33µs+17µs) by Foswiki::Plugins::WysiwygPlugin::initPlugin at line 72 of /usr/local/src/github.com/foswiki/core/lib/Foswiki/Plugins/WysiwygPlugin.pm # once (33µs+16µs) by Foswiki::Plugins::WysiwygPlugin::initPlugin at line 70 of /usr/local/src/github.com/foswiki/core/lib/Foswiki/Plugins/WysiwygPlugin.pm # once (28µs+17µs) by Foswiki::Plugins::WysiwygPlugin::initPlugin at line 74 of /usr/local/src/github.com/foswiki/core/lib/Foswiki/Plugins/WysiwygPlugin.pm
sub registerRESTHandler {
65236454µs my ( $alias, $function, %options ) = @_;
653621µs ASSERT($Foswiki::Plugins::SESSION) if DEBUG;
# spent 21µs making 6 calls to Assert::ASSERTS_OFF, avg 3µs/call
654 my $plugin = caller;
655635µs $plugin =~ s/.*:://; # strip off Foswiki::Plugins:: prefix
# spent 35µs making 6 calls to Foswiki::Func::CORE:subst, avg 6µs/call
656
657 # Use an anonymous function so it gets inlined at compile time.
658 # Make sure we don't mangle the session reference.
659 require Foswiki::UI::Rest;
660 Foswiki::UI::Rest::registerRESTHandler(
661 $plugin, $alias,
662 sub {
663 my $record = $Foswiki::Plugins::SESSION;
664 $Foswiki::Plugins::SESSION = $_[0];
665 my $result = &$function(@_);
666 $Foswiki::Plugins::SESSION = $record;
667 return $result;
668 },
669683µs %options
# spent 83µs making 6 calls to Foswiki::UI::Rest::registerRESTHandler, avg 14µs/call
670 );
671}
672
673=begin TML
674
675---+++ registerMETA($macro, $spec)
676Deprecated: please use Foswiki::Meta::registerMETA instead.
677
678=cut
679
680sub registerMETA {
681
682 #my ( $macro, %spec ) = @_;
683 Foswiki::Meta::registerMETA(@_);
684}
685
686=begin TML
687
688---++ Preferences
689
690=cut
691
692=begin TML
693
694---+++ getPreferencesValue( $key, $web ) -> $value
695
696Get a preferences value for the currently requested context, from the currently request topic, its web and the site.
697 * =$key= - Preference name
698 * =$web= - Name of web, optional. if defined, we shortcircuit to the WebPreferences (and its Sitewide defaults)
699Return: =$value= Preferences value; empty string if not set
700
701 * Example for preferences setting:
702 * WebPreferences topic has: =* Set WEBBGCOLOR = #FFFFC0=
703 * =my $webColor = Foswiki::Func::getPreferencesValue( 'WEBBGCOLOR', 'Sandbox' );=
704
705 * Example for MyPlugin setting:
706 * if the %SYSTEMWEB%.MyPlugin topic has: =* Set COLOR = red=
707 * Use ="MYPLUGIN_COLOR"= for =$key=
708 * =my $color = Foswiki::Func::getPreferencesValue( "MYPLUGIN_COLOR" );=
709
710*NOTE:* If =$NO_PREFS_IN_TOPIC= is enabled in the plugin, then
711preferences set in the plugin topic will be ignored.
712
713=cut
714
715
# spent 2.49ms (520µs+1.97) within Foswiki::Func::getPreferencesValue which was called 22 times, avg 113µs/call: # 5 times (144µs+382µs) by Foswiki::Plugins::TablePlugin::preRenderingHandler at line 56 of /usr/local/src/github.com/foswiki/core/lib/Foswiki/Plugins/TablePlugin.pm, avg 105µs/call # 4 times (80µs+260µs) by Foswiki::Func::getPreferencesFlag at line 779, avg 85µs/call # once (42µs+157µs) by Foswiki::Plugins::AutoViewTemplatePlugin::initPlugin at line 47 of /usr/local/src/github.com/foswiki/core/lib/Foswiki/Plugins/AutoViewTemplatePlugin.pm # once (26µs+164µs) by Foswiki::Plugins::JQueryPlugin::FOSWIKI::init at line 59 of /usr/local/src/github.com/foswiki/core/lib/Foswiki/Plugins/JQueryPlugin/FOSWIKI.pm # once (19µs+135µs) by Foswiki::Plugins::TablePlugin::_readPluginSettings at line 121 of /usr/local/src/github.com/foswiki/core/lib/Foswiki/Plugins/TablePlugin.pm # once (19µs+133µs) by Foswiki::Plugins::InterwikiPlugin::initPlugin at line 66 of /usr/local/src/github.com/foswiki/core/lib/Foswiki/Plugins/InterwikiPlugin.pm # once (22µs+116µs) by Foswiki::Plugins::TablePlugin::Core::handler at line 1867 of /usr/local/src/github.com/foswiki/core/lib/Foswiki/Plugins/TablePlugin/Core.pm # once (18µs+112µs) by Foswiki::Plugins::JQueryPlugin::FOSWIKI::init at line 73 of /usr/local/src/github.com/foswiki/core/lib/Foswiki/Plugins/JQueryPlugin/FOSWIKI.pm # once (26µs+101µs) by Foswiki::Plugins::TwistyPlugin::_exportAnimationSpeed at line 63 of /usr/local/src/github.com/foswiki/core/lib/Foswiki/Plugins/TwistyPlugin.pm # once (33µs+78µs) by Foswiki::Plugins::CommentPlugin::Comment::prompt at line 22 of /usr/local/src/github.com/foswiki/core/lib/Foswiki/Plugins/CommentPlugin/Comment.pm # once (19µs+83µs) by Foswiki::Plugins::InterwikiPlugin::initPlugin at line 62 of /usr/local/src/github.com/foswiki/core/lib/Foswiki/Plugins/InterwikiPlugin.pm # once (19µs+64µs) by Foswiki::Plugins::SmiliesPlugin::initPlugin at line 25 of /usr/local/src/github.com/foswiki/core/lib/Foswiki/Plugins/SmiliesPlugin.pm # once (18µs+63µs) by Foswiki::Plugins::CommentPlugin::Comment::prompt at line 36 of /usr/local/src/github.com/foswiki/core/lib/Foswiki/Plugins/CommentPlugin/Comment.pm # once (18µs+62µs) by Foswiki::Plugins::SmiliesPlugin::initPlugin at line 28 of /usr/local/src/github.com/foswiki/core/lib/Foswiki/Plugins/SmiliesPlugin.pm # once (17µs+61µs) by Foswiki::Plugins::SpreadSheetPlugin::initPlugin at line 55 of /usr/local/src/github.com/foswiki/core/lib/Foswiki/Plugins/SpreadSheetPlugin.pm
sub getPreferencesValue {
71688454µs my ( $key, $web ) = @_;
7172277µs ASSERT($Foswiki::Plugins::SESSION) if DEBUG;
# spent 77µs making 22 calls to Assert::ASSERTS_OFF, avg 3µs/call
718 if ($web) {
719 $web = _checkWTA($web);
720 return undef unless defined $web;
721
722 # Web preference
723 my $webObject = Foswiki::Meta->new( $Foswiki::Plugins::SESSION, $web );
724 return $webObject->getPreference($key);
725 }
726 else {
727
728 # Global preference
729221.89ms return $Foswiki::Plugins::SESSION->{prefs}->getPreference($key);
# spent 1.89ms making 22 calls to Foswiki::Prefs::getPreference, avg 86µs/call
730 }
731}
732
733=begin TML
734
735---+++ getPluginPreferencesValue( $key ) -> $value
736
737Get a preferences value from your Plugin
738 * =$key= - Plugin Preferences key w/o PLUGINNAME_ prefix.
739Return: =$value= Preferences value; empty string if not set
740
741__Note__: This function will will *only* work when called from the Plugin.pm file itself. it *will not work* if called from a sub-package (e.g. Foswiki::Plugins::MyPlugin::MyModule)
742
743*NOTE:* If =$NO_PREFS_IN_TOPIC= is enabled in the plugin, then
744preferences set in the plugin topic will be ignored.
745
746=cut
747
748
# spent 197µs (41+157) within Foswiki::Func::getPluginPreferencesValue which was called: # once (41µs+157µs) by Foswiki::Plugins::TwistyPlugin::_exportAnimationSpeed at line 63 of /usr/local/src/github.com/foswiki/core/lib/Foswiki/Plugins/TwistyPlugin.pm
sub getPluginPreferencesValue {
749547µs my ($key) = @_;
75015µs ASSERT($Foswiki::Plugins::SESSION) if DEBUG;
# spent 5µs making 1 call to Assert::ASSERTS_OFF
751 my $package = caller;
75218µs $package =~ s/.*:://; # strip off Foswiki::Plugins:: prefix
# spent 8µs making 1 call to Foswiki::Func::CORE:subst
7531144µs return $Foswiki::Plugins::SESSION->{prefs}
# spent 144µs making 1 call to Foswiki::Prefs::getPreference
754 ->getPreference("\U$package\E_$key");
755}
756
757=begin TML
758
759---+++ getPreferencesFlag( $key, $web ) -> $value
760
761Get a preferences flag from Foswiki or from a Plugin
762 * =$key= - Preferences key
763 * =$web= - Name of web, optional. Current web if not specified; does not apply to settings of Plugin topics
764Return: =$value= Preferences flag ='1'= (if set), or ="0"= (for preferences values ="off"=, ="no"= and ="0"=)
765
766 * Example for Plugin setting:
767 * MyPlugin topic has: =* Set SHOWHELP = off=
768 * Use ="MYPLUGIN_SHOWHELP"= for =$key=
769 * =my $showHelp = Foswiki::Func::getPreferencesFlag( "MYPLUGIN_SHOWHELP" );=
770
771*NOTE:* If =$NO_PREFS_IN_TOPIC= is enabled in the plugin, then
772preferences set in the plugin topic will be ignored.
773
774=cut
775
776
# spent 447µs (71+375) within Foswiki::Func::getPreferencesFlag which was called 4 times, avg 112µs/call: # once (29µs+104µs) by Foswiki::Plugins::SpreadSheetPlugin::initPlugin at line 35 of /usr/local/src/github.com/foswiki/core/lib/Foswiki/Plugins/SpreadSheetPlugin.pm # once (16µs+98µs) by Foswiki::Plugins::EditTablePlugin::initPlugin at line 52 of /usr/local/src/github.com/foswiki/core/lib/Foswiki/Plugins/EditTablePlugin.pm # once (14µs+87µs) by Foswiki::Plugins::EditTablePlugin::initPlugin at line 53 of /usr/local/src/github.com/foswiki/core/lib/Foswiki/Plugins/EditTablePlugin.pm # once (13µs+86µs) by Foswiki::Plugins::SpreadSheetPlugin::initPlugin at line 53 of /usr/local/src/github.com/foswiki/core/lib/Foswiki/Plugins/SpreadSheetPlugin.pm
sub getPreferencesFlag {
777
778 # my( $key, $web ) = @_;
779868µs4340µs my $t = getPreferencesValue(@_);
# spent 340µs making 4 calls to Foswiki::Func::getPreferencesValue, avg 85µs/call
780435µs return Foswiki::isTrue($t);
# spent 35µs making 4 calls to Foswiki::isTrue, avg 9µs/call
781}
782
783=begin TML
784
785---+++ getPluginPreferencesFlag( $key ) -> $boolean
786
787Get a preferences flag from your Plugin
788 * =$key= - Plugin Preferences key w/o PLUGINNAME_ prefix.
789Return: false for preferences values ="off"=, ="no"= and ="0"=, or values not set at all. True otherwise.
790
791__Note__: This function will will *only* work when called from the Plugin.pm file itself. it *will not work* if called from a sub-package (e.g. Foswiki::Plugins::MyPlugin::MyModule)
792
793*NOTE:* If =$NO_PREFS_IN_TOPIC= is enabled in the plugin, then
794preferences set in the plugin topic will be ignored.
795
796=cut
797
798sub getPluginPreferencesFlag {
799 my ($key) = @_;
800 my $package = caller;
801 $package =~ s/.*:://; # strip off Foswiki::Plugins:: prefix
802 return getPreferencesFlag("\U$package\E_$key");
803}
804
805=begin TML
806
807---+++ setPreferencesValue($name, $val)
808
809Set the preferences value so that future calls to getPreferencesValue will
810return this value, and =%$name%= will expand to the preference when used in
811future variable expansions.
812
813The preference only persists for the rest of this request. Finalised
814preferences cannot be redefined using this function.
815
816=cut
817
818sub setPreferencesValue {
819 my ( $name, $value ) = @_;
820 return $Foswiki::Plugins::SESSION->{prefs}
821 ->setSessionPreferences( $name => $value );
822}
823
824=begin TML
825
826---++ User Handling and Access Control
827---+++ getDefaultUserName( ) -> $loginName
828Get default user name as defined in the configuration as =DefaultUserLogin=
829
830Return: =$loginName= Default user name, e.g. ='guest'=
831
832=cut
833
834sub getDefaultUserName {
835 return $Foswiki::cfg{DefaultUserLogin};
836}
837
838=begin TML
839
840---+++ getCanonicalUserID( $user ) -> $cUID
841 * =$user= can be a login, wikiname or web.wikiname
842Return the cUID of the specified user. A cUID is a unique identifier which
843is assigned by Foswiki for each user.
844BEWARE: While the default TopicUserMapping uses a cUID that looks like a user's
845LoginName, some characters are modified to make them compatible with rcs.
846Other usermappings may use other conventions - the !JoomlaUserMapping
847for example, has cUIDs like 'JoomlaeUserMapping_1234'.
848
849If $user is undefined, it assumes the currently logged-in user.
850
851Return: =$cUID=, an internal unique and portable escaped identifier for
852registered users. This may be autogenerated for an authenticated but
853unregistered user.
854
855=cut
856
857
# spent 103µs (74+28) within Foswiki::Func::getCanonicalUserID which was called 6 times, avg 17µs/call: # 4 times (30µs+0s) by Foswiki::Func::getWikiName at line 893, avg 8µs/call # once (34µs+28µs) by Foswiki::Func::checkAccessPermission at line 1355 # once (10µs+0s) by Foswiki::Func::isAnAdmin at line 1085
sub getCanonicalUserID {
8581880µs my $user = shift;
859 return $Foswiki::Plugins::SESSION->{user} unless ($user);
86013µs ASSERT($Foswiki::Plugins::SESSION) if DEBUG;
# spent 3µs making 1 call to Assert::ASSERTS_OFF
861 my $cUID;
862 if ($user) {
863125µs $cUID = $Foswiki::Plugins::SESSION->{users}->getCanonicalUserID($user);
# spent 25µs making 1 call to Foswiki::Users::getCanonicalUserID
864 if ( !$cUID ) {
865
866 # Not a login name or a wiki name. Is it a valid cUID?
867 my $ln = $Foswiki::Plugins::SESSION->{users}->getLoginName($user);
868 $cUID = $user if defined $ln && $ln ne 'unknown';
869 }
870 }
871 else {
872 $cUID = $Foswiki::Plugins::SESSION->{user};
873 }
874 return $cUID;
875}
876
877=begin TML
878
879---+++ getWikiName( $user ) -> $wikiName
880
881return the WikiName of the specified user
882if $user is undefined Get Wiki name of logged in user
883
884 * $user can be a cUID, login, wikiname or web.wikiname
885
886Return: =$wikiName= Wiki Name, e.g. ='JohnDoe'=
887
888=cut
889
890
# spent 204µs (123+81) within Foswiki::Func::getWikiName which was called 4 times, avg 51µs/call: # 2 times (76µs+49µs) by Foswiki::Plugins::SubscribePlugin::_SUBSCRIBE at line 36 of /usr/local/src/github.com/foswiki/core/lib/Foswiki/Plugins/SubscribePlugin.pm, avg 62µs/call # 2 times (47µs+32µs) by Foswiki::Plugins::SubscribePlugin::_SUBSCRIBE at line 63 of /usr/local/src/github.com/foswiki/core/lib/Foswiki/Plugins/SubscribePlugin.pm, avg 40µs/call
sub getWikiName {
89120102µs my $user = shift;
892413µs ASSERT($Foswiki::Plugins::SESSION) if DEBUG;
# spent 13µs making 4 calls to Assert::ASSERTS_OFF, avg 3µs/call
893430µs my $cUID = getCanonicalUserID($user);
# spent 30µs making 4 calls to Foswiki::Func::getCanonicalUserID, avg 8µs/call
894 unless ( defined $cUID ) {
895 my ( $w, $u ) =
896 normalizeWebTopicName( $Foswiki::cfg{UsersWebName}, $user );
897 return $u;
898 }
899438µs return $Foswiki::Plugins::SESSION->{users}->getWikiName($cUID);
# spent 38µs making 4 calls to Foswiki::Users::getWikiName, avg 10µs/call
900}
901
902=begin TML
903
904---+++ getWikiUserName( $user ) -> $wikiName
905
906return the userWeb.WikiName of the specified user
907if $user is undefined Get Wiki name of logged in user
908
909 * $user can be a cUID, login, wikiname or web.wikiname
910
911Return: =$wikiName= Wiki Name, e.g. ="Main.JohnDoe"=
912
913=cut
914
915sub getWikiUserName {
916 my $user = shift;
917 ASSERT($Foswiki::Plugins::SESSION) if DEBUG;
918 my $cUID = getCanonicalUserID($user);
919 unless ( defined $cUID ) {
920 my ( $w, $u ) =
921 normalizeWebTopicName( $Foswiki::cfg{UsersWebName}, $user );
922 return "$w.$u";
923 }
924 return $Foswiki::Plugins::SESSION->{users}->webDotWikiName($cUID);
925}
926
927=begin TML
928
929---+++ wikiToUserName( $id ) -> $loginName
930Translate a Wiki name to a login name.
931 * =$id= - Wiki name, e.g. ='Main.JohnDoe'= or ='JohnDoe'=.
932 $id may also be a login name. This will normally
933 be transparent, but should be borne in mind if you have login names
934 that are also legal wiki names.
935
936Return: =$loginName= Login name of user, e.g. ='jdoe'=, or undef if not
937matched.
938
939Note that it is possible for several login names to map to the same wikiname.
940This function will only return the *first* login name that maps to the
941wikiname.
942
943returns undef if the WikiName is not found.
944
945=cut
946
947sub wikiToUserName {
948 my ($wiki) = @_;
949 ASSERT($Foswiki::Plugins::SESSION) if DEBUG;
950 return '' unless $wiki;
951
952 my $cUID = getCanonicalUserID($wiki);
953 if ($cUID) {
954 my $login = $Foswiki::Plugins::SESSION->{users}->getLoginName($cUID);
955 return if !$login || $login eq 'unknown';
956 return $login;
957 }
958 return;
959}
960
961=begin TML
962
963---+++ userToWikiName( $loginName, $dontAddWeb ) -> $wikiName
964Translate a login name to a Wiki name
965 * =$loginName= - Login name, e.g. ='jdoe'=. This may
966 also be a wiki name. This will normally be transparent, but may be
967 relevant if you have login names that are also valid wiki names.
968 * =$dontAddWeb= - Do not add web prefix if ="1"=
969Return: =$wikiName= Wiki name of user, e.g. ='Main.JohnDoe'= or ='JohnDoe'=
970
971userToWikiName will always return a name. If the user does not
972exist in the mapping, the $loginName parameter is returned. (backward compatibility)
973
974=cut
975
976sub userToWikiName {
977 my ( $login, $dontAddWeb ) = @_;
978 return '' unless $login;
979 ASSERT($Foswiki::Plugins::SESSION) if DEBUG;
980 my $users = $Foswiki::Plugins::SESSION->{users};
981 my $user = getCanonicalUserID($login);
982 return (
983 $dontAddWeb
984 ? $login
985 : ( $Foswiki::cfg{UsersWebName} . '.' . $login )
986 ) unless $user and $users->userExists($user);
987 return $users->getWikiName($user) if $dontAddWeb;
988 return $users->webDotWikiName($user);
989}
990
991=begin TML
992
993---+++ emailToWikiNames( $email, $dontAddWeb ) -> @wikiNames
994 * =$email= - email address to look up
995 * =$dontAddWeb= - Do not add web prefix if ="1"=
996Find the wikinames of all users who have the given email address as their
997registered address. Since several users could register with the same email
998address, this returns a list of wikinames rather than a single wikiname.
999
1000=cut
1001
1002sub emailToWikiNames {
1003 my ( $email, $dontAddWeb ) = @_;
1004 ASSERT($email) if DEBUG;
1005
1006 my %matches;
1007 my $users = $Foswiki::Plugins::SESSION->{users};
1008 my $ua = $users->findUserByEmail($email);
1009 if ($ua) {
1010 foreach my $user (@$ua) {
1011 if ($dontAddWeb) {
1012 $matches{ $users->getWikiName($user) } = 1;
1013 }
1014 else {
1015 $matches{ $users->webDotWikiName($user) } = 1;
1016 }
1017 }
1018 }
1019
1020 return sort keys %matches;
1021}
1022
1023=begin TML
1024
1025---+++ wikinameToEmails( $user ) -> @emails
1026 * =$user= - wikiname of user to look up
1027Returns the registered email addresses of the named user. If $user is
1028undef, returns the registered email addresses for the logged-in user.
1029
1030$user may also be a group.
1031
1032=cut
1033
1034sub wikinameToEmails {
1035 my ($wikiname) = @_;
1036 if ($wikiname) {
1037 if ( isGroup($wikiname) ) {
1038 return $Foswiki::Plugins::SESSION->{users}->getEmails($wikiname);
1039 }
1040 else {
1041 my $uids =
1042 $Foswiki::Plugins::SESSION->{users}
1043 ->findUserByWikiName($wikiname);
1044 my @em = ();
1045 foreach my $user (@$uids) {
1046 push( @em,
1047 $Foswiki::Plugins::SESSION->{users}->getEmails($user) );
1048 }
1049 return @em;
1050 }
1051 }
1052 else {
1053 my $user = $Foswiki::Plugins::SESSION->{user};
1054 return $Foswiki::Plugins::SESSION->{users}->getEmails($user);
1055 }
1056}
1057
1058=begin TML
1059
1060---+++ isGuest( ) -> $boolean
1061
1062Test if logged in user is a guest (WikiGuest)
1063
1064=cut
1065
1066sub isGuest {
1067 ASSERT($Foswiki::Plugins::SESSION) if DEBUG;
1068 return $Foswiki::Plugins::SESSION->{user} eq
1069 $Foswiki::Plugins::SESSION->{users}
1070 ->getCanonicalUserID( $Foswiki::cfg{DefaultUserLogin} );
1071}
1072
1073=begin TML
1074
1075---+++ isAnAdmin( $id ) -> $boolean
1076
1077Find out if the user is an admin or not. If the user is not given,
1078the currently logged-in user is assumed.
1079 * $id can be either a login name or a WikiName
1080
1081=cut
1082
1083
# spent 57µs (28+28) within Foswiki::Func::isAnAdmin which was called: # once (28µs+28µs) by Foswiki::Plugins::UpdatesPlugin::initPlugin at line 31 of /usr/local/src/github.com/foswiki/core/lib/Foswiki/Plugins/UpdatesPlugin.pm
sub isAnAdmin {
1084230µs my $user = shift;
1085228µs return $Foswiki::Plugins::SESSION->{users}
# spent 18µs making 1 call to Foswiki::Users::isAdmin # spent 10µs making 1 call to Foswiki::Func::getCanonicalUserID
1086 ->isAdmin( getCanonicalUserID($user) );
1087}
1088
1089=begin TML
1090
1091---+++ isGroupMember( $group, $id, $options ) -> $boolean
1092
1093Find out if $id is in the named group. The expand option controls whether or not nested groups are searched.
1094
1095e.g. Is jordi in the HesperionXXGroup, and not in a nested group. e.g.
1096<verbatim>
1097if( Foswiki::Func::isGroupMember( "HesperionXXGroup", "jordi", { expand => 0 } )) {
1098 ...
1099}
1100</verbatim>
1101If =$user= is =undef=, it defaults to the currently logged-in user.
1102
1103 * $id can be a login name or a WikiName
1104 * Nested groups are expanded unless $options{ expand => } is set to false.
1105
1106=cut
1107
1108sub isGroupMember {
1109 my ( $group, $user, $options ) = @_;
1110 my $users = $Foswiki::Plugins::SESSION->{users};
1111
1112 my $expand = Foswiki::Func::isTrue( $options->{expand}, 1 );
1113
1114 return () unless $users->isGroup($group);
1115 if ($user) {
1116
1117 #my $login = wikiToUserName( $user );
1118 #return 0 unless $login;
1119 $user = getCanonicalUserID($user) || $user;
1120 }
1121 else {
1122 $user = $Foswiki::Plugins::SESSION->{user};
1123 }
1124 return $users->isInGroup( $user, $group, { expand => $expand } );
1125}
1126
1127=begin TML
1128
1129---+++ eachUser() -> $iterator
1130Get an iterator over the list of all the registered users *not* including
1131groups. The iterator will return each wiki name in turn (e.g. 'FredBloggs').
1132
1133Use it as follows:
1134<verbatim>
1135 my $iterator = Foswiki::Func::eachUser();
1136 while ($it->hasNext()) {
1137 my $user = $it->next();
1138 # $user is a wikiname
1139 }
1140</verbatim>
1141
1142*WARNING* on large sites, this could be a long list!
1143
1144=cut
1145
1146sub eachUser {
1147 my $it = $Foswiki::Plugins::SESSION->{users}->eachUser();
1148 $it->{process} = sub {
1149 return $Foswiki::Plugins::SESSION->{users}->getWikiName( $_[0] );
1150 };
1151 return $it;
1152}
1153
1154=begin TML
1155
1156---+++ eachMembership($id) -> $iterator
1157 * =$id= - WikiName or login name of the user.
1158 If =$id= is =undef=, defaults to the currently logged-in user.
1159Get an iterator over the names of all groups that the user is a member of.
1160
1161=cut
1162
1163sub eachMembership {
1164 my ($user) = @_;
1165 my $users = $Foswiki::Plugins::SESSION->{users};
1166
1167 if ($user) {
1168 my $login = wikiToUserName($user);
1169 return 0 unless $login;
1170 $user = getCanonicalUserID($login);
1171 }
1172 else {
1173 $user = $Foswiki::Plugins::SESSION->{user};
1174 }
1175
1176 return $users->eachMembership($user);
1177}
1178
1179=begin TML
1180
1181---+++ eachGroup() -> $iterator
1182Get an iterator over all groups.
1183
1184Use it as follows:
1185<verbatim>
1186 my $iterator = Foswiki::Func::eachGroup();
1187 while ($it->hasNext()) {
1188 my $group = $it->next();
1189 # $group is a group name e.g. AdminGroup
1190 }
1191</verbatim>
1192
1193*WARNING* on large sites, this could be a long list!
1194
1195=cut
1196
1197sub eachGroup {
1198 my $session = $Foswiki::Plugins::SESSION;
1199 my $it = $session->{users}->eachGroup();
1200 return $it;
1201}
1202
1203=begin TML
1204
1205---+++ isGroup( $group ) -> $boolean
1206
1207Checks if =$group= is the name of a user group.
1208
1209=cut
1210
1211sub isGroup {
1212 my ($group) = @_;
1213
1214 return $Foswiki::Plugins::SESSION->{users}->isGroup($group);
1215}
1216
1217=begin TML
1218
1219---+++ eachGroupMember($group) -> $iterator
1220Get an iterator over all the members of the named group. Returns undef if
1221$group is not a valid group. Nested groups are expanded unless the
1222expand option is set to false.
1223
1224Use it as follows: Process all users in RadioHeadGroup without expanding nested groups
1225<verbatim>
1226 my $iterator = Foswiki::Func::eachGroupMember('RadioheadGroup', {expand => 'false');
1227 while ($it->hasNext()) {
1228 my $user = $it->next();
1229 # $user is a wiki name e.g. 'TomYorke', 'PhilSelway'
1230 # With expand set to false, group names can also be returned.
1231 # Users are not checked to exist.
1232 }
1233</verbatim>
1234
1235*WARNING* on large sites, this could be a long list!
1236
1237=cut
1238
1239
# spent 4.28s (255ms+4.03) within Foswiki::Func::eachGroupMember which was called 12164 times, avg 352µs/call: # 12164 times (255ms+4.03s) by Foswiki::Contrib::MailerContrib::WebNotify::subscribe at line 131 of /usr/local/src/github.com/foswiki/core/lib/Foswiki/Contrib/MailerContrib/WebNotify.pm, avg 352µs/call
sub eachGroupMember {
124048662252ms my ( $user, $options ) = @_;
1241
124212164194ms my $expand = Foswiki::Func::isTrue( $options->{expand}, 1 );
# spent 194ms making 12164 calls to Foswiki::Func::isTrue, avg 16µs/call
1243
1244 my $session = $Foswiki::Plugins::SESSION;
1245 return
1246121643.82s unless $Foswiki::Plugins::SESSION->{users}->isGroup($user);
# spent 3.82s making 12164 calls to Foswiki::Users::isGroup, avg 314µs/call
1247210.1ms my $it =
# spent 10.1ms making 2 calls to Foswiki::Users::eachGroupMember, avg 5.03ms/call
1248 $Foswiki::Plugins::SESSION->{users}
1249 ->eachGroupMember( $user, { expand => $expand } );
1250
# spent 5.18ms (184µs+4.99) within Foswiki::Func::__ANON__[/usr/local/src/github.com/foswiki/core/lib/Foswiki/Func.pm:1252] which was called 18 times, avg 288µs/call: # 18 times (184µs+4.99ms) by Foswiki::AggregateIterator::next at line 117 of /usr/local/src/github.com/foswiki/core/lib/Foswiki/AggregateIterator.pm, avg 288µs/call
$it->{process} = sub {
125118175µs184.99ms return $Foswiki::Plugins::SESSION->{users}->getWikiName( $_[0] );
# spent 4.99ms making 18 calls to Foswiki::Users::getWikiName, avg 277µs/call
1252 };
1253 return $it;
1254}
1255
1256=begin TML
1257
1258---+++ addUserToGroup( $group, $id, $create ) -> $boolean
1259
1260 * $id can be a login name or a WikiName
1261
1262=cut
1263
1264sub addUserToGroup {
1265 my ( $user, $group, $create ) = @_;
1266 my $users = $Foswiki::Plugins::SESSION->{users};
1267
1268 return () unless ( $users->isGroup($group) || $create );
1269 if ( defined $user && !$users->isGroup($user) )
1270 { #requires isInGroup to also work on nested groupnames
1271 $user = getCanonicalUserID($user) || $user;
1272 return unless ( defined($user) );
1273 }
1274 return $users->addUserToGroup( $user, $group, $create );
1275}
1276
1277=begin TML
1278
1279---+++ removeUserFromGroup( $group, $id ) -> $boolean
1280
1281 * $id can be a login name or a WikiName
1282
1283=cut
1284
1285sub removeUserFromGroup {
1286 my ( $user, $group ) = @_;
1287 my $users = $Foswiki::Plugins::SESSION->{users};
1288
1289 return () unless $users->isGroup($group);
1290
1291 if ( !$users->isGroup($user) )
1292 { #requires isInGroup to also work on nested groupnames
1293 $user = getCanonicalUserID($user) || $user;
1294 return unless ( defined($user) );
1295 }
1296 return $users->removeUserFromGroup( $user, $group );
1297}
1298
1299=begin TML
1300
1301---+++ checkAccessPermission( $type, $id, $text, $topic, $web, $meta ) -> $boolean
1302
1303Check access permission for a topic based on the
1304[[%SYSTEMWEB%.AccessControl]] rules
1305 * =$type= - Access type, required, e.g. ='VIEW'=, ='CHANGE'=.
1306 * =$id= - WikiName of remote user, required, e.g. ="RickShaw"=.
1307 $id may also be a login name.
1308 If =$id= is '', 0 or =undef= then access is *always permitted*. This is used
1309 by other functions if the caller should be able to bypass access checks.
1310 * =$text= - Topic text, optional. If 'perl false' (undef, 0 or ''),
1311 topic =$web.$topic= is consulted. =$text= may optionally contain embedded
1312 =%META:PREFERENCE= tags. Provide this parameter if:
1313 1 You are setting different access controls in the text to those defined
1314 in the stored topic,
1315 1 You already have the topic text in hand, and want to help avoid
1316 having to read it again,
1317 1 You are providing a =$meta= parameter.
1318 * =$topic= - Topic name, optional, e.g. ='PrivateStuff'=, '' or =undef=
1319 * If undefined, the Web preferences are checked.
1320 * If null, the default (WebHome) topic is checked.
1321 * If topic specified but does not exist, the web preferences are checked,
1322 allowing the caller to determine
1323 _"If the topic existed, would the operation be permitted"._
1324 * =$web= - Web name, required, e.g. ='Sandbox'=
1325 * If missing, the default Users Web (Main) is used.
1326 * =$meta= - Meta-data object, as returned by =readTopic=. Optional.
1327 If =undef=, but =$text= is defined, then access controls will be parsed
1328 from =$text=. If defined, then metadata embedded in =$text= will be
1329 ignored. This parameter is always ignored if =$text= is undefined.
1330 Settings in =$meta= override =Set= settings in $text.
1331A perl true result indicates that access is permitted.
1332
1333*Note* the weird parameter order is due to compatibility constraints with
1334earlier releases.
1335
1336*Tip* if you want, you can use this method to check your own access control types. For example, if you:
1337 * Set ALLOWTOPICSPIN = IncyWincy
1338in =ThatWeb.ThisTopic=, then a call to =checkAccessPermission('SPIN', 'IncyWincy', undef, 'ThisTopic', 'ThatWeb', undef)= will return =true=.
1339
1340=cut
1341
1342
# spent 60.8s (95µs+60.8) within Foswiki::Func::checkAccessPermission which was called: # once (95µs+60.8s) by Foswiki::Plugins::InterwikiPlugin::initPlugin at line 76 of /usr/local/src/github.com/foswiki/core/lib/Foswiki/Plugins/InterwikiPlugin.pm
sub checkAccessPermission {
13431476µs my ( $type, $user, $text, $inTopic, $inWeb, $meta ) = @_;
1344 return 1 unless ($user);
1345
1346199µs my ( $web, $topic ) = _checkWTA( $inWeb, $inTopic );
# spent 99µs making 1 call to Foswiki::Func::_checkWTA
1347 return 0 unless defined $web; #Web name is illegal.
1348 if ( defined $inTopic ) {
1349 my $top = $topic;
1350 return 0 unless ( defined $topic ); #Topic name is illegal
1351 }
1352
135314µs ASSERT($Foswiki::Plugins::SESSION) if DEBUG;
# spent 4µs making 1 call to Assert::ASSERTS_OFF
1354 $text = undef unless $text;
1355162µs my $cUID = getCanonicalUserID($user)
# spent 62µs making 1 call to Foswiki::Func::getCanonicalUserID
1356 || getCanonicalUserID( $Foswiki::cfg{DefaultUserLogin} );
1357 if ( !defined($meta) ) {
1358 if ($text) {
1359 $meta = Foswiki::Meta->new( $Foswiki::Plugins::SESSION,
1360 $web, $topic, $text );
1361 }
1362 else {
1363125.3ms $meta =
# spent 25.3ms making 1 call to Foswiki::Meta::load
1364 Foswiki::Meta->load( $Foswiki::Plugins::SESSION, $web, $topic );
1365 }
1366 }
1367 elsif ( $text && !defined( $meta->text() ) ) {
1368
1369 # Ouch!
1370 $meta->text($text);
1371 } # Otherwise meta overrides text - Item2953
1372160.8s return $meta->haveAccess( $type, $cUID );
# spent 60.8s making 1 call to Foswiki::Meta::haveAccess
1373}
1374
1375=begin TML
1376
1377---++ Traversing
1378
1379=cut
1380
1381=begin TML
1382
1383---+++ getListOfWebs( $filter [, $web] ) -> @webs
1384
1385 * =$filter= - spec of web types to recover
1386Gets a list of webs, filtered according to the spec in the $filter,
1387which may include one of:
1388 1 'user' (for only user webs)
1389 2 'template' (for only template webs i.e. those starting with "_")
1390=$filter= may also contain the word 'public' which will further filter
1391out webs that have NOSEARCHALL set on them.
1392'allowed' filters out webs the current user can't read.
1393 * =$web= - (*Since* 2009-01-01) name of web to get list of subwebs for. Defaults to the root.
1394 note that if set, the list will not contain the web specified in $web
1395
1396For example, the deprecated getPublicWebList function can be duplicated
1397as follows:
1398<verbatim>
1399 my @webs = Foswiki::Func::getListOfWebs( "user,public" );
1400</verbatim>
1401
1402=cut
1403
1404sub getListOfWebs {
1405 my $filter = shift;
1406 my $web = shift;
1407 if ( defined $web ) {
1408 $web = _checkWTA($web);
1409 return () unless defined $web;
1410 }
1411 ASSERT($Foswiki::Plugins::SESSION) if DEBUG;
1412 require Foswiki::WebFilter;
1413 my $f = new Foswiki::WebFilter( $filter || '' );
1414 return $Foswiki::Plugins::SESSION->deepWebList( $f, $web );
1415}
1416
1417=begin TML
1418
1419---+++ isValidWebName( $name [, $system] ) -> $boolean
1420
1421Check for a valid web name. If $system is true, then
1422system web names are considered valid (names starting with _)
1423otherwise only user web names are valid
1424
1425If $Foswiki::cfg{EnableHierarchicalWebs} is off, it will also return false
1426when a nested web name is passed to it.
1427
1428=cut
1429
1430sub isValidWebName {
1431 return Foswiki::isValidWebName(@_);
1432}
1433
1434=begin TML
1435
1436---+++ webExists( $web ) -> $boolean
1437
1438Test if web exists
1439 * =$web= - Web name, required, e.g. ='Sandbox'=
1440
1441=cut
1442
1443sub webExists {
1444 my ($web) = _checkWTA(@_);
1445 return 0 unless defined $web;
1446
1447 ASSERT($Foswiki::Plugins::SESSION) if DEBUG;
1448 return $Foswiki::Plugins::SESSION->webExists($web);
1449}
1450
1451=begin TML
1452
1453---+++ getTopicList( $web ) -> @topics
1454
1455Get list of all topics in a web
1456 * =$web= - Web name, required, e.g. ='Sandbox'=
1457Return: =@topics= Topic list, e.g. =( 'WebChanges', 'WebHome', 'WebIndex', 'WebNotify' )=
1458
1459=cut
1460
1461sub getTopicList {
1462
1463 my ($web) = _validateWTA(@_);
1464
1465 my $webObject = Foswiki::Meta->new( $Foswiki::Plugins::SESSION, $web );
1466 my $it = $webObject->eachTopic();
1467 return $it->all();
1468}
1469
1470=begin TML
1471
1472---+++ isValidTopicName( $name [, $allowNonWW] ) -> $boolean
1473
1474Check for a valid topic name.
1475 * =$name= - topic name
1476 * =$allowNonWW= - true to allow non-wikiwords
1477
1478=cut
1479
1480sub isValidTopicName {
1481 return Foswiki::isValidTopicName(@_);
1482}
1483
1484=begin TML
1485
1486---+++ topicExists( $web, $topic ) -> $boolean
1487
1488Test if topic exists
1489 * =$web= - Web name, optional, e.g. ='Main'=.
1490 * =$topic= - Topic name, required, e.g. ='TokyoOffice'=, or ="Main.TokyoOffice"=
1491
1492$web and $topic are parsed as described in the documentation for =normalizeWebTopicName=.
1493Specifically, the %USERSWEB% is used if $web is not specified and $topic has no web specifier.
1494To get an expected behaviour it is recommened to specify the current web for $web; don't leave it empty.
1495
1496=cut
1497
1498
# spent 681µs (64+617) within Foswiki::Func::topicExists which was called 2 times, avg 341µs/call: # 2 times (64µs+617µs) by Foswiki::Contrib::MailerContrib::WebNotify::new at line 55 of /usr/local/src/github.com/foswiki/core/lib/Foswiki/Contrib/MailerContrib/WebNotify.pm, avg 341µs/call
sub topicExists {
1499860µs26µs ASSERT($Foswiki::Plugins::SESSION) if DEBUG;
# spent 6µs making 2 calls to Assert::ASSERTS_OFF, avg 3µs/call
15002190µs my ( $web, $topic ) = _checkWTA(@_);
# spent 190µs making 2 calls to Foswiki::Func::_checkWTA, avg 95µs/call
1501 return 0 unless defined $web && defined $topic;
15022422µs return $Foswiki::Plugins::SESSION->topicExists( $web, $topic );
# spent 422µs making 2 calls to Foswiki::topicExists, avg 211µs/call
1503}
1504
1505=begin TML
1506
1507---+++ readTopic( $web, $topic, $rev ) -> ( $meta, $text )
1508
1509Read topic text and meta data, regardless of access permissions.
1510 * =$web= - Web name, required, e.g. ='Main'=
1511 * =$topic= - Topic name, required, e.g. ='TokyoOffice'=
1512 * =$rev= - revision to read (default latest)
1513Return: =( $meta, $text )= Meta data object and topic text
1514
1515=$meta= is a perl 'object' of class =Foswiki::Meta=. This class is
1516fully documented in the source code documentation shipped with the
1517release, or can be inspected in the =lib/Foswiki/Meta.pm= file.
1518
1519This method *ignores* topic access permissions. You should be careful to use
1520=checkAccessPermission= to ensure the current user has read access to the
1521topic.
1522
1523=cut
1524
1525
# spent 3.16s (136µs+3.16) within Foswiki::Func::readTopic which was called 2 times, avg 1.58s/call: # 2 times (136µs+3.16s) by Foswiki::Contrib::MailerContrib::WebNotify::_load at line 333 of /usr/local/src/github.com/foswiki/core/lib/Foswiki/Contrib/MailerContrib/WebNotify.pm, avg 1.58s/call
sub readTopic {
1526
152710102µs my ( $web, $topic, $rev ) = @_;
15282213µs ( $web, $topic ) = _validateWTA( $web, $topic );
# spent 213µs making 2 calls to Foswiki::Func::_validateWTA, avg 106µs/call
152928µs ASSERT($Foswiki::Plugins::SESSION) if DEBUG;
# spent 8µs making 2 calls to Assert::ASSERTS_OFF, avg 4µs/call
1530
153123.16s my $meta =
# spent 3.16s making 2 calls to Foswiki::Meta::load, avg 1.58s/call
1532 Foswiki::Meta->load( $Foswiki::Plugins::SESSION, $web, $topic, $rev );
15332208µs return ( $meta, $meta->text() );
# spent 208µs making 2 calls to Foswiki::Meta::text, avg 104µs/call
1534}
1535
1536=begin TML
1537
1538---+++ getRevisionInfo($web, $topic, $rev, $attachment ) -> ( $date, $user, $rev, $comment )
1539
1540Get revision info of a topic or attachment
1541 * =$web= - Web name, optional, e.g. ='Main'=
1542 * =$topic= - Topic name, required, e.g. ='TokyoOffice'=
1543 * =$rev= - revsion number, or tag name (can be in the format 1.2, or just the minor number)
1544 * =$attachment= -attachment filename
1545Return: =( $date, $user, $rev, $comment )= List with: ( last update date, login name of last user, minor part of top revision number, comment of attachment if attachment ), e.g. =( 1234561, 'phoeny', "5", )=
1546| $date | in epochSec |
1547| $user | Wiki name of the author (*not* login name) |
1548| $rev | actual rev number |
1549| $comment | comment given for uploaded attachment |
1550
1551NOTE: if you are trying to get revision info for a topic, use
1552=$meta->getRevisionInfo= instead if you can - it is significantly
1553more efficient.
1554
1555=cut
1556
1557sub getRevisionInfo {
1558 my ( $web, $topic, $rev, $attachment ) = @_;
1559
1560 ( $web, $topic ) = _validateWTA( $web, $topic );
1561
1562 ASSERT($Foswiki::Plugins::SESSION) if DEBUG;
1563
1564 my $topicObject;
1565 my $info;
1566 if ($attachment) {
1567 $topicObject =
1568 Foswiki::Meta->load( $Foswiki::Plugins::SESSION, $web, $topic );
1569 $info = $topicObject->getAttachmentRevisionInfo( $attachment, $rev );
1570 }
1571 else {
1572 $topicObject =
1573 Foswiki::Meta->load( $Foswiki::Plugins::SESSION, $web, $topic, $rev );
1574 $info = $topicObject->getRevisionInfo();
1575 }
1576 return ( $info->{date},
1577 $Foswiki::Plugins::SESSION->{users}->getWikiName( $info->{author} ),
1578 $info->{version}, $info->{comment} );
1579}
1580
1581=begin TML
1582
1583---+++ getRevisionAtTime( $web, $topic, $time ) -> $rev
1584
1585Get the revision number of a topic at a specific time.
1586 * =$web= - web for topic
1587 * =$topic= - topic
1588 * =$time= - time (in epoch secs) for the rev
1589Return: Single-digit revision number, or undef if it couldn't be determined
1590(either because the topic isn't that old, or there was a problem)
1591
1592=cut
1593
1594sub getRevisionAtTime {
1595 my ( $web, $topic, $time ) = @_;
1596 ( $web, $topic ) = _validateWTA( $web, $topic );
1597 ASSERT($Foswiki::Plugins::SESSION) if DEBUG;
1598 my $topicObject =
1599 Foswiki::Meta->new( $Foswiki::Plugins::SESSION, $web, $topic );
1600 return $topicObject->getRevisionAtTime($time);
1601}
1602
1603=begin TML
1604
1605---+++ getAttachmentList( $web, $topic ) -> @list
1606Get a list of the attachments on the given topic.
1607
1608*Since:* 31 Mar 2009
1609
1610=cut
1611
1612sub getAttachmentList {
1613 my ( $web, $topic ) = @_;
1614 ( $web, $topic ) = _validateWTA( $web, $topic );
1615 my $topicObject =
1616 Foswiki::Meta->new( $Foswiki::Plugins::SESSION, $web, $topic );
1617 my $it = $topicObject->eachAttachment();
1618 return sort $it->all();
1619}
1620
1621=begin TML
1622
1623---+++ attachmentExists( $web, $topic, $attachment ) -> $boolean
1624
1625Test if attachment exists
1626 * =$web= - Web name, optional, e.g. =Main=.
1627 * =$topic= - Topic name, required, e.g. =TokyoOffice=, or =Main.TokyoOffice=
1628 * =$attachment= - attachment name, e.g.=logo.gif=
1629$web and $topic are parsed as described in the documentation for =normalizeWebTopicName=.
1630
1631The attachment must exist in the store (it is not sufficient for it to be referenced
1632in the object only)
1633
1634=cut
1635
1636sub attachmentExists {
1637 my ( $web, $topic, $attachment ) = _checkWTA(@_);
1638 return 0 unless defined $web && defined $topic && defined $attachment;
1639
1640 my $topicObject =
1641 Foswiki::Meta->new( $Foswiki::Plugins::SESSION, $web, $topic );
1642 return $topicObject->hasAttachment($attachment);
1643}
1644
1645=begin TML
1646
1647---+++ readAttachment( $web, $topic, $name, $rev ) -> $data
1648
1649 * =$web= - web for topic - must not be tainted
1650 * =$topic= - topic - must not be tainted
1651 * =$name= - attachment name - must not be tainted
1652 * =$rev= - revision to read (default latest)
1653Read an attachment from the store for a topic, and return it as a string. The
1654names of attachments on a topic can be recovered from the meta-data returned
1655by =readTopic=. If the attachment does not exist, or cannot be read, undef
1656will be returned. If the revision is not specified, the latest version will
1657be returned.
1658
1659View permission on the topic is required for the
1660read to be successful. Access control violations are flagged by a
1661Foswiki::AccessControlException. Permissions are checked for the current user.
1662
1663<verbatim>
1664use Error qw(:try);
1665use Foswiki::AccessControlException ();
1666
1667my( $meta, $text ) = Foswiki::Func::readTopic( $web, $topic );
1668my @attachments = $meta->find( 'FILEATTACHMENT' );
1669foreach my $a ( @attachments ) {
1670 try {
1671 my $data = Foswiki::Func::readAttachment( $web, $topic, $a->{name} );
1672 ...
1673 } catch Foswiki::AccessControlException with {
1674 };
1675}
1676</verbatim>
1677
1678This is the way 99% of extensions will access attachments.
1679See =Foswiki::Meta::openAttachment= for a lower level interface that does
1680not check access controls.
1681
1682=cut
1683
1684sub readAttachment {
1685 my ( $web, $topic, $attachment, $rev ) = @_;
1686
1687 ( $web, $topic, $attachment ) = _validateWTA( $web, $topic, $attachment );
1688
1689 ASSERT($Foswiki::Plugins::SESSION) if DEBUG;
1690 my $result;
1691
1692 my $topicObject =
1693 Foswiki::Meta->new( $Foswiki::Plugins::SESSION, $web, $topic );
1694 unless ( $topicObject->haveAccess('VIEW') ) {
1695 throw Foswiki::AccessControlException( 'VIEW',
1696 $Foswiki::Plugins::SESSION->{user},
1697 $web, $topic, $Foswiki::Meta::reason );
1698 }
1699 my $fh;
1700 try {
1701 $fh = $topicObject->openAttachment( $attachment, '<', version => $rev );
1702 }
1703 catch Error::Simple with {
1704 $fh = undef;
1705 };
1706 return undef unless $fh;
1707 local $/;
1708 my $data = <$fh>;
1709 return $data;
1710}
1711
1712=begin TML
1713
1714---++ Manipulating
1715
1716=cut
1717
1718=begin TML
1719
1720---+++ createWeb( $newWeb, $baseWeb, $opts )
1721
1722 * =$newWeb= is the name of the new web.
1723 * =$baseWeb= is the name of an existing web (a template web). If the base web is a system web, all topics in it will be copied into the new web. If it is a normal web, only topics starting with 'Web' will be copied. If no base web is specified, an empty web (with no topics) will be created. If it is specified but does not exist, an error will be thrown.
1724 * =$opts= is a ref to a hash that contains settings to be modified in
1725the web preferences topic in the new web.
1726
1727<verbatim>
1728use Error qw( :try );
1729use Foswiki::AccessControlException ();
1730
1731try {
1732 Foswiki::Func::createWeb( "Newweb" );
1733} catch Foswiki::AccessControlException with {
1734 my $e = shift;
1735 # see documentation on Foswiki::AccessControlException
1736} catch Error::Simple with {
1737 my $e = shift;
1738 # see documentation on Error::Simple
1739} otherwise {
1740 ...
1741};
1742</verbatim>
1743
1744=cut
1745
1746sub createWeb {
1747 my ( $web, $baseweb ) = @_;
1748 ($web) = _validateWTA($web);
1749 if ( defined $baseweb ) {
1750 ($baseweb) = _validateWTA($baseweb);
1751 }
1752 ASSERT($Foswiki::Plugins::SESSION) if DEBUG;
1753
1754 my ($parentWeb) = $web =~ m#(.*)/[^/]+$#;
1755
1756 my $rootObject =
1757 Foswiki::Meta->new( $Foswiki::Plugins::SESSION, $parentWeb );
1758 unless ( $rootObject->haveAccess('CHANGE') ) {
1759 throw Foswiki::AccessControlException( 'CHANGE',
1760 $Foswiki::Plugins::SESSION->{user},
1761 $web, '', $Foswiki::Meta::reason );
1762 }
1763
1764 my $baseObject = Foswiki::Meta->new( $Foswiki::Plugins::SESSION, $baseweb );
1765 unless ( $baseObject->haveAccess('VIEW') ) {
1766 throw Foswiki::AccessControlException( 'VIEW',
1767 $Foswiki::Plugins::SESSION->{user},
1768 $web, '', $Foswiki::Meta::reason );
1769 }
1770
1771 my $webObject = Foswiki::Meta->new( $Foswiki::Plugins::SESSION, $web );
1772 $webObject->populateNewWeb($baseweb);
1773}
1774
1775=begin TML
1776
1777---+++ moveWeb( $oldName, $newName )
1778
1779Move (rename) a web.
1780
1781<verbatim>
1782use Error qw( :try );
1783use Foswiki::AccessControlException ();
1784
1785try {
1786 Foswiki::Func::moveWeb( "Oldweb", "Newweb" );
1787} catch Foswiki::AccessControlException with {
1788 my $e = shift;
1789 # see documentation on Foswiki::AccessControlException
1790} catch Error::Simple with {
1791 my $e = shift;
1792 # see documentation on Error::Simple
1793} otherwise {
1794 ...
1795};
1796</verbatim>
1797
1798To delete a web, move it to a subweb of =Trash=
1799<verbatim>
1800Foswiki::Func::moveWeb( "Deadweb", "Trash.Deadweb" );
1801</verbatim>
1802
1803=cut
1804
1805sub moveWeb {
1806 ASSERT($Foswiki::Plugins::SESSION) if DEBUG;
1807 my ( $from, $to ) = @_;
1808 ($from) = _validateWTA($from);
1809 ($to) = _validateWTA($to);
1810
1811 $from = Foswiki::Meta->new( $Foswiki::Plugins::SESSION, $from );
1812 $to = Foswiki::Meta->new( $Foswiki::Plugins::SESSION, $to );
1813 return $from->move($to);
1814
1815}
1816
1817=begin TML
1818
1819---+++ checkTopicEditLock( $web, $topic, $script ) -> ( $oopsUrl, $loginName, $unlockTime )
1820
1821Check if a lease has been taken by some other user.
1822 * =$web= Web name, e.g. ="Main"=, or empty
1823 * =$topic= Topic name, e.g. ="MyTopic"=, or ="Main.MyTopic"=
1824Return: =( $oopsUrl, $loginName, $unlockTime )= - The =$oopsUrl= for calling redirectCgiQuery(), user's =$loginName=, and estimated =$unlockTime= in minutes, or ( '', '', 0 ) if no lease exists.
1825 * =$script= The script to invoke when continuing with the edit
1826
1827=cut
1828
1829sub checkTopicEditLock {
1830 my ( $web, $topic, $script ) = @_;
1831 ASSERT($Foswiki::Plugins::SESSION) if DEBUG;
1832
1833 ( $web, $topic ) = _checkWTA( $web, $topic );
1834 return ( '', '', 0 ) unless defined $web && defined $topic;
1835
1836 $script ||= 'edit';
1837
1838 my $topicObject =
1839 Foswiki::Meta->new( $Foswiki::Plugins::SESSION, $web, $topic );
1840 my $lease = $topicObject->getLease();
1841 if ($lease) {
1842 my $remain = $lease->{expires} - time();
1843 my $session = $Foswiki::Plugins::SESSION;
1844
1845 if ( $remain > 0 ) {
1846 my $who = $lease->{user};
1847 require Foswiki::Time;
1848 my $past = Foswiki::Time::formatDelta( time() - $lease->{taken},
1849 $Foswiki::Plugins::SESSION->i18n );
1850 my $future = Foswiki::Time::formatDelta( $lease->{expires} - time(),
1851 $Foswiki::Plugins::SESSION->i18n );
1852 my $url = getScriptUrl(
1853 $web, $topic, 'oops',
1854 template => 'oopsleaseconflict',
1855 def => 'lease_active',
1856 param1 => $who,
1857 param2 => $past,
1858 param3 => $future,
1859 param4 => $script
1860 );
1861 my $login = $session->{users}->getLoginName($who);
1862 return ( $url, $login || $who, $remain / 60 );
1863 }
1864 }
1865 return ( '', '', 0 );
1866}
1867
1868=begin TML
1869
1870---+++ setTopicEditLock( $web, $topic, $lock )
1871
1872 * =$web= Web name, e.g. ="Main"=, or empty
1873 * =$topic= Topic name, e.g. ="MyTopic"=, or ="Main.MyTopic"=
1874 * =$lock= 1 to lease the topic, 0 to clear an existing lease
1875
1876Takes out a "lease" on the topic. The lease doesn't prevent
1877anyone from editing and changing the topic, but it does redirect them
1878to a warning screen, so this provides some protection. The =edit= script
1879always takes out a lease.
1880
1881It is *impossible* to fully lock a topic. Concurrent changes will be
1882merged.
1883
1884=cut
1885
1886sub setTopicEditLock {
1887 my ( $web, $topic, $lock ) = @_;
1888 ASSERT($Foswiki::Plugins::SESSION) if DEBUG;
1889 ( $web, $topic ) = _validateWTA( $web, $topic );
1890 my $topicObject =
1891 Foswiki::Meta->new( $Foswiki::Plugins::SESSION, $web, $topic );
1892 if ($lock) {
1893 $topicObject->setLease( $Foswiki::cfg{LeaseLength} );
1894 }
1895 else {
1896 $topicObject->clearLease();
1897 }
1898 return '';
1899}
1900
1901=begin TML
1902
1903---+++ saveTopic( $web, $topic, $meta, $text, $options )
1904
1905 * =$web= - web for the topic
1906 * =$topic= - topic name
1907 * =$meta= - reference to Foswiki::Meta object
1908 (optional, set to undef to create a new topic containing just text,
1909 or to just change that topic's text)
1910 * =$text= - text of the topic (without embedded meta-data!!!
1911 * =\%options= - ref to hash of save options
1912 =\%options= may include:
1913 | =dontlog= | mark this change so it doesn't appear in the statistics |
1914 | =minor= | True if this change is not to be notified |
1915 | =forcenewrevision= | force the save to increment the revision counter |
1916 | =ignorepermissions= | don't check acls |
1917For example,
1918<verbatim>
1919use Error qw( :try );
1920use Foswiki::AccessControlException ();
1921
1922my( $meta, $text );
1923if (Foswiki::Func::topicExists($web, $topic)) {
1924 ( $meta, $text ) = Foswiki::Func::readTopic( $web, $topic );
1925} else {
1926 #if the topic doesn't exist, we can either leave $meta undefined
1927 #or if we need to set more than just the topic text, we create a new Meta object and use it.
1928 $meta = new Foswiki::Meta($Foswiki::Plugins::SESSION, $web, $topic );
1929 $text = '';
1930}
1931$text =~ s/APPLE/ORANGE/g;
1932try {
1933 Foswiki::Func::saveTopic( $web, $topic, $meta, $text );
1934} catch Foswiki::AccessControlException with {
1935 my $e = shift;
1936 # see documentation on Foswiki::AccessControlException
1937} catch Error::Simple with {
1938 my $e = shift;
1939 # see documentation on Error::Simple
1940} otherwise {
1941 ...
1942};
1943</verbatim>
1944
1945In the event of an error an exception will be thrown. Callers can elect
1946to trap the exceptions thrown, or allow them to propagate to the calling
1947environment. May throw Foswiki::OopsException or Error::Simple.
1948
1949*Note:* The =ignorepermissions= option is only available in Foswiki 1.1 and
1950later.
1951
1952=cut
1953
1954sub saveTopic {
1955 my ( $web, $topic, $smeta, $text, $options ) = @_;
1956 ASSERT($Foswiki::Plugins::SESSION) if DEBUG;
1957 ( $web, $topic ) = _validateWTA( $web, $topic );
1958 my $topicObject =
1959 Foswiki::Meta->new( $Foswiki::Plugins::SESSION, $web, $topic );
1960
1961 unless ( $options->{ignorepermissions}
1962 || $topicObject->haveAccess('CHANGE') )
1963 {
1964 throw Foswiki::AccessControlException( 'CHANGE',
1965 $Foswiki::Plugins::SESSION->{user},
1966 $web, $topic, $Foswiki::Meta::reason );
1967 }
1968
1969 # Set the new text and meta, now that access to the existing topic
1970 # is verified
1971 $topicObject->text($text);
1972 $topicObject->copyFrom($smeta) if $smeta;
1973 return $topicObject->save(%$options);
1974}
1975
1976=begin TML
1977
1978---+++ moveTopic( $web, $topic, $newWeb, $newTopic )
1979
1980 * =$web= source web - required
1981 * =$topic= source topic - required
1982 * =$newWeb= dest web
1983 * =$newTopic= dest topic
1984Renames the topic. Throws an exception if something went wrong.
1985If $newWeb is undef, it defaults to $web. If $newTopic is undef, it defaults
1986to $topic.
1987
1988The destination topic must not already exist.
1989
1990Rename a topic to the $Foswiki::cfg{TrashWebName} to delete it.
1991
1992<verbatim>
1993use Error qw( :try );
1994
1995try {
1996 moveTopic( "Work", "TokyoOffice", "Trash", "ClosedOffice" );
1997} catch Foswiki::AccessControlException with {
1998 my $e = shift;
1999 # see documentation on Foswiki::AccessControlException
2000} catch Error::Simple with {
2001 my $e = shift;
2002 # see documentation on Error::Simple
2003} otherwise {
2004 ...
2005};
2006</verbatim>
2007
2008=cut
2009
2010sub moveTopic {
2011 my ( $web, $topic, $newWeb, $newTopic ) = @_;
2012 ( $web, $topic ) = _validateWTA( $web, $topic );
2013 ( $newWeb, $newTopic ) =
2014 _validateWTA( $newWeb || $web, $newTopic || $topic );
2015
2016 return if ( $newWeb eq $web && $newTopic eq $topic );
2017
2018 my $from = Foswiki::Meta->new( $Foswiki::Plugins::SESSION, $web, $topic );
2019 unless ( $from->haveAccess('CHANGE') ) {
2020 throw Foswiki::AccessControlException( 'CHANGE',
2021 $Foswiki::Plugins::SESSION->{user},
2022 $web, $topic, $Foswiki::Meta::reason );
2023 }
2024
2025 my $toWeb = Foswiki::Meta->new( $Foswiki::Plugins::SESSION, $newWeb );
2026 unless ( $from->haveAccess('CHANGE') ) {
2027 throw Foswiki::AccessControlException( 'CHANGE',
2028 $Foswiki::Plugins::SESSION->{user},
2029 $newWeb, undef, $Foswiki::Meta::reason );
2030 }
2031
2032 my $to =
2033 Foswiki::Meta->new( $Foswiki::Plugins::SESSION, $newWeb, $newTopic );
2034
2035 $from->move($to);
2036}
2037
2038=begin TML
2039
2040---+++ saveAttachment( $web, $topic, $attachment, \%opts )
2041 * =$web= - web for topic
2042 * =$topic= - topic to atach to
2043 * =$attachment= - name of the attachment
2044 * =\%opts= - Ref to hash of options
2045Create an attachment on the given topic.
2046=\%opts= may include:
2047| =dontlog= | mark this change so it is not picked up in statistics |
2048| =comment= | comment for save |
2049| =hide= | if the attachment is to be hidden in normal topic view |
2050| =stream= | Stream of file to upload |
2051| =file= | Name of a file to use for the attachment data. ignored if stream is set. Local file on the server. |
2052| =filepath= | Client path to file |
2053| =filesize= | Size of uploaded data |
2054| =filedate= | Date |
2055| =createlink= | Set true to create a link at the end of the topic |
2056| =notopicchange= | Set to true to *prevent* this upload being recorded in the meta-data of the topic. |
2057Save an attachment to the store for a topic. On success, returns undef.
2058If there is an error, an exception will be thrown. The current user must
2059have CHANGE access on the topic being attached to.
2060
2061<verbatim>
2062 try {
2063 Foswiki::Func::saveAttachment( $web, $topic, 'image.gif',
2064 { file => 'image.gif',
2065 comment => 'Picture of Health',
2066 hide => 1 } );
2067 } catch Foswiki::AccessControlException with {
2068 # Topic CHANGE access denied
2069 } catch Error::Simple with {
2070 # see documentation on Error
2071 } otherwise {
2072 ...
2073 };
2074</verbatim>
2075This is the way 99% of extensions will create new attachments. See
2076=Foswiki::Meta::openAttachment= for a much lower-level interface.
2077
2078=cut
2079
2080sub saveAttachment {
2081 my ( $web, $topic, $attachment, $data ) = @_;
2082 ( $web, $topic, $attachment ) = _validateWTA( $web, $topic, $attachment );
2083
2084 ASSERT($Foswiki::Plugins::SESSION) if DEBUG;
2085 my $topicObject =
2086 Foswiki::Meta->new( $Foswiki::Plugins::SESSION, $web, $topic );
2087 unless ( $topicObject->haveAccess('CHANGE') ) {
2088 throw Foswiki::AccessControlException( 'CHANGE',
2089 $Foswiki::Plugins::SESSION->{user},
2090 $web, $topic, $Foswiki::Meta::reason );
2091 }
2092 $topicObject->attach( name => $attachment, %$data );
2093}
2094
2095=begin TML
2096
2097---+++ moveAttachment( $web, $topic, $attachment, $newWeb, $newTopic, $newAttachment )
2098
2099 * =$web= source web - required
2100 * =$topic= source topic - required
2101 * =$attachment= source attachment - required
2102 * =$newWeb= dest web
2103 * =$newTopic= dest topic
2104 * =$newAttachment= dest attachment
2105Renames the attachment. Throws an exception on error or access violation.
2106If $newWeb is undef, it defaults to $web. If $newTopic is undef, it defaults
2107to $topic. If $newAttachment is undef, it defaults to $attachment. If all of $newWeb, $newTopic and $newAttachment are undef, it is an error.
2108
2109The destination topic must already exist, but the destination attachment must
2110*not* exist.
2111
2112Rename an attachment to $Foswiki::cfg{TrashWebName}.TrashAttament to delete it.
2113
2114<verbatim>
2115use Error qw( :try );
2116
2117try {
2118 # move attachment between topics
2119 moveAttachment( "Countries", "Germany", "AlsaceLorraine.dat",
2120 "Countries", "France" );
2121 # Note destination attachment name is defaulted to the same as source
2122} catch Foswiki::AccessControlException with {
2123 my $e = shift;
2124 # see documentation on Foswiki::AccessControlException
2125} catch Error::Simple with {
2126 my $e = shift;
2127 # see documentation on Error::Simple
2128};
2129</verbatim>
2130
2131=cut
2132
2133sub moveAttachment {
2134 my ( $web, $topic, $attachment, $newWeb, $newTopic, $newAttachment ) = @_;
2135
2136 ( $web, $topic, $attachment ) = _validateWTA( $web, $topic, $attachment );
2137
2138 ( $newWeb, $newTopic, $newAttachment ) = _validateWTA(
2139 $newWeb || $web,
2140 $newTopic || $topic,
2141 $newAttachment || $attachment
2142 );
2143
2144 return
2145 if ( $newWeb eq $web
2146 && $newTopic eq $topic
2147 && $newAttachment eq $attachment );
2148
2149 my $from = Foswiki::Meta->load( $Foswiki::Plugins::SESSION, $web, $topic );
2150 unless ( $from->haveAccess('CHANGE') ) {
2151 throw Foswiki::AccessControlException( 'CHANGE',
2152 $Foswiki::Plugins::SESSION->{user},
2153 $web, $topic, $Foswiki::Meta::reason );
2154 }
2155 my @opts;
2156 push( @opts, new_name => $newAttachment ) if defined $newAttachment;
2157
2158 if ( $web eq $newWeb
2159 && $topic eq $newTopic
2160 && defined $newAttachment )
2161 {
2162 $from->moveAttachment( $attachment, $from, @opts );
2163 }
2164 else {
2165 my $to =
2166 Foswiki::Meta->load( $Foswiki::Plugins::SESSION, $newWeb, $newTopic );
2167 unless ( $to->haveAccess('CHANGE') ) {
2168 throw Foswiki::AccessControlException( 'CHANGE',
2169 $Foswiki::Plugins::SESSION->{user},
2170 $newWeb, $newTopic, $Foswiki::Meta::reason );
2171 }
2172
2173 $from->moveAttachment( $attachment, $to, @opts );
2174 }
2175}
2176
2177=begin TML
2178
2179---+++ copyAttachment( $web, $topic, $attachment, $newWeb, $newTopic, $newAttachment )
2180
2181 * =$web= source web - required
2182 * =$topic= source topic - required
2183 * =$attachment= source attachment - required
2184 * =$newWeb= dest web
2185 * =$newTopic= dest topic
2186 * =$newAttachment= dest attachment
2187Copies the attachment. Throws an exception on error or access violation.
2188If $newWeb is undef, it defaults to $web. If $newTopic is undef, it defaults
2189to $topic. If $newAttachment is undef, it defaults to $attachment. If all of $newWeb, $newTopic and $newAttachment are undef, it is an error.
2190
2191The destination topic must already exist, but the destination attachment must
2192*not* exist.
2193
2194Rename an attachment to $Foswiki::cfg{TrashWebName}.TrashAttament to delete it.
2195
2196<verbatim>
2197use Error qw( :try );
2198
2199try {
2200 # copy attachment between topics
2201 copyAttachment( "Countries", "Germany", "AlsaceLorraine.dat",
2202 "Countries", "France" );
2203 # Note destination attachment name is defaulted to the same as source
2204} catch Foswiki::AccessControlException with {
2205 my $e = shift;
2206 # see documentation on Foswiki::AccessControlException
2207} catch Error::Simple with {
2208 my $e = shift;
2209 # see documentation on Error::Simple
2210};
2211</verbatim>
2212
2213*Since:* 19 Jul 2010
2214
2215=cut
2216
2217sub copyAttachment {
2218 my ( $web, $topic, $attachment, $newWeb, $newTopic, $newAttachment ) = @_;
2219
2220 ( $web, $topic, $attachment ) = _validateWTA( $web, $topic, $attachment );
2221
2222 ( $newWeb, $newTopic, $newAttachment ) = _validateWTA(
2223 $newWeb || $web,
2224 $newTopic || $topic,
2225 $newAttachment || $attachment
2226 );
2227
2228 return
2229 if ( $newWeb eq $web
2230 && $newTopic eq $topic
2231 && $newAttachment eq $attachment );
2232
2233 my $from = Foswiki::Meta->load( $Foswiki::Plugins::SESSION, $web, $topic );
2234 unless ( $from->haveAccess('CHANGE') ) {
2235 throw Foswiki::AccessControlException( 'CHANGE',
2236 $Foswiki::Plugins::SESSION->{user},
2237 $web, $topic, $Foswiki::Meta::reason );
2238 }
2239 my @opts;
2240 push( @opts, new_name => $newAttachment ) if defined $newAttachment;
2241
2242 if ( $web eq $newWeb
2243 && $topic eq $newTopic
2244 && defined $newAttachment )
2245 {
2246 $from->copyAttachment( $attachment, $from, @opts );
2247 }
2248 else {
2249 my $to =
2250 Foswiki::Meta->load( $Foswiki::Plugins::SESSION, $newWeb, $newTopic );
2251 unless ( $to->haveAccess('CHANGE') ) {
2252 throw Foswiki::AccessControlException( 'CHANGE',
2253 $Foswiki::Plugins::SESSION->{user},
2254 $newWeb, $newTopic, $Foswiki::Meta::reason );
2255 }
2256
2257 $from->copyAttachment( $attachment, $to, @opts );
2258 }
2259}
2260
2261=begin TML
2262
2263---++ Finding changes
2264
2265=cut
2266
2267=begin TML
2268
2269---+++ eachChangeSince($web, $time) -> $iterator
2270
2271Get an iterator over the list of all the changes in the given web between
2272=$time= and now. $time is a time in seconds since 1st Jan 1970, and is not
2273guaranteed to return any changes that occurred before (now -
2274{Store}{RememberChangesFor}). {Store}{RememberChangesFor}) is a
2275setting in =configure=. Changes are returned in *most-recent-first*
2276order.
2277
2278Use it as follows:
2279<verbatim>
2280 my $iterator = Foswiki::Func::eachChangeSince(
2281 $web, time() - 7 * 24 * 60 * 60); # the last 7 days
2282 while ($iterator->hasNext()) {
2283 my $change = $iterator->next();
2284 # $change is a perl hash that contains the following fields:
2285 # topic => topic name
2286 # user => wikiname - wikiname of user who made the change
2287 # time => time of the change
2288 # revision => revision number *after* the change
2289 # more => more info about the change (e.g. 'minor')
2290 }
2291</verbatim>
2292
2293=cut
2294
2295sub eachChangeSince {
2296 my ( $web, $time ) = @_;
2297 ASSERT($Foswiki::Plugins::SESSION) if DEBUG;
2298 ($web) = _validateWTA($web);
2299 ASSERT( $Foswiki::Plugins::SESSION->webExists($web) ) if DEBUG;
2300
2301 my $webObject = Foswiki::Meta->new( $Foswiki::Plugins::SESSION, $web );
2302
2303 # eachChange returns changes with cUIDs. these have to be mapped
2304 # to wikinames per the Foswiki::Func 'spec' (changes used to be stored
2305 # with wikinames)
2306 require Foswiki::Iterator::ProcessIterator;
2307 require Foswiki::Users::BaseUserMapping;
2308 return new Foswiki::Iterator::ProcessIterator(
2309 $webObject->eachChange($time),
2310 sub {
2311 my $n = shift;
2312 $n->{user} = $Foswiki::Users::BaseUserMapping::UNKNOWN_USER_CUID
2313 unless defined $n->{user};
2314 $n->{user} =
2315 $Foswiki::Plugins::SESSION->{users}->getWikiName( $n->{user} );
2316 return $n;
2317 }
2318 );
2319}
2320
2321=begin TML
2322
2323---+++ summariseChanges($web, $topic, $orev, $nrev, $tml) -> $text
2324Generate a summary of the changes between rev $orev and rev $nrev of the
2325given topic.
2326 * =$web=, =$topic= - topic (required)
2327 * =$orev= - older rev (required)
2328 * =$nrev= - later rev (may be undef for the latest)
2329 * =$tml= - if true will generate renderable TML (i.e. HTML with NOPs. if false will generate a summary suitable for use in plain text (mail, for example)
2330Generate a (max 3 line) summary of the differences between the revs.
2331
2332If there is only one rev, a topic summary will be returned.
2333
2334If =$tml= is not set, all HTML will be removed.
2335
2336In non-tml, lines are truncated to 70 characters. Differences are shown using + and - to indicate added and removed text.
2337
2338If access is denied to either revision, then it will be treated as blank
2339text.
2340
2341*Since* 2009-03-06
2342
2343=cut
2344
2345sub summariseChanges {
2346 my ( $web, $topic, $orev, $nrev, $tml ) = @_;
2347 ( $web, $topic ) = _validateWTA( $web, $topic );
2348
2349 my $topicObject =
2350 Foswiki::Meta->new( $Foswiki::Plugins::SESSION, $web, $topic );
2351 return $topicObject->summariseChanges( Foswiki::Store::cleanUpRevID($orev),
2352 Foswiki::Store::cleanUpRevID($nrev), $tml );
2353}
2354
2355=begin TML
2356
2357---++ Templates
2358
2359=cut
2360
2361=begin TML
2362
2363---+++ readTemplate( $name, $skin ) -> $text
2364
2365Read a template or skin. Embedded [[%SYSTEMWEB%.SkinTemplates][template directives]] get expanded
2366 * =$name= - Template name, e.g. ='view'=
2367 * =$skin= - Comma-separated list of skin names, optional, e.g. ='print'=
2368Return: =$text= Template text
2369
2370=cut
2371
2372sub readTemplate {
2373
2374 my ( $name, $skin ) = @_;
2375 ASSERT($Foswiki::Plugins::SESSION) if DEBUG;
2376 return $Foswiki::Plugins::SESSION->templates->readTemplate(
2377 $name,
2378 skins => $skin,
2379 no_oops => 1
2380 ) || '';
2381}
2382
2383=begin TML
2384
2385---+++ loadTemplate ( $name, $skin, $web ) -> $text
2386
2387 * =$name= - template file name
2388 * =$skin= - comma-separated list of skins to use (default: current skin)
2389 * =$web= - the web to look in for topics that contain templates (default: current web)
2390Return: expanded template text (what's left after removal of all %TMPL:DEF% statements)
2391
2392Reads a template and extracts template definitions, adding them to the
2393list of loaded templates, overwriting any previous definition.
2394
2395How Foswiki searches for templates is described in SkinTemplates.
2396
2397If template text is found, extracts include statements and fully expands them.
2398
2399=cut
2400
2401
# spent 430ms (66µs+430) within Foswiki::Func::loadTemplate which was called: # once (66µs+430ms) by Foswiki::Plugins::CommentPlugin::Comment::prompt at line 41 of /usr/local/src/github.com/foswiki/core/lib/Foswiki/Plugins/CommentPlugin/Comment.pm
sub loadTemplate {
2402865µs13µs ASSERT($Foswiki::Plugins::SESSION) if DEBUG;
# spent 3µs making 1 call to Assert::ASSERTS_OFF
2403 my ( $name, $skin, $web ) = @_;
2404
2405 my %opts = ( no_oops => 1 );
2406 $opts{skins} = $skin if defined $skin;
2407 ( $opts{web} ) = _validateWTA($web) if defined $web;
2408
24092430ms my $tmpl =
# spent 430ms making 1 call to Foswiki::Templates::readTemplate # spent 9µs making 1 call to Foswiki::templates
2410 $Foswiki::Plugins::SESSION->templates->readTemplate( $name, %opts );
2411 $tmpl = '' unless defined $tmpl;
2412
2413 return $tmpl;
2414}
2415
2416=begin TML
2417
2418---+++ expandTemplate( $def ) -> $string
2419
2420Do a =%<nop>TMPL:P{$def}%=, only expanding the template (not expanding any variables other than =%TMPL%=.)
2421 * =$def= - template name or parameters (as a string)
2422Return: the text of the expanded template
2423
2424A template is defined using a =%TMPL:DEF%= statement in a template
2425file. See the [[System.SkinTemplates][documentation on Foswiki templates]] for more information.
2426
2427eg:
2428 #load the templates (relying on the system-wide skin path.)
2429 Foswiki::Func::loadTemplate('linkedin');
2430 #get the 'profile' DEF section
2431 my $tml = Foswiki::Func::expandTemplate('profile');
2432 #get the 'profile' DEF section expanding the inline Template macros (such as %USER% and %TYPE%)
2433 #NOTE: when using it this way, it is important to use the double quotes "" to delineate the values of the parameters.
2434 my $tml = Foswiki::Func::expandTemplate(
2435 '"profile" USER="' . $user . '" TYPE="' . $type . '"' );
2436
2437=cut
2438
2439
# spent 1.08ms (84µs+999µs) within Foswiki::Func::expandTemplate which was called 3 times, avg 361µs/call: # once (38µs+588µs) by Foswiki::Plugins::CommentPlugin::Comment::prompt at line 55 of /usr/local/src/github.com/foswiki/core/lib/Foswiki/Plugins/CommentPlugin/Comment.pm # once (24µs+214µs) by Foswiki::Plugins::CommentPlugin::Comment::prompt at line 153 of /usr/local/src/github.com/foswiki/core/lib/Foswiki/Plugins/CommentPlugin/Comment.pm # once (22µs+197µs) by Foswiki::Plugins::CommentPlugin::Comment::prompt at line 84 of /usr/local/src/github.com/foswiki/core/lib/Foswiki/Plugins/CommentPlugin/Comment.pm
sub expandTemplate {
2440674µs311µs ASSERT($Foswiki::Plugins::SESSION) if DEBUG;
# spent 11µs making 3 calls to Assert::ASSERTS_OFF, avg 4µs/call
24416988µs return $Foswiki::Plugins::SESSION->templates->expandTemplate(@_);
# spent 958µs making 3 calls to Foswiki::Templates::expandTemplate, avg 319µs/call # spent 30µs making 3 calls to Foswiki::templates, avg 10µs/call
2442}
2443
2444=begin TML
2445
2446---++ Rendering
2447
2448=cut
2449
2450=begin TML
2451
2452---+++ expandCommonVariables( $text, $topic, $web, $meta ) -> $text
2453
2454Expand all common =%<nop>VARIABLES%=
2455 * =$text= - Text with variables to expand, e.g. ='Current user is %<nop>WIKIUSER%'=
2456 * =$topic= - Current topic name, e.g. ='WebNotify'=
2457 * =$web= - Web name, optional, e.g. ='Main'=. The current web is taken if missing
2458 * =$meta= - topic meta-data to use while expanding
2459Return: =$text= Expanded text, e.g. ='Current user is <nop>WikiGuest'=
2460
2461See also: expandVariablesOnTopicCreation
2462
2463=cut
2464
2465
# spent 1.25s (30.4ms+1.21) within Foswiki::Func::expandCommonVariables which was called 1094 times, avg 1.14ms/call: # 1092 times (30.4ms+1.21s) by Foswiki::Contrib::MailerContrib::WebNotify::_load at line 344 of /usr/local/src/github.com/foswiki/core/lib/Foswiki/Contrib/MailerContrib/WebNotify.pm, avg 1.14ms/call # once (39µs+1.39ms) by Foswiki::Plugins::TablePlugin::_readPluginSettings at line 132 of /usr/local/src/github.com/foswiki/core/lib/Foswiki/Plugins/TablePlugin.pm # once (32µs+1.23ms) by Foswiki::Plugins::TablePlugin::_readPluginSettings at line 135 of /usr/local/src/github.com/foswiki/core/lib/Foswiki/Plugins/TablePlugin.pm
sub expandCommonVariables {
2466547027.0ms my ( $text, $topic, $web, $meta ) = @_;
246710943.82ms ASSERT($Foswiki::Plugins::SESSION) if DEBUG;
# spent 3.82ms making 1094 calls to Assert::ASSERTS_OFF, avg 3µs/call
24681094105ms ( $web, $topic ) = _validateWTA(
# spent 105ms making 1094 calls to Foswiki::Func::_validateWTA, avg 96µs/call
2469 $web || $Foswiki::Plugins::SESSION->{webName},
2470 $topic || $Foswiki::Plugins::SESSION->{topicName}
2471 );
24722105µs $meta ||= Foswiki::Meta->new( $Foswiki::Plugins::SESSION, $web, $topic );
# spent 105µs making 2 calls to Foswiki::Meta::new, avg 53µs/call
2473
247410942.30ms return $meta->expandMacros($text);
# spent 1.11s making 1094 calls to Foswiki::Meta::expandMacros, avg 1.01ms/call, recursion: max depth 1, sum of overlapping time 1.10s
2475}
2476
2477=begin TML
2478
2479---+++ expandVariablesOnTopicCreation ( $text ) -> $text
2480
2481Expand the limited set of variables that are always expanded during topic creation
2482 * =$text= - the text to process
2483Return: text with variables expanded
2484
2485Expands only the variables expected in templates that must be statically
2486expanded in new content.
2487
2488The expanded variables are:
2489 * =%<nop>DATE%= Signature-format date
2490 * =%<nop>SERVERTIME%= See [[Macros]]
2491 * =%<nop>GMTIME%= See [[Macros]]
2492 * =%<nop>USERNAME%= Base login name
2493 * =%<nop>WIKINAME%= Wiki name
2494 * =%<nop>WIKIUSERNAME%= Wiki name with prepended web
2495 * =%<nop>URLPARAM{...}%= - Parameters to the current CGI query
2496 * =%<nop>NOP%= No-op
2497
2498See also: expandVariables
2499
2500=cut
2501
2502sub expandVariablesOnTopicCreation {
2503 ASSERT($Foswiki::Plugins::SESSION) if DEBUG;
2504 my $topicObject = Foswiki::Meta->new(
2505 $Foswiki::Plugins::SESSION,
2506 $Foswiki::Plugins::SESSION->{webName},
2507 $Foswiki::Plugins::SESSION->{topicName}, $_[0]
2508 );
2509 $topicObject->expandNewTopic();
2510 return $topicObject->text();
2511}
2512
2513=begin TML
2514
2515---+++ renderText( $text, $web, $topic ) -> $text
2516
2517Render text from TML into XHTML as defined in [[%SYSTEMWEB%.TextFormattingRules]]
2518 * =$text= - Text to render, e.g. ='*bold* text and =fixed font='=
2519 * =$web= - Web name, optional, e.g. ='Main'=. The current web is taken if missing
2520 * =$topic= - topic name, optional, defaults to web home
2521Return: =$text= XHTML text, e.g. ='&lt;b>bold&lt;/b> and &lt;code>fixed font&lt;/code>'=
2522
2523=cut
2524
2525sub renderText {
2526
2527 my ( $text, $web, $topic ) = @_;
2528 ASSERT($Foswiki::Plugins::SESSION) if DEBUG;
2529 $web ||= $Foswiki::Plugins::SESSION->{webName};
2530 $topic ||= $Foswiki::cfg{HomeTopicName};
2531 my $webObject =
2532 Foswiki::Meta->new( $Foswiki::Plugins::SESSION, $web, $topic );
2533 return $webObject->renderTML($text);
2534}
2535
2536=begin TML
2537
2538---+++ internalLink( $pre, $web, $topic, $label, $anchor, $createLink ) -> $text
2539
2540Render topic name and link label into an XHTML link. Normally you do not need to call this funtion, it is called internally by =renderText()=
2541 * =$pre= - Text occuring before the link syntax, optional
2542 * =$web= - Web name, required, e.g. ='Main'=
2543 * =$topic= - Topic name to link to, required, e.g. ='WebNotify'=
2544 * =$label= - Link label, required. Usually the same as =$topic=, e.g. ='notify'=
2545 * =$anchor= - Anchor, optional, e.g. ='#Jump'=
2546 * =$createLink= - Set to ='1'= to add question linked mark after topic name if topic does not exist;<br /> set to ='0'= to suppress link for non-existing topics
2547Return: =$text= XHTML anchor, e.g. ='&lt;a href='/cgi-bin/view/Main/WebNotify#Jump'>notify&lt;/a>'=
2548
2549=cut
2550
2551sub internalLink {
2552 my $pre = shift;
2553 ASSERT($Foswiki::Plugins::SESSION) if DEBUG;
2554
2555 # my( $web, $topic, $label, $anchor, $anchor, $createLink ) = @_;
2556 return $pre . $Foswiki::Plugins::SESSION->renderer->internalLink(@_);
2557}
2558
2559=begin TML
2560
2561---+++ addToZone( $zone, $id, $data, $requires )
2562
2563Direct interface to %<nop>ADDTOZONE (see %SYSTEMWEB%.VarADDTOZONE)
2564
2565 * =$zone= - name of the zone
2566 * =$id= - unique ID
2567 * =$data= - the content.
2568 * =requires= optional, comma-separated list of =$id= identifiers that should
2569 precede the content
2570
2571All macros present in =$data= will be expanded before being inserted into the =<head>= section.
2572
2573<blockquote class="foswikiHelp">%X%
2574*Note:* Read the developer supplement at Foswiki:Development.AddToZoneFromPluginHandlers if you are
2575calling =addToZone()= from a rendering or macro/tag-related plugin handler
2576</blockquote>
2577
2578Examples:
2579<verbatim>
2580Foswiki::Func::addToZone( 'head', 'PATTERN_STYLE',
2581 '<link rel="stylesheet" type="text/css" href="%PUBURL%/Foswiki/PatternSkin/layout.css" media="all" />');
2582
2583Foswiki::Func::addToZone( 'script', 'MY_JQUERY',
2584 '<script type="text/javascript" src="%PUBURL%/Myweb/MyJQuery/myjquery.js"></scipt>',
2585 'JQUERYPLUGIN::FOSWIKI');
2586</verbatim>
2587
2588=cut=
2589
2590
# spent 1.08ms (281µs+801µs) within Foswiki::Func::addToZone which was called 14 times, avg 77µs/call: # 5 times (103µs+324µs) by Foswiki::Plugins::JQueryPlugin::Plugin::init at line 125 of /usr/local/src/github.com/foswiki/core/lib/Foswiki/Plugins/JQueryPlugin/Plugin.pm, avg 85µs/call # 5 times (84µs+261µs) by Foswiki::Plugins::JQueryPlugin::Plugin::init at line 128 of /usr/local/src/github.com/foswiki/core/lib/Foswiki/Plugins/JQueryPlugin/Plugin.pm, avg 69µs/call # once (29µs+66µs) by Foswiki::Plugins::JQueryPlugin::Plugins::init at line 60 of /usr/local/src/github.com/foswiki/core/lib/Foswiki/Plugins/JQueryPlugin/Plugins.pm # once (30µs+60µs) by Foswiki::Plugins::TwistyPlugin::_exportAnimationSpeed at line 71 of /usr/local/src/github.com/foswiki/core/lib/Foswiki/Plugins/TwistyPlugin.pm # once (17µs+49µs) by Foswiki::Plugins::JQueryPlugin::Plugins::createTheme at line 115 of /usr/local/src/github.com/foswiki/core/lib/Foswiki/Plugins/JQueryPlugin/Plugins.pm # once (17µs+41µs) by Foswiki::Plugins::JQueryPlugin::FOSWIKI::init at line 90 of /usr/local/src/github.com/foswiki/core/lib/Foswiki/Plugins/JQueryPlugin/FOSWIKI.pm
sub addToZone {
2591
2592 #my ( $zone, $tag, $data, $requires ) = @_;
259342246µs my $session = $Foswiki::Plugins::SESSION;
25941446µs ASSERT($session) if DEBUG;
# spent 46µs making 14 calls to Assert::ASSERTS_OFF, avg 3µs/call
2595
259614754µs $session->addToZone(@_);
# spent 754µs making 14 calls to Foswiki::addToZone, avg 54µs/call
2597}
2598
2599=begin TML
2600
2601---++ Controlling page output
2602
2603=cut
2604
2605=begin TML
2606
2607---+++ writeHeader()
2608
2609Prints a basic content-type HTML header for text/html to standard out.
2610
2611=cut
2612
2613sub writeHeader {
2614 ASSERT($Foswiki::Plugins::SESSION) if DEBUG;
2615 $Foswiki::Plugins::SESSION->generateHTTPHeaders();
2616}
2617
2618=begin TML
2619
2620---+++ redirectCgiQuery( $query, $url, $passthru )
2621
2622Redirect to URL
2623 * =$query= - CGI query object. Ignored, only there for compatibility. The session CGI query object is used instead.
2624 * =$url= - URL to redirect to
2625 * =$passthru= - enable passthrough.
2626
2627Return: none
2628
2629Print output to STDOUT that will cause a 302 redirect to a new URL.
2630Nothing more should be printed to STDOUT after this method has been called.
2631
2632The =$passthru= parameter allows you to pass the parameters that were passed
2633to the current query on to the target URL, as long as it is another URL on the
2634same installation. If =$passthru= is set to a true value, then Foswiki
2635will save the current URL parameters, and then try to restore them on the
2636other side of the redirect. Parameters are stored on the server in a cache
2637file.
2638
2639Note that if =$passthru= is set, then any parameters in =$url= will be lost
2640when the old parameters are restored. if you want to change any parameter
2641values, you will need to do that in the current CGI query before redirecting
2642e.g.
2643<verbatim>
2644my $query = Foswiki::Func::getRequestObject();
2645$query->param(-name => 'text', -value => 'Different text');
2646Foswiki::Func::redirectCgiQuery(
2647 undef, Foswiki::Func::getScriptUrl($web, $topic, 'edit'), 1);
2648</verbatim>
2649=$passthru= does nothing if =$url= does not point to a script in the current
2650Foswiki installation.
2651
2652=cut
2653
2654sub redirectCgiQuery {
2655 my ( $query, $url, $passthru ) = @_;
2656 ASSERT($Foswiki::Plugins::SESSION) if DEBUG;
2657 return $Foswiki::Plugins::SESSION->redirect( $url, $passthru );
2658}
2659
2660=begin TML
2661
2662---++ Plugin-specific file handling
2663
2664=cut
2665
2666=begin TML
2667
2668---+++ getWorkArea( $pluginName ) -> $directorypath
2669
2670Gets a private directory for Plugin use. The Plugin is entirely responsible
2671for managing this directory; Foswiki will not read from it, or write to it.
2672
2673The directory is guaranteed to exist, and to be writable by the webserver
2674user. By default it will *not* be web accessible.
2675
2676The directory and its contents are permanent, so Plugins must be careful
2677to keep their areas tidy.
2678
2679=cut
2680
2681sub getWorkArea {
2682 my ($plugin) = @_;
2683 ASSERT($Foswiki::Plugins::SESSION) if DEBUG;
2684 return $Foswiki::Plugins::SESSION->getWorkArea($plugin);
2685}
2686
2687=begin TML
2688
2689---+++ readFile( $filename ) -> $text
2690
2691Read file, low level. Used for Plugin workarea.
2692 * =$filename= - Full path name of file
2693Return: =$text= Content of file, empty if not found
2694
2695__NOTE:__ Use this function only for the Plugin workarea, *not* for topics and attachments. Use the appropriate functions to manipulate topics and attachments.
2696
2697=cut
2698
2699sub readFile {
2700 my $name = shift;
2701 my $data = '';
2702 my $IN_FILE;
2703 open( $IN_FILE, '<', $name ) || return '';
2704 local $/ = undef; # set to read to EOF
2705 $data = <$IN_FILE>;
2706 close($IN_FILE);
2707 $data = '' unless $data; # no undefined
2708 return $data;
2709}
2710
2711=begin TML
2712
2713---+++ saveFile( $filename, $text )
2714
2715Save file, low level. Used for Plugin workarea.
2716 * =$filename= - Full path name of file
2717 * =$text= - Text to save
2718Return: none
2719
2720__NOTE:__ Use this function only for the Plugin workarea, *not* for topics and attachments. Use the appropriate functions to manipulate topics and attachments.
2721
2722=cut
2723
2724sub saveFile {
2725 my ( $name, $text ) = @_;
2726 my $FILE;
2727 unless ( open( $FILE, '>', $name ) ) {
2728 die "Can't create file $name - $!\n";
2729 }
2730 print $FILE $text;
2731 close($FILE);
2732}
2733
2734=begin TML
2735
2736---++ General Utilities
2737
2738=cut
2739
2740=begin TML
2741
2742---+++ normalizeWebTopicName($web, $topic) -> ($web, $topic)
2743
2744Parse a web and topic name, supplying defaults as appropriate.
2745 * =$web= - Web name, identifying variable, or empty string
2746 * =$topic= - Topic name, may be a web.topic string, required.
2747Return: the parsed Web/Topic pair
2748
2749| *Input* | *Return* |
2750| <tt>( 'Web', 'Topic' ) </tt> | <tt>( 'Web', 'Topic' ) </tt> |
2751| <tt>( '', 'Topic' ) </tt> | <tt>( 'Main', 'Topic' ) </tt> |
2752| <tt>( '', '' ) </tt> | <tt>( 'Main', 'WebHome' ) </tt> |
2753| <tt>( '', 'Web/Topic' ) </tt> | <tt>( 'Web', 'Topic' ) </tt> |
2754| <tt>( '', 'Web/Subweb/Topic' ) </tt> | <tt>( 'Web/Subweb', 'Topic' ) </tt> |
2755| <tt>( '', 'Web.Topic' ) </tt> | <tt>( 'Web', 'Topic' ) </tt> |
2756| <tt>( '', 'Web.Subweb.Topic' ) </tt> | <tt>( 'Web/Subweb', 'Topic' ) </tt> |
2757| <tt>( 'Web1', 'Web2.Topic' )</tt> | <tt>( 'Web2', 'Topic' ) </tt> |
2758
2759Note that hierarchical web names (Web.SubWeb) are only available if hierarchical webs are enabled in =configure=.
2760
2761The symbols %<nop>USERSWEB%, %<nop>SYSTEMWEB% and %<nop>DOCWEB% can be used in the input to represent the web names set in $cfg{UsersWebName} and $cfg{SystemWebName}. For example:
2762| *Input* | *Return* |
2763| <tt>( '%<nop>USERSWEB%', 'Topic' )</tt> | <tt>( 'Main', 'Topic' ) </tt> |
2764| <tt>( '%<nop>SYSTEMWEB%', 'Topic' )</tt> | <tt>( 'System', 'Topic' ) </tt> |
2765| <tt>( '', '%<nop>DOCWEB%.Topic' )</tt> | <tt>( 'System', 'Topic' ) </tt> |
2766
2767=cut
2768
2769
# spent 745ms (207+538) within Foswiki::Func::normalizeWebTopicName which was called 12255 times, avg 61µs/call: # 12164 times (205ms+534ms) by Foswiki::Contrib::MailerContrib::WebNotify::_subscribeTopic at line 430 of /usr/local/src/github.com/foswiki/core/lib/Foswiki/Contrib/MailerContrib/WebNotify.pm, avg 61µs/call # 22 times (362µs+1.42ms) by Foswiki::Search::formatResults at line 728 of /usr/local/src/github.com/foswiki/core/lib/Foswiki/Search.pm, avg 81µs/call # 22 times (345µs+1.36ms) by Foswiki::Store::Interfaces::QueryAlgorithm::__ANON__[/usr/local/src/github.com/foswiki/core/lib/Foswiki/Store/Interfaces/QueryAlgorithm.pm:187] at line 166 of /usr/local/src/github.com/foswiki/core/lib/Foswiki/Store/Interfaces/QueryAlgorithm.pm, avg 78µs/call # 22 times (355µs+989µs) by Foswiki::Store::QueryAlgorithms::BruteForce::_webQuery at line 177 of /usr/local/src/github.com/foswiki/core/lib/Foswiki/Store/QueryAlgorithms/BruteForce.pm, avg 61µs/call # 22 times (309µs+879µs) by Foswiki::Search::InfoCache::addTopics at line 76 of /usr/local/src/github.com/foswiki/core/lib/Foswiki/Search/InfoCache.pm, avg 54µs/call # 2 times (55µs+101µs) by Foswiki::Contrib::MailerContrib::_isSubscribedToTopic at line 156 of /usr/local/src/github.com/foswiki/core/lib/Foswiki/Contrib/MailerContrib.pm, avg 78µs/call # once (27µs+73µs) by Foswiki::Plugins::InterwikiPlugin::initPlugin at line 73 of /usr/local/src/github.com/foswiki/core/lib/Foswiki/Plugins/InterwikiPlugin.pm
sub normalizeWebTopicName {
2770
2771 #my( $web, $topic ) = @_;
277224510179ms1225542.2ms ASSERT($Foswiki::Plugins::SESSION) if DEBUG;
# spent 42.2ms making 12255 calls to Assert::ASSERTS_OFF, avg 3µs/call
277312255496ms return $Foswiki::Plugins::SESSION->normalizeWebTopicName(@_);
# spent 496ms making 12255 calls to Foswiki::normalizeWebTopicName, avg 40µs/call
2774}
2775
2776=begin TML
2777
2778---+++ query($searchString, $topics, \%options ) -> iterator (resultset)
2779
2780Query the topic data in the specified webs. A programatic interface to SEARCH results.
2781
2782 * =$searchString= - the search string, as appropriate for the selected type
2783 * =$topics= - undef OR reference to a ResultSet, Iterator, or array containing the web.topics to be evaluated.
2784 if undef, then all the topics in the webs specified will be evaluated.
2785 * =\%option= - reference to an options hash
2786The =\%options= hash may contain the following options:
2787 * =type= - =regex=, =keyword=, =query=, ... defaults to =query=
2788 * =web= - The web/s to search in - string can have the same form as the =web= param of SEARCH (if not specified, defaults to BASEWEB)
2789 * =casesensitive= - false to ignore case (default true)
2790 * =files_without_match= - true to return files only (default false). If =files_without_match= is specified, it will return on the first match in each topic (i.e. it will return only one match per
2791 * topic, excludetopic and other params as per SEARCH
2792
2793To iterate over the returned topics use:
2794<verbatim>
2795 my $matches = Foswiki::Func::query( "Slimy Toad", undef,
2796 { web => 'Main,San*', casesensitive => 0, files_without_match => 0 } );
2797 while ($matches->hasNext) {
2798 my $webtopic = $matches->next;
2799 my ($web, $topic) = Foswiki::Func::normalizeWebTopicName('', $webtopic);
2800 ...etc
2801</verbatim>
2802
2803=cut
2804
2805sub query {
2806 my ( $searchString, $topics, $options ) = @_;
2807 ASSERT($Foswiki::Plugins::SESSION) if DEBUG;
2808
2809 my $inputTopicSet = $topics;
2810 if ( $topics and ( ref($topics) eq 'ARRAY' ) ) {
2811 $inputTopicSet = new Foswiki::ListIterator($topics);
2812 }
2813 $options->{type} ||= 'query';
2814 my $query =
2815 $Foswiki::Plugins::SESSION->search->parseSearch( $searchString,
2816 $options );
2817
2818 return Foswiki::Meta::query( $query, $inputTopicSet, $options );
2819}
2820
2821=begin TML
2822
2823---+++ decodeFormatTokens($str) -> $unencodedString
2824
2825Foswiki has an informal standard set of tokens used in =format=
2826parameters that are used to block evaluation of paramater strings.
2827For example, if you were to write
2828
2829=%<nop>MYTAG{format="%<nop>WURBLE%"}%=
2830
2831then %<nop>WURBLE would be expanded *before* %<NOP>MYTAG is evaluated. To avoid
2832this Foswiki uses escapes in the format string. For example:
2833
2834=%<nop>MYTAG{format="$percentWURBLE$percent"}%=
2835
2836This lets you enter arbitrary strings into parameters without worrying that
2837Foswiki will expand them before your plugin gets a chance to deal with them
2838properly. Once you have processed your tag, you will want to expand these
2839tokens to their proper value. That's what this function does.
2840
2841The set of tokens that is expanded is described in System.FormatTokens.
2842
2843=cut
2844
2845sub decodeFormatTokens {
2846 return Foswiki::expandStandardEscapes(@_);
2847}
2848
2849=begin TML
2850
2851---+++ sanitizeAttachmentName($fname) -> ($fileName, $origName)
2852
2853Given a file path, sanitise it according to the rules for transforming
2854attachment names. Returns
2855the sanitised name together with the basename before sanitisation.
2856
2857Sanitation includes filtering illegal characters and mapping client
2858file names to legal server names.
2859
2860Avoid using this if you can; rewriting attachment names uses some very
2861nasty heuristics that cannot be changed because of compatibility issues.
2862It is much better use point-of-source validation to ensure only valid
2863attachment names are uploaded.
2864
2865=cut
2866
2867sub sanitizeAttachmentName {
2868 require Foswiki::Sandbox;
2869 return Foswiki::Sandbox::sanitizeAttachmentName(@_);
2870}
2871
2872=begin TML
2873
2874---+++ spaceOutWikiWord( $word, $sep ) -> $text
2875
2876Spaces out a wiki word by inserting a string (default: one space) between each word component.
2877With parameter $sep any string may be used as separator between the word components; if $sep is undefined it defaults to a space.
2878
2879=cut
2880
2881sub spaceOutWikiWord {
2882
2883 #my ( $word, $sep ) = @_;
2884 return Foswiki::spaceOutWikiWord(@_);
2885}
2886
2887=begin TML
2888
2889---+++ isTrue( $value, $default ) -> $boolean
2890
2891Returns 1 if =$value= is true, and 0 otherwise. "true" means set to
2892something with a Perl true value, with the special cases that "off",
2893"false" and "no" (case insensitive) are forced to false. Leading and
2894trailing spaces in =$value= are ignored.
2895
2896If the value is undef, then =$default= is returned. If =$default= is
2897not specified it is taken as 0.
2898
2899=cut
2900
2901
# spent 194ms (107+87.0) within Foswiki::Func::isTrue which was called 12167 times, avg 16µs/call: # 12164 times (107ms+86.9ms) by Foswiki::Func::eachGroupMember at line 1242, avg 16µs/call # 2 times (19µs+16µs) by Foswiki::Plugins::TablePlugin::Core::_parseAttributes at line 282 of /usr/local/src/github.com/foswiki/core/lib/Foswiki/Plugins/TablePlugin/Core.pm, avg 18µs/call # once (8µs+57µs) by Foswiki::Plugins::TablePlugin::Core::_parseAttributes at line 248 of /usr/local/src/github.com/foswiki/core/lib/Foswiki/Plugins/TablePlugin/Core.pm
sub isTrue {
2902
2903 # my ( $value, $default ) = @_;
2904
29051216792.5ms1216787.0ms return Foswiki::isTrue(@_);
# spent 87.0ms making 12167 calls to Foswiki::isTrue, avg 7µs/call
2906}
2907
2908=begin TML
2909
2910---+++ isValidWikiWord ( $text ) -> $boolean
2911
2912Check for a valid WikiWord or WikiName
2913 * =$text= - Word to test
2914
2915=cut
2916
2917sub isValidWikiWord {
2918 return Foswiki::isValidWikiWord(@_);
2919}
2920
2921=begin TML
2922
2923---+++ extractParameters($attr ) -> %params
2924
2925Extract all parameters from a variable string and returns a hash of parameters
2926 * =$attr= - Attribute string
2927Return: =%params= Hash containing all parameters. The nameless parameter is stored in key =_DEFAULT=
2928
2929 * Example:
2930 * Variable: =%<nop>TEST{ 'nameless' name1="val1" name2="val2" }%=
2931 * First extract text between ={...}= to get: ='nameless' name1="val1" name2="val2"=
2932 * Then call this on the text: <br />
2933 * params = Foswiki::Func::extractParameters( $text );=
2934 * The =%params= hash contains now: <br />
2935 =_DEFAULT => 'nameless'= <br />
2936 =name1 => "val1"= <br />
2937 =name2 => "val2"=
2938
2939=cut
2940
2941
# spent 924µs (85+839) within Foswiki::Func::extractParameters which was called 3 times, avg 308µs/call: # once (35µs+375µs) by Foswiki::Plugins::TablePlugin::_readPluginSettings at line 139 of /usr/local/src/github.com/foswiki/core/lib/Foswiki/Plugins/TablePlugin.pm # once (23µs+328µs) by Foswiki::Plugins::TablePlugin::_readPluginSettings at line 140 of /usr/local/src/github.com/foswiki/core/lib/Foswiki/Plugins/TablePlugin.pm # once (27µs+136µs) by Foswiki::Plugins::TablePlugin::Core::handler at line 1889 of /usr/local/src/github.com/foswiki/core/lib/Foswiki/Plugins/TablePlugin/Core.pm
sub extractParameters {
29421884µs my ($attr) = @_;
2943 require Foswiki::Attrs;
29443839µs my $params = new Foswiki::Attrs($attr);
# spent 839µs making 3 calls to Foswiki::Attrs::new, avg 280µs/call
2945
2946 # take out _RAW and _ERROR (compatibility)
2947 delete $params->{_RAW};
2948 delete $params->{_ERROR};
2949 return %$params;
2950}
2951
2952=begin TML
2953
2954---+++ extractNameValuePair( $attr, $name ) -> $value
2955
2956Extract a named or unnamed value from a variable parameter string
2957- Note: | Function Foswiki::Func::extractParameters is more efficient for extracting several parameters
2958 * =$attr= - Attribute string
2959 * =$name= - Name, optional
2960Return: =$value= Extracted value
2961
2962 * Example:
2963 * Variable: =%<nop>TEST{ 'nameless' name1="val1" name2="val2" }%=
2964 * First extract text between ={...}= to get: ='nameless' name1="val1" name2="val2"=
2965 * Then call this on the text: <br />
2966 =my $noname = Foswiki::Func::extractNameValuePair( $text );= <br />
2967 =my $val1 = Foswiki::Func::extractNameValuePair( $text, "name1" );= <br />
2968 =my $val2 = Foswiki::Func::extractNameValuePair( $text, "name2" );=
2969
2970=cut
2971
2972sub extractNameValuePair {
2973 require Foswiki::Attrs;
2974 return Foswiki::Attrs::extractValue(@_);
2975}
2976
2977=begin TML
2978
2979---+++ sendEmail ( $text, $retries ) -> $error
2980
2981 * =$text= - text of the mail, including MIME headers
2982 * =$retries= - number of times to retry the send (default 1)
2983Send an e-mail specified as MIME format content. To specify MIME
2984format mails, you create a string that contains a set of header
2985lines that contain field definitions and a message body such as:
2986<verbatim>
2987To: liz@windsor.gov.uk
2988From: serf@hovel.net
2989CC: george@whitehouse.gov
2990Subject: Revolution
2991
2992Dear Liz,
2993
2994Please abolish the monarchy (with King George's permission, of course)
2995
2996Thanks,
2997
2998A. Peasant
2999</verbatim>
3000Leave a blank line between the last header field and the message body.
3001
3002=cut
3003
3004sub sendEmail {
3005
3006 #my( $text, $retries ) = @_;
3007 ASSERT($Foswiki::Plugins::SESSION) if DEBUG;
3008 return $Foswiki::Plugins::SESSION->net->sendEmail(@_);
3009}
3010
3011=begin TML
3012
3013---++ Logging
3014
3015=cut
3016
3017=begin TML
3018
3019---+++ writeEvent( $action, $extra )
3020
3021Log an event.
3022 * =$action= - name of the event (keep them unique!)
3023 * =$extra= - arbitrary extra information to add to the log.
3024You can enumerate the contents of the log using the =eachEventSince= function.
3025
3026*NOTE:* Older plugins may use =$Foswiki::cfg{LogFileName}=. These
3027plugins must be modified to use =writeEvent= and =eachEventSince= instead.
3028
3029To maintain compatibility with older Foswiki releases, you can write
3030conditional code as follows:
3031<verbatim>
3032if (defined &Foswiki::Func::writeEvent) {
3033 # use writeEvent and eachEventSince
3034} else {
3035 # old code using {LogFileName}
3036}
3037</verbatim>
3038
3039Note that the ability to read/write =$Foswiki::cfg{LogFileName}= is
3040maintained for compatibility but is *deprecated* (should not be used
3041in new code intended to work only with Foswiki 1.1 and later) and will
3042not work with any installation that stores logs in a database.
3043
3044=cut
3045
3046sub writeEvent {
3047 my ( $action, $extra ) = @_;
3048 ASSERT($Foswiki::Plugins::SESSION) if DEBUG;
3049 my $webTopic =
3050 $Foswiki::Plugins::SESSION->{webName} . '.'
3051 . $Foswiki::Plugins::SESSION->{topicName};
3052 return $Foswiki::Plugins::SESSION->logEvent( $action, $webTopic, $extra );
3053}
3054
3055=begin TML
3056
3057---+++ writeWarning( $text )
3058
3059Log a warning that may require admin intervention to the warnings log (=data/warn*.txt=)
3060 * =$text= - Text to write; timestamp gets added
3061
3062=cut
3063
3064sub writeWarning {
3065 ASSERT($Foswiki::Plugins::SESSION) if DEBUG;
3066 return $Foswiki::Plugins::SESSION->logger->log( 'warning',
3067 scalar( caller() ), @_ );
3068}
3069
3070=begin TML
3071
3072---+++ writeDebug( $text )
3073
3074Log debug message to the debug log
3075 * =$text= - Text to write; timestamp gets added
3076
3077=cut
3078
3079sub writeDebug {
3080
3081 # my( $text ) = @_;
3082 ASSERT($Foswiki::Plugins::SESSION) if DEBUG;
3083 return $Foswiki::Plugins::SESSION->logger->log( 'debug', @_ );
3084}
3085
3086=begin TML
3087
3088---+++ eachEventSince($time, $level) -> $iterator
3089 * =$time= - a time in the past (seconds since the epoch)
3090 * =$level= - log level to return events for.
3091
3092Get an iterator over the list of all the events at the given level
3093between =$time= and now. Events are written to the event log using
3094=writeEvent=. The Foswiki core will write other events that will
3095also be returned.
3096
3097Events are returned in *oldest-first* order.
3098
3099Each event is returned as a reference to an array. The elements are:
3100 1 date of the event (seconds since the epoch)
3101 1 login name of the user who triggered the event
3102 1 the event name (the $action passed to =writeEvent=)
3103 1 the Web.Topic that the event applied to
3104 1 Extras (the $extra passed to =writeEvent=)
3105 1 The IP address that was the source of the event (if known)
3106
3107Use the iterator like this:
3108<verbatim>
3109my $it = Foswiki::Func::eachEventSince(Foswiki::Time::parseTime("1 Apr 2010"));
3110while ($it->hasNext()) {
3111 my $entry = $it->next();
3112 my $date = $entry->[0];
3113 my $loginName = $entry->[1];
3114 ...
3115}
3116</verbatim>
3117
3118=cut
3119
3120sub eachEventSince {
3121 my $time = shift;
3122 return $Foswiki::Plugins::SESSION->logger->eachEventSince( $time, 'info' );
3123}
3124
3125=begin TML
3126
3127---++ Deprecated functions
3128
3129From time-to-time, the Foswiki developers will add new functions to the interface (either to =Foswiki::Func=, or new handlers). Sometimes these improvements mean that old functions have to be deprecated to keep the code manageable. When this happens, the deprecated functions will be supported in the interface for at least one more release, and probably longer, though this cannot be guaranteed.
3130
3131Updated plugins may still need to define deprecated handlers for compatibility with old Foswiki versions. In this case, the plugin package that defines old handlers can suppress the warnings in %<nop>FAILEDPLUGINS%.
3132
3133This is done by defining a map from the handler name to the =Foswiki::Plugins= version _in which the handler was first deprecated_. For example, if we need to define the =endRenderingHandler= for compatibility with =Foswiki::Plugins= versions before 1.1, we would add this to the plugin:
3134<verbatim>
3135package Foswiki::Plugins::SinkPlugin;
3136use vars qw( %FoswikiCompatibility );
3137$FoswikiCompatibility{endRenderingHandler} = 1.1;
3138</verbatim>
3139If the currently-running code version is 1.1 _or later_, then the _handler will not be called_ and _the warning will not be issued_. Wersions of =Foswiki::Plugins= before 1.1 will still call the handler as required.
3140
3141The following functions are retained for compatibility only. You should
3142stop using them as soon as possible.
3143
3144=cut
3145
3146=begin TML
3147
3148---+++ getRegularExpression( $name ) -> $expr
3149
3150*Deprecated* 28 Nov 2008 - use =$Foswiki::regex{...}= instead, it is directly
3151equivalent.
3152
3153See System.DevelopingPlugins for more information
3154
3155=cut
3156
3157sub getRegularExpression {
3158 my ($regexName) = @_;
3159 return $Foswiki::regex{$regexName};
3160}
3161
3162=begin TML
3163
3164---+++ getScriptUrlPath( ) -> $path
3165
3166Get script URL path
3167
3168*Deprecated* 28 Nov 2008 - use =getScriptUrl= instead.
3169
3170Return: =$path= URL path of bin scripts, e.g. ="/cgi-bin"=
3171
3172*WARNING:* you are strongly recommended *not* to use this function, as the
3173{ScriptUrlPaths} URL rewriting rules will not apply to urls generated
3174using it.
3175
3176=cut
3177
3178sub getScriptUrlPath {
3179 ASSERT($Foswiki::Plugins::SESSION) if DEBUG;
3180 return $Foswiki::Plugins::SESSION->getScriptUrl( 0, '' );
3181}
3182
3183=begin TML
3184
3185---+++ getWikiToolName( ) -> $name
3186
3187*Deprecated* 28 Nov 2008 in Foswiki; use $Foswiki::cfg{WikiToolName} instead
3188
3189=cut
3190
3191sub getWikiToolName { return $Foswiki::cfg{WikiToolName}; }
3192
3193=begin TML
3194
3195---+++ getMainWebname( ) -> $name
3196
3197*Deprecated* 28 Nov 2008 in Foswiki; use $Foswiki::cfg{UsersWebName} instead
3198
3199=cut
3200
3201sub getMainWebname { return $Foswiki::cfg{UsersWebName}; }
3202
3203=begin TML
3204
3205---+++ getTwikiWebname( ) -> $name
3206
3207*Deprecated* 28 Nov 2008 in Foswiki; use $Foswiki::cfg{SystemWebName} instead
3208
3209=cut
3210
3211sub getTwikiWebname { return $Foswiki::cfg{SystemWebName}; }
3212
3213=begin TML
3214
3215---+++ getOopsUrl( $web, $topic, $template, $param1, $param2, $param3, $param4 ) -> $url
3216
3217Compose fully qualified 'oops' dialog URL
3218 * =$web= - Web name, e.g. ='Main'=. The current web is taken if empty
3219 * =$topic= - Topic name, e.g. ='WebNotify'=
3220 * =$template= - Oops template name, e.g. ='oopsmistake'=. The 'oops' is optional; 'mistake' will translate to 'oopsmistake'.
3221 * =$param1= ... =$param4= - Parameter values for %<nop>PARAM1% ... %<nop>PARAMn% variables in template, optional
3222Return: =$url= URL, e.g. ="http://example.com:80/cgi-bin/oops.pl/ Main/WebNotify?template=oopslocked&amp;param1=joe"=
3223
3224*Deprecated* 28 Nov 2008, the recommended approach is to throw an oops exception.
3225<verbatim>
3226 use Error qw( :try );
3227
3228 throw Foswiki::OopsException(
3229 'toestuckerror',
3230 web => $web,
3231 topic => $topic,
3232 params => [ 'I got my toe stuck' ]);
3233</verbatim>
3234(this example will use the =oopstoestuckerror= template.)
3235
3236If this is not possible (e.g. in a REST handler that does not trap the exception)
3237then you can use =getScriptUrl= instead:
3238<verbatim>
3239 my $url = Foswiki::Func::getScriptUrl($web, $topic, 'oops',
3240 template => 'oopstoestuckerror',
3241 param1 => 'I got my toe stuck');
3242 Foswiki::Func::redirectCgiQuery( undef, $url );
3243 return 0;
3244</verbatim>
3245
3246=cut
3247
3248sub getOopsUrl {
3249 my ( $web, $topic, $template, @params ) = @_;
3250
3251 my $n = 1;
3252 @params = map { 'param' . ( $n++ ) => $_ } @params;
3253 return getScriptUrl(
3254 $web, $topic, 'oops',
3255 template => $template,
3256 @params
3257 );
3258}
3259
3260=begin TML
3261
3262---+++ wikiToEmail( $wikiName ) -> $email
3263
3264 * =$wikiname= - wiki name of the user
3265Get the e-mail address(es) of the named user. If the user has multiple
3266e-mail addresses (for example, the user is a group), then the list will
3267be comma-separated.
3268
3269*Deprecated* 28 Nov 2008 in favour of wikinameToEmails, because this function only
3270returns a single email address, where a user may in fact have several.
3271
3272$wikiName may also be a login name.
3273
3274=cut
3275
3276sub wikiToEmail {
3277 my ($user) = @_;
3278 my @emails = wikinameToEmails($user);
3279 if ( scalar(@emails) ) {
3280 return $emails[0];
3281 }
3282 return '';
3283}
3284
3285=begin TML
3286
3287---+++ permissionsSet( $web ) -> $boolean
3288
3289Test if any access restrictions are set for this web, ignoring settings on
3290individual pages
3291 * =$web= - Web name, required, e.g. ='Sandbox'=
3292
3293*Deprecated* 28 Nov 2008 - use =getPreferencesValue= instead to determine
3294what permissions are set on the web, for example:
3295<verbatim>
3296foreach my $type (qw( ALLOW DENY )) {
3297 foreach my $action (qw( CHANGE VIEW )) {
3298 my $pref = $type . 'WEB' . $action;
3299 my $val = Foswiki::Func::getPreferencesValue( $pref, $web ) || '';
3300 if( $val =~ /\S/ ) {
3301 print "$pref is set to $val on $web\n";
3302 }
3303 }
3304}
3305</verbatim>
3306
3307=cut
3308
3309sub permissionsSet {
3310 my ($web) = @_;
3311
3312 foreach my $type (qw( ALLOW DENY )) {
3313 foreach my $action (qw( CHANGE VIEW RENAME )) {
3314 my $pref = $type . 'WEB' . $action;
3315 my $val = getPreferencesValue( $pref, $web ) || '';
3316 return 1 if ( $val =~ /\S/ );
3317 }
3318 }
3319
3320 return 0;
3321}
3322
3323=begin TML
3324
3325---+++ getPublicWebList( ) -> @webs
3326
3327*Deprecated* 28 Nov 2008 - use =getListOfWebs= instead.
3328
3329Get list of all public webs, e.g. all webs *and subwebs* that do not have the =NOSEARCHALL= flag set in the WebPreferences
3330
3331Return: =@webs= List of all public webs *and subwebs*
3332
3333=cut
3334
3335sub getPublicWebList {
3336 return getListOfWebs("user,public");
3337}
3338
3339=begin TML
3340
3341---+++ formatTime( $time, $format, $timezone ) -> $text
3342
3343*Deprecated* 28 Nov 2008 - use =Foswiki::Time::formatTime= instead (it has an identical interface).
3344
3345Format the time in seconds into the desired time string
3346 * =$time= - Time in epoch seconds
3347 * =$format= - Format type, optional. Default e.g. ='31 Dec 2002 - 19:30'=. Can be ='$iso'= (e.g. ='2002-12-31T19:30Z'=), ='$rcs'= (e.g. ='2001/12/31 23:59:59'=, ='$http'= for HTTP header format (e.g. ='Thu, 23 Jul 1998 07:21:56 GMT'=), or any string with tokens ='$seconds, $minutes, $hours, $day, $wday, $month, $mo, $year, $ye, $tz'= for seconds, minutes, hours, day of month, day of week, 3 letter month, 2 digit month, 4 digit year, 2 digit year, timezone string, respectively
3348 * =$timezone= - either not defined (uses the displaytime setting), 'gmtime', or 'servertime'
3349Return: =$text= Formatted time string
3350| Note: | if you used the removed formatGmTime, add a third parameter 'gmtime' |
3351
3352=cut
3353
3354sub formatTime {
3355
3356 # my ( $epSecs, $format, $timezone ) = @_;
3357 require Foswiki::Time;
3358 return Foswiki::Time::formatTime(@_);
3359}
3360
3361=begin TML
3362
3363---+++ formatGmTime( $time, $format ) -> $text
3364
3365*Deprecated* 28 Nov 2008 - use =Foswiki::Time::formatTime= instead.
3366
3367Format the time to GM time
3368 * =$time= - Time in epoc seconds
3369 * =$format= - Format type, optional. Default e.g. ='31 Dec 2002 - 19:30'=, can be ='iso'= (e.g. ='2002-12-31T19:30Z'=), ='rcs'= (e.g. ='2001/12/31 23:59:59'=, ='http'= for HTTP header format (e.g. ='Thu, 23 Jul 1998 07:21:56 GMT'=)
3370Return: =$text= Formatted time string
3371
3372=cut
3373
3374sub formatGmTime {
3375
3376 # my ( $epSecs, $format ) = @_;
3377 require Foswiki::Time;
3378 return Foswiki::Time::formatTime( @_, 'gmtime' );
3379}
3380
3381=begin TML
3382
3383---+++ getDataDir( ) -> $dir
3384
3385*Deprecated* 28 Nov 2008 - use the "Webs, Topics and Attachments" functions
3386to manipulate topics instead
3387
3388=cut
3389
3390sub getDataDir {
3391 return $Foswiki::cfg{DataDir};
3392}
3393
3394=begin TML
3395
3396---+++ getPubDir( ) -> $dir
3397
3398*Deprecated* 28 Nov 2008 - use the "Webs, Topics and Attachments" functions
3399to manipulate attachments instead
3400
3401=cut
3402
3403sub getPubDir { return $Foswiki::cfg{PubDir}; }
3404
3405=begin TML
3406
3407---+++ getCgiQuery( ) -> $query
3408
3409*Deprecated* 31 Mar 2009 - use =getRequestObject= instead if you can. Code
3410that is expected to run with pre-1.1 versions of Foswiki will still need to
3411use this method, as =getRequestObject= will not be available.
3412
3413=cut
3414
341511148µs11211µs
# spent 340µs (129+211) within Foswiki::Func::getCgiQuery which was called 11 times, avg 31µs/call: # 3 times (32µs+46µs) by Foswiki::Plugins::WysiwygPlugin::beforeCommonTagsHandler at line 262 of /usr/local/src/github.com/foswiki/core/lib/Foswiki/Plugins/WysiwygPlugin.pm, avg 26µs/call # 2 times (26µs+41µs) by Foswiki::Plugins::SubscribePlugin::_SUBSCRIBE at line 32 of /usr/local/src/github.com/foswiki/core/lib/Foswiki/Plugins/SubscribePlugin.pm, avg 33µs/call # 2 times (16µs+27µs) by Foswiki::Plugins::TablePlugin::Core::_parseAttributes at line 273 of /usr/local/src/github.com/foswiki/core/lib/Foswiki/Plugins/TablePlugin/Core.pm, avg 21µs/call # once (16µs+33µs) by Foswiki::Plugins::TablePlugin::initPlugin at line 41 of /usr/local/src/github.com/foswiki/core/lib/Foswiki/Plugins/TablePlugin.pm # once (16µs+22µs) by Foswiki::Plugins::EditTablePlugin::initPlugin at line 46 of /usr/local/src/github.com/foswiki/core/lib/Foswiki/Plugins/EditTablePlugin.pm # once (12µs+22µs) by Foswiki::Plugins::TinyMCEPlugin::initPlugin at line 30 of /usr/local/src/github.com/foswiki/core/lib/Foswiki/Plugins/TinyMCEPlugin.pm # once (12µs+20µs) by Foswiki::Plugins::TablePlugin::Core::handler at line 1835 of /usr/local/src/github.com/foswiki/core/lib/Foswiki/Plugins/TablePlugin/Core.pm
sub getCgiQuery { return getRequestObject(); }
# spent 211µs making 11 calls to Foswiki::Func::getRequestObject, avg 19µs/call
3416
3417# Removed; it was never used
3418sub checkDependencies {
3419 die
3420"checkDependencies removed; contact plugin author or maintainer and tell them to use BuildContrib DEPENDENCIES instead";
3421}
3422
3423=begin TML
3424
3425---+++ readTopicText( $web, $topic, $rev, $ignorePermissions ) -> $text
3426
3427Read topic text, including meta data
3428 * =$web= - Web name, e.g. ='Main'=, or empty
3429 * =$topic= - Topic name, e.g. ='MyTopic'=, or ="Main.MyTopic"=
3430 * =$rev= - Topic revision to read, optional. Specify the minor part of the revision, e.g. ="5"=, not ="1.5"=; the top revision is returned if omitted or empty.
3431 * =$ignorePermissions= - Set to ="1"= if checkAccessPermission() is already performed and OK; an oops URL is returned if user has no permission
3432
3433Return: =$text= Topic text with embedded meta data; an oops URL for calling redirectCgiQuery() is returned in case of an error
3434
3435*Deprecated: 6 Aug 2009. Use =readTopic= instead.
3436This method returns meta-data embedded in the text. Plugins authors must be very careful to avoid damaging meta-data. Use readTopic instead, which is a lot safer and supports the full set of read options.
3437
3438=cut
3439
3440
# spent 20.3s (197µs+20.3) within Foswiki::Func::readTopicText which was called 2 times, avg 10.1s/call: # once (109µs+20.3s) by Foswiki::Plugins::SmiliesPlugin::initPlugin at line 38 of /usr/local/src/github.com/foswiki/core/lib/Foswiki/Plugins/SmiliesPlugin.pm # once (88µs+5.66ms) by Foswiki::Plugins::InterwikiPlugin::initPlugin at line 87 of /usr/local/src/github.com/foswiki/core/lib/Foswiki/Plugins/InterwikiPlugin.pm
sub readTopicText {
344118198µs my ( $web, $topic, $rev, $ignorePermissions ) = @_;
344227µs ASSERT($Foswiki::Plugins::SESSION) if DEBUG;
# spent 7µs making 2 calls to Assert::ASSERTS_OFF, avg 4µs/call
3443
3444 my $user;
3445 $user = $Foswiki::Plugins::SESSION->{user}
3446 unless defined($ignorePermissions);
3447
3448220.3s my $topicObject =
# spent 20.3s making 2 calls to Foswiki::Meta::load, avg 10.1s/call
3449 Foswiki::Meta->load( $Foswiki::Plugins::SESSION, $web, $topic, $rev );
3450
3451 my $text;
3452 if ( $ignorePermissions
3453 || $topicObject->haveAccess( 'VIEW',
3454 $Foswiki::Plugins::SESSION->{user} ) )
3455 {
345626.97ms $text = $topicObject->getEmbeddedStoreForm();
# spent 6.97ms making 2 calls to Foswiki::Meta::getEmbeddedStoreForm, avg 3.49ms/call
3457 }
3458 else {
3459 $text = getScriptUrl(
3460 $web, $topic, 'oops',
3461 template => 'oopsaccessdenied',
3462 def => 'topic_access',
3463 param1 => 'VIEW',
3464 param2 => $Foswiki::Meta::reason
3465 );
3466 }
3467
3468 return $text;
3469}
3470
3471=begin TML
3472
3473---+++ saveTopicText( $web, $topic, $text, $ignorePermissions, $dontNotify ) -> $oopsUrl
3474
3475Save topic text, typically obtained by readTopicText(). Topic data usually includes meta data; the file attachment meta data is replaced by the meta data from the topic file if it exists.
3476 * =$web= - Web name, e.g. ='Main'=, or empty
3477 * =$topic= - Topic name, e.g. ='MyTopic'=, or ="Main.MyTopic"=
3478 * =$text= - Topic text to save, assumed to include meta data
3479 * =$ignorePermissions= - Set to ="1"= if checkAccessPermission() is already performed and OK
3480 * =$dontNotify= - Set to ="1"= if not to notify users of the change
3481
3482*Deprecated* 6 Aug 2009 - use saveTopic instead.
3483=saveTopic= supports embedded meta-data in the saved text, and also
3484supports the full set of save options.
3485
3486Return: =$oopsUrl= Empty string if OK; the =$oopsUrl= for calling redirectCgiQuery() in case of error
3487
3488<verbatim>
3489my $text = Foswiki::Func::readTopicText( $web, $topic );
3490
3491# check for oops URL in case of error:
3492if( $text =~ /^http.*?\/oops/ ) {
3493 Foswiki::Func::redirectCgiQuery( $query, $text );
3494 return;
3495}
3496# do topic text manipulation like:
3497$text =~ s/old/new/g;
3498# do meta data manipulation like:
3499$text =~ s/(META\:FIELD.*?name\=\"TopicClassification\".*?value\=\")[^\"]*/$1BugResolved/;
3500$oopsUrl = Foswiki::Func::saveTopicText( $web, $topic, $text ); # save topic text
3501</verbatim>
3502
3503=cut
3504
3505sub saveTopicText {
3506 my ( $web, $topic, $text, $ignorePermissions, $dontNotify ) = @_;
3507 ASSERT($Foswiki::Plugins::SESSION) if DEBUG;
3508
3509 my $session = $Foswiki::Plugins::SESSION;
3510
3511 # extract meta data and merge old attachment meta data
3512 require Foswiki::Meta;
3513 my $topicObject = Foswiki::Meta->new( $session, $web, $topic );
3514 $topicObject->remove('FILEATTACHMENT');
3515
3516 my $oldMeta = Foswiki::Meta->load( $session, $web, $topic );
3517 $topicObject->copyFrom( $oldMeta, 'FILEATTACHMENT' );
3518
3519 my $outcome = '';
3520 unless ( $ignorePermissions || $topicObject->haveAccess('CHANGE') ) {
3521 my @caller = caller();
3522 return getScriptUrl(
3523 $web, $topic, 'oops',
3524 template => 'oopsattention',
3525 def => 'topic_access',
3526 param1 => ( $caller[0] || 'unknown' )
3527 );
3528 }
3529 $topicObject->text($text);
3530
3531 try {
3532 $topicObject->save( minor => $dontNotify );
3533 }
3534 catch Error::Simple with {
3535 $outcome = getScriptUrl(
3536 $web, $topic, 'oops',
3537 template => 'oopsattention',
3538 def => 'save_error',
3539 param1 => shift->{-text}
3540 );
3541 };
3542 return $outcome;
3543}
3544
3545=begin TML
3546
3547---+++ addToHEAD( $id, $data, $requires )
3548
3549Adds =$data= to the HTML header (the <head> tag).
3550
3551*Deprecated* 26 Mar 2010 - use =addZoZone('head', ...)=.
3552
3553%X% *Note:* Any calls using addToHEAD for javascript should be rewritten to use the
3554new =script= zone in addToZone as soon as possible.
3555
3556Rewrite:
3557<verbatim>
3558Foswiki::Func::addToHEAD("id", "<script>...</script>", "JQUERYPLUGIN");
3559</verbatim>
3560To:
3561<verbatim>
3562Foswiki::Func::addToZone("script", "id", "<script>...</script>", "JQUERYPLUGIN");
3563</verbatim>
3564
3565The reason is that all &lt;script> markup should be added to a dedicated zone, script,
3566and so any usage of ADDTOHEAD - which adds to the head zone - will be unable to
3567satisfy ordering requirements when the requirements exist in another zone ( script ).
3568
3569See Foswiki:Development/UpdatingExtensionsScriptZone for more details.
3570
3571=cut
3572
3573
# spent 68µs (17+51) within Foswiki::Func::addToHEAD which was called: # once (17µs+51µs) by Foswiki::Plugins::TablePlugin::Core::_writeStyleToHead at line 1308 of /usr/local/src/github.com/foswiki/core/lib/Foswiki/Plugins/TablePlugin/Core.pm
sub addToHEAD {
3574117µs151µs $Foswiki::Plugins::SESSION->addToZone( 'head', @_ );
# spent 51µs making 1 call to Foswiki::addToZone
3575}
3576
3577=begin TML
3578
3579---+++ searchInWebContent($searchString, $web, \@topics, \%options ) -> reference to a hash - keys of which are topic names
3580
3581*Deprecated* 17 Oct 2010 - use =query( ...)=.
3582__WARNING: This function has been deprecated in foswiki 1.1.0 for scalability reasons__
3583
3584
3585Search for a string in the content of a web. The search is over all content, including meta-data.
3586Meta-data matches will be returned as formatted lines within the topic content (meta-data matches are returned as lines of the format %META:\w+{.*}%)
3587 * =$searchString= - the search string, in egrep format
3588 * =$web= - The web/s to search in - string can have the same form as the =web= param of SEARCH
3589 * =\@topics= - reference to a list of topics to search (if undef, then the store will search all topics in the specified web/webs.)
3590 * =\%option= - reference to an options hash
3591The =\%options= hash may contain the following options:
3592 * =type= - =regex=, =keyword=, =query= - defaults to =regex=
3593 * =casesensitive= - false to ignore case (default true)
3594 * =files_without_match= - true to return files only (default false). If =files_without_match= is specified, it will return on the first match in each topic (i.e. it will return only one match per topic, and will not return matching lines).
3595 * TODO: topic, excludetopic and other params as per SEARCH
3596
3597The return value is a reference to a hash which maps each matching topic
3598name to a list of the lines in that topic that matched the search,
3599as would be returned by 'grep'.
3600
3601To iterate over the returned topics use:
3602<verbatim>
3603 my $matches = Foswiki::Func::searchInWebContent( "Slimy Toad", $searchWeb, \@topics,
3604 { casesensitive => 0, files_without_match => 0 } );
3605 foreach my $topic (keys(%$matches)) {
3606 ...etc
3607</verbatim>
3608
3609
3610=cut
3611
3612sub searchInWebContent {
3613
3614 my ( $searchString, $webs, $topics, $options ) = @_;
3615 ASSERT($Foswiki::Plugins::SESSION) if DEBUG;
3616
3617 my $inputTopicSet = $topics;
3618 if ( $topics and ( ref($topics) eq 'ARRAY' ) ) {
3619 $inputTopicSet = new Foswiki::ListIterator($topics);
3620 }
3621 $options->{type} ||= 'regex';
3622 $options->{web} = $webs;
3623 my $query =
3624 $Foswiki::Plugins::SESSION->search->parseSearch( $searchString,
3625 $options );
3626
3627 my $itr = Foswiki::Meta::query( $query, $inputTopicSet, $options );
3628 my %matches;
3629 while ( $itr->hasNext ) {
3630 my $webtopic = $itr->next;
3631 my ( $web, $searchTopic ) =
3632 Foswiki::Func::normalizeWebTopicName( '', $webtopic );
3633 $matches{$searchTopic} = 1;
3634 }
3635 return \%matches;
3636}
3637
363816µs1;
3639
3640__END__
 
# spent 129µs within Foswiki::Func::CORE:match which was called 26 times, avg 5µs/call: # 26 times (129µs+0s) by Foswiki::Func::registerTagHandler at line 540, avg 5µs/call
sub Foswiki::Func::CORE:match; # opcode
# spent 42µs within Foswiki::Func::CORE:subst which was called 7 times, avg 6µs/call: # 6 times (35µs+0s) by Foswiki::Func::registerRESTHandler at line 655, avg 6µs/call # once (8µs+0s) by Foswiki::Func::getPluginPreferencesValue at line 752
sub Foswiki::Func::CORE:subst; # opcode