File Coverage

blib/lib/Kossy/Connection.pm
Criterion Covered Total %
statement 18 53 33.9
branch 0 6 0.0
condition 0 18 0.0
subroutine 7 12 58.3
pod 0 7 0.0
total 25 96 26.0


line stmt bran cond sub pod time code
1             package Kossy::Connection;
2              
3 7     7   23 use strict;
  7         7  
  7         153  
4 7     7   20 use warnings;
  7         7  
  7         197  
5             use Class::Accessor::Lite (
6 7         44 new => 1,
7             rw => [qw/req res stash args tx debug/]
8 7     7   83 );
  7         8  
9 7     7   3287 use JSON qw//;
  7         46616  
  7         134  
10 7     7   26 use Kossy::Exception;
  7         8  
  7         3040  
11              
12             our $VERSION = '0.40';
13             my $_JSON = JSON->new()->allow_blessed(1)->convert_blessed(1)->ascii(1);
14              
15             # for IE7 JSON venularity.
16             # see http://www.atmarkit.co.jp/fcoding/articles/webapp/05/webapp05a.html
17             # Copy from Amon2::Plugin::Web::JSON => Fixed to escape only string parts
18             my %_ESCAPE = (
19             '+' => '\\u002b', # do not eval as UTF-7
20             '<' => '\\u003c', # do not eval as HTML
21             '>' => '\\u003e', # ditto.
22             );
23             sub escape {
24 0     0 0 0 my $self = shift;
25 0         0 my $body = shift;
26 0         0 $body =~ s!([+<>])!$_ESCAPE{$1}!g;
27 0         0 return qq("$body");
28             }
29             sub escape_json {
30 0     0 0 0 my $self = shift;
31 0         0 my $body = shift;
32             # escape only string parts
33 0         0 $body =~ s/"((?:\\"|[^"])*)"/$self->escape($1)/eg;
  0         0  
34 0         0 return $body;
35             }
36              
37             *request = \&req;
38             *response = \&res;
39              
40             sub env {
41 1     1 0 7 $_[0]->{req}->env;
42             }
43              
44             sub halt {
45 4     4 0 4 my $self = shift;
46 4         19 die Kossy::Exception->new(@_);
47             }
48              
49             sub redirect {
50 0     0 0   my $self = shift;
51 0           $self->res->redirect(@_);
52 0           $self->res;
53             }
54              
55             sub render {
56 0     0 0   my $self = shift;
57 0           my $file = shift;
58 0 0 0       my %args = ( @_ && ref $_[0] ) ? %{$_[0]} : @_;
  0            
59 0           my %vars = (
60             c => $self,
61             stash => $self->stash,
62             %args,
63             );
64              
65 0           my $body = $self->tx->render($file, \%vars);
66 0           $self->res->status( 200 );
67 0           $self->res->content_type('text/html; charset=UTF-8');
68 0           $self->res->body( $body );
69 0           $self->res;
70             }
71              
72             sub render_json {
73 0     0 0   my $self = shift;
74 0           my $obj = shift;
75              
76             # defense from JSON hijacking
77             # Copy from Amon2::Plugin::Web::JSON
78 0 0 0       if ( exists $self->req->env->{'HTTP_X_REQUESTED_WITH'} &&
      0        
      0        
      0        
      0        
79             ($self->req->env->{'HTTP_USER_AGENT'}||'') =~ /android/i &&
80             exists $self->req->env->{'HTTP_COOKIE'} &&
81             ($self->req->method||'GET') eq 'GET'
82             ) {
83 0           $self->halt(403,"Your request is maybe JSON hijacking.\nIf you are not a attacker, please add 'X-Requested-With' header to each request.");
84             }
85              
86 0           my $body = $_JSON->encode($obj);
87 0           $body = $self->escape_json($body);
88              
89 0 0 0       if ( ( $self->req->env->{'HTTP_USER_AGENT'} || '' ) =~ m/Safari/ ) {
90 0           $body = "\xEF\xBB\xBF" . $body;
91             }
92              
93 0           $self->res->status( 200 );
94 0           $self->res->content_type('application/json; charset=UTF-8');
95 0           $self->res->header( 'X-Content-Type-Options' => 'nosniff' ); # defense from XSS
96 0           $self->res->body( $body );
97 0           $self->res;
98             }
99              
100              
101              
102             1;
103