Permalink
Browse files

Moved to a singleton for the EyefiCard model. Moved all the old stuff…

… to the EyefiCardInstance class.
  • Loading branch information...
1 parent 9c4343e commit bcc19757b5f63bfa1aee321e538bb9aa3aa3dc1e @kenkeiter committed Jun 5, 2010
Showing with 62 additions and 19 deletions.
  1. +6 −9 app.rb
  2. +0 −3 lib/archive.rb
  3. +44 −4 lib/eyefi.rb
  4. +12 −3 lib/ryfi.rb
View
15 app.rb
@@ -5,22 +5,19 @@
require 'stringio'
require 'exifr'
-MyCard = EyefiCard.new('000000000000', 'superSecretUploadKeyInHex')
+# Register as many cards as you wish (accepts the card's MAC + upload key)
+EyefiCard.register('782201658100', '2c3eadb135e2bd6cff25115ff51ee4c8')
class MyApp < RyfiApp
- authorize_cards :find_card
handle_photos_with :handle_photo
- def find_card(mac)
- {'000000000000' => MyCard}[mac]
- end
-
def handle_photo(card, photo)
- puts "New photo from: #{photo.exif[:model]}"
- photo.save_with_original_name! '/Path/To/My/Deskop'
+ EyefiCard.log.debug "Received new photo (#{photo.original_name}) shot with an #{photo.exif[:model]}."
+ photo.save_with_original_name! '/Users/kkeiter/Desktop/test'
end
end
-MyApp.run! :host => 'localhost', :port => 59278 # must be on this port for card
+# Server must be run on 59278 so that the card can reach it.
+MyApp.run! :host => 'localhost', :port => 59278
View
@@ -289,7 +289,6 @@ def initialize(header = nil, fp = nil)
@header = Header.new(header)
if @header.file?
- puts "File: #{@header.name}, #{@header.size} bytes"
size = @header.size
if size > 0
@@ -312,8 +311,6 @@ def extract_data! # {{{
puts "Couldn't create file for writing, or something: " + e.message
end
end
-
- File.utime(@header.mtime, Time.new, target + @header.name)
end # }}}
end # }}}
end
View
@@ -4,6 +4,8 @@
require 'lib/archive'
require 'stringio'
require 'exifr'
+require 'singleton'
+require 'logger'
module Exceptions
class IntegrityError < StandardError; end
@@ -12,17 +14,49 @@ class IncompleteMetadataError < StandardError; end
class EyefiCard
+ include Singleton
@Roman2K

Roman2K Jun 5, 2011

What's the point of this? This class is never instantiated (via EyefiCard.instance).

@kenkeiter

kenkeiter Jun 5, 2011

Owner

I appreciate all the feedback in here -- this was a first project when I was trying to get back into Ruby (coming from Python). It's on my list to do some major updates to Ryfi -- any chance you wanna submit a pull request for your changes? Thanks :)

@Roman2K

Roman2K Jun 5, 2011

Kenneth: I'm sorry but I don't have time to make those changes and test them. I'm not interested in this project (just stumbled upon this particular commit) but I appreciate the open-source effort, so I pointed some things out to help improve the code quality. Good luck with getting back into Ruby, this project seems like a perfect opportunity :-)

+
+ @@cards = {}
+ @@log = nil
+
+ class << self
+
+ def find_by_mac(mac)
+ @@cards[mac]
+ end
+
+ def log
+ @@log = Logger.new(STDOUT) if @@log.nil?
+ @@log.level = Logger::DEBUG
+ return @@log
+ end
@Roman2K

Roman2K Jun 5, 2011

For module-wide loggers, I prefer to assign it to a constant that can be referred to througout the module and its namespaced modules and classes:

class EyefiCard
  LOG = begin
    logger = Logger.new STDOUT
    logger.level = Logger::DEBUG
    logger
  end

  def receive_photo(...)
    LOG.debug "#{self}: attempting to receive a new photo [...]"
    ...
  end
end
+
+ def register(*args)
+ inst = EyefiCardInstance.new(*args)
+ @@cards[args[0]] = inst unless @@cards.key? args[0]
+ return inst
@Roman2K

Roman2K Jun 5, 2011

Instances are being created even if they're not being saved in the registry Hash. This could be simplified / cleaned-up to:

@@cards[args.first] ||= EyefiCardInstance.new(*args)

However:

  1. Since you want to index instances by MAC addresses, you should name the variable receiving it as first argument, to make this explicit.
  2. You're forwarding arguments to the constructor of EyefiCardInstance, so the potential block shouldn't be left out.

So IMO, this method should rather look like:

def register(mac_address, *args, &block)
  @@cards[mac_address] ||= EyefiCardInstance.new(mac_address, *args, &block)
end
+ end
+
+ end
+
+end
+
+class EyefiCardInstance
@Roman2K

Roman2K Jun 5, 2011

From what I understand, EyefiCard is just a placeholder for global variables (the card registry and logger, for now), it shouldn't even be a class really. EyefiCardInstance should be merged into EyefiCard, while keeping EyefiCard's existing class variables and methods:

class EyefiCard
  def self.register(...)
  def self.find_by_mac(...)
  def self.log

  attr_reader ...

  def initialize(...)
end
+
attr_reader :upload_key
attr_reader :mac_address
+ attr_reader :photos
def initialize(mac_address, upload_key)
+ EyefiCard.log.debug "Instantiating new card: #{mac_address}, #{upload_key}"
@mac_address, @upload_key, @photos = mac_address, upload_key, {}
end
def receive_photo(temp_file, integrity_digest, meta = nil)
unless meta.nil?
+ EyefiCard.log.debug "Card #{@mac_address} attempting to receive new photo: #{temp_file}, #{integrity_digest}."
received_photo = Photo.new(self, temp_file, integrity_digest, meta)
- @photos[received_photo.orginal_name] = received_photo
+ @photos[received_photo.original_name] = received_photo
return received_photo
else
raise Exceptions::IncompleteMetadataError
@@ -43,6 +77,7 @@ def initialize(card, temp_file, integrity_digest, meta)
@card, @exif, @meta = card, nil, meta
@tar_fp = StringIO.new(temp_file.read)
unless integrity_compromised? integrity_digest
+ EyefiCard.log.debug "#{self}: File integrity verified!"
@photo_fp = StringIO.new(extract_data(@tar_fp))
update_exif!
else
@@ -51,7 +86,9 @@ def initialize(card, temp_file, integrity_digest, meta)
end
def integrity_compromised?(digest)
- tar_bytes = @tar_fp.read # we need this to be a string
+ EyefiCard.log.debug "#{self} verifying file integrity against digest: #{digest}"
+
+ @tar_fp.rewind; tar_bytes = @tar_fp.read # we need this to be a string
pos, tcp_sums = 0, []
while tar_bytes.length % 512 != 0 do
tar_bytes << "\x00"
@@ -74,8 +111,8 @@ def save_with_original_name!(path)
end
def save!(path)
- File.new(path, 'w+')
- fp << @photo_fp.read
+ fp = File.new(path, 'w+')
+ @photo_fp.rewind; fp << @photo_fp.read
fp.close
end
@@ -84,15 +121,18 @@ def save!(path)
#######
def update_exif!
+ EyefiCard.log.debug "#{self}'s updating exif."
@exif = EXIFR::JPEG.new(@photo_fp).exif
end
def extract_data(fp)
+ fp.rewind
components = []
tar = Archive::Tar::Reader.new(fp)
tar.each_entry{|entry|
components << entry.extract_data!
}
+ EyefiCard.log.debug "#{self} extracted archive (length: #{fp.length})"
components.first
end
View
@@ -27,7 +27,10 @@ def soap_action(pattern)
class RyfiApp < PatchedSinatraApp
+ set :lock, true
+
@@snonce = Digest::MD5.hexdigest((0...8).map{65.+(rand(25)).chr}.join)
+ @@card_auth_handler = nil
class << self
def handle_photos_with(handler)
@@ -48,15 +51,19 @@ def authorize_cards(handler)
params[:soap] = soap_to_object(params[:SOAPENVELOPE])
end
# find card by mac
- params[:card] = self.send(@@card_auth_handler, params[:soap].macaddress)
+ unless @@card_auth_handler.nil?
+ params[:card] = self.send(@@card_auth_handler, params[:soap].macaddress)
+ else
+ params[:card] = EyefiCard.find_by_mac(params[:soap].macaddress)
+ end
response['Server'] = 'Eye-Fi Agent/2.0.4.0 (Windows XP SP2)'
content_type 'application/xml', :charset => 'utf-8'
- end
+ end
end
# Handle StartSession
post '/api/soap/eyefilm/v1', :soap_action => 'urn:StartSession', :agent => /Eye-Fi Card/ do
-
+
builder do |xml|
xml.instruct! :xml, :version => '1.0'
xml.tag!('SOAP-ENV:Envelope', 'xmlns:SOAP-ENV' => 'http://schemas.xmlsoap.org/soap/envelope/'){
@@ -111,6 +118,8 @@ def authorize_cards(handler)
photo = params[:card].receive_photo(params['FILENAME'][:tempfile], params['INTEGRITYDIGEST'], params[:soap])
self.send(@@photo_handler, params[:card], photo)
+ EyefiCard.log.debug "Sending upload response..."
+
builder do |xml|
xml.instruct! :xml
xml.tag!('SOAP-ENV:Envelope', 'xmlns:SOAP-ENV' => 'http://schemas.xmlsoap.org/soap/envelope/'){

0 comments on commit bcc1975

Please sign in to comment.