File Coverage

blib/lib/Gallery/Remote.pm
Criterion Covered Total %
statement 72 238 30.2
branch 0 84 0.0
condition n/a
subroutine 24 40 60.0
pod 1 11 9.0
total 97 373 26.0


line stmt bran cond sub pod time code
1             package Gallery::Remote;
2              
3             # An implementation of the gallery remote protocol as defined by
4             # http://gallery.menalto.com/modules.php?op=modload&name=GalleryDocs&file=index&page=gallery-remote.protocol.php
5             #
6             # Copyright (C) 2004, Tanner Lovelace
7             #
8             # This library is free software; you can redistribute it and/or
9             # modify it under the terms of the GNU General Public
10             # License as published by the Free Software Foundation; either
11             # version 2 of the License, or (at your option) any later version.
12             #
13             # This library is distributed in the hope that it will be useful,
14             # but WITHOUT ANY WARRANTY; without even the implied warranty of
15             # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16             # General Public License for more details.
17             #
18             # You should have received a copy of the GNU General Public License
19             # along with this perl module; see the file COPYING. If not, write to
20             # the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
21             # Boston, MA 02111-1307, USA.
22              
23 1     1   797 use strict;
  1         2  
  1         42  
24 1     1   6 use Carp;
  1         2  
  1         110  
25 1         117 use vars qw(
26             $VERSION
27             $REVISION
28             @ISA
29             @EXPORT
30             @EXPORT_OK
31             @configs
32 1     1   6 );
  1         5  
33              
34             require Exporter;
35 1     1   255306 use LWP::UserAgent;
  1         617594  
  1         35  
36 1     1   963 use HTTP::Cookies;
  1         16241  
  1         35  
37 1     1   2039 use HTTP::Request::Common;
  1         3752  
  1         95  
38             #use HTTP::Response;
39              
40 1     1   8 use constant PROTOCOL_VERSION => '2.7';
  1         2  
  1         866  
41 1     1   12 use constant PROTOCOL_MAJOR => '2';
  1         1  
  1         82  
42 1     1   6 use constant PROTOCOL_MINOR => '7';
  1         1  
  1         58  
43 1     1   6 use constant RESPONSE_BEGINNING => '#__GR2PROTO__\n';
  1         3  
  1         158  
44              
45             # Response Status Codes
46             #
47             # Status name
48             # Code
49             # Description
50             #
51             # GR_STAT_SUCCESS
52             # 0
53             # The command the client sent in the request completed
54             # successfully. The data (if any) in the response should be considered
55             # valid.
56             #
57             # GR_STAT_PROTO_MAJ_VER_INVAL
58             # 101
59             # The protocol major version the client is using is not supported.
60             #
61             # GR_STAT_PROTO_MIN_VER_INVAL
62             # 102
63             # The protocol minor version the client is using is not supported.
64             #
65             # GR_STAT_PROTO_VER_FMT_INVAL
66             # 103
67             # The format of the protocol version string the client sent in the
68             # request is invalid.
69             #
70             # GR_STAT_PROTO_VER_MISSING
71             # 104
72             # The request did not contain the required protocol_version key.
73             #
74             # GR_STAT_PASSWD_WRONG
75             # 201
76             # The password and/or username the client send in the request is
77             # invalid.
78             #
79             # GR_STAT_LOGIN_MISSING
80             # 202
81             # The client used the login command in the request but failed to
82             # include either the username or password (or both) in the request.
83             #
84             # GR_STAT_UNKNOWN_CMD
85             # 301
86             # The value of the cmd key is not valid.
87             #
88             # GR_STAT_NO_ADD_PERMISSION
89             # 401
90             # The user does not have permission to add an item to the gallery.
91             #
92             # GR_STAT_NO_FILENAME
93             # 402
94             # No filename was specified.
95             #
96             # GR_STAT_UPLOAD_PHOTO_FAIL
97             # 403
98             # The file was received, but could not be processed or added to the
99             # album.
100             #
101             # GR_STAT_NO_WRITE_PERMISSION
102             # 404
103             # No write permission to destination album.
104             #
105             # GR_STAT_NO_CREATE_ALBUM_PERMISSION
106             # 501
107             # A new album could not be created because the user does not have
108             # permission to do so.
109             #
110             # GR_STAT_CREATE_ALBUM_FAILED
111             # 502
112             # A new album could not be created, for a different reason (name
113             # conflict).
114 1     1   268 use constant GR_STAT_SUCCESS => '0';
  1         2  
  1         47  
115 1     1   4 use constant GR_STAT_PROTO_MAJ_VER_INVAL => '101';
  1         2  
  1         34  
116 1     1   4 use constant GR_STAT_PROTO_MIN_VER_INVAL => '102';
  1         1  
  1         32  
117 1     1   12 use constant GR_STAT_PROTO_VER_FMT_INVAL => '103';
  1         2  
  1         51  
118 1     1   5 use constant GR_STAT_PROTO_VER_MISSING => '104';
  1         2  
  1         41  
119 1     1   5 use constant GR_STAT_PASSWD_WRONG => '201';
  1         1  
  1         42  
120 1     1   5 use constant GR_STAT_LOGIN_MISSING => '202';
  1         2  
  1         38  
121 1     1   4 use constant GR_STAT_UNKNOWN_CMD => '301';
  1         2  
  1         38  
122 1     1   4 use constant GR_STAT_NO_ADD_PERMISSION => '401';
  1         2  
  1         45  
123 1     1   5 use constant GR_STAT_NO_FILENAME => '402';
  1         1  
  1         31  
124 1     1   4 use constant GR_STAT_UPLOAD_PHOTO_FAIL => '403';
  1         2  
  1         44  
125 1     1   6 use constant GR_STAT_NO_WRITE_PERMISSION => '404';
  1         1  
  1         1646  
126 1     1   7 use constant GR_STAT_NO_CREATE_ALBUM_PERMISSION => '501';
  1         2  
  1         44  
127 1     1   6 use constant GR_STAT_CREATE_ALBUM_FAILED => '502';
  1         1  
  1         4177  
128              
129              
130             @ISA = qw(Exporter);
131             # Items to export into callers namespace by default. Note: do not export
132             # names by default without a very good reason. Use EXPORT_OK instead.
133             # Do not simply export all your public functions/methods/constants.
134             @EXPORT = qw(
135             );
136             $VERSION = '0.2';
137             $REVISION = (qw$Rev: 13 $)[-1];
138              
139             # Preloaded methods go here.
140              
141             sub new {
142 0     0 1   my $classname = shift;
143 0           my $self = {};
144 0           bless($self, $classname);
145 0           $self->_init(@_);
146 0           return $self;
147             }
148              
149             #
150             # Intenal methods
151             #
152             sub _init
153             {
154 0     0     my $self = shift;
155              
156 0           $self->{LOGGEDIN} = 0;
157              
158 0 0         if (@_) {
159 0           my %extra = @_;
160 0           @$self{keys %extra} = values %extra;
161             }
162 0 0         if ($self->{URL}) {
163 0           $self->{REMOTE_URL} = $self->{URL} . "gallery_remote2.php";
164             }
165             }
166              
167             sub _check_response
168             {
169 0     0     my $self = shift;
170 0           my $response = shift;
171 0           my $url = shift;
172              
173 0           my $response_code = $response->code;
174 0           my $response_text = $self->_get_response_text($response);
175              
176             # Error!
177 0 0         if ($response_code != 200) {
178 0 0         if ($response_code == 404) {
179 0           die "Remote gallery not found at " . $url ."\n" .
180             "Code : " . $response_code . "\n" .
181             "Message: " . $response_text . "\n";
182             } else {
183 0           die "Could not log in to remote gallery at " . $url ."\n" .
184             "Code : " . $response_code . "\n" .
185             "Message: " . $response_text . "\n";
186             }
187             }
188 0           return 1;
189             }
190              
191             sub _get_response_text
192             {
193 0     0     my $self = shift;
194 0           my $response = shift;
195 0 0         if ($response->is_error) {
196 0           return $response->error_as_HTML;
197             }
198 0           return $response->content;
199             }
200              
201             sub _fill_in_response_fields
202             {
203 0     0     my $self = shift;
204 0           my $field_string = shift;
205              
206 0           my $fields = {};
207              
208 0 0         print STDERR "Response string:\n$field_string\n" if ($self->{DEBUG});
209              
210             # Strip off the the stuff before responses.
211 0           my $resp_beg = RESPONSE_BEGINNING;
212 0           $field_string =~ s/.*$resp_beg//s;
213 0 0         print STDERR "Response string (header stripped off):\n$field_string\n" if ($self->{DEBUG});
214 0           my @field_lines = split('\n',$field_string);
215 0           foreach my $line (@field_lines) {
216             #print STDERR "Response line: $line\n" if ($self->{DEBUG});
217 0           my ($field_key, $field_value) = split('=', $line);
218 0 0         print STDERR "Response field: $field_key = $field_value\n" if ($self->{DEBUG});
219 0 0         $fields->{$field_key} = $field_value if ($field_value ne "");
220             }
221              
222 0           return $fields;
223             }
224              
225             sub _fill_in_album_data
226             {
227 0     0     my $self = shift;
228 0           my $response_fields = shift;
229             # Array reference for returning album data
230 0           my $album_data = ();
231              
232 0           for (my $i = 1; $i <= $response_fields->{album_count}; $i++) {
233 0           my $album_entry = {};
234 0           $album_entry->{name} = $response_fields->{"album.name.$i"};
235 0           $album_entry->{title} = $response_fields->{"album.title.$i"};
236 0           $album_entry->{parent} = $response_fields->{"album.parent.$i"};
237 0 0         $album_entry->{add} = ($response_fields->{"album.perms.add.$i"} eq 'true' ? 1 : 0);
238 0 0         $album_entry->{write} = ($response_fields->{"album.perms.write.$i"} eq 'true' ? 1 : 0);
239 0 0         $album_entry->{del_item} = ($response_fields->{"album.perms.del_item.$i"} eq 'true' ? 1 : 0);
240 0 0         $album_entry->{del_alb} = ($response_fields->{"album.perms.del_alb.$i"} eq 'true' ? 1 : 0);
241 0 0         $album_entry->{create_sub} = ($response_fields->{"album.perms.create_sub.$i"} eq 'true' ? 1 : 0);
242              
243 0 0         print STDERR "Response fields: \n" .
244             " album.name.$i = " . $response_fields->{"album.name.$i"} . "\n" .
245             " album.title.$i = " . $response_fields->{"album.title.$i"} . "\n" .
246             " album.parent.$i = " . $response_fields->{"album.parent.$i"} . "\n" .
247             " album.perms.add.$i = " . $response_fields->{"album.perms.add.$i"} . "\n" .
248             " album.perms.write.$i = " . $response_fields->{"album.perms.write.$i"} . "\n" .
249             " album.perms.del_item.$i = " . $response_fields->{"album.perms.del_item.$i"} . "\n" .
250             " album.perms.del_alb.$i = " . $response_fields->{"album.perms.del_alb.$i"} . "\n" .
251             " album.perms.create_sub.$i = " . $response_fields->{"album.perms.create_sub.$i"} . "\n"
252             if ($self->{DEBUG});
253            
254 0           push @$album_data, $album_entry;
255             }
256            
257 0           return $album_data;
258             }
259              
260             #
261             # External methods
262             #
263             sub set_server
264             {
265 0     0 0   my $self = shift;
266              
267 0 0         if ($self->{LOGGEDIN}) { $self->logout(); }
  0            
268              
269             # Setup values.
270 0           $self->{URL} = shift;
271 0           $self->{USERNAME} = shift;
272 0           $self->{PASSWORD} = shift;
273              
274 0           $self->{REMOTE_URL} = $self->{URL} . "gallery_remote2.php";
275             }
276              
277             sub login
278             {
279 0     0 0   my $self = shift;
280              
281 0 0         die "URL must be set to login to remote gallery" unless $self->{REMOTE_URL};
282 0 0         die "USERNAME must be set to login to remote gallery" unless $self->{USERNAME};
283 0 0         die "PASSWORD must be set to login to remote gallery" unless $self->{PASSWORD};
284              
285 0           $self->{_UA} = LWP::UserAgent->new;
286 0           $self->{_UA}->cookie_jar(HTTP::Cookies->new(file => 'cookie_jar', autosave => 1));
287              
288 0           my $response = $self->{_UA}->request(POST $self->{REMOTE_URL},
289             Content_Type => 'form-data',
290             Content => [ protocol_version => PROTOCOL_VERSION,
291             cmd => "login",
292             uname => $self->{USERNAME},
293             password => $self->{PASSWORD}
294             ] );
295              
296 0           my $response_text = $self->_get_response_text($response);
297              
298 0           $self->_check_response($response,$self->{URL});
299              
300             # Ok, the file was there. Parse the response codes.
301 0           my $response_fields = $self->_fill_in_response_fields($response_text);
302              
303 0 0         print STDERR "Response status: $response_fields->{status}\n" if ($self->{DEBUG});
304              
305 0 0         if ($response_fields->{status} eq GR_STAT_SUCCESS) {
306             # Make sure our version number is high enough
307 0           my ($major, $minor) = split('\.', $response_fields->{server_version});
308 0 0         if ($major != PROTOCOL_MAJOR) {
309 0           die "Major protocol mismatch. Was expecting " . PROTOCOL_MAJOR . ". Got: $major";
310             }
311 0 0         if ($minor < PROTOCOL_MINOR) {
312 0           die "Need a minor protocol of at least " . PROTOCOL_MINOR . ". Got: $minor";
313             }
314 0           $self->{LOGGEDIN} = 1;
315 0 0         print "Login successful\n" if ($self->{VERBOSE});
316             } else {
317 0           die "Could not log in to remote gallery at " . $self->{URL} ."\n" .
318             "Status: " . $response_fields->{status} . "\n" .
319             "Text : " . $response_fields->{status_text} . "\n";
320             }
321             }
322              
323             sub logout
324             {
325 0     0 0   my $self = shift;
326              
327             # No specific logout command, so reset variables
328              
329 0           $self->{LOGGEDIN} = 0;
330 0           $self->{_UA} = undef;
331             }
332              
333              
334             # Getting a list of albums
335             #
336             # The fetch-albums command asks the server to return a list of all
337             # albums (visible with the client's logged in user permissions).
338             #
339             # Context
340             #
341             # A request with the login command must be made before the
342             # fetch-albums command is used.
343             #
344             # Form data
345             #
346             # cmd=fetch-albums
347             # protocol_version=2.0
348             #
349             # Results
350             #
351             # #__GR2PROTO__
352             # status=result-code
353             # status_text=explanatory-text
354             # /album.name.ref-num=album-url-name
355             # |album.title.ref-num=album-display-name
356             # |album.summary.ref-num=album-summary [since 2.8]
357             # |album.parent.ref-num=parent-ref-num
358             # |album.resize_size.ref-num=image-resize-size [since 2.8]
359             # 0...n |album.perms.add.ref-num=boolean
360             # |album.perms.write.ref-num=boolean
361             # |album.perms.del_item.ref-num=boolean
362             # |album.perms.del_alb.ref-num=boolean
363             # |album.perms.create_sub.ref-num=boolean
364             # \album.info.extrafields.ref-num=extra-fields [since 2.3]
365             # album_count=number-of-albums
366             # can_create_root=yes/no [since 2.11]
367             #
368             # If the result-code is equal to GR_STAT_SUCCESS, the album data was
369             # fetched successfully.
370             #
371             # If successful, a response to the fetch-albums command returns
372             # several keys for each album in the gallery, where
373             #
374             # ref-num is a reference number,
375             #
376             # album-url-name is the name of the partial URL for the gallery,
377             #
378             # album-display-name is the gallery's visual name,
379             #
380             # album-summary is the summary of the album,
381             #
382             # parent-ref-num refers to some other album's ref-num. A
383             # parent-ref-num of 0 (zero) indicates that the album is a "top-level"
384             # album (it has no parent).
385             #
386             # image-resize-size is the intermediate size of images created when a
387             # large image is added to an album,
388             #
389             # extra-fields is a comma-separated list of extra fields names, and
390             # boolean represents a boolean value. true is considered true, any
391             # other value false.
392             #
393             # Several "permissions" are reported for each album. The reported
394             # permissions are the effective permissions of the currently logged in
395             # user:
396             #
397             # the add permission allows the user to add a picture to the album.
398             #
399             # the write permission allows the user to add and change pictures in
400             # the album.
401             #
402             # the del_item permission allows the user remove pictures from the
403             # album.
404             #
405             # the del_alb permission allows the user to delete the album.
406             #
407             # the create_sub permission allows the user to create nested albums in
408             # the album.
409             #
410             # The number of albums in the response is returned as
411             # number-of-albums.
412             #
413             # can_create_root will be set to either yes or no depending on the
414             # user's permissions to create albums at the root level.
415             sub fetch_albums
416             {
417 0     0 0   my $self = shift;
418              
419 0 0         die "Must log in before fetching albums" unless ($self->{LOGGEDIN});
420              
421 0           my $response = $self->{_UA}->request(POST $self->{REMOTE_URL},
422             Content_Type => 'form-data',
423             Content => [ protocol_version => PROTOCOL_VERSION,
424             cmd => "fetch-albums",
425             ] );
426              
427 0           my $response_text = $self->_get_response_text($response);
428              
429 0           $self->_check_response($response,$self->{URL});
430              
431             # Ok, the file was there. Parse the response codes.
432 0           my $response_fields = $self->_fill_in_response_fields($response_text);
433              
434 0 0         if ($response_fields->{status} ne GR_STAT_SUCCESS) {
435 0           die "Could not fetch-albums from remote gallery at " . $self->{URL} ."\n" .
436             "Status: " . $response_fields->{status} . "\n" .
437             "Text : " . $response_fields->{status_text} . "\n";
438             }
439              
440 0           return($self->_fill_in_album_data($response_fields));
441             }
442              
443              
444             # Getting a list of albums v2, more efficient [since 2.2]
445             #
446             # The fetch-albums-prune command asks the server to return a list of
447             # all albums that the user can either write to, or that are visible to
448             # the user and contain a sub-album that is writable (including
449             # sub-albums several times removed).
450             #
451             # The reason for this slightly altered version of fetch-albums is
452             # two-fold: the previous version was slow on the server-side, because
453             # of the way it was structured, and limitation in the Gallery mode of
454             # operation; it returns all albums the the user can read, even if
455             # writing is not allowed. This new version is faster, because it uses
456             # a more efficient algorithm to find albums; it is more efficient
457             # because it only sends albums that are useful to the client. It also
458             # doesn't parse the pictures database, which makes it run much faster
459             # on the server.
460             #
461             # Context
462             #
463             # A request with the login command must be made before the
464             # fetch-albums-prune command is used.
465             #
466             # Form data
467             #
468             # cmd=fetch-albums-prune
469             # protocol_version=2.2
470             # check_writeable=yes/no [since 2.13]
471             #
472             # Results
473             #
474             # #__GR2PROTO__
475             # status=result-code
476             # status_text=explanatory-text
477             # /album.name.ref-num=album-url-name
478             # |album.title.ref-num=album-display-name
479             # |album.summary.ref-num=album-summary [since 2.8]
480             # |album.parent.ref-num=parent-ref-num
481             # |album.resize_size.ref-num=image-resize-size [since 2.8]
482             # |album.thumb_size.ref-num=image-thumb-size [since 2.9]
483             # 0...n |album.perms.add.ref-num=boolean
484             # |album.perms.write.ref-num=boolean
485             # |album.perms.del_item.ref-num=boolean
486             # |album.perms.del_alb.ref-num=boolean
487             # |album.perms.create_sub.ref-num=boolean
488             # \album.info.extrafields.ref-num=extra-fields [since 2.3]
489             # album_count=number-of-albums
490             # can_create_root=yes/no [since 2.11]
491             #
492             # If the result-code is equal to GR_STAT_SUCCESS, the album data was
493             # fetched successfully.
494             #
495             # If successful, a response to the fetch-albums-prune command returns
496             # several keys for each album in the gallery, where
497             #
498             # ref-num is a reference number,
499             #
500             # album-url-name is the name of the partial URL for the gallery,
501             #
502             # album-display-name is the gallery's visual name,
503             #
504             # album-summary is the summary of the album,
505             #
506             # parent-ref-num refers to some other album's ref-num. A
507             # parent-ref-num of 0 (zero) indicates that the album is a "top-level"
508             # album (it has no parent).
509             #
510             # image-resize-size is the intermediate size of images created when a
511             # large image is added to an album,
512             #
513             # extra-fields is a comma-separated list of extra fields names,
514             #
515             # and boolean represents a boolean value. true is considered true, any
516             # other value false.
517             #
518             # Several "permissions" are reported for each album. The reported
519             # permissions are the effective permissions of the currently logged in
520             # user:
521             #
522             # the add permission allows the user to add a picture to the album.
523             #
524             # the write permission allows the user to add and change pictures in
525             # the album.
526             #
527             # the del_item permission allows the user remove pictures from the
528             # album.
529             #
530             # the del_alb permission allows the user to delete the album.
531             #
532             # the create_sub permission allows the user to create nested albums in
533             # the album.
534             #
535             # The number of albums in the response is returned as number-of-albums.
536             #
537             # can_create_root will be set to either yes or no depending on the
538             # user's permissions to create albums at the root level.
539             sub fetch_albums_prune
540             {
541 0     0 0   my $self = shift;
542              
543 0 0         die "Must log in before fetching albums" unless ($self->{LOGGEDIN});
544              
545 0           my $response = $self->{_UA}->request(POST $self->{REMOTE_URL},
546             Content_Type => 'form-data',
547             Content => [ protocol_version => PROTOCOL_VERSION,
548             cmd => "fetch-albums-prune",
549             ] );
550              
551 0           my $response_text = $self->_get_response_text($response);
552              
553 0           $self->_check_response($response,$self->{URL});
554              
555             # Ok, the file was there. Parse the response codes.
556 0           my $response_fields = $self->_fill_in_response_fields($response_text);
557              
558 0 0         if ($response_fields->{status} ne GR_STAT_SUCCESS) {
559 0           die "Could not fetch-albums-prune from remote gallery at " . $self->{URL} ."\n" .
560             "Status: " . $response_fields->{status} . "\n" .
561             "Text : " . $response_fields->{status_text} . "\n";
562             }
563              
564 0           return($self->_fill_in_album_data($response_fields));
565             }
566              
567             # Uploading a photo to an album
568             #
569             # The add-item command asks the server to add a photo to a specified
570             # album.
571             #
572             # Context
573             #
574             # A request with the login command must be made before the add-item
575             # command is used.
576             #
577             # Form data
578             #
579             # cmd=add-item
580             # protocol_version=2.0
581             # set_albumName=album name
582             # userfile=form-data-encoded image data [since 2.0] or URL of image [since 2.12]
583             # userfile_name=file name (usually inserted automatically by HTTP library, which is why we also have force_filename
584             # caption=caption (optional) [since 2.0]
585             # force_filename=name of the file on the server (optional) [since 2.0]
586             # auto_rotate=yes/no (optional) [since 2.5]
587             # extrafield.fieldname=value of the extra field fieldname (optional) [since 2.3]
588             #
589             # Multiple extrafield lines with different fieldname values can be
590             # used.
591             #
592             # Only gallery administrators can specify a URL as the userfile.
593             #
594             # Results
595             #
596             # #__GR2PROTO__
597             # status=result-code
598             # status_text=explanatory-text
599             #
600             # If the result-code is equal to GR_STAT_SUCCESS, the file upload
601             # succeeded.
602             sub add_item
603             {
604 0     0 0   my $self = shift;
605              
606 0 0         die "Must log in before getting album properties" unless ($self->{LOGGEDIN});
607              
608 0           my %params = @_;
609              
610 0 0         if (!$params{set_albumName}) {
611 0           die "Must specify album to add items to it.";
612             }
613 0 0         if (!$params{userfile}) {
614 0           die "Must specify an image file or url for add_item.";
615             }
616 0 0         if (!$params{userfile_name}) {
617 0           die "Must specify an image file name or url for add_item.";
618             }
619              
620 0           my $content = { protocol_version => PROTOCOL_VERSION,
621             cmd => "add-item",
622             };
623              
624             # Set everything at once.
625 0           @$content{keys %params} = values %params;
626              
627 0           my $response = $self->{_UA}->request(POST $self->{REMOTE_URL},
628             Content_Type => 'form-data',
629             Content => $content );
630              
631 0           my $response_text = $self->_get_response_text($response);
632              
633 0           $self->_check_response($response,$self->{URL});
634              
635             # Ok, the file was there. Parse the response codes.
636 0           my $response_fields = $self->_fill_in_response_fields($response_text);
637              
638 0 0         if ($response_fields->{status} ne GR_STAT_SUCCESS) {
639 0           die "Could not execute album-properties command on remote gallery at " . $self->{URL} ."\n" .
640             "Status: " . $response_fields->{status} . "\n" .
641             "Text : " . $response_fields->{status_text} . "\n";
642             }
643              
644             # XXX - Do we want to return this for all methods?
645 0           return $response_fields;
646             }
647              
648             # Getting information about an album [since 2.0]
649             #
650             # The album-properties command asks the server for information about
651             # an album.
652             #
653             # Context
654             #
655             # A request with the login command must be made before the
656             # album-properties command is used.
657             #
658             # Form data
659             #
660             # cmd=album-properties
661             # protocol_version=2.0
662             # set_albumName=album name
663             #
664             # Results
665             #
666             # #__GR2PROTO__
667             # status=result-code
668             # status_text=explanatory-text
669             # auto_resize=resize-dimension
670             # add_to_beginning=yes/no
671             #
672             # If the result-code is equal to GR_STAT_SUCCESS, the request
673             # succeeded.
674             #
675             # If an image is uploaded such that its largest dimension is greater
676             # than resize-dimension, the server will resize it. Otherwise, the
677             # server will use the original image that was uploaded for both the
678             # full-sized and the resized size. In all cases a thumbnail-sized
679             # image will be created. The creation of a thumbnail is highly
680             # dependant on the size of the image that was uploaded.
681             #
682             # If the value is 0 (zero), the Gallery server does not intend to
683             # resize uploaded images.
684             #
685             # add_to_beginning will contain yes or no based on whether the album
686             # will add images to the beginning or the end of the album. [since
687             # 2.10]
688             sub album_properties
689             {
690 0     0 0   my $self = shift;
691              
692 0 0         die "Must log in before getting album properties" unless ($self->{LOGGEDIN});
693              
694 0           my %params = @_;
695              
696 0 0         if (!$params{set_albumName}) {
697 0           die "Must specify album to get its properties";
698             }
699              
700 0           my $content = { protocol_version => PROTOCOL_VERSION,
701             cmd => "album-properties",
702             };
703              
704             # Set everything at once.
705 0           @$content{keys %params} = values %params;
706              
707 0           my $response = $self->{_UA}->request(POST $self->{REMOTE_URL},
708             Content_Type => 'form-data',
709             Content => $content );
710              
711 0           my $response_text = $self->_get_response_text($response);
712              
713 0           $self->_check_response($response,$self->{URL});
714              
715             # Ok, the file was there. Parse the response codes.
716 0           my $response_fields = $self->_fill_in_response_fields($response_text);
717              
718 0 0         if ($response_fields->{status} ne GR_STAT_SUCCESS) {
719 0           die "Could not execute album-properties command on remote gallery at " . $self->{URL} ."\n" .
720             "Status: " . $response_fields->{status} . "\n" .
721             "Text : " . $response_fields->{status_text} . "\n";
722             }
723              
724             # XXX - Do we want to return this for all methods?
725 0           return $response_fields;
726             }
727              
728             # Creating a new album [since 2.1]
729             #
730             # The new-album command asks the server to add a new album to the
731             # gallery installation.
732             #
733             # Context
734             #
735             # A request with the login command must be made before the new-album
736             # command is used.
737             #
738             # Form data
739             #
740             # cmd=new-album
741             # protocol_version=2.1
742             # set_albumName=parent-album-name
743             # newAlbumName=album-name (optional)
744             # newAlbumTitle=album-title (optional)
745             # newAlbumDesc=album-description (optional)
746             #
747             # parent-album-name is the name of the gallery that the new album
748             # should be created under, or 0 to create the album at the top-level;
749             #
750             # album-name is the new album's desired name. The name must be unique
751             # within the Gallery. If it is not, then Gallery will assign an
752             # automatically-generated name. An automatically generated name will
753             # also be used if this parameter is not provided or is empty;
754             #
755             # album-title is the new album's desired title;
756             #
757             # album-description is the new album's desired description.
758             #
759             # Results
760             #
761             # #__GR2PROTO__
762             # status=result-code
763             # status_text=explanatory-text
764             # album_name=actual-name [since 2.5]
765             #
766             # If the result-code is equal to GR_STAT_SUCCESS, the request
767             # succeeded.
768             #
769             # If the result-code is equal to GR_STAT_NO_CREATE_ALBUM_PERMISSION,
770             # the logged-in user doesn't have permission to create an album in the
771             # specified location.
772             #
773             # If an album is created with the same name as an already existing
774             # album or album-title is left blank, gallery will automatically
775             # generate an album name. actual-name will return the name of the
776             # newly created album.
777             sub new_album
778             {
779 0     0 0   my $self = shift;
780              
781 0 0         die "Must log in before creating albums" unless ($self->{LOGGEDIN});
782              
783 0           my %params = @_;
784              
785 0           my $content = { protocol_version => PROTOCOL_VERSION,
786             cmd => "new-album",
787             };
788              
789             # Set everything at once.
790 0           @$content{keys %params} = values %params;
791              
792 0           my $response = $self->{_UA}->request(POST $self->{REMOTE_URL},
793             Content_Type => 'form-data',
794             Content => $content );
795              
796 0           my $response_text = $self->_get_response_text($response);
797              
798 0           $self->_check_response($response,$self->{URL});
799              
800             # Ok, the file was there. Parse the response codes.
801 0           my $response_fields = $self->_fill_in_response_fields($response_text);
802              
803 0 0         if ($response_fields->{status} ne GR_STAT_SUCCESS) {
804 0           die "Could not execute new-album command on remote gallery at " . $self->{URL} ."\n" .
805             "Status: " . $response_fields->{status} . "\n" .
806             "Text : " . $response_fields->{status_text} . "\n";
807             }
808              
809 0           return $response_fields->{album_name};
810             }
811              
812             # Getting the list of photos in an album [since 2.4]
813             #
814             # The fetch-album-images command asks the server to return information
815             # about all the images in an album. It ignores sub-albums.
816             #
817             # Context
818             #
819             # A request with the login command can be made before the
820             # fetch-album-images command is used, but since viewing photos in an
821             # album is generally (but not always) open to non logged-in users, a
822             # login is not always necessary.
823             #
824             # Form data
825             #
826             # cmd=fetch-album-images
827             # protocol_version=2.4
828             # set_albumName=album-name
829             # albums_too=yes/no [since 2.13]
830             #
831             # If set_albumName empty, the root albums are listed. Of course, this
832             # only works if albums_too is also used [since 2.13]
833             #
834             # Results
835             #
836             # #__GR2PROTO__
837             # status=result-code
838             # status_text=explanatory-text
839             # /image.name.ref_num=filename of the image
840             # |image.raw_width.ref_num=the width of the full-sized image
841             # |image.raw_height.ref_num=the height of the full-sized image
842             # |image.resizedName.ref_num=filename of the resized image, if there is one
843             # |image.resized_width.ref_num=the width of the resized image, if there is one [since 2.9]
844             # |image.resized_height.ref_num=the height of the resized image, if there is one [since 2.9]
845             # |image.thumbName.ref_num=filename of the thumbnail [since 2.9]
846             # |image.thumb_width.ref_num=the width of the thumbnail [since 2.9]
847             # |image.thumb_height.ref_num=the height of the thumbnail [since 2.9]
848             # |image.raw_filesize.ref_num=size of the full-sized image
849             # |image.caption.ref_num=caption associated with the image
850             # 0...n |image.extrafield.fieldname.ref_num=value of the extra field of key fieldname
851             # |image.clicks.ref_num=number of clicks on the image
852             # |image.capturedate.year.ref_num=date of capture of the image (year)
853             # |image.capturedate.mon.ref_num=date of capture of the image (month)
854             # |image.capturedate.mday.ref_num=date of capture of the image (day of the month)
855             # |image.capturedate.hours.ref_num=date of capture of the image (hour)
856             # |image.capturedate.minutes.ref_num=date of capture of the image (minute)
857             # \image.capturedate.seconds.ref_num=date of capture of the image (second)
858             # OR album.name.ref_num=name of the album [since 2.13]
859             # image_count=total number of images in the album
860             # baseurl=URL of the album
861             #
862             # If the result-code is equal to GR_STAT_SUCCESS, the request
863             # succeeded.
864             #
865             # The baseurl contains a fully-qualified URL. A URL to each image can
866             # be obtained by appending the filename of the image to this.
867             #
868             # The name and resizedName include the type (extension), but do not
869             # include any path information.
870             #
871             # Multiple extrafield lines with different fieldname values can be
872             # used.
873             #
874             # If albums_too is yes, the list of results can contain album
875             # references. In this case, none of the image.*.ref_num fields will be
876             # present. Instead, album.name.ref_num will provide the reference to
877             # the sub-album. This allows reursive getting of all images in an
878             # album hierarchy.
879             sub fetch_album_images
880             {
881 0     0 0   my $self = shift;
882              
883 0           die "XXX - fetch_album_images not implemented yet!";
884             }
885              
886             # Moving an album [since 2.7]
887             #
888             # The move-album command asks the server to move an album to a new
889             # location within the photo gallery.
890             #
891             # Context
892             #
893             # A request with the login command must be made before the move-album
894             # command is used.
895             #
896             # Form data
897             #
898             # cmd=move-album
899             # protocol_version=2.7
900             # set_albumName=source-album
901             # set_destalbumName=destination-album
902             #
903             # source-album is the name of the album that you intend to move;
904             #
905             # destination-album is the name of the album that the source-album
906             # will be moved into, or 0 if the source-album should be moved to the
907             # root level;
908             #
909             # Results
910             #
911             # #__GR2PROTO__
912             # status=result-code
913             # status_text=explanatory-text
914             #
915             # If the result-code is equal to GR_STAT_SUCCESS, the album move succeeded.
916             sub move_album
917             {
918 0     0 0   my $self = shift;
919              
920 0 0         die "Must log in before creating albums" unless ($self->{LOGGEDIN});
921              
922 0           my %params = @_;
923              
924 0 0         if (!$params{set_albumName}) {
925 0           die "Must specify album to move";
926             }
927 0 0         if (!$params{set_destalbumName}) {
928 0           die "Must specify destination for move";
929             }
930              
931 0           my $content = { protocol_version => PROTOCOL_VERSION,
932             cmd => "move-album",
933             };
934              
935             # Set everything at once.
936 0           @$content{keys %params} = values %params;
937              
938 0           my $response = $self->{_UA}->request(POST $self->{REMOTE_URL},
939             Content_Type => 'form-data',
940             Content => $content );
941              
942 0           my $response_text = $self->_get_response_text($response);
943              
944 0           $self->_check_response($response,$self->{URL});
945              
946             # Ok, the file was there. Parse the response codes.
947 0           my $response_fields = $self->_fill_in_response_fields($response_text);
948              
949 0 0         if ($response_fields->{status} ne GR_STAT_SUCCESS) {
950 0           die "Could not execute move-album command on remote gallery at " . $self->{URL} ."\n" .
951             "Status: " . $response_fields->{status} . "\n" .
952             "Text : " . $response_fields->{status_text} . "\n";
953             }
954              
955 0           return $response_fields->{status};
956             }
957              
958             1;
959             __END__