Kodak Gallery is holding our photos hostage. But me and Open Source are here to bust them out! (Ruby source code included)

I used kodakgallery.com in 2004 for some photos. I was younger then. I didn't know that I shouldn't bother storing photos on one of the worst photo hosts on the Internet. I thought Kodak was a brand I could trust.

"WE DON'T WANT TO DELETE YOUR PHOTOS" says the email I got today. Fine, delete them. But only after I download them. And I'm not going to pay you $20 to get an Archive CD either.


They're well within their rights to do so (heck, everyone needs to make some money) -- but they also make it quite difficult to download these photos. If you had 200 photos, you would have to click the "Download Full Resolution" button 200 times individually. If these photos are mine, then shouldn't it be a little easier? Sorry, a product manager in some stovepiped organization said no.

A quick google search returned basically no super-easy way to download and archive these things in one fell swoop.

I thought I'd whip up this simple ruby script to download them to your local directory. It requires the 'mechanize' and Ruby 1.8.6+. Save this code to a file, e.g. "kodak_easyshare.rb",  edit your username and password in the script below, then run 'ruby kodak_easyshare.rb' -- and watch the magic happen.

You own those photos. Get them. Download them. Don't let Kodak hold you hostage.

This is hereby released under MIT license.

 
require 'rubygems' 
require 'mechanize' 
require 'fileutils' 
 
agent = WWW::Mechanize.new 
signin_page = agent.get('http://www.kodakgallery.com/Signin.jsp') 
signin_page.forms[0].email = 'yourlogin_at_gmail.com' 
signin_page.forms[0].password = 'your_password_here' 
signin_page.forms[0].submit 
 
album_page = agent.get('http://www.kodakgallery.com/AlbumMenu.jsp?Upost_signin=Welcome.jsp') 
albums = album_page.links.map{|l| (l.href.match(/BrowsePhotos.jsp/) && l.text && l.text.match(/[A-Za-z0-9]/)) ? {:href => l.href, :name => l.text} : nil}.compact 
 
albums.each do |album_hash| 
  puts "\n\n\n" 
  puts "-----------------------------------------" 
  puts "'#{album_hash[:name]}'" 
  puts "#{album_hash[:href]}" 
 
  gallery_page = agent.get("http://www.kodakgallery.com/#{album_hash[:href]}") 
  photos = gallery_page.links.map{|l| (l.href.match(/PhotoView.jsp/) && !l.href.match(/javascript/)) ? l.href : nil}.compact.uniq 
 
  album_dirname = album_hash[:name].gsub(/[\n\t\?\:\>\<\\\/|]/, '_') 
 
  unless File.exists?(album_dirname) 
   puts "creating album #{album_dirname}" 
   FileUtils.mkdir(album_dirname) 
  end 
 
  FileUtils.cd(album_dirname, :verbose => true) do 
 
   photos.each do |p| 
    photo_page = agent.get("http://www.kodakgallery.com/#{p}") 
    fullres = photo_page.links.map{|l| (l.href.match(/FullResDownload/) && !l.href.match(/javascript/)) ? l.href : nil}.compact.uniq.first 
 
    file_to_dl = "http://www.kodakgallery.com#{fullres}" 
    result = agent.get(file_to_dl) 
    if result.class == WWW::Mechanize::File 
     result.save 
     puts "Saved #{file_to_dl}" 
    else 
     puts "FAIL on #{file_to_dl}" 
    end 
 
   end 
 
  end 
 
  puts "-----------------------------------------" 
  puts "-----------------------------------------" 
  puts "-----------------------------------------" 
end 
 
views

Tags

56 responses
perfct! lol! hope they read that (one day).
if result.class == WWW::Mechanize::File

Type-checking in a duck-typed language? For serious?

Haha, well, what are you gonna do? If the fetch method returns other kinds of objects and you know success is only defined by a File, then you do what you gotta do. ;-)
Checking if you have the right type is a fine way to do error checking. You more often do this when you're checking if something is None in python. That's essentially a type comparison.
Thanks! for those of us with more than 16 albums, change this line to get all of them.
FROM THIS:
album_page = agent.get('http://www.kodakgallery.com/AlbumMenu.jsp?Upost...)
TO THIS:
album_page = agent.get('http://www.kodakgallery.com/AlbumMenu.jsp?Upost...)
you guys are really great. i am stting at my pc here and smiling.
@garry: They did what? How do they port a Perl lib to Ruby and change the API in such a way that you now need to do type checking? *sigh* (The perl one returns a response object that you can ask if it's a success or fail and get the body/etc)
Excellent script. Saved me from having to individually download 125+ images.
"If the fetch method returns other kinds of objects and you know success is only defined by a File..."

I'm not blaming you, I'm just saying it is pretty sick if the best way to check for a successful grab is by checking the returned class. Why wouldn't it always return the same class? Or in absence of that sensibility, None (or nil, or w/e)?

It's just that a fetch can return "Page" or "Meta" and other types, not just "File"
One more suggestion: If you let it, mechanize will keep a copy of previously loaded pages in memory. This script doesn't need that, and it's a big waste of system resources, especially when downloading hundreds of pictures. To avoid it, change this line:

agent = WWW::Mechanize.new

to be this:

agent = WWW::Mechanize.new{ |agent|
agent.history.max_size=0
}

(learned from http://my.opera.com/dduenker/blog/2008/09/03/ruby-prevent-www-mechanize-from-stealing-your-memory )

can anyone host this easily? would be great to offer it as a service available to more than those that with a local ruby instance...

p.s., luv that posterous displays this code so well.

Garry, this is awesome. We must have signed up the same time of year as I just got the message that I jad 13 days to make a $4.99 purchased or lose my photos. The script is running in the background right now and I am so glad I saw this post.
I've been using Kodakgallery since 2003 (when there weren't many options and I figured Kodak was a good enough name to stay around). I didn't even mind buying stuff form them until photographs became passe.

I even tried to buy their Archive CD except their system can't process > 40,000 images via Archive CD.

They keep canceling my order without comment.

(Current photo storage: 62.532 GB Used,
219 galleries,
Your Archive CD Pricing:
Number of Photos: 42666
Cost of your CD: $667.85

FYI).

Works like a champ. Send me an address and I'll send you some beer or money or something.

nice. you could probably write something to use their XMI interface if you ran easyshare desktop app through something like Charles. Might even be a little (only slightly) cleaner.
Okay... This news is great, and I am very thankful that someone has giving me a chance to get back all my daughters baby pictures I haved stored on Ofoto. But, I have a massive problem that needs attention !!!

For the last 2 hours, I have tried to figure out how to run the script posted above using Ruby. It says you need Mechanize, which has no exe to launch, so how the hell does it work.I have it downloaded, but there's no setup or exe or launch method, very F@*#@$g frustrating...Does it run with IE, or Firefox, or in the Run cmd line...What is the order to launch...Mechanize, then Ruby than the script. How do I tell that Mechanize is running. I type in the script posted above with the mono settings as mentioned ( usually default ) and it does nothing... Where does it download to, does it show a file percentage downloaded... Is Mechanize suppose to be running without notification...Forgive me as I am not a computer idiot, just have no clue how this works whatsoever !!!

I've read the articles on Ruby, Mechanize and still have no clue how or where or what should be happening on my screen or how this can work...I am in hell, please help this idiot,,,I beg you... lol : )

Hi mnicw -- Sorry this doesn't work very well at all using Windows. This script is most easily run on OS X or on Linux. You can probably run it on Windows if you install this: http://rubyforge.org/projects/rubyinstaller/ (I haven't used this but it seems like this would help)

You would need to install the mechanize gem by first running gem install mechanize. Then you would run ruby myscript.rb.

You would need to install the mechanize gem by first running gem install mechanize -

Where and how using what program, where do I input this command... Do i have to open a program ??? Where does this go ??? Sorry, but I'm still lost !

mcnicw -- They're command line programs (no GUI, no program that is clickable)I.

If you still have problems, I suggest trying http://www.picwing.com/blog/?p=1457 -- there's no setup involved, and we know those guys and they're awesome!

picwing does do a great job importing but they do downres your photos; if you're a windows user you can download the kodak easyshare software (http://www.kodak.com/eknec/PageQuerier.jhtml?pq-path=130&pq-locale=en_US&_requestid=7662) and download all your images that way; should be your hi-res originals...
We'd be happy to import your pictures at Picwing. Let me know if you need any help. We actually don't downres the photos anymore, as we keep a hires version for printing purposes.
Hey guys...Thanks for all your help. Unfortunately, I installed the Picwing program and none of my pictures are there when I entered my Kodak Username and password. It just displayed and empty folder... I'm considering wiping out my wfie's computer and installing Linux so I can try the scripting suggested...Is it too late??? I have no photos at all, very saddened... I wil supply my username and pass if somebody trustworthy could try the scripting for me to see if the 500 pictures are there...

Help please : (

Hi mnicw,

Its Edward from Picwing. I just tested our kodak gallery import program and didn't see any problems. It's possible that Kodak already deleted your photos so we couldn't find anything to import =(. Send me an email and i'll try to help you out.

Thanks, out Boy Scout troop had almost 6 Gigs of photos. Now we can xfer them to our own server. The script works great!
Looks like a limitation in the script. I had one folder with 246 photos and the script kept aborting at 223 pictures. I moved some photos around and put the album at 220 and it works fine now.
Ack... I think they pages have changed and this script no longer works. Oh well...
Kodak strikes again. I think they're site rebuild broke the picwing program. Picwing gave me this error "We're sorry, but something went wrong." Well, you're a hero for building this, wish I found it before the new kodak launched.
Picwing strikes back again! Kodak broke our import tool when they launched their new site, but we've since modified the script so that Kodak import is up and working once again.
Hi Garry, is it possible that you can update your code a bit? I tried to tweaking to get the sign-in page to work, but that isn't working out..

That would be awesome if you could.

Adding to that, the sign-in page didn't work, so I ended up finding an old page that did work!

Below:
http://classic.kodakgallery.com/Signin.jsp?

I got past the login but still having troubles, hope this helps if you don't mind updating your script.

Gosh I got it Working!!

I'll report back, later with the new code. Just want to see if it works well!

Very cool -- if you want to email me garry@posterous.com I can update the code and provide a link to you / your blog / whatever.
Thx, Garry and all for the comments.

I updated your code and got it to work. Here's what I did:

1. updated the agent code to avoid memory problems (thx @turbodingo)
agent = WWW::Mechanize.new{ |agent|
agent.history.max_size=0
}

2. updated albums per page (thx @turbodingo's) since i have more than 16 albums
album_page = agent.get('http://www.kodakgallery.com/AlbumMenu.jsp?Upost...

3. updated the kodakgallery urls from www.kodakgallery.com to classic.kodaygallery.com

what I haven't been able to figure out is how to skip photos that already exist in the folder - there was some trial and error going on so i had to restart the process a couple of times.
@juamps thats awesome, I just sent him those exact fixes on Nov 5th!! Wierd.

Even posted a tutorial how to do it on a windows machine.

http://www.computerrich.com/news/kodak-gallery-download-ruby-script-windows-automation-tool/

Nice stuff. Worked really well. Liberation from Kodak!
i am not to good with computers, is there a simple way to do this?
thanks
can this be used to download pics from friends' galleries?
With about a month to go before Kodak Gallery shuts down, this site is still one of the top search hits for folks wanting to download Kodak Gallery albums.

Garry's original script was great, but as others have noted no longer works due to changes at Kodak Gallery (URL changes, SSL being required), and changes in Mechanize.

I've updated the script to work with Kodak Gallery (as of May 2012) and current versions of Ruby and Mechanize, and also added in additional functionality I really needed. The main new features are the ability to download pictures in album order (1.jpg, 2.jpg, and so on) and to save captions inside the downloaded JPG. For my use of Kodak Gallery, the order of pictures in the album and the captions were very important for me to be able to save.

I've also written up a lot of documentation to help the non-programmer perform these steps.

I'll post the code in the next comment, and the documentation after that.

Here's the code. Same MIT License as Garry's original. I never programmed Ruby before this exercise, so go easy on me ;-)

[code lang='ruby']
require 'rubygems'
require 'mechanize'
require 'fileutils'
require './mini_exiftool'
require 'set'
require 'cgi'

$email = ''
$password = ''

# if $download_captions is true, captions are downloaded and saved to each JPG
$download_captions = true

# if $print_captions_to_screen is true, captions are written to the console as a picture is downloaded
$print_captions_to_screen = false

# if $skip_album_if_dir_exists is true, albums are not re-downloaded if an album directory already exists.
# to re-download an album, either set $skip_album_if_dir_exists to false or delete the album directory.
$skip_album_if_dir_exists = true

# if $skip_photo_if_file_exists is true, a photo (e.g. 5.jpg) is not re-downloaded if a file already exists with that name
# for the album currently being processed. note that no validation is performed that the file contents match
# (it is assumed you are not adding/deleting/modifying pictures in an album).
# this setting only matters if $skip_album_if_dir_exists is set to false.
$skip_photo_if_file_exists = true

# the directory to which albums will be downloaded (will be created if it does not exist)
$download_dir = "downloaded_albums"

# if $print_warning_messages is true, certain warning messages will print to the screen.
$print_warning_messages = true

def downloadAlbum(agent, album_hash, album_names_to_download, num_albums, album_num)
album_name = "#{album_hash[:name]}"

puts "Processing album '#{album_name}' (#{album_num} of #{num_albums})"
#puts "#{album_hash[:href]}"

if (album_names_to_download.length != 0)
if (!album_names_to_download.include?(album_name.downcase))
puts "Skipping album '#{album_name}'"
return
end
end

album_dirname = album_name.gsub(/[\n\t\?\:\>\<\\\ />

if (File.exists?(album_dirname))
if ($skip_album_if_dir_exists)
puts "Skipping album since folder '#{album_dirname}' already exists"
return
end
else
puts "Creating album directory '#{album_dirname}'"
FileUtils.mkdir(album_dirname)
end

gallery_page = agent.get("http://classic.kodakgallery.com/#{album_hash[:h...)
photos = gallery_page.links.map{|l| (l.href.match(/PhotoView.jsp/) && !l.href.match(/javascript/) && !l.attributes.attributes['class'].value.match(/comment-icon/)) ? l.href : nil}.compact.uniq

puts "Album contains #{photos.size} pictures"

FileUtils.cd(album_dirname, :verbose => false) do

puts "Downloading album pictures"
num = 1

photos.each do |photo|

downloadPhoto(agent, photo, num)
num += 1

end

puts "\n"
puts "Finished downloading album '#{album_name}'"

end

end

def downloadPhoto(agent, photo, num)

filename = "#{num}.jpg"
if (File.exists?(filename))
if ($skip_photo_if_file_exists)
puts "Skipping photo since '#{filename}' already exists"
return
end
end

photo_page = agent.get("http://classic.kodakgallery.com/#{photo}")
fullres = photo_page.links.map{|l| (l.href.match(/FullResDownload/) && !l.href.match(/javascript/)) ? l.href : nil}.compact.uniq.first
caption = ""

if ($download_captions)
caption = getCaptionForPhoto(photo_page)
end

if ($download_captions && $print_captions_to_screen)
puts caption
else
print "."
end

file_to_dl = "http://classic.kodakgallery.com#{fullres}"

result = agent.get(file_to_dl)
if result.class == Mechanize::Image
# result.save won't overwrite, so we have to first manually delete.
# pushed this logic down close to result.save in case of errors.
if (File.exists?(filename))
File.delete(filename)
end
result.save(filename)
if ($download_captions)
addCaptionToPhoto(filename, caption)
end
else
puts "***Failed to download #{file_to_dl}***"
end
end

def getCaptionForPhoto(photo_page)
captionElement = photo_page.search("//span[@id='photoCaption']")
captionNode = captionElement.children
caption = "#{captionNode}"
# unescape & (&), < (<),>). above calls seem to automatically unescape some values, like ', (, ), "
caption = CGI.unescapeHTML(caption)
return caption
end

# need to escape various characters to pass successfully to exiftool
def getCaptionForExif(caption)

# found \n in one of my captions, curious
caption.gsub!("\n", " ")

# \ escaping may be necessary in some situations but none
# i encountered. might actually need to make it 8 \'s, not 4,
# and the 2 \'s might need to be 4. \ escaping is always confusing.
# hopefully \ is uncommon in captions - i had none.
#caption.gsub!("\\", "\\\\")

# " escaping is always necessary but doesn't always work right.
# a " in the middle of a double quoted string won't work with mini_exiftool.
caption.gsub!("\"", "\\\"")

# &, <,> should not be escaped unless in double quoted strings.
# if they are in double quoted strings, the calls below (commented out) will escape them.
# i.e, a caption of '1 < 2' or '1 & 2' (with or without surrounding single quotes) will work fine.
# a caption of "1 < 2" or "1 & 2" (with surrounding double quotes) requires ^ escapes.
# i gave up trying to handle all of these cases perfectly. it was more common in my captions
# to have these characters not in double quoted strings, so i let any in double quoted strings fail
# and i manually fixed them (or i reran the script on just those pictures after uncommenting the below lines).
#caption.gsub!("&", "^&")
#caption.gsub!("<",><")<br />", "^>")

return caption
end

def savePhotoWithCaption(filename, photo, caption)
begin
success = photo.save
if !success
puts "***Failed saving caption '#{caption}' to #{filename}***"
end

rescue Errno::EACCES => exp
puts "EACCESS error for #{filename}, sleeping 5 seconds and trying again"
sleep 5
savePhotoWithCaption(filename, photo, caption)
end
end

def addCaptionToPhoto(filename, caption)
if ($print_warning_messages)
if (caption.include?("\"") && (caption.include?("<")>") || caption.include?("&")))
puts "Warning: caption '#{caption}' for '#{filename}' contains a \" and at least one of '<',>', and '&', recommend manual verification of caption"
end
end
exifCaption = getCaptionForExif(caption)
photo = MiniExiftool.new filename
# set 3 common caption fields
photo.Description = exifCaption
photo.Title = exifCaption
photo['Caption-Abstract'] = exifCaption
savePhotoWithCaption(filename, photo, caption)
end

def checkForDuplicateAlbumNames(albums)
album_names = Set.new
found_duplicates = false

albums.each do |album_hash|
album_name = "#{album_hash[:name]}"
album_name_lowcase = album_name.downcase
if (album_names.include?(album_name_lowcase))
puts "Found duplicate album name '#{album_name}'"
found_duplicates = true
end
album_names.add(album_name_lowcase)
end
return found_duplicates
end

def main()

puts "Setting up certificate store"

cert_store = OpenSSL::X509::Store.new
cert_store.add_file 'cacert.pem'

puts "Connecting to Kodak Gallery"

agent = Mechanize.new
agent.cert_store = cert_store
agent.history.max_size=0
signin_page = agent.get('https://secure.kodakgallery.com/Signin.jsp')
signin_page.forms[0].email = $email
signin_page.forms[0].password = $password

puts "Signing in as #{$email}"

signin_page.forms[0].submit

# i don't actually validate successful login - you'll see 0 albums below if you didn't log in successfully
#puts "Successfully signed in"

album_page = agent.get('http://classic.kodakgallery.com/AlbumMenu.jsp?&...)
albums = album_page.links.map{|l| (l.href.match(/BrowsePhotos.jsp/) && l.text && l.text.match(/[A-Za-z0-9]/)) ? {:href => l.href, :name => l.text} : nil}.compact

num_albums = albums.size
if (num_albums == 0)
puts "Found 0 albums, please validate email and password are correct"
return
end

puts "Found #{num_albums} albums"

if (checkForDuplicateAlbumNames(albums))
puts "Duplicate album names were found on Kodak Gallery. Rename the albums in Kodak Gallery and then re-run this script."
return
end


if ($download_captions)
puts "Will download picture captions"
else
puts "Will not download picture captions"
end

album_names_to_download = Set.new

if (ARGV.length != 0)
puts "Will download album(s) with the following names (matching case insensitively):"
ARGV.each do |album_name|
puts " #{album_name}"
album_names_to_download.add(album_name.downcase)
end
end

album_num = 1

unless File.exists?($download_dir)
puts "Creating '#{$download_dir}'directory to save downloaded albums"
FileUtils.mkdir($download_dir)
end

FileUtils.cd($download_dir, :verbose => false) do

albums.each do |album_hash|
puts "-----------------------------------------"
downloadAlbum(agent, album_hash, album_names_to_download, num_albums, album_num)
album_num += 1
end

puts "-----------------------------------------"

end

end

main()
[/code]

Well that didn't format well at all. The code and instructions are in a zip I'll make available for the next month at

http://home.comcast.net/~snowymike/kodakgallery/kodakgallery.zip

The documentation is in the zip, but also available at

http://home.comcast.net/~snowymike/kodakgallery/Downloading%20Kodak%20Gallery...

Good luck to everyone in my shoes that is trying to save everything before July 2nd.

Thanks Garry for the original code - couldn't have done this without your initial script.

As far as I can tell the "classic" version of the site does not allow access to the full-res versions of photos in friends' shared albums, and personally I'm feeling much more urgency to back those up as they apparently won't transfer over during the switch to Shutterfly.

Is anyone working on trying to get this script to login to the main site? As far as I can tell they're setting a ton of cookies through Javascript during the login -- it even seems to gather up information about precisely what plugins your browser has installed. I'm at a bit of a loss to figure out which ones are actually essential to get their server to see you as logged in.

Friends' pictures will transfer to Shutterfly (unless they opt out), but you're right that there won't be a convenient way for you to access those pictures after migration unless those friends manually reshare those albums with you. And even if they do, there's no high-res download option in Shutterfly.

In my case, I'm lucky that my friends/family that do use Kodak Gallery are willing to run the updated script I posted above to download their albums/photos/captions. If I need their photos, I can get the originals from them.

I don't see an easy way to update the script (my updated version) to download friends' albums, since the classic version of kodak gallery doesn't offer a download hi-res option, as you noted. Looking at the HTML source when viewing a friends' picture, I think we could parse out the personid, collid, and photoid, which are the values that are used to construct the download hi-res URL used for downloading ones own pictures. However, when I attempted to do that for a single friends' picture I got a 401 Unauthorized back from kodak gallery. Which might be intended behavior, since classic kodak gallery probably doesn't want you downloading hi-res versions of friends' photos. I may have been constructing the URL incorrectly, and further testing may reveal a solution. I'm not currently investigating that, however, nor am I investigating updating the script for the non-classic version of the site. If you come up with a way to download a friends' hi-res image through the classic version of the site, I can post back script updates that would support that.

I added a script to download friends' albums in low resolution. It's essentially the same script I updated to support downloading one's own albums, with slight modifications to download friends' albums instead. It's not ideal, but it's the only automated solution I'm currently aware of that supports downloading friends' albums while preserving album order and writing captions to the downloaded photos..

The code and instructions are in a zip I'll make available for the next few weeks at

http://home.comcast.net/~snowymike/friendskodakgallery/friends_kodak_gallery_...

The instructions are in that zip, but also available at

http://home.comcast.net/~snowymike/friendskodakgallery/Downloading%20Friends%...

If anyone figures out a way to download high-resolution friends' photos through the classic version of the site, I'm still open to updating the script to support that. Still a few weeks left for someone to figure that out.

To the authors and editors of the Ruby script...I CANNOT THANK YOU ENOUGH! I stopped using kodakgallery a couple of years ago and have been enjoying Smugmug ever since. Figuring out a way to download our 10+gb of photos, and their captions, has been weighing on my shoulders every week. With the upcoming deadline looming, it added urgency for me to get this done...then I found this post.

I spent about 45 mins reading through the instructions and configuring the tools, and overnight, my 231 albums magically appeared on my local machine....THANK YOU. It was the best Father's Day gift...ever.

Garry thanks for the script. To get it to work on Windows XP with rubyinstaller-1.9.3-p194.exe I had to modify the script. The changes are:

1) Turn off SSL checking
2) Take out WWW before Mechanize references
3) Remove the result.class check (it was failing)
4) Change urls to eu.com for downloading albums outside USA (change these back to just .com if your albums are USA)

Modified script:

require 'rubygems'
require 'mechanize'
require 'fileutils'

OpenSSL::SSL::VERIFY_PEER = OpenSSL::SSL::VERIFY_NONE

agent = Mechanize.new
signin_page = agent.get('http://www.kodakgallery.eu.com/Signin.jsp')
signin_page.forms[0].email = 'email'
signin_page.forms[0].password = 'password here'
signin_page.forms[0].submit

album_page = agent.get('http://www.kodakgallery.eu.com/AlbumMenu.jsp?Up...)
albums = album_page.links.map{|l| (l.href.match(/BrowsePhotos.jsp/) && l.text && l.text.match(/[A-Za-z0-9]/)) ? {:href => l.href, :name => l.text} : nil}.compact

albums.each do |album_hash|
puts "\n\n\n"
puts "-----------------------------------------"
puts "'#{album_hash[:name]}'"
puts "#{album_hash[:href]}"

gallery_page = agent.get("http://www.kodakgallery.eu.com/#{album_hash[:hr...)
photos = gallery_page.links.map{|l| (l.href.match(/PhotoView.jsp/) && !l.href.match(/javascript/)) ? l.href : nil}.compact.uniq

album_dirname = album_hash[:name].gsub(/[\n\t\?\:\>\<\\\ />

unless File.exists?(album_dirname)
puts "creating album #{album_dirname}"
FileUtils.mkdir(album_dirname)
end

FileUtils.cd(album_dirname, :verbose => true) do

photos.each do |p|
photo_page = agent.get("http://www.kodakgallery.eu.com/#{p}")
fullres = photo_page.links.map{|l| (l.href.match(/FullResDownload/) && !l.href.match(/javascript/)) ? l.href : nil}.compact.uniq.first

file_to_dl = "http://www.kodakgallery.eu.com#{fullres}"

result = agent.get(file_to_dl)
# if result.class == Mechanize::File
result.save
puts "Saved #{file_to_dl}"
# else
# puts "FAIL on #{file_to_dl}"
# end

end

end

puts "-----------------------------------------"
puts "-----------------------------------------"
puts "-----------------------------------------"
end

Thanks for this script, it worked great for two accounts that I needed to download the images from and saved us alot of trouble!

I've run into an issue with a 3rd account that i'm trying to download pics from, where the download high-res link is not available for each picture in the classic version of the site. I haven't found a way to make that link available in her account, and I'm guessing it was removed since she never purchased any pictures from Kodak or upgraded her account. The high res pictures are there, in the new version of the site, I just can't get to them from classic using the script.

any ideas appreciated, but i may just download the low-resl versions by using the download friend albums script.

Haven't encountered that before. The first thing I'd try is logging in to the non-classic version of the site as that user and see if enabling download for an album fixes the classic problem for that album. I'm guessing not, but that's easier than what I'll suggest next.

When I view an individual picture through the Classic version of the site, the URL is of the form

http://classic.kodakgallery.com/PhotoView.jsp?&collid=A.B.C&photoid=P&folderi...

where A, B, C, and P are sequences of numbers.

the associated high res download url is of the form

http://classic.kodakgallery.com/servlet/FullResDownload?collid=A.B&photoid=A.P&

I'd suggest you view a picture through the classic version of the site, record the values for A, B, and P (C seems irrelevant), construct the URL for the high res download URL using the format listed above, and see if you can successfully download the high res version if you access that URL directly. If not, I think we're stuck. But if that URL works, even though it's not visible on the page, one could update the script to dynamically construct that download high res URL by parsing the picture URL. Please post back what you uncover.

One other thing you could try is ordering a picture from Kodak Gallery, which possibly will enable the high res download option.

I tried everything except for purchasing photos for her. When I reconstructed the url using your recommendations i got a 401 Unauthorized page.

Thanks for the feedback!

Rats. 401 Unauthorized is the same error I got attempting to download friends' albums in high res (guessing at what the URL would be), and is likely an intentional error response on the part of Kodak Gallery.

The low-res friends version of the script I posted is probably your best bet now with just a day to go before Kodak Gallery is shutdown. You should still have time to share albums from the user with download difficulty (user A) to a user without download difficulty (user B) and then download friends' albums for user B to get low res versions of user A's pictures.

-mike

Unfortunately this is probably too late to help anyone, except people in the same boat as me-- night owls with just a few friends' photos to download.

After poking around a bit I found a way to download friends' pictures, full res, even though I don't have download permission from them.

First, I noticed that the image links in my friend's slideshow were of this form:
http://www.kodakgallery.com/imaging-site/services/doc/NUMBERA:NUMBERB/jpeg/SM

Where NumberA was a short 4-5 digit number, and NumberB was a pretty long number, like 12-13 digits.

Second, I uploaded one test pic of my own, and downloaded it in full res (since I did have permission). Then I copied the download link from Firefox. The link was of this form:
http://www.kodakgallery.com/site/rest/v1.0/picture/NUMBERB/jpeg/FS

Much to my surprise, I found I could sub my friend's images' links' NUMBERB from the slideshow, for the full size download link's NUMBERB, and it worked, I got what look to me like full res images.

(BTW, the two digit code at the end of a lot of these links, was either "BG", "SM", "MO", or "FS" depending on where I was poking around, but I'm guessing FS means Full Size, SM means Small, BG Big, etc.)

It may be a quirk-- my friend's images were uploaded nearly a decade ago, I guess to Ofoto-- maybe permissions are different on those older albums. But may be worth a try for someone.

OK, that got me closer. I couldn't find that friend slideshow URL you referred to, but I can find NUMBERB from the classic version of the site. It's the photoid embedded in the URL. If I supply the photoid to the REST interface, I can download the photo in a browser after logging in to the non-classic version of Kodak Gallery. Unfortunately, we'd still have to figure out how to log in to the non-classic version of the site from the script, which nobody has done yet. I get this error when I try to download after logging in just to the classic version of the site.:

.C:/Programs/Ruby193/lib/ruby/gems/1.9.1/gems/mechanize-2.5.1/lib/mechanize/http
/agent.rb:697:in `response_authenticate': 401 => Net::HTTPUnauthorized for http:
//www.kodakgallery.com/site/rest/v1.0/picture/216... -- WWW-Authenticate header missing in response (Mechanize::UnauthorizedError)

I'm out of time today, but here are the updates I made to the downloadPhoto method in my friends version of the script. If someone can figure out how to authenticate to the non-classic version of the site, this script update will download friends albums in high res, even friends' albums that weren't download enabled.

photo_page = agent.get("http://classic.kodakgallery.com/#{photo}")
photo_url = ""

if /photoid=(\d+)&/.match(photo)
photoid = $1
photo_url = "http://www.kodakgallery.com/site/rest/v1.0/pict..."
else
puts "Unable to extract high res photoid from photo URL #{photo}, photo will be downloaded in low res"
photo_url = photo_page.search("//img[@id='photo']")[0]["src"]
end

caption = ""

if ($download_captions)
caption = getCaptionForPhoto(photo_page)
end

if ($download_captions && $print_captions_to_screen)
puts caption
else
print "."
end

file_to_dl = photo_url

OK, Holy Grail time.

Got high resolution download of friends' albums working (plus captions, pictures in album order), thanks to jimdavis2001's tip and my figuring out how to authenticate to the non-classic version of the site.

http://home.comcast.net/~snowymike/friendskodakgalleryhighres/Downloading Friends Kodak Gallery Albums in High Resolution.htm

http://home.comcast.net/~snowymike/friendskodakgalleryhighres/friends_kodak_g...

Only a few hours left, so download your friends' albums quickly.

You are one straightforward writer. I enjoyed reading your article and taking in all the interesting information. I share your thoughts on many points in this content. This is great.

Depository trust & clearing corporation

1 visitor upvoted this post.