1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
|
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
#
# This Source Code Form is "Incompatible With Secondary Licenses", as
# defined by the Mozilla Public License, v. 2.0.
package Bugzilla::Extension::Bitly::WebService;
use 5.10.1;
use strict;
use warnings;
use base qw(Bugzilla::WebService);
use Bugzilla::CGI;
use Bugzilla::Constants;
use Bugzilla::Error;
use Bugzilla::Search;
use Bugzilla::Search::Quicksearch;
use Bugzilla::Util ();
use Bugzilla::WebService::Util 'validate';
use JSON;
use LWP::UserAgent;
use URI;
use URI::Escape;
use URI::QueryParam;
use constant PUBLIC_METHODS => qw(
list
shorten
);
sub _validate_uri {
my ($self, $params) = @_;
# extract url from params
if (!defined $params->{url}) {
ThrowCodeError(
'param_required',
{ function => 'Bitly.shorten', param => 'url' }
);
}
my $url = ref($params->{url}) ? $params->{url}->[0] : $params->{url};
# only allow buglist queries for this bugzilla install
my $uri = URI->new($url);
$uri->query(undef);
$uri->fragment(undef);
if ($uri->as_string ne Bugzilla->localconfig->{urlbase} . 'buglist.cgi') {
ThrowUserError('bitly_unsupported');
}
return URI->new($url);
}
sub shorten {
my ($self) = shift;
my $uri = $self->_validate_uri(@_);
# the list_id is user-specific, remove it
$uri->query_param_delete('list_id');
return $self->_bitly($uri);
}
sub list {
my ($self) = shift;
my $uri = $self->_validate_uri(@_);
# map params to cgi vars, converting quicksearch if required
my $params = $uri->query_param('quicksearch')
? Bugzilla::CGI->new(quicksearch($uri->query_param('quicksearch')))->Vars
: Bugzilla::CGI->new($uri->query)->Vars;
# execute the search
my $search = Bugzilla::Search->new(
params => $params,
fields => ['bug_id'],
limit => Bugzilla->params->{max_search_results},
);
my $data = $search->data;
# form a bug_id only url, sanity check the length
$uri = URI->new(Bugzilla->localconfig->{urlbase} . 'buglist.cgi?bug_id=' . join(',', map { $_->[0] } @$data));
if (length($uri->as_string) > CGI_URI_LIMIT) {
ThrowUserError('bitly_failure', { message => "Too many bugs returned by search" });
}
# shorten
return $self->_bitly($uri);
}
sub _bitly {
my ($self, $uri) = @_;
# form request url
# http://dev.bitly.com/links.html#v3_shorten
my $bitly_url = sprintf(
'https://api-ssl.bitly.com/v3/shorten?access_token=%s&longUrl=%s',
Bugzilla->params->{bitly_token},
uri_escape($uri->as_string)
);
# is Mozilla::CA isn't installed, skip certificate verification
eval { require Mozilla::CA };
$ENV{PERL_LWP_SSL_VERIFY_HOSTNAME} = $@ ? 0 : 1;
# request
my $ua = LWP::UserAgent->new(agent => 'Bugzilla');
$ua->timeout(10);
$ua->protocols_allowed(['http', 'https']);
if (my $proxy_url = Bugzilla->params->{proxy_url}) {
$ua->proxy(['http', 'https'], $proxy_url);
}
else {
$ua->env_proxy();
}
my $response = $ua->get($bitly_url);
if ($response->is_error) {
ThrowUserError('bitly_failure', { message => $response->message });
}
my $result = decode_json($response->decoded_content);
if ($result->{status_code} != 200) {
ThrowUserError('bitly_failure', { message => $result->{status_txt} });
}
# return just the short url
return { url => $result->{data}->{url} };
}
sub rest_resources {
return [
qr{^/bitly/shorten$}, {
GET => {
method => 'shorten',
},
},
qr{^/bitly/list$}, {
GET => {
method => 'list',
},
},
]
}
1;
|