1
###################################################
3
# Copyright (C) Mario Kemper <mario.kemper@googlemail.com> and Shutter Team
5
# This file is part of Shutter.
7
# Shutter is free software; you can redistribute it and/or modify
8
# it under the terms of the GNU General Public License as published by
9
# the Free Software Foundation; either version 3 of the License, or
10
# (at your option) any later version.
12
# Shutter is distributed in the hope that it will be useful,
13
# but WITHOUT ANY WARRANTY; without even the implied warranty of
14
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
# GNU General Public License for more details.
17
# You should have received a copy of the GNU General Public License
18
# along with Shutter; if not, write to the Free Software
19
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21
###################################################
27
Image::ImageShack - Upload images to be hosted at imageshack.us without needing any account information.
31
require Image::ImageShack;
33
my $ishack = Image::ImageShack->new();
35
#you can access the LWP::UserAgent via the user_agent method
36
#proxy can be specified by
37
$ishack->user_agent->proxy(['http'], 'http://localhost:8080/');
39
my $image_url = 'http://www.domain.com/image.png';
41
#upload specifying a url
42
my $url1 = $ishack->host($image_url); #upload with real size, just optimizes
43
my $url2 = $ishack->host($image_url, 320); #resize to 320x240 (for websites and email)
46
my $url3 = $ishack->host('image.jpg'); #upload file
48
#get the thumbnail address
49
my $thumb_url = $ishack->thumb_url();
55
Image::ImageShack intends to make programmatically possible to upload image files to the website L<http://imageshack.us/>.
57
imageshack.us allows you to upload image files (jpg, jpeg, png, gif, bmp, tif, tiff, swf < 1.5 megabytes) and to optimize and or resize these files while making them available to others via imageshack.us servers (even direct linking).
59
A thumbnail is always created.
63
package Shutter::Upload::ImageShack;
67
use HTTP::Request::Common;
75
#--------------------------------------
76
use constant TRUE => 1;
77
use constant FALSE => 0;
79
#--------------------------------------
81
use Carp qw(carp croak);
86
our $VERSION = '0.03';
87
$VERSION = eval $VERSION;
89
our $url = 'http://imageshack.us';
90
our $uri = 'transloader.php';
91
our $agent = 'Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1)'; #nice "fake"
97
=item new(attr=>value)
100
Initializes the object.
108
L<LWP::UserAgent|LWP::UserAgent> object to used make HTTP requests
112
Boolean indicating whether thumbnails should have a black bar at the bottom with real image size
116
Id used to upload the files. If you have registered with imageshack.us, you should have received an email with a link similar to: http://reg.imageshack.us/setlogin.php?login=SOME_IDENTIFIER
118
If you intend to be able to later on use the web interface to erase files, you should pass either that link as the login parameter or only the user_id (SOME_IDENTIFIER).
120
No verification on the validity of the user_id is currently made
127
my ($pack, %attrs) = @_;
129
my $self = bless {}, $pack;
131
if(ref($attrs{'lwp_ua'}) && $attrs{'lwp_ua'}->isa('LWP::UserAngent')){
132
$self->ua($attrs{'lwp_ua'});
134
my $ua = LWP::UserAgent->new(
143
$self->ua->cookie_jar(HTTP::Cookies->new(file => "$ENV{HOME}/.cookies.txt"));
145
if(defined($attrs{'bar'})){
146
$self->{'bar'} = $attrs{'bar'};
149
#FOLLOWING ATTS ADDED BY SHUTTER TEAM - quick and dirty - maybe fixme
150
$self->{_host} = undef;
151
$self->{_username} = undef;
152
$self->{_filename} = undef;
153
$self->{_url} = undef;
154
$self->{_url_thumb} = undef;
155
$self->{_status} = undef;
156
$self->{_gettext_object} = undef;
157
$self->{_main_gtk_window} = undef;
158
$self->{_shutter_root} = undef;
160
$self->{_notebook} = Gtk2::Notebook->new;
161
$self->{_notebook}->set( homogeneous => 1 );
162
$self->{_notebook}->set_scrollable(TRUE);
171
Returns or sets the L<LWP::UserAgent|LWP::UserAgent> object used internally so that it can the customised
176
my ($self, $ua) = @_;
177
if(ref($ua) && $ua->isa('LWP::UserAgent')){
180
return $self->{'_ua'};
183
#just an internal alias
186
our @optsize = (100, 150, 320, 640, 800, 1024, 1280, 1600, 'resample');
188
=item host($url, $size)
190
Given an url (starts with http:// or https://) or a filename and a width in pixels uploads the image to image imageshack.us and resizes it to the desired size.
191
Returns the url of the hosted image and croaks on error.
193
Possible values for C<$size> are:
207
320 x 240 ( for websites and email )
211
640x480 (for message boards)
215
800 x 600 ( 15 -inch monitor )
219
1024x768 (17-inch monitor)
223
1280 x 1024 ( 19 -inch monitor )
227
1600x1200 (21-inch monitor)
238
my ($self, $image, $size) = @_;
241
croak("No url to host");
245
'uploadtype' => 'on',
250
my $is_external = $image=~ m{^https??://};
252
$params{'url'} = $image;
254
$params{'fileupload'} = [$image];
255
$params{'MAX_FILE_SIZE'} = 3145728;
256
#XXX is this really necessary
257
$params{'url'} = 'paste image url here';
262
$params{'optimage'} = 1;
265
if(grep{$_ eq $size}@optsize){
266
$size="${size}x${size}";
268
croak("unknown size $size");
272
$params{'optsize'} = $size;
275
delete($params{'rembar'});
282
"$url/" . ($is_external ? $uri : ''),
283
'Content_Type' => 'form-data',
284
'Content' => [%params]
287
my $req = HTTP::Request::Common::POST(@params);
288
push @{ $self->ua->requests_redirectable }, 'POST';
289
my $rsp = $self->ua->request($req);
291
if($rsp->is_success){
292
my $txt = $rsp->content;
293
#~ if($txt =~ m{<\s*input\s+[^>]+\s+value\s*=\s*"([^"]+)"[^>]+>\s*</\s*td\s*>\s*<\s*td[^>]*>\s*Direct\s+link\s+to\s+image}ism){
294
# Changed by "Oleg Fiksel" <fleg@lavabit.com>
295
if($txt =~ /Direct.+?href=['"]*([^'"]+)['"]*/ism){
297
if($txt =~/thumbnail for/i){
298
my $uri = $self->hosted();
299
$uri =~ s{\.([^\.]+)$}{\.th\.$1};
300
$self->hosted_thumb($uri);
302
#small images have no thumbnail
303
$self->hosted_thumb(undef);
305
return $self->hosted;
307
croak("direct link not found in. Maybe an error ocurred during upload. [".$rsp->as_string."]");
311
croak($rsp->status_line."[".$rsp->as_string."]")
315
my $gen_method = sub{
319
my ($self, $val) = @_;
321
$self->{$field}=$val;
324
return $self->{$field};
328
*bar = $gen_method->('bar');
332
Returns the url of the last uploaded image.
336
*hosted = $gen_method->('hosted');
340
Returns the url of the thumbnail last uploaded image.
341
Could be non existent for small images.
345
*hosted_thumb = $gen_method->('hosted_thumb');
349
Returns or sets the user_id.
355
my $username = shift;
356
my $password = shift;
358
$self->{_username} = $username;
359
$self->{_password} = $password;
361
#Login authentication
362
#anonym. authentication with empty password
363
if($self->{_username} ne '' && $self->{_password} ne ''){
365
'username' => $self->{_username},
366
'password' => $self->{_password},
370
'Content_Type' => 'form-data',
371
'Content' => [%authparams]
373
my $authreq = HTTP::Request::Common::POST(@authparams);
374
push @{ $self->ua->requests_redirectable }, 'POST';
375
my $authrsp = $self->ua->request($authreq);
376
unless($authrsp->is_success && $authrsp->content eq 'OK'){
378
croak($authrsp->status_line."[".$authrsp->as_string."]");
387
Resets user_id. From now on images won't be associated with any user.
394
$self->ua->cookie_jar->clear;
399
# Preloaded methods go here.
404
my $clipboard = Gtk2::Clipboard->get( Gtk2::Gdk->SELECTION_CLIPBOARD );
407
my $tooltips = Gtk2::Tooltips->new;
409
my $upload_hbox = Gtk2::HBox->new( FALSE, 0 );
410
my $upload_hbox1 = Gtk2::HBox->new( TRUE, 10 );
411
my $upload_hbox2 = Gtk2::HBox->new( FALSE, 10 );
412
my $upload_hbox3 = Gtk2::HBox->new( TRUE, 10 );
413
my $upload_hbox4 = Gtk2::HBox->new( FALSE, 10 );
414
my $upload_hbox5 = Gtk2::HBox->new( TRUE, 10 );
415
my $upload_hbox6 = Gtk2::HBox->new( FALSE, 10 );
416
my $upload_hbox7 = Gtk2::HBox->new( TRUE, 10 );
417
my $upload_hbox8 = Gtk2::HBox->new( FALSE, 10 );
418
my $upload_vbox = Gtk2::VBox->new( FALSE, 0 );
419
my $label_status = Gtk2::Label->new( $self->{_gettext_object}->get("Upload status:") . " " . status_message($self->{_status}) );
421
$upload_hbox->pack_start( Gtk2::Image->new_from_pixbuf( Gtk2::Gdk::Pixbuf->new_from_file_at_scale( "$self->{_shutter_root}/share/shutter/resources/icons/logo-imageshack.png", 100, 100, TRUE ) ), TRUE, TRUE, 0 );
422
$upload_hbox->pack_start( $label_status, TRUE, TRUE, 0 );
424
my $entry_direct = Gtk2::Entry->new();
425
my $entry_hotweb = Gtk2::Entry->new();
426
my $label_thumb1 = Gtk2::Label->new( $self->{_gettext_object}->get("Thumbnail for websites") );
427
my $label_thumb2 = Gtk2::Label->new( $self->{_gettext_object}->get("Thumbnail for forums") );
428
my $label_direct = Gtk2::Label->new( $self->{_gettext_object}->get("Direct link") );
429
my $label_hotweb = Gtk2::Label->new( $self->{_gettext_object}->get("Hotlink for websites") );
431
$entry_direct->set_text("$self->{_url}");
432
$entry_hotweb->set_text("<a href=\"http:\/\/imageshack.us\"><img src=\"$self->{_url}\" border=\"0\" alt=\"Image Hosted by ImageShack.us\"\/><\/a><br\/>By <a href=\"https:\/\/launchpad.net\/shutter\">Shutter<\/a>");
433
$upload_vbox->pack_start( $upload_hbox, TRUE, TRUE, 10 );
435
if ($self->{_url_thumb}) {
436
my $entry_thumb1 = Gtk2::Entry->new();
437
my $entry_thumb2 = Gtk2::Entry->new();
439
my $upload_copy1 = Gtk2::Button->new;
440
$tooltips->set_tip( $upload_copy1, $self->{_gettext_object}->get("Copy this code to clipboard") );
441
$upload_copy1->set_image( Gtk2::Image->new_from_stock( 'gtk-copy', 'menu' ) );
442
$upload_copy1->signal_connect(
444
my ( $widget, $entry ) = @_;
445
$clipboard->set_text( $entry->get_text );
450
my $upload_copy2 = Gtk2::Button->new;
451
$tooltips->set_tip( $upload_copy2, $self->{_gettext_object}->get("Copy this code to clipboard") );
452
$upload_copy2->set_image( Gtk2::Image->new_from_stock( 'gtk-copy', 'menu' ) );
453
$upload_copy2->signal_connect(
455
my ( $widget, $entry ) = @_;
456
$clipboard->set_text( $entry->get_text );
461
$entry_thumb1->set_text("<a href=\"$self->{_url}\"><img src=\"$self->{_url_thumb}\" border=\"0\" alt=\"Image Hosted by ImageShack.us\"\/><\/a>");
462
$entry_thumb2->set_text("\[url\=$self->{_url}\]\[img\]$self->{_url_thumb}\[\/img\]\[\/url\]");
463
$upload_hbox1->pack_start_defaults($label_thumb1);
464
$upload_hbox1->pack_start_defaults($entry_thumb1);
465
$upload_hbox2->pack_start_defaults($upload_hbox1);
466
$upload_hbox2->pack_start( $upload_copy1, FALSE, TRUE, 10 );
467
$upload_hbox3->pack_start_defaults($label_thumb2);
468
$upload_hbox3->pack_start_defaults($entry_thumb2);
469
$upload_hbox4->pack_start_defaults($upload_hbox3);
470
$upload_hbox4->pack_start( $upload_copy2, FALSE, TRUE, 10 );
474
my $upload_copy3 = Gtk2::Button->new;
475
$tooltips->set_tip( $upload_copy3, $self->{_gettext_object}->get("Copy this code to clipboard") );
476
$upload_copy3->set_image( Gtk2::Image->new_from_stock( 'gtk-copy', 'menu' ) );
477
$upload_copy3->signal_connect(
479
my ( $widget, $entry ) = @_;
480
$clipboard->set_text( $entry->get_text );
485
my $upload_copy4 = Gtk2::Button->new;
486
$tooltips->set_tip( $upload_copy4, $self->{_gettext_object}->get("Copy this code to clipboard") );
487
$upload_copy4->set_image( Gtk2::Image->new_from_stock( 'gtk-copy', 'menu' ) );
488
$upload_copy4->signal_connect(
490
my ( $widget, $entry ) = @_;
491
$clipboard->set_text( $entry->get_text );
496
$upload_hbox5->pack_start_defaults($label_direct);
497
$upload_hbox5->pack_start_defaults($entry_direct);
498
$upload_hbox6->pack_start_defaults($upload_hbox5);
499
$upload_hbox6->pack_start( $upload_copy3, FALSE, TRUE, 10 );
500
$upload_hbox7->pack_start_defaults($label_hotweb);
501
$upload_hbox7->pack_start_defaults($entry_hotweb);
502
$upload_hbox8->pack_start_defaults($upload_hbox7);
503
$upload_hbox8->pack_start( $upload_copy4, FALSE, TRUE, 10 );
505
$upload_vbox->pack_start_defaults($upload_hbox2);
506
$upload_vbox->pack_start_defaults($upload_hbox4);
507
$upload_vbox->pack_start_defaults($upload_hbox6);
508
$upload_vbox->pack_start_defaults($upload_hbox8);
516
#are there any uploaded files?
517
return FALSE if $self->{_notebook}->get_n_pages < 1;
519
my $dlg_header = $self->{_gettext_object}->get("Upload") . " - " . $self->{_host} . " - " . $self->{_username};
520
my $upload_dialog = Gtk2::Dialog->new( $dlg_header, $self->{_main_gtk_window}, [qw/modal destroy-with-parent/], 'gtk-ok' => 'accept' );
521
$upload_dialog->set_default_response('accept');
523
$upload_dialog->vbox->add($self->{_notebook});
524
$upload_dialog->show_all;
525
my $upload_response = $upload_dialog->run;
527
if ( $upload_response eq "accept" ) {
528
$upload_dialog->destroy();
531
$upload_dialog->destroy();
537
my ( $self, $host, $username, $filename, $url, $url_thumb, $status, $d, $window, $shutter_root ) = @_;
539
$self->{_host} = $host;
540
$self->{_username} = $username;
541
$self->{_filename} = $filename;
542
$self->{_url} = $url;
543
$self->{_url_thumb} = $url_thumb;
544
$self->{_status} = $status;
545
$self->{_gettext_object} = $d;
546
$self->{_main_gtk_window} = $window;
547
$self->{_shutter_root} = $shutter_root;
549
$self->{_notebook}->append_page( $self->create_tab(), $self->{_filename} );
564
The author declines ANY responsibility for possible infringement of ImageShack® Terms of Service.
566
This module doesn't use imageshack's XML API but the HTML/web interface instead.
572
No guarantee that this will ever be implemented
574
=item HTML code for forums, thumbnails, websites, etc (if you really need this, please ask the author)
578
=item Implement XML API (probably never or on a different)
585
L<LWP::UserAgent|LWP::UserAgent>
589
http://reg.imageshack.us/content.php?page=faq
591
http://reg.imageshack.us/content.php?page=rules
595
Cláudio Valente, E<lt>plank@cpan.orgE<gt>
597
=head1 COPYRIGHT AND LICENSE
599
Copyright (C) 2008 by Cláudio Valente
601
This library is free software; you can redistribute it and/or modify
602
it under the same terms as Perl itself, either Perl version 5.8.8 or,
603
at your option, any later version of Perl 5 you may have available.