File Coverage

blib/lib/Flickr/API.pm
Criterion Covered Total %
statement 222 417 53.2
branch 54 134 40.3
condition 38 86 44.1
subroutine 30 39 76.9
pod 13 18 72.2
total 357 694 51.4


line stmt bran cond sub pod time code
1             package Flickr::API;
2              
3 15     15   1556635 use strict;
  15         31  
  15         554  
4 15     15   98 use warnings;
  15         36  
  15         2327  
5 15     15   10867 use LWP::UserAgent;
  15         957020  
  15         731  
6 15     15   8088 use XML::Parser::Lite::Tree;
  15         93165  
  15         671  
7 15     15   8077 use XML::LibXML::Simple;
  15         1013880  
  15         1314  
8 15     15   8693 use Flickr::API::Request;
  15         63  
  15         632  
9 15     15   7634 use Flickr::API::Response;
  15         49  
  15         560  
10 15     15   98 use Net::OAuth;
  15         24  
  15         398  
11 15     15   99 use Digest::MD5 qw(md5_hex);
  15         26  
  15         1116  
12 15     15   99 use Scalar::Util qw(blessed);
  15         26  
  15         710  
13 15     15   86 use Encode qw(encode_utf8);
  15         32  
  15         718  
14 15     15   81 use Carp;
  15         26  
  15         1027  
15 15     15   99 use Storable qw(store_fd retrieve_fd);
  15         28  
  15         84930  
16              
17             our @ISA = qw(LWP::UserAgent);
18              
19             our $VERSION = '1.29';
20              
21             sub new {
22 8     8 1 718943 my ($class, $args) = @_;
23              
24 8         20 my $self;
25 8 50       41 if ($args->{lwpobj}){
26 0         0 my $lwpobj = $args->{lwpobj};
27 0 0       0 if (defined($lwpobj)){
28 0         0 my $lwpobjtype = Scalar::Util::blessed($lwpobj);
29 0 0       0 if (defined($lwpobjtype)){
30 0         0 $self = $lwpobj;
31 0         0 @ISA = ($lwpobjtype);
32             }
33             }
34             }
35 8 50       88 $self = LWP::UserAgent->new unless $self;
36              
37             #
38             # If the args have consumer_key, handle as oauth
39             #
40 8 100       16095 if (defined($args->{consumer_key})) {
41              
42 4         13 $self->{api_type} = 'oauth';
43 4   50     28 $self->{rest_uri} = $args->{rest_uri} || 'https://api.flickr.com/services/rest/';
44 4   50     38 $self->{auth_uri} = $args->{auth_uri} || 'https://api.flickr.com/services/oauth/authorize';
45 4   50     18 $self->{upload_uri} = $args->{upload_uri} || 'https://api.flickr.com/services/upload/';
46              
47 4 50       25 if (defined($args->{consumer_secret})) {
48              
49             #
50             # for the flickr api object
51             #
52 4         12 $self->{oauth_request} = 'consumer';
53 4         11 $self->{consumer_key} = $args->{consumer_key};
54 4         16 $self->{consumer_secret} = $args->{consumer_secret};
55 4   50     18 $self->{unicode} = $args->{unicode} || 0;
56             #
57             # for Net::OAuth Consumer Requests
58             #
59 4   100     19 $self->{oauth}->{request_method} = $args->{request_method} || 'GET';
60 4         10 $self->{oauth}->{request_url} = $self->{rest_uri};
61 4         9 $self->{oauth}->{consumer_secret} = $args->{consumer_secret};
62 4         8 $self->{oauth}->{consumer_key} = $args->{consumer_key};
63 4   66     21 $self->{oauth}->{nonce} = $args->{nonce} || _make_nonce();
64 4   100     21 $self->{oauth}->{signature_method} = $args->{signature_method} ||'HMAC-SHA1';
65 4   66     18 $self->{oauth}->{timestamp} = $args->{timestamp} || time;
66 4         8 $self->{oauth}->{version} = '1.0';
67 4         20 $self->{oauth}->{callback} = $args->{callback};
68              
69             }
70             else {
71              
72 0         0 carp "OAuth calls must have at least a consumer_key and a consumer_secret";
73 0         0 $self->_set_status(0,"OAuth call without consumer_secret");
74              
75             }
76              
77 4 100 66     34 if (defined($args->{token}) && defined($args->{token_secret})) {
78              
79             #
80             # If we have token/token secret then we are for protected resources
81             #
82 2         7 $self->{oauth}->{token_secret} = $args->{token_secret};
83 2         9 $self->{oauth}->{token} = $args->{token};
84 2         6 $self->{oauth_request} = 'protected resource';
85              
86             }
87              
88             #
89             # Preserve request and access tokens
90             #
91 4 50 33     32 if (defined($args->{request_token}) and
92             ref($args->{request_token}) eq 'Net::OAuth::V1_0A::RequestTokenResponse') {
93              
94 0         0 $self->{oauth}->{request_token} = $args->{request_token};
95              
96             }
97 4 50 33     14 if (defined($args->{access_token}) and
98             ref($args->{access_token}) eq 'Net::OAuth::AccessTokenResponse') {
99              
100 0         0 $self->{oauth}->{access_token} = $args->{access_token};
101              
102             }
103             }
104              
105             else {
106              
107 4         16 $self->{api_type} = 'flickr';
108 4   66     43 $self->{api_key} = $args->{api_key} || $args->{key};
109 4   100     23 $self->{api_secret} = $args->{api_secret} || $args->{secret};
110 4   50     37 $self->{rest_uri} = $args->{rest_uri} || 'https://api.flickr.com/services/rest/';
111 4   50     38 $self->{auth_uri} = $args->{auth_uri} || 'https://api.flickr.com/services/auth/';
112 4   50     22 $self->{upload_uri} = $args->{upload_uri} || 'https://api.flickr.com/services/upload/';
113 4   50     21 $self->{unicode} = $args->{unicode} || 0;
114              
115 4 100 66     19 if (defined($args->{key}) or defined ($self->{key})) {
116 3         9 delete $args->{key};
117 3         8 delete $self->{key};
118             # Silenty switch key to api_key until a later release
119             # carp "Argument 'key' is deprecated and has been changed to api_key";
120             }
121              
122 4 100 66     25 if (defined ($args->{secret}) or defined ($self->{secret})) {
123 1         20 delete $args->{secret};
124 1         4 delete $self->{secret};
125             # Silenty switch secret to api_secret until a later release
126             # carp "Argument 'secret' is deprecated and has been changed to api_secret";
127             }
128              
129 4         14 $self->{fauth}->{frob} = $args->{frob};
130 4         13 $self->{fauth}->{api_key} = $self->{api_key};
131 4         8 $self->{fauth}->{api_secret} = $self->{api_secret};
132 4         12 $self->{fauth}->{token} = $args->{token};
133              
134 4 50       13 carp "You must pass an API key or a Consumer key to the constructor" unless defined $self->{api_key};
135              
136             }
137              
138 8         17 eval {
139 8         2900 require Compress::Zlib;
140              
141 8         275005 $self->default_header('Accept-Encoding' => 'gzip');
142             };
143              
144 8         630 bless $self, $class;
145 8         42 $self->_clear_status();
146 8         32 $self->_initialize();
147 8         71 return $self;
148             }
149              
150              
151              
152             #
153             # Execution Methods
154             #
155              
156             sub execute_method {
157 2     2 1 1728 my ($self, $method, $args) = @_;
158 2         5 my $request;
159              
160 2 50       11 if ($self->is_oauth) {
161              
162             #
163             # Consumer Request Params
164             #
165 0         0 my $oauth = {};
166              
167 0         0 $oauth->{nonce} = _make_nonce();
168 0         0 $oauth->{consumer_key} = $self->{oauth}->{consumer_key};
169 0         0 $oauth->{consumer_secret} = $self->{oauth}->{consumer_secret};
170 0         0 $oauth->{timestamp} = time;
171 0         0 $oauth->{signature_method} = $self->{oauth}->{signature_method};
172 0         0 $oauth->{version} = $self->{oauth}->{version};
173              
174 0 0 0     0 if (defined($args->{'token'}) or defined($args->{'token_secret'})) {
175              
176 0         0 carp "\ntoken and token_secret must be specified in Flickr::API->new() and are being discarded\n";
177 0         0 undef $args->{'token'};
178 0         0 undef $args->{'token_secret'};
179             }
180              
181 0 0 0     0 if (defined($args->{'consumer_key'}) or defined($args->{'consumer_secret'})) {
182              
183 0         0 carp "\nconsumer_key and consumer_secret must be specified in Flickr::API->new() and are being discarded\n";
184 0         0 undef $args->{'consumer_key'};
185 0         0 undef $args->{'consumer_secret'};
186             }
187              
188              
189 0         0 $oauth->{extra_params} = $args;
190 0         0 $oauth->{extra_params}->{method} = $method;
191              
192             #
193             # Protected resource params
194             #
195 0 0       0 if (defined($self->{oauth}->{token})) {
196              
197 0         0 $oauth->{token} = $self->{oauth}->{token};
198 0         0 $oauth->{token_secret} = $self->{oauth}->{token_secret};
199              
200             }
201              
202             $request = Flickr::API::Request->new({
203             'api_type' => 'oauth',
204             'method' => $method,
205             'args' => $oauth,
206             'rest_uri' => $self->{rest_uri},
207             'unicode' => $self->{unicode},
208 0         0 });
209             }
210             else {
211              
212             $request = Flickr::API::Request->new({
213             'api_type' => 'flickr',
214             'method' => $method,
215             'args' => $args,
216             'rest_uri' => $self->{rest_uri},
217             'unicode' => $self->{unicode},
218 2         37 });
219             }
220              
221 2         16 return $self->execute_request($request);
222              
223             }
224              
225             sub execute_request {
226 2     2 1 7 my ($self, $request) = @_;
227              
228 2         19 $request->{api_args}->{method} = $request->{api_method};
229              
230 2 50       10 unless ($self->is_oauth) { $request->{api_args}->{api_key} = $self->{api_key}; }
  2         9  
231              
232 2 50 33     14 if (defined($self->{api_secret}) && length($self->{api_secret})) {
233              
234 2 50       5 unless ($self->is_oauth) { $request->{api_args}->{api_sig} = $self->_sign_args($request->{api_args}); }
  2         10  
235              
236             }
237              
238 2 50       5 unless ($self->is_oauth) { $request->encode_args(); }
  2         20  
239              
240 2         21 my $response = $self->request($request);
241 2         874414 bless $response, 'Flickr::API::Response';
242              
243 2         12 $response->init_flickr();
244              
245 2 50       10 if ($response->{_rc} != 200){
246 0         0 $response->set_fail(0, "API returned a non-200 status code ($response->{_rc})");
247 0         0 return $response;
248             }
249              
250 2         16 my $content = $response->decoded_content();
251 2 50       4360 $content = $response->content() unless defined $content;
252              
253 2         34 my $xls = XML::LibXML::Simple->new(ForceArray => 0);
254 2         107 my $tree = XML::Parser::Lite::Tree::instance()->parse($content);
255              
256 2         1828 my $hashref = $xls->XMLin($content,KeyAttr => []);
257              
258 2         2378 my $rsp_node = $self->_find_tag($tree->{children});
259              
260 2 50       8 if ($rsp_node->{name} ne 'rsp'){
261 0         0 $response->set_fail(0, "API returned an invalid response");
262 0         0 return $response;
263             }
264              
265 2 50       11 if ($rsp_node->{attributes}->{stat} eq 'fail'){
266 2         7 my $fail_node = $self->_find_tag($rsp_node->{children});
267 2 50       11 if ($fail_node->{name} eq 'err'){
268 2         13 $response->set_fail($fail_node->{attributes}->{code}, $fail_node->{attributes}->{msg});
269             }
270             else {
271 0         0 $response->set_fail(0, "Method failed but returned no error code");
272             }
273 2         63 return $response;
274             }
275              
276 0 0       0 if ($rsp_node->{attributes}->{stat} eq 'ok'){
277 0         0 $response->set_ok($rsp_node,$hashref);
278 0         0 return $response;
279             }
280              
281 0         0 $response->set_fail(0, "API returned an invalid status code");
282 0         0 return $response;
283             }
284              
285              
286              
287             sub upload {
288 0     0 0 0 my ($self, $args) = @_;
289 0         0 my $upload;
290              
291 0 0 0     0 unless ($self->api_permissions() eq 'write' || $self->api_permissions() eq 'delete') {
292 0         0 croak "insufficient permission for upload";
293             }
294              
295 0         0 my %cfg = $self->export_config;
296 0         0 $cfg{'request_url'} = $self->{upload_uri};
297              
298 0         0 $upload = Flickr::API::Upload->new({
299             'photo' => $args,
300             'api' => \%cfg,
301             'api_type' => $self->api_type(),
302             });
303              
304 0         0 my $response = $self->request($upload);
305 0         0 bless $response, 'Flickr::API::Response';
306              
307 0         0 $response->init_flickr();
308              
309 0 0       0 if ($response->{_rc} != 200){
310 0         0 $response->set_fail(0, "Upload returned a non-200 status code ($response->{_rc})");
311 0         0 return $response;
312             }
313              
314 0         0 my $content = $response->decoded_content();
315 0 0       0 $content = $response->content() unless defined $content;
316              
317 0         0 my $xls = XML::LibXML::Simple->new(ForceArray => 0);
318 0         0 my $tree = XML::Parser::Lite::Tree::instance()->parse($content);
319              
320 0         0 my $hashref = $xls->XMLin($content,KeyAttr => []);
321              
322 0         0 my $rsp_node = $self->_find_tag($tree->{children});
323              
324 0 0       0 if ($rsp_node->{name} ne 'rsp'){
325 0         0 $response->set_fail(0, "Upload returned an invalid response");
326 0         0 return $response;
327             }
328              
329 0 0       0 if ($rsp_node->{attributes}->{stat} eq 'fail'){
330 0         0 my $fail_node = $self->_find_tag($rsp_node->{children});
331 0 0       0 if ($fail_node->{name} eq 'err'){
332 0         0 $response->set_fail($fail_node->{attributes}->{code}, $fail_node->{attributes}->{msg});
333             }
334             else {
335 0         0 $response->set_fail(0, "Upload failed but returned no error code");
336             }
337 0         0 return $response;
338             }
339              
340 0 0       0 if ($rsp_node->{attributes}->{stat} eq 'ok'){
341 0         0 $response->set_ok($rsp_node,$hashref);
342 0         0 return $response;
343             }
344              
345 0         0 $response->set_fail(0, "API returned an invalid status code");
346              
347 0         0 return $response;
348              
349             }
350              
351             #
352             # Persistent config methods
353             #
354              
355              
356             #
357             # Method to return hash of important Flickr or OAuth parameters.
358             # OAuth can also export meaningful subsets of parameters based
359             # on OAuth message type.
360             #
361             sub export_config {
362 7     7 1 8560 my ($self, $type, $params) = @_;
363              
364 7 100       26 if ($self->is_oauth) {
365              
366 5 100       41 unless($params) { $params='do_it'; }
  1         4  
367              
368 5         11 my %oauth;
369              
370 5 100       15 if (defined($type)) {
371 4 100       31 if ($params =~ m/^m.*/i) {
    50          
372 2         3 %oauth = map { ($_) => undef } @{Net::OAuth->request($type)->all_message_params()};
  13         16131  
  2         39  
373             }
374             elsif ($params =~ m/^a.*/i) {
375 2         5 %oauth = map { ($_) => undef } @{Net::OAuth->request($type)->all_api_params()};
  15         177  
  2         17  
376             }
377             else {
378 0         0 %oauth = map { ($_) => undef } @{Net::OAuth->request($type)->all_params()};
  0         0  
  0         0  
379             }
380 4         20 foreach my $param (keys %oauth) {
381 27 100       129 if (defined ($self->{oauth}->{$param})) { $oauth{$param} = $self->{oauth}->{$param}; }
  18         43  
382             }
383 4         47 return %oauth;
384             }
385             else {
386 1         2 return %{$self->{oauth}};
  1         15  
387             }
388             }
389             else {
390 2         2 return %{$self->{fauth}};
  2         15  
391             }
392              
393             }
394              
395             #
396             # Use perl core Storable to save important parameters.
397             #
398             sub export_storable_config {
399 2     2 1 7592 my ($self,$file) = @_;
400              
401 2 50       208 open my $EXPORT, '>', $file or croak "\nCannot open $file for write: $!\n";
402 2         11 my %config = $self->export_config();
403 2         17 store_fd(\%config, $EXPORT);
404 2         704 close $EXPORT;
405 2         23 return;
406             }
407              
408             #
409             # Use perl core Storable for re-vivifying an API object from saved parameters
410             #
411             sub import_storable_config {
412 2     2 1 1620 my ($class,$file) = @_;
413              
414 2 50       111 open my $IMPORT, '<', $file or croak "\nCannot open $file for read: $!\n";
415 2         13 my $config_ref = retrieve_fd($IMPORT);
416 2         218 close $IMPORT;
417 2         15 my $api = $class->new($config_ref);
418 2         16 return $api;
419             }
420              
421              
422              
423             #
424             # Preauthorization Methods
425             #
426             # Handle request token requests (process: REQUEST TOKEN, authorize, access token)
427             #
428             sub oauth_request_token {
429 0     0 1 0 my ($self, $args) = @_;
430              
431 0         0 my %oauth = %{$self->{oauth}};
  0         0  
432              
433 0 0       0 unless ($self->is_oauth) {
434 0         0 carp "\noauth_request_token called for Non-OAuth Flickr::API object\n";
435 0         0 return;
436             }
437 0 0       0 unless ($self->get_oauth_request_type() eq 'consumer') {
438 0         0 croak "\noauth_request_token called using protected resource Flickr::API object\n";
439             }
440              
441 0         0 $self->{oauth_request} = 'Request Token';
442 0   0     0 $oauth{request_url} = $args->{request_token_url} || 'https://api.flickr.com/services/oauth/request_token';
443 0   0     0 $oauth{callback} = $args->{callback} || 'https://127.0.0.1';
444              
445 0         0 $Net::OAuth::PROTOCOL_VERSION = Net::OAuth::PROTOCOL_VERSION_1_0A;
446              
447 0         0 my $orequest = Net::OAuth->request('Request Token')->new(%oauth);
448              
449 0         0 $orequest->sign;
450              
451 0         0 my $response = $self->get($orequest->to_url);
452              
453 0         0 my $content = $response->decoded_content();
454 0 0       0 $content = $response->content() unless defined $content;
455              
456 0 0       0 if ($content =~ m/^oauth_problem=(.+)$/) {
457              
458 0         0 carp "\nRequest token not granted: '",$1,"'\n";
459 0         0 $self->{oauth}->{request_token} = $1;
460 0         0 return $1;
461             }
462              
463 0         0 $self->{oauth}->{request_token} = Net::OAuth->response('request token')->from_post_body($content);
464 0         0 $self->{oauth}->{callback} = $oauth{callback};
465 0         0 return 'ok';
466             }
467              
468             #
469             # Participate in authorization (process: request token, AUTHORIZE, access token)
470             #
471             sub oauth_authorize_uri {
472              
473 0     0 1 0 my ($self, $args) = @_;
474              
475 0 0       0 unless ($self->is_oauth) {
476 0         0 carp "oauth_authorize_uri called for Non-OAuth Flickr::API object";
477 0         0 return;
478             }
479 0         0 my %oauth = %{$self->{oauth}};
  0         0  
480              
481 0         0 $self->{oauth_request} = 'User Authentication';
482 0   0     0 $oauth{perms} = lc($args->{perms}) || 'read';
483              
484             carp "\nThe 'perms' parameter must be one of: read, write, delete\n"
485 0 0 0     0 and return unless defined($oauth{perms}) && $oauth{perms} =~ /^(read|write|delete)$/;
      0        
486              
487 0         0 $Net::OAuth::PROTOCOL_VERSION = Net::OAuth::PROTOCOL_VERSION_1_0A;
488              
489             return $self->{auth_uri} .
490             '?oauth_token=' . $oauth{'request_token'}{'token'} .
491 0         0 '&perms=' . $oauth{perms};
492              
493             }
494              
495             #
496             # flickr preauthorization
497             #
498              
499             sub request_auth_url {
500 5     5 1 1569 my ($self, $perms, $frob) = @_;
501              
502 5 50       17 if ($self->is_oauth) {
503              
504 0         0 carp "request_auth_url called for an OAuth instantiated Flickr::API";
505 0         0 return;
506              
507             }
508              
509 5         17 $perms = lc($perms);
510              
511 5 100 50     387 carp "\nThe 'perms' parameter must be one of: read, write, delete\n"
      66        
512             and return unless defined($perms) && $perms =~ /^(read|write|delete)$/;
513              
514 4 100 66     27 return unless defined $self->{api_secret} && length $self->{api_secret};
515              
516             my %fauth = (
517             'api_key' => $self->{api_key},
518 3         14 'perms' => $perms
519             );
520              
521 3 50       9 if ($frob) {
522 3         7 $fauth{frob} = $frob;
523             }
524              
525 3         12 my $sig = $self->_sign_args(\%fauth);
526 3         9 $fauth{api_sig} = $sig;
527              
528 3         21 my $uri = URI->new($self->{auth_uri});
529 3         379 $uri->query_form(%fauth);
530              
531 3         472 return $uri;
532             }
533              
534              
535             #
536             # Access Token (post authorization) Methods
537             #
538             # Handle access token requests (process: request token, authorize, ACCESS TOKEN)
539             #
540             sub oauth_access_token {
541              
542 0     0 1 0 my ($self, $args) = @_;
543              
544 0 0       0 unless ($self->is_oauth) {
545 0         0 carp "oauth_access_token called for Non-OAuth Flickr::API object";
546 0         0 return;
547             }
548 0 0       0 if ($args->{token} ne $self->{oauth}->{request_token}->{token}) {
549              
550 0         0 carp "Request token in API does not match token for access token request";
551 0         0 return;
552              
553             }
554              
555             #
556             # Stuff the values for the Net::OAuth factory
557             #
558 0         0 $self->{oauth}->{verifier} = $args->{verifier};
559 0         0 $self->{oauth}->{token} = $args->{token};
560 0         0 $self->{oauth}->{token_secret} = $self->{oauth}->{request_token}->{token_secret};
561              
562 0         0 my %oauth = %{$self->{oauth}};
  0         0  
563              
564 0   0     0 $oauth{request_url} = $args->{access_token_url} || 'https://api.flickr.com/services/oauth/access_token';
565              
566 0         0 $Net::OAuth::PROTOCOL_VERSION = Net::OAuth::PROTOCOL_VERSION_1_0A;
567              
568 0         0 my $request = Net::OAuth->request('Access Token')->new(%oauth);
569              
570 0         0 $request->sign;
571              
572 0         0 my $response = $self->get($request->to_url);
573              
574 0         0 my $content = $response->decoded_content();
575 0 0       0 $content = $response->content() unless defined $content;
576              
577 0 0       0 if ($content =~ m/^oauth_problem=(.+)$/) {
578              
579 0         0 carp "\nAccess token not granted: '",$1,"'\n";
580 0         0 $self->{oauth}->{access_token} = $1;
581              
582 0         0 delete $self->{oauth}->{token}; # Not saving problematic request token
583 0         0 delete $self->{oauth}->{token_secret}; # token secret
584 0         0 delete $self->{oauth}->{verifier}; # and verifier copies
585              
586 0         0 return $1;
587              
588             }
589              
590 0         0 $self->{oauth}->{access_token} = Net::OAuth->response('access token')->from_post_body($content);
591 0         0 $self->{oauth}->{token} = $self->{oauth}->{access_token}->token();
592 0         0 $self->{oauth}->{token_secret} = $self->{oauth}->{access_token}->token_secret();
593              
594 0         0 delete $self->{oauth}->{request_token}; #No longer valid, anyway
595 0         0 delete $self->{oauth}->{verifier};
596              
597 0         0 return 'ok';
598              
599             }
600              
601             sub flickr_access_token {
602 0     0 1 0 my ($self,$frob) = @_;
603              
604 0         0 my $rsp = $self->execute_method('flickr.auth.getToken', {api_key => $self->{api_key}, frob => $frob });
605 0         0 my $response_ref = $rsp->as_hash();
606              
607 0         0 $self->{fauth}->{frob} = $frob;
608              
609 0         0 $self->{token} = $response_ref->{auth}->{token};
610 0         0 $self->{fauth}->{token} = $response_ref->{auth}->{token};
611              
612 0         0 $self->{fauth}->{user} = $response_ref->{auth}->{user};
613              
614 0         0 return $response_ref->{stat};
615              
616             }
617              
618              
619             #
620             # Utility methods
621             #
622              
623              
624             sub is_oauth {
625 32     32 1 3051 my ($self) = @_;
626 32 100 66     201 if (defined $self->{api_type} and $self->{api_type} eq 'oauth') {
627 7         30 return 1;
628             }
629             else {
630 25         83 return 0;
631             }
632             }
633              
634              
635             sub get_oauth_request_type {
636 2     2 1 10 my ($self) = @_;
637              
638 2 50 33     16 if (defined $self->{api_type} and $self->{api_type} eq 'oauth') {
639 2         14 return $self->{oauth_request};
640             }
641             else {
642 0         0 return;
643             }
644             }
645              
646             sub api_type {
647 2     2 0 6 my ($self) = @_;
648              
649 2         29 return $self->{api_type};
650              
651             }
652              
653              
654             sub api_success {
655 0     0 0 0 my ($self) = @_;
656              
657 0         0 return $self->{flickr}->{status}->{api_success};
658              
659             }
660              
661              
662              
663              
664             sub api_message {
665 0     0 0 0 my ($self) = @_;
666              
667 0         0 return $self->{flickr}->{status}->{api_message};
668             }
669              
670              
671             sub api_permissions {
672 0     0 0 0 my ($self) = @_;
673 0         0 my $rsp;
674             my $check;
675 0         0 my $retval;
676              
677 0 0       0 if ($self->is_oauth) {
678              
679 0 0       0 if (defined($self->{oauth}->{perms})) {
680              
681 0         0 $self->_set_status(1,"Permissions retrieved from config.");
682              
683             }
684             else {
685              
686 0         0 $self->{oauth}->{perms} = 'none'; #preload no perms
687              
688 0         0 $rsp = $self->execute_method('flickr.auth.oauth.checkToken');
689              
690 0 0       0 if (!$rsp->success()) {
691              
692 0         0 $rsp->_propagate_status($self->{flickr}->{status});
693              
694             carp "\nUnable to validate OAuth token. Flickr error: ",
695             $self->{flickr}->{status}->{error_code}," - \"",
696 0         0 $self->{flickr}->{status}->{error_message},"\" \n";
697 0         0 delete $self->{oauth}->{perms};
698 0         0 $self->_set_status(0,"Unable to validate OAuth token, Flickr API call not successful.");
699              
700             }
701             else {
702              
703 0         0 $check = $rsp->as_hash();
704              
705 0         0 $self->{oauth}->{perms} = $check->{oauth}->{perms};
706 0         0 $self->_set_status(1,"Permissions retrieved from Flickr.");
707              
708             }
709             } # else not cached
710              
711 0         0 $retval = $self->{oauth}->{perms};
712              
713             } # is_oauth
714             else { # is_flickr
715              
716 0 0       0 if (defined($self->{fauth}->{perms})) {
717              
718 0         0 $self->_set_status(1,"Permissions retrieved from config.");
719              
720             }
721             else {
722              
723 0         0 $self->{fauth}->{perms} = 'none'; #preload no perms
724 0         0 $rsp = $self->execute_method('flickr.auth.checkToken',{'auth_token' => $self->{fauth}->{token}});
725              
726 0 0       0 if (!$rsp->success()) {
727              
728 0         0 $rsp->_propagate_status($self->{flickr}->{status});
729              
730             carp "\nUnable to validate Flickr token. Flickr error: ",
731             $self->{flickr}->{status}->{error_code}," - \"",
732 0         0 $self->{flickr}->{status}->{error_message},"\" \n";
733 0         0 delete $self->{fauth}->{perms};
734 0         0 $self->_set_status(0,"Unable to validate Flickr token, Flickr API call not successful.");
735              
736             }
737             else {
738              
739 0         0 $check = $rsp->as_hash();
740              
741 0         0 $self->{fauth}->{perms} = $check->{auth}->{perms};
742 0         0 $self->_set_status(1,"Permissions retrieved from Flickr.");
743             }
744             } # else not cached
745              
746 0         0 $retval = $self->{fauth}->{perms};
747              
748             } # else is_flickr
749              
750              
751 0         0 return $retval;
752              
753             }
754              
755              
756             #
757             # Private methods
758             #
759              
760             sub _sign_args {
761 9     9   990 my ($self, $args) = @_;
762              
763 9 50       25 if ($self->is_oauth) {
764              
765 0         0 carp "_sign_args called for an OAuth instantiated Flickr::API";
766 0         0 return;
767              
768             }
769              
770 9         24 my $sig = $self->{api_secret};
771              
772 9         18 foreach my $key (sort {$a cmp $b} keys %{$args}) {
  12         38  
  9         71  
773              
774 18 100       50 my $value = (defined($args->{$key})) ? $args->{$key} : "";
775 18         39 $sig .= $key . $value;
776             }
777              
778 9 100       61 return md5_hex(encode_utf8($sig)) if $self->{unicode};
779 5         40 return md5_hex($sig);
780             }
781              
782             sub _find_tag {
783 4     4   10 my ($self, $children) = @_;
784 4         7 for my $child(@{$children}){
  4         11  
785 8 100       30 return $child if $child->{type} eq 'element';
786             }
787 0         0 return {};
788             }
789              
790             sub _make_nonce {
791              
792 4     4   1484 return md5_hex(rand);
793              
794             }
795             sub _export_api {
796 1     1   2055408 my ($self) = @_;
797 1         6 my $api = {};
798              
799 1         15 $api->{oauth} = $self->{oauth};
800 1         9 $api->{fauth} = $self->{fauth};
801 1         11 $api->{flickr} = $self->{flickr};
802              
803 1         14 $api->{api_type} = $self->{api_type};
804 1         7 $api->{api_key} = $self->{api_key};
805 1         6 $api->{api_secret} = $self->{api_secret};
806 1         9 $api->{rest_uri} = $self->{rest_uri};
807 1         11 $api->{unicode} = $self->{unicode};
808 1         13 $api->{auth_uri} = $self->{auth_uri};
809 1         13 $api->{upload_uri} = $self->{upload_uri};
810              
811 1         7 return $api;
812             }
813              
814              
815             sub _initialize {
816              
817 8     8   20 my ($self) = @_;
818 8         25 $self->_set_status(1,'Base API initialized');
819 8         13 return;
820              
821             }
822              
823             sub _full_status {
824              
825 0     0   0 my ($self) = @_;
826 0         0 return $self->{flickr}->{status};
827             }
828              
829             sub _clear_status {
830              
831 8     8   25 my ($self) = @_;
832              
833             # the API status
834 8         35 $self->_set_status(1,'');
835             # the propagated response status
836 8         23 $self->{flickr}->{status}->{_rc} = 0;
837 8         23 $self->{flickr}->{status}->{success} = 1; # initialize as successful
838 8         19 $self->{flickr}->{status}->{error_code} = 0;
839 8         25 $self->{flickr}->{status}->{error_message} = '';
840              
841 8         14 return;
842              
843             }
844              
845             sub _set_status {
846              
847 16     16   39 my ($self, $good, $msg) = @_;
848              
849 16 50       70 if ($good != 0) { $good = 1; }
  16         27  
850              
851 16         97 $self->{flickr}->{status}->{api_success} = $good;
852 16         34 $self->{flickr}->{status}->{api_message} = $msg;
853              
854 16         32 return;
855             }
856              
857              
858              
859             1;
860              
861             __END__