source: extensions/pLoader/trunk/src/Uploader/PWG/WebServices.pm @ 4291

Last change on this file since 4291 was 4291, checked in by ronosman, 14 years ago

Bug 1058 fixed : double check photo transfer with pwg.images.exist.

  • Property svn:eol-style set to LF
File size: 13.4 KB
Line 
1# +-----------------------------------------------------------------------+
2# | pLoader - a Perl photo uploader for Piwigo                            |
3# +-----------------------------------------------------------------------+
4# | Copyright(C) 2008      Piwigo Team                  http://piwigo.org |
5# +-----------------------------------------------------------------------+
6# | This program is free software; you can redistribute it and/or modify  |
7# | it under the terms of the GNU General Public License as published by  |
8# | the Free Software Foundation                                          |
9# |                                                                       |
10# | This program is distributed in the hope that it will be useful, but   |
11# | WITHOUT ANY WARRANTY; without even the implied warranty of            |
12# | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU      |
13# | General Public License for more details.                              |
14# |                                                                       |
15# | You should have received a copy of the GNU General Public License     |
16# | along with this program; if not, write to the Free Software           |
17# | Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, |
18# | USA.                                                                  |
19# +-----------------------------------------------------------------------+
20package Uploader::PWG::WebServices;
21 
22use strict;
23use warnings;
24use MIME::Base64 qw(encode_base64); 
25use JSON;
26use LWP::UserAgent;
27use Data::Dumper;
28use Digest::MD5::File qw/file_md5_hex md5_hex/;
29use File::Slurp;
30use File::Spec;
31use POSIX qw(ceil floor);
32use base qw/
33           Uploader::Object
34           Class::Accessor::Fast
35           /;
36
37__PACKAGE__->mk_accessors( 
38    qw/
39           uagent
40           urlbase
41           username
42           password
43           qry_list_categories
44           qry_add_categories
45           qry_list_tags
46           items
47           tags
48           categories
49           site_high_file
50           site_resized_file
51           site_thumb_file
52           site_image_name
53           site_tags
54           rank
55           site_author
56           site_comment
57           site_img_date_creation
58           uagent_response
59           login_result
60           action_result
61           upload_high
62           chunk_size
63           sum_high_file
64           sum_resized_file
65           sum_thumb_file
66           sum_original_file
67      / 
68);
69
70$|=1;
71
72sub Init {
73    my ( $self, $version ) = @_ ;
74 
75    $self->uagent(
76        LWP::UserAgent->new(
77            agent => sprintf("Mozilla/pLoader %s", $version)       
78        )
79    );
80   
81    $self->uagent->cookie_jar({});     
82
83    $self->urlbase(
84        $self->{site_url}
85    );
86   
87    $self->username(
88        $self->{site_username}
89    );
90   
91    $self->password(
92        $self->{site_password}
93    );
94   
95    $self->chunk_size(
96        $self->{chunk_size}
97    );
98
99   
100    $self->uagent->default_headers->authorization_basic(
101        $self->{http_username}||$self->username, 
102        $self->{http_password}||$self->password
103    );
104   
105   
106    $self->qry_list_categories( sprintf
107        "%s/ws.php?format=json&method=%s&recursive=%s",
108        $self->urlbase,
109#        'pwg.categories.getAdminList',
110        'pwg.categories.getList',
111        'true',
112    );
113
114    $self->qry_list_tags( sprintf
115        "%s/ws.php?format=json&method=%s",
116        $self->urlbase,
117        'pwg.tags.getAdminList',
118    );
119
120
121    my $form = {
122        method => 'pwg.session.login',
123        username => $self->username,
124        password => $self->password,
125    };
126 
127    $self->uagent_response(
128        $self->uagent->post(
129            $self->urlbase.'/ws.php?format=json',
130            $form
131        )
132    );
133   
134    my $hresult = {} ;
135
136    if($self->uagent_response->is_success){
137        eval {
138            $hresult = from_json(
139                $self->uagent_response->content
140            );
141        };
142    }
143    else{
144        $hresult = {
145            'message' => $self->uagent_response->message,
146            'stat'    => 'fail',
147        };
148    }
149
150    $self->login_result(
151        $hresult
152    );
153
154}
155
156sub GetCategories {
157    my ( $self ) = @_;
158
159    my $result;
160    eval {
161        $result = $self->uagent->get(
162            $self->qry_list_categories
163        );
164    };
165
166    if($@){
167        printf("An error occured in query execution %s\n%s",
168            $self->qry_list_categories,
169            $@,
170        );     
171    }
172    my $hresult;
173   
174    eval {
175        $hresult = from_json(
176            $result->content
177        );
178    };
179   
180    $hresult ||= {};
181
182    my $categories = $hresult->{result}{categories};
183
184    $categories;       
185}
186
187sub GetTags {
188    my ( $self ) = @_;
189
190    my $result;
191    eval {
192        $result = $self->uagent->get(
193            $self->qry_list_tags
194        );
195    };
196
197    if($@){
198        printf("An error occured in query execution %s\n%s",
199            $self->qry_list_tags,
200            $@,
201        );     
202    }
203    my $hresult;
204   
205    eval {
206        $hresult = from_json(
207            $result->content
208        );
209    };
210   
211    $hresult ||= {};
212
213    $hresult->{result}{tags};
214}
215
216sub AddTags {
217    my ( $self, $name ) = @_;
218
219    my $form = {
220        method            => 'pwg.tags.add',
221        name              => $name,
222       
223    };
224
225    my $result = $self->uagent->post(
226        $self->urlbase.'/ws.php?format=json',
227        $form
228    );
229
230    my $content = {};
231        eval {
232            $content = from_json(
233                $result->content
234            );
235        };
236
237    return ( $result->is_success, $result->status_line, $content );
238       
239} 
240
241
242sub UploadImage {
243    my ( $self, $progress ) = @_;
244
245    $self->sum_resized_file(
246        $self->_checksum(
247            $self->site_resized_file,
248            $progress
249        )
250    );
251
252    $self->sum_thumb_file(
253        $self->_checksum(
254            $self->site_thumb_file,
255            $progress
256        )
257    );
258 
259    $self->sum_high_file(
260        $self->_checksum(
261            $self->site_high_file,
262            $progress
263        )
264    );
265    # is the same in pLoader but may be different
266    $self->sum_original_file(
267        $self->sum_high_file
268    );
269
270
271    my $site_image_name = $self->site_image_name; 
272
273    my $image_id = $self->_exists($self->sum_original_file);;
274    my $status = 0;
275    my $status_line = "An error has occured during upload.";
276    my $content = {};
277    my $doubleCheck;
278    my $form;
279    while(1){
280        if(!defined($image_id)){
281               
282            my $resized_params = $self->_send_chunks('file', $progress);
283            $status_line = $resized_params->{message};
284            last if !$resized_params->{ok};
285         
286            my $thumb_params = $self->_send_chunks('thumb', $progress);
287            $status_line = $thumb_params->{message};
288            last if !$thumb_params->{ok};
289       
290            $form = {
291                method            => 'pwg.images.add',
292                original_sum      => $self->sum_original_file,
293                file_sum          => $self->sum_resized_file,
294                thumbnail_sum     => $self->sum_thumb_file,
295                categories        => $self->categories,
296                name              => $site_image_name,
297                rank              => $self->rank,
298                author            => $self->site_author,
299                comment           => $self->site_comment,
300                date_creation     => $self->site_img_date_creation,
301                tag_ids           => $self->site_tags,
302               
303            };
304   
305            if($self->upload_high){
306                my $high_params = $self->_send_chunks('high', $progress);
307                $status_line = $high_params->{message};
308                last if !$high_params->{ok};
309            }
310            $doubleCheck = 1;
311        }
312        else {
313            $form = {
314                method            => 'pwg.images.setInfo',
315                image_id          => $image_id,
316                categories        => $self->categories,
317                name              => $site_image_name,
318                rank              => $self->rank,
319                author            => $self->site_author,
320                comment           => $self->site_comment,
321                date_creation     => $self->site_img_date_creation,
322                tag_ids           => $self->site_tags,
323            };
324            $progress->{yield}->();
325        }
326
327        delete $form->{tag_ids} unless defined $self->site_tags;
328        delete $form->{tag_ids} if '' eq $self->site_tags;
329
330        $progress->{yield}->();
331        my $result = $self->uagent->post(
332            $self->urlbase.'/ws.php?format=json',
333            $form
334        );
335        eval {
336            $content = from_json(
337                $result->content
338            );
339        };
340
341   
342        $status = $result->is_success;
343        $status_line = $result->status_line; 
344
345        if($doubleCheck){
346            $content->{stat} = 'fail' if !$self->_exists($self->sum_original_file); 
347        }
348
349        last;
350    }
351   
352    return ( $status,  $status_line, $content);
353}
354
355sub _exists {
356    my ( $self, $md5_sum ) = @_;
357
358    my $form = {
359        method            => 'pwg.images.exist',
360        md5sum_list       => $md5_sum,
361    };
362
363    my $result = $self->uagent->post(
364        $self->urlbase.'/ws.php?format=json',
365        $form
366    );
367
368    my $hresult = {};
369    eval {
370        $hresult = from_json(
371            $result->{_content}
372        );
373    };
374    my $id;
375    $id = $hresult->{result}{$self->sum_original_file} if 'ok' eq $hresult->{stat};
376   
377    $id;
378} 
379
380sub _checksum {
381    my ( $self, $file, $progress ) = @_;
382    my $file_sum;
383
384    my $yield = $progress->{yield};
385
386    $yield->();
387    $progress->{msg_details}->(
388        sprintf(
389            "%s : %s", 
390            $progress->{checksum_msg}, 
391            $file
392        )
393    );
394    eval {
395        $file_sum = file_md5_hex(
396            $file
397        );
398    };
399    $yield->();
400
401    $file_sum;
402}
403
404sub _send_chunks {
405    my ( $self, $type, $progress ) = @_;
406
407    my $msg = {
408        thumb=>'thumbnail_msg',
409        file=>'resized_msg',
410        high=>'highdef_msg',
411    };
412
413    my $filepath = {
414        thumb=>$self->site_thumb_file,
415        file=>$self->site_resized_file,
416        high=>$self->site_high_file,
417    };
418
419    $progress->{current_msg} = $progress->{$msg->{$type}};
420    $progress->{yield}->();
421
422    my $params = {
423         filepath      => $filepath->{$type},
424         type          => $type,
425         original_sum  => $self->sum_original_file,
426    };
427
428    $self->send_chunks(
429       $params,
430       $progress,
431    );
432    $progress->{yield}->();
433
434    $params;
435}
436
437sub AddCategories{
438    my ( $self, $name, $parentid ) = @_;
439
440    my $form = {
441        method            => 'pwg.categories.add',
442        name              => $name,
443        parent            => $parentid,
444       
445    };
446
447    my $result = $self->uagent->post(
448        $self->urlbase.'/ws.php?format=json',
449        $form
450    );
451
452    my $content = {};
453        eval {
454            $content = from_json(
455                $result->content
456            );
457        };
458
459    return ( $result->is_success, $result->status_line, $content );
460       
461}
462
463sub SetInfoCategories{
464    my ( $self, $name, $comment, $parentid ) = @_;
465
466    my $form = {
467        method            => 'pwg.categories.setInfo',
468        name              => $name,
469        comment           => $comment,
470        category_id       => $parentid,
471       
472    };
473
474    my $result = $self->uagent->post(
475        $self->urlbase.'/ws.php?format=json',
476        $form
477    );
478
479    my $content = {};
480        eval {
481            $content = from_json(
482                $result->content
483            );
484        };
485
486    return ( $result->is_success, $result->status_line, $content );
487       
488}
489
490
491sub send_chunks {
492    my ( $self, $params, $progress ) = @_;
493
494    my $yield = $progress->{yield};
495    my ( $vol, $dir, $filename ) = File::Spec->splitpath($params->{filepath});
496
497    $yield->();
498    $progress->{bar}->(0);
499    $yield->();
500    $progress->{msg_details}->(
501        sprintf(
502            "%s : %s", 
503            $progress->{current_msg}, 
504            $filename
505        )
506    );
507
508
509    $yield->();
510    my $content = read_file(
511        $params->{filepath},
512        binmode => ':raw',
513    );
514    $yield->();
515
516    my $content_length = length($content);
517    my $nb_chunks = ceil($content_length / $self->chunk_size);
518
519    my $chunk_pos = 0;
520    my $chunk_id = 1;
521
522
523    while ($chunk_pos < $content_length) {
524
525        my $chunk = substr(
526            $content,
527            $chunk_pos,
528            $self->chunk_size
529        );
530        $chunk_pos += $self->chunk_size;
531        my $response = $self->uagent->post(
532            $self->urlbase.'/ws.php?format=json',
533            {
534                method       => 'pwg.images.addChunk',
535                data         => encode_base64($chunk),
536                original_sum => $params->{original_sum},
537                position     => $chunk_id,
538                type         => $params->{type},
539            }
540        );
541        $yield->();
542        $progress->{bar}->(100*($chunk_pos/$content_length));
543        $progress->{msg_details}->(
544            sprintf(
545                "%s : %s", 
546                $progress->{current_msg}, 
547                $filename
548            )
549        );
550        $params->{ok} = 1;
551        if ($response->code != 200) {
552            printf("response code    : %u\n", $response->code);
553            printf("response message : %s\n", $response->message);
554            $params->{ok} = 0;
555            $params->{message} = $response->message;
556            $params->{code} = $response->code;
557            last;
558        }
559
560        $chunk_id++;
561    }
562}
563
564 
5651;
566   
Note: See TracBrowser for help on using the repository browser.