1
# See bottom of file for license and copyright information
5
---+ package Foswiki::Attrs
7
Class of attribute sets, designed for parsing and storing attribute values
8
from a macro e.g. =%<nop>MACRO{"joe" fred="bad" joe="mad"}%=
10
An attribute set is a hash containing an entry for each parameter. The
11
default parameter (unnamed quoted string) is named <code>_<nop>DEFAULT</code> in the hash.
13
Attributes declared later in the string will override those of the same
14
name defined earlier. The one exception to this is the _DEFAULT key, where
15
the _first_ instance is always taken.
17
As well as the default Foswiki syntax (parameter values double-quoted)
18
this class also parses single-quoted values, unquoted spaceless
19
values, spaces around the =, and commas as well as spaces separating values.
20
The extended syntax has to be enabled by passing the =$friendly= parameter
23
API version $Date: 2009-01-06 19:25:41 +0100 (Tue, 06 Jan 2009) $ (revision $Rev: 4272 (2009-06-21) $)
25
*Since* _date_ indicates where functions or parameters have been added since
26
the baseline of the API (TWiki release 4.2.3). The _date_ indicates the
27
earliest date of a Foswiki release that will support that function or
30
*Deprecated* _date_ indicates where a function or parameters has been
31
[[http://en.wikipedia.org/wiki/Deprecation][deprecated]]. Deprecated
32
functions will still work, though they should
33
_not_ be called in new plugins and should be replaced in older plugins
34
as soon as possible. Deprecated parameters are simply ignored in Foswiki
35
releases after _date_.
37
*Until* _date_ indicates where a function or parameter has been removed.
38
The _date_ indicates the latest date at which Foswiki releases still supported
39
the function or parameter.
43
# THIS PACKAGE IS PART OF THE PUBLISHED API USED BY EXTENSION AUTHORS.
44
# DO NOT CHANGE THE EXISTING APIS (well thought out extensions are OK)
45
# AND ENSURE ALL POD DOCUMENTATION IS COMPLETE AND ACCURATE.
47
package Foswiki::Attrs;
52
our $VERSION = '$Rev: 4272 (2009-06-21) $';
54
our $ERRORKEY = '_ERROR';
55
our $DEFAULTKEY = '_DEFAULT';
60
---++ ClassMethod new ($string) => \%attrsObjectRef
62
* =$string= - String containing attribute specification
64
Parse a standard attribute string containing name=value pairs and create a new
65
attributes object. The value may be a word or a quoted string. If there is an
66
error during parsing, the parse will complete but $attrs->{_ERROR} will be
67
set in the new object. $attrs->{_RAW} will always contain the full unprocessed
73
my ( $class, $string, $friendly ) = @_;
74
my $this = bless( {}, $class );
76
$this->{$RAWKEY} = $string;
78
return $this unless defined($string);
81
s/\\(["'])/$Foswiki::TranslationToken.sprintf("%.2u", ord($1))/ge; # escapes
83
my $sep = ( $friendly ? "[\\s,]" : "\\s" );
86
if ( !$friendly && $string =~ s/^\s*\"(.*?)\"\s*(\w+\s*=\s*\"|$)/$2/s ) {
87
$this->{$DEFAULTKEY} = $1;
89
while ( $string =~ m/\S/s ) {
92
if ( $string =~ s/^$sep*(\w+)\s*=\s*\"(.*?)\"//is ) {
97
# simple double-quoted value with no name, sets the default
98
elsif ( $string =~ s/^$sep*\"(.*?)\"//os ) {
99
$this->{$DEFAULTKEY} = $1
100
unless defined( $this->{$DEFAULTKEY} );
106
if ( $string =~ s/^$sep*(\w+)\s*=\s*'(.*?)'//is ) {
111
elsif ( $string =~ s/^$sep*(\w+)\s*=\s*([^\s,\}\'\"]*)//is ) {
115
# simple single-quoted value with no name, sets the default
116
elsif ( $string =~ s/^$sep*'(.*?)'//os ) {
117
$this->{$DEFAULTKEY} = $1
118
unless defined( $this->{$DEFAULTKEY} );
121
# simple name with no value (boolean, or _DEFAULT)
122
elsif ( $string =~ s/^$sep*([a-z]\w*)\b//is ) {
127
# otherwise the whole string - sans padding - is the default
129
# SMELL: unchecked implicit untaint?
130
if ( $string =~ m/^\s*(.*?)\s*$/s
131
&& !defined( $this->{$DEFAULTKEY} ) )
133
$this->{$DEFAULTKEY} = $1;
138
# SMELL: unchecked implicit untaint?
139
elsif ( $string =~ m/^\s*(.*?)\s*$/s ) {
140
$this->{$DEFAULTKEY} = $1 if ($first);
144
foreach my $k ( keys %$this ) {
145
$this->{$k} =~ s/$Foswiki::TranslationToken(\d\d)/chr($1)/geo; # escapes
152
---++ ObjectMethod isEmpty() -> boolean
154
Return false if attribute set is not empty.
161
foreach my $k ( keys %$this ) {
162
return 0 if $k ne $RAWKEY;
169
---++ ObjectMethod remove($key) -> $value
171
* =$key= - Attribute to remove
172
Remove an attr value from the map, return old value. After a call to
173
=remove= the attribute is no longer defined.
178
my ( $this, $attr ) = @_;
179
my $val = $this->{$attr};
180
delete( $this->{$attr} ) if ( exists $this->{$attr} );
186
---++ ObjectMethod stringify() -> $string
188
Generate a printed form for the map, using strict
189
attribute syntax, with only the single-quote extension
190
syntax observed (no {} brackets, though).
198
foreach $key ( sort keys %$this ) {
199
if ( $key ne $ERRORKEY && $key ne $RAWKEY ) {
200
my $es = ( $key eq $DEFAULTKEY ) ? '' : $key . '=';
201
my $val = $this->{$key};
203
push( @ss, $es . '"' . $val . '"' );
206
return join( ' ', @ss );
209
# ---++ StaticMethod extractValue() -> $string
211
# Legacy support, formerly known as extractNameValuePair. This
212
# static method uses context information to determine how a value
213
# string is to be parsed. For example, if you have an attribute string
216
# "abc def="ghi" jkl" def="qqq"
218
# then call extractValue( "def" ), it will return "ghi".
221
my ( $str, $name ) = @_;
224
return $value unless ($str);
225
$str =~ s/\\\"/\\$Foswiki::TranslationToken/g; # escape \"
229
# format is: %VAR{ ... name = "value" }%
230
if ( $str =~ /(^|[^\S])$name\s*=\s*\"([^\"]*)\"/ ) {
231
$value = $2 if defined $2; # distinguish between '' and "0"
237
# test if format: { "value" ... }
238
# SMELL: unchecked implicit untaint?
239
if ( $str =~ /(^|\=\s*\"[^\"]*\")\s*\"(.*?)\"\s*(\w+\s*=\s*\"|$)/ ) {
241
# is: %VAR{ "value" }%
242
# or: %VAR{ "value" param="etc" ... }%
243
# or: %VAR{ ... = "..." "value" ... }%
244
# Note: "value" may contain embedded double quotes
245
$value = $2 if defined $2; # distinguish between '' and "0";
248
elsif ( ( $str =~ /^\s*\w+\s*=\s*\"([^\"]*)/ ) && ($1) ) {
250
# is: %VAR{ name = "value" }%
251
# do nothing, is not a standalone var
256
# format is: %VAR{ value }%
260
$value =~ s/\\$Foswiki::TranslationToken/\"/go; # resolve \"
264
# ---++ ObjectMethod get($key) -> $value
266
# | $key | Attribute to get |
267
# Get an attr value from the map.
269
# Synonymous with $attrs->{$key}. Retained mainly for compatibility with
270
# the old AttrsContrib.
272
my ( $this, $field ) = @_;
273
return $this->{$field};
278
# Module of Foswiki - The Free and Open Source Wiki, http://foswiki.org/
280
# Copyright (C) 2008-2009 Foswiki Contributors. Foswiki Contributors
281
# are listed in the AUTHORS file in the root of this distribution.
282
# NOTE: Please extend that file, not this notice.
284
# Additional copyrights apply to some or all of the code in this
286
# Derived from Contrib::Attrs, which is
287
# Copyright (C) 2001 Motorola - All rights reserved
288
# Copyright (C) 1999-2007 TWiki Contributors. All Rights Reserved.
289
# TWiki Contributors are listed in the AUTHORS file in the root of
290
# this distribution. NOTE: Please extend that file, not this notice.
292
# This program is free software; you can redistribute it and/or
293
# modify it under the terms of the GNU General Public License
294
# as published by the Free Software Foundation; either version 2
295
# of the License, or (at your option) any later version. For
296
# more details read LICENSE in the root of this distribution.
298
# This program is distributed in the hope that it will be useful,
299
# but WITHOUT ANY WARRANTY; without even the implied warranty of
300
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
302
# As per the GPL, removal of this notice is prohibited.