[Jifty-commit] jifty branch, master, updated. e52f12d49f342d861484709cafa8911445b2a52d
Jifty commits
jifty-commit at lists.jifty.org
Thu Jan 7 18:09:50 EST 2010
The branch, master has been updated
via e52f12d49f342d861484709cafa8911445b2a52d (commit)
from d6ed667414e6270fd3aa2834535ade0b4906b322 (commit)
Summary of changes:
Makefile.PL | 4 +-
lib/Jifty/JSON.pm | 153 ++++++++++----------------
lib/Jifty/Plugin/REST/Dispatcher.pm | 4 +-
lib/Jifty/Plugin/SetupWizard/View.pm | 4 +-
lib/Jifty/Plugin/SinglePage.pm | 2 +-
lib/Jifty/Request.pm | 2 +-
lib/Jifty/Script/Po.pm | 7 +-
lib/Jifty/Web/Form/Element.pm | 17 +--
lib/Jifty/Web/Form/Field.pm | 7 +-
lib/Jifty/Web/Menu.pm | 2 +-
lib/Jifty/Web/PageRegion.pm | 2 +-
share/web/templates/__jifty/webservices/json | 2 +-
t/TestApp-Plugin-REST/t/03-format.t | 4 +-
t/TestApp/t/16-template-region.t | 2 +-
14 files changed, 85 insertions(+), 127 deletions(-)
- Log -----------------------------------------------------------------
commit e52f12d49f342d861484709cafa8911445b2a52d
Author: Thomas Sibley <trs at bestpractical.com>
Date: Thu Jan 7 18:04:32 2010 -0500
Update Jifty::JSON to use modern JSON.pm (2.xx)
Jifty::JSON's pure Perl functions no longer worked with modern
JSON.pm's, and JSON::Syck has been more or less deprecated in favor of
modern JSON and JSON::XS.
This deprecates the "singlequote" option that the previous version of
Jifty::JSON supported. Single quoted strings are a violation of the
JSON spec. Instead, HTML escape the entire blob of JSON if you plan to
put it in an HTML attribute. Jifty::JSON will croak if you attempt to
use the "singlequote" option.
diff --git a/Makefile.PL b/Makefile.PL
index 30cd50e..140f816 100644
--- a/Makefile.PL
+++ b/Makefile.PL
@@ -53,6 +53,7 @@ requires('Hook::LexWrap');
requires('IPC::PubSub' => '0.23' );
requires('IPC::Run3');
requires('Jifty::DBI' => '0.60' ); # Jifty::DBI::Collection Jifty::DBI::Handle Jifty::DBI::Record::Cachable Jifty::DBI::SchemaGenerator
+requires('JSON' => 2.17);
requires('List::MoreUtils');
requires('Locale::Maketext::Extract' => '0.35');
requires('Locale::Maketext::Lexicon' => '0.77');
@@ -96,11 +97,10 @@ if (can_cc()) {
requires('YAML' => 0.35); # Use YAML::Dump for the moment since YAML.pm segfaults on
# reading stupidly long (~20K characters) double-quoted
# strings, and we need to produce YAML.pm-readable output.
- requires('JSON::Syck' => 0.29);
+ requires('JSON::XS' => 2.27);
}
else {
requires('YAML' => 0.35) unless can_use('YAML::Syck' => 0.71);
- requires('JSON' => 0.01) unless can_use('JSON::Syck' => 0.29);
}
feature 'Administrative Interface (web)' =>
diff --git a/lib/Jifty/JSON.pm b/lib/Jifty/JSON.pm
index 040a21e..711b0b3 100644
--- a/lib/Jifty/JSON.pm
+++ b/lib/Jifty/JSON.pm
@@ -4,7 +4,10 @@ use strict;
package Jifty::JSON;
use base 'Exporter';
-our @EXPORT_OK = qw/jsonToObj objToJson/;
+our @EXPORT_OK = qw/jsonToObj objToJson decode_json encode_json/;
+
+use Carp qw//;
+use JSON qw/ -support_by_pp -no_export /;
=head1 NAME
@@ -12,128 +15,88 @@ Jifty::JSON -- Wrapper around L<JSON>
=head1 SYNOPSIS
- use Jifty::JSON qw/jsonToObj objToJson/;
+ use Jifty::JSON qw/decode_json encode_json/;
- # Even though you might be using JSON::Syck, use the original JSON names
- my $obj = jsonToObj(q! { 'x': 1, 'y': 2, 'z': 3 } !);
- my $json = objToJson($obj);
+ my $obj = decode_json(q! { "x": "1", "y": "2", "z": "3" } !);
+ my $json = encode_json($obj);
=head1 DESCRIPTION
-Provides a wrapper around the L<JSON> library.
+Provides a thin wrapper around the L<JSON> 2.xx library, which provides a
+frontend for L<JSON::XS> and L<JSON::PP>.
-The JSON specification at L<http://www.json.org/> states that only
-double-quotes are possible for specifying strings. However, for the purposes
-of embedding Javascript-compatible objects in XHTML attributes (which use
-double-quotes), we sometimes want to provide strings in single quotes.
-This provides a version of L<JSON/objToJson> which allows
-single-quoted string output.
+This module used to wrap L<JSON::Syck> and L<JSON> 1.xx with special-casing for
+outputing JSON with single quoted values. Single quotes make it easy to
+simply plop JSON into HTML attributes but are in violation of the JSON spec
+which mandates only double quoted strings.
-If the faster L<JSON::Syck> is available, it is preferred over the pure-perl
-L<JSON>, as it provides native support for single-quoted strings.
+The old behavior is now unsupported and it is recommended that you simply HTML
+escape your entire blob of JSON if you are sticking it in an HTML attribute.
+You can use L<Jifty-E<gt>web-E<gt>escape()|Jifty::Web/escape> to properly
+escape problematic characters for HTML.
-=head1 METHODS
+=head1 FUNCTIONS
-=cut
+=head2 decode_json JSON, [ARGUMENT HASHREF]
-BEGIN {
- # Errors that happen here, stay here.
- local $@;
-
- # We're hacking, so tell the nannies to leave for a minute
- no strict 'refs';
- no warnings 'once';
-
- # If a good version of JSON::Syck is available use that...
- if (eval { require JSON::Syck; JSON::Syck->VERSION(0.05) }) {
- *jsonToObj = *_jsonToObj_syck;
- *objToJson = *_objToJson_syck;
- $JSON::Syck::ImplicitUnicode = 1;
- }
-
- # Bummer, fallback to the pure Perl implementation
- else {
- require JSON;
- *jsonToObj = *_jsonToObj_pp;
- *objToJson = *_objToJson_pp;
- $JSON::UTF8 = 1;
- }
-}
+=head2 encode_json JSON, [ARGUMENT HASHREF]
-=head2 jsonToObj JSON, [ARGUMENTS]
+These functions are just like L<JSON>'s, except that you can pass options to
+them like you can with L<JSON>'s C<from_json> and C<to_json> functions.
-For completeness, C<Jifty::JSON> provides a C<jsonToObj>. It is
-identical to L<JSON/jsonToObj>.
+By default they encode/decode using UTF8 (like L<JSON>'s functions of the same
+name), but you can turn that off by passing C<utf8 =E<gt> 0> in the
+options. The L<allow_nonref|JSON/allow_nonref> flag is also enabled for
+backwards compatibility with earlier versions of this module. It allows
+encoding/decoding of values that are not references.
+
+L<JSON> is imported with the C<-support_by_pp> flag in order to support all
+options that L<JSON::PP> provides when using L<JSON::XS> as the backend. If
+you are concerned with speed, be careful what options you specify as it may
+cause the pure Perl backend to be used. Read L<JSON/JSON::PP SUPPORT METHODS>
+for more information.
=cut
-sub _jsonToObj_syck {
- local $JSON::Syck::SingleQuote = 0;
- JSON::Syck::Load($_[0]);
+sub decode_json {
+ JSON::from_json( $_[0], { utf8 => 1, allow_nonref => 1, %{$_[1] || {}} } );
}
-sub _jsonToObj_pp {
- return JSON::jsonToObj(@_);
+sub encode_json {
+ JSON::to_json( $_[0], { utf8 => 1, allow_nonref => 1, %{$_[1] || {}} } );
}
-=head2 objToJson OBJECT, [ARGUMENTS]
+=head2 DEPRECATED jsonToObj JSON, [ARGUMENTS]
+
+=head2 DEPRECATED objToJson JSON, [ARGUMENTS]
-This method is identical to L<JSON/objToJson>, except it has an
-additional possible option. The C<singlequote> option, if set to a
-true value in the C<ARGUMENTS> hashref, overrides L<JSON::Converter>'s
-string output method to output single quotes as delimters instead of
-double quotes.
+These functions are deprecated and provided for backwards compatibility. They
+wrap the appropriate function above, but L<Carp/croak> if you try to set the
+C<singlequote> option.
=cut
-sub _objToJson_syck {
- my ($obj, $args) = @_;
-
- local $JSON::Syck::SingleQuote = $args->{singlequote};
- local $JSON::Syck::ImplicitUnicode = 1;
- my $json = JSON::Syck::Dump($obj);
- if (! $args->{singlequote}) {
- $json =~ s/\n\n\n/\\n/gs; # fix syck bug
- $json =~ s/\n/\\n/gs; # just to be safe
- $json =~ s/\r/\\r/gs;
- }
- return $json;
+sub jsonToObj {
+ my $args = $_[1] || {};
+ Carp::croak("Attempted to set 'singlequote' option, but it is no longer supported.".
+ " You may need to HTML escape the resulting JSON.".
+ " Please read the POD of Jifty::JSON and fix your code.")
+ if exists $args->{'singlequote'};
+ decode_json( @_ );
}
-# We should escape double-quotes somehow, so that we can guarantee
-# that double-quotes *never* appear in the JSON string that is
-# returned.
-sub _objToJson_pp {
- my ($obj, $args) = @_;
-
- # Unless we're asking for single-quoting, just do what JSON.pm
- # does
- return JSON::Converter::objToJson($obj)
- unless delete $args->{singlequote};
-
- # Otherwise, insert our own stringify sub
- no warnings 'redefine';
- my %esc = (
- "\n" => '\n',
- "\r" => '\r',
- "\t" => '\t',
- "\f" => '\f',
- "\b" => '\b',
- "'" => '\\\'',
- "\\" => '\\\\',
- );
- local *JSON::Converter::_stringfy = sub {
- my $arg = shift;
- $arg =~ s/([\\\n'\r\t\f\b])/$esc{$1}/eg;
- $arg =~ s/([\x00-\x07\x0b\x0e-\x1f])/'\\u00' . unpack('H2',$1)/egs;
- return "'" . $arg ."'";
- };
- return JSON::objToJson($obj, $args);
+sub objToJson {
+ my $args = $_[1] || {};
+ Carp::croak("Attempted to set 'singlequote' option, but it is no longer supported.".
+ " You may need to HTML escape the resulting JSON.".
+ " Please read the POD of Jifty::JSON and fix your code.")
+ if exists $args->{'singlequote'};
+ encode_json( @_ );
}
=head1 LICENSE
-Jifty is Copyright 2005-2006 Best Practical Solutions, LLC.
+Jifty is Copyright 2005-2010 Best Practical Solutions, LLC.
Jifty is distributed under the same terms as Perl itself.
=cut
diff --git a/lib/Jifty/Plugin/REST/Dispatcher.pm b/lib/Jifty/Plugin/REST/Dispatcher.pm
index cecc1f4..4dfec7d 100644
--- a/lib/Jifty/Plugin/REST/Dispatcher.pm
+++ b/lib/Jifty/Plugin/REST/Dispatcher.pm
@@ -223,7 +223,7 @@ sub output_format {
format => 'JSON',
extension => 'json',
content_type => 'application/json; charset=UTF-8',
- freezer => \&Jifty::JSON::objToJson,
+ freezer => \&Jifty::JSON::encode_json,
};
}
elsif ($accept =~ /j(?:ava)?s|ecmascript/i) {
@@ -231,7 +231,7 @@ sub output_format {
format => 'JS',
extension => 'js',
content_type => 'application/javascript; charset=UTF-8',
- freezer => sub { 'var $_ = ' . Jifty::JSON::objToJson( @_, { singlequote => 1 } ) },
+ freezer => sub { 'var $_ = ' . Jifty::JSON::encode_json( @_ ) },
};
}
elsif ($accept =~ qr{^(?:application/x-)?(?:perl|pl)$}i) {
diff --git a/lib/Jifty/Plugin/SetupWizard/View.pm b/lib/Jifty/Plugin/SetupWizard/View.pm
index 4229f4e..1cb102f 100644
--- a/lib/Jifty/Plugin/SetupWizard/View.pm
+++ b/lib/Jifty/Plugin/SetupWizard/View.pm
@@ -175,7 +175,7 @@ template '/__jifty/admin/setupwizard/language' => sub {
template '/__jifty/admin/setupwizard/database' => sub {
# XXX: We've got to add a sane way to unquote stuff in onfoo handlers...
my $onchange = 'Jifty.update('
- . Jifty::JSON::objToJson({
+ . Jifty::JSON::encode_json({
actions => {},
action_arguments => {},
fragments => [
@@ -187,7 +187,7 @@ template '/__jifty/admin/setupwizard/database' => sub {
],
continuation => undef,
- }, {singlequote => 1})
+ })
. ', this)';
$onchange =~ s/PLACEHOLDER/'+this.value+'/;
diff --git a/lib/Jifty/Plugin/SinglePage.pm b/lib/Jifty/Plugin/SinglePage.pm
index 7a0ed97..9b00526 100644
--- a/lib/Jifty/Plugin/SinglePage.pm
+++ b/lib/Jifty/Plugin/SinglePage.pm
@@ -74,7 +74,7 @@ sub _sp_link {
$self->_push_onclick($args, {
region => $self->region_name,
replace_with => $url,
- beforeclick => qq{SPA.historyChange('$complete_url', { 'continuation':{}, 'actions':{}, 'fragments':[{'mode':'Replace','args':@{[ Jifty::JSON::objToJson($args->{parameters})]},'region':'__page','path':'$url'}],'action_arguments':{}}, true);},
+ beforeclick => qq{SPA.historyChange('$complete_url', { 'continuation':{}, 'actions':{}, 'fragments':[{'mode':'Replace','args':@{[ Jifty::JSON::encode_json($args->{parameters})]},'region':'__page','path':'$url'}],'action_arguments':{}}, true);},
args => { %{$args->{parameters}}} });
}
elsif (exists $args->{submit} && !$args->{onclick}) {
diff --git a/lib/Jifty/Request.pm b/lib/Jifty/Request.pm
index 89af7d8..b83950b 100644
--- a/lib/Jifty/Request.pm
+++ b/lib/Jifty/Request.pm
@@ -128,7 +128,7 @@ sub fill {
# Check it for something appropriate
if ($data) {
if ($ct =~ m{^text/x-json}) {
- return $self->from_data_structure(eval{Jifty::JSON::jsonToObj($data)}, $cgi);
+ return $self->from_data_structure(eval{Jifty::JSON::decode_json($data)}, $cgi);
} elsif ($ct =~ m{^text/x-yaml}) {
return $self->from_data_structure(eval{Jifty::YAML::Load($data)}, $cgi);
}
diff --git a/lib/Jifty/Script/Po.pm b/lib/Jifty/Script/Po.pm
index 4f8a44c..47451ac 100644
--- a/lib/Jifty/Script/Po.pm
+++ b/lib/Jifty/Script/Po.pm
@@ -95,10 +95,9 @@ sub _js_gen {
no strict 'refs';
print $fh
- Jifty::JSON::objToJson( { map { my $text = ${"Jifty::I18N::".$lang."::Lexicon"}{$_};
- defined $text ? ( $_ => $text ) : () }
- keys %{$LMExtract->lexicon} },
- { singlequote => 1 } );
+ Jifty::JSON::encode_json( { map { my $text = ${"Jifty::I18N::".$lang."::Lexicon"}{$_};
+ defined $text ? ( $_ => $text ) : () }
+ keys %{$LMExtract->lexicon} } );
}
}
diff --git a/lib/Jifty/Web/Form/Element.pm b/lib/Jifty/Web/Form/Element.pm
index 4d11c6e..397e9fd 100644
--- a/lib/Jifty/Web/Form/Element.pm
+++ b/lib/Jifty/Web/Form/Element.pm
@@ -553,15 +553,13 @@ sub javascript_attrs {
@{ $trigger_structure->{value} };
if ( @$fragments or ( !$actions || %$actions ) ) {
- my $update_json = Jifty::JSON::objToJson({
+ my $update_json = Jifty::JSON::encode_json({
actions => $actions,
action_arguments => $trigger_structure->{action_arguments},
fragments => $fragments,
continuation => $self->continuation,
preload_key => $trigger_structure->{preload_key},
- },
- { singlequote => 1 },
- );
+ });
my $update = "Jifty.update($update_json, this);";
@@ -575,10 +573,7 @@ sub javascript_attrs {
}
if ($trigger_structure->{confirm}) {
- my $text = Jifty::JSON::objToJson(
- $trigger_structure->{confirm},
- {singlequote => 1},
- );
+ my $text = Jifty::JSON::encode_json( $trigger_structure->{confirm} );
$string = "if(!confirm($text)){ Jifty.stopEvent(event); return false; }" . $string;
}
@@ -644,10 +639,10 @@ sub key_binding_javascript {
: $self->label;
if ($key) {
return "Jifty.KeyBindings.add("
- . Jifty::JSON::objToJson( uc($key), { singlequote => 1 } ).","
+ . Jifty::JSON::encode_json( uc $key ).","
. "'click', "
- . Jifty::JSON::objToJson( $self->id, { singlequote => 1 } ).","
- . Jifty::JSON::objToJson( $label, { singlequote => 0 } )
+ . Jifty::JSON::encode_json( $self->id ).","
+ . Jifty::JSON::encode_json( $label )
. ");";
}
}
diff --git a/lib/Jifty/Web/Form/Field.pm b/lib/Jifty/Web/Form/Field.pm
index 70879d9..a789692 100644
--- a/lib/Jifty/Web/Form/Field.pm
+++ b/lib/Jifty/Web/Form/Field.pm
@@ -432,6 +432,7 @@ sub render_inline_javascript {
);
if($javascript =~ /\S/) {
+ $javascript = Jifty->web->escape( $javascript );
Jifty->web->out(qq{<script type="text/javascript">$javascript</script>
});
}
@@ -450,6 +451,7 @@ sub render_preload_javascript {
my $javascript = $self->preload_javascript;
if($javascript =~ /\S/) {
+ $javascript = Jifty->web->escape( $javascript );
Jifty->web->out(qq{<script type="text/javascript">$javascript</script>
});
}
@@ -747,12 +749,11 @@ sub preload_javascript {
my @preloaded;
- my $preload_json = Jifty::JSON::objToJson(
+ my $preload_json = Jifty::JSON::encode_json(
{
fragments => $trigger_structure->{fragments},
preload_key => $trigger_structure->{preload_key},
- },
- { singlequote => 1 },
+ }
);
push @javascript, "Jifty.preload($preload_json, this);";
diff --git a/lib/Jifty/Web/Menu.pm b/lib/Jifty/Web/Menu.pm
index 6d41336..ea6dc1c 100644
--- a/lib/Jifty/Web/Menu.pm
+++ b/lib/Jifty/Web/Menu.pm
@@ -447,7 +447,7 @@ sub render_as_yui_menu {
);
my $showjs = $args{'show'} ? "menu.show();" : "";
- my $json = Jifty::JSON::objToJson( $args{'options'} );
+ my $json = Jifty->web->escape( Jifty::JSON::encode_json( $args{'options'} ) );
# Bind to a button to show the menu
my $binding = (defined $args{'button'} and length $args{'button'}) ? 1 : 0;
diff --git a/lib/Jifty/Web/PageRegion.pm b/lib/Jifty/Web/PageRegion.pm
index 5db344f..504eb5d 100644
--- a/lib/Jifty/Web/PageRegion.pm
+++ b/lib/Jifty/Web/PageRegion.pm
@@ -320,7 +320,7 @@ sub make_body {
if ( $self->region_wrapper ) {
$buffer->append(qq|<script type="text/javascript">\n|
. qq|new Region('| . $self->qualified_name . qq|',|
- . Jifty::JSON::objToJson( \%arguments, { singlequote => 1 } ) . qq|,|
+ . Jifty->web->escape(Jifty::JSON::encode_json( \%arguments )) . qq|,|
. qq|'| . $self->path . qq|',|
. ( $self->parent ? qq|'| . $self->parent->qualified_name . qq|'| : q|null|)
. qq|,| . (Jifty->web->form->is_open ? '1' : 'null')
diff --git a/share/web/templates/__jifty/webservices/json b/share/web/templates/__jifty/webservices/json
index bacde46..1471053 100644
--- a/share/web/templates/__jifty/webservices/json
+++ b/share/web/templates/__jifty/webservices/json
@@ -1,5 +1,5 @@
% $r->content_type("text/x-json");
-<% Jifty::JSON::objToJson(\%results) |n%>
+<% Jifty::JSON::encode_json(\%results) |n%>
<%INIT>
my %results = Jifty->web->response->results;
diff --git a/t/TestApp-Plugin-REST/t/03-format.t b/t/TestApp-Plugin-REST/t/03-format.t
index 14ca829..adfb307 100644
--- a/t/TestApp-Plugin-REST/t/03-format.t
+++ b/t/TestApp-Plugin-REST/t/03-format.t
@@ -35,11 +35,11 @@ sub result_of {
my %loaders = (
yml => \&Jifty::YAML::Load,
- json => \&Jifty::JSON::jsonToObj,
+ json => \&Jifty::JSON::decode_json,
js => sub {
my $js = shift;
$js =~ s/.*? = //; # variable assignment
- return Jifty::JSON::jsonToObj($js);
+ return Jifty::JSON::decode_json($js);
},
);
diff --git a/t/TestApp/t/16-template-region.t b/t/TestApp/t/16-template-region.t
index 7c6984b..6c9dca9 100644
--- a/t/TestApp/t/16-template-region.t
+++ b/t/TestApp/t/16-template-region.t
@@ -10,7 +10,7 @@ my @tests = (
text => q|list!
<span>1</span>
<span>2</span><script type="text/javascript">
-new Region('special',{'id':3},'/foo/item',null,null);
+new Region('special',{"id":3},'/foo/item',null,null);
</script><div id="region-special" class="jifty-region">
<span>3</span></div>|
},
-----------------------------------------------------------------------
More information about the Jifty-commit
mailing list