Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion ipa_reader.gemspec
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ Gem::Specification.new do |s|
s.description = "I am using this gem to get version to build the over the air iPhone Ad Hoc distribution plist file."
s.email = "schlueter@gmail.com"
s.executables = ["ipa_reader"]
s.files = ["History.txt", "README.md", "Rakefile", "bin/ipa_reader", "lib/ipa_reader.rb", "lib/ipa_reader/ipa_file.rb", "lib/ipa_reader/plist_binary.rb", "lib/ipa_reader/png_file.rb", "spec/ipa_reader_spec.rb", "spec/spec_helper.rb", "test/MultiG.ipa", "test/test_ipa_reader.rb", "version.txt"]
s.files = ["History.txt", "README.md", "Rakefile", "bin/ipa_reader", "lib/ipa_reader.rb", "lib/ipa_reader/ipa_file.rb", "lib/ipa_reader/plist_binary.rb", "lib/ipa_reader/png_file.rb", "spec/ipa_reader_spec.rb", "spec/spec_helper.rb", "test/Find iPhone.ipa", "test/test_ipa_reader.rb", "version.txt"]
s.homepage = "http://github.com/schlu/Ipa-Reader"
s.require_paths = ["lib"]
s.rubyforge_project = "ipa_reader"
Expand Down
92 changes: 81 additions & 11 deletions lib/ipa_reader/ipa_file.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,28 @@
require 'zip'
end

module DeviceFamily
IPhone = 1
IPad = 2
end

module IpaReader
class IpaFile
attr_accessor :plist, :file_path
attr_accessor :plist, :file_path, :meta_plist
def initialize(file_path)
self.file_path = file_path
info_plist_file = nil
regex = /Payload\/[^\/]+.app\/Info.plist/
Zip::ZipFile.foreach(file_path) { |f| info_plist_file = f if f.name.match(regex) }
cf_plist = CFPropertyList::List.new(:data => self.read_file(regex), :format => CFPropertyList::List::FORMAT_BINARY)
cf_plist = CFPropertyList::List.new(:data => self.read_file(regex), :format => CFPropertyList::List::FORMAT_AUTO)
self.plist = cf_plist.value.to_rb

meta_data = self.read_file(/iTunesMetadata.plist/)
if meta_data
meta_data.chomp! "\u0000"
self.meta_plist = CFPropertyList::List.new(:data => meta_data, :format => CFPropertyList::List::FORMAT_AUTO).value.to_rb
else
self.meta_plist = {}
end
end

def version
Expand All @@ -39,22 +51,25 @@ def minimum_os_version

def url_schemes
if plist["CFBundleURLTypes"] && plist["CFBundleURLTypes"][0] && plist["CFBundleURLTypes"][0]["CFBundleURLSchemes"]
plist["CFBundleURLTypes"][0]["CFBundleURLSchemes"]
plist["CFBundleURLTypes"][0]["CFBundleURLSchemes"].value.map { |schema| schema.value }
else
[]
end
end

def icon_file
file = nil
if plist["CFBundleIconFiles"]
data = read_file(Regexp.new("#{plist["CFBundleIconFiles"][0]}$"))
file = file_name(Regexp.new("#{plist["CFBundleIconFiles"][-1]}$"))
elsif plist["CFBundleIconFile"]
data = read_file(Regexp.new("#{plist["CFBundleIconFile"]}$"))
end
if data
IpaReader::PngFile.normalize_png(data)
file = file_name(Regexp.new("#{plist["CFBundleIconFile"]}$"))
elsif plist['CFBundleIcons']
primary_icon = plist["CFBundleIcons"]["CFBundlePrimaryIcon"].value
icon_files = primary_icon['CFBundleIconFiles'].value
icon_file = icon_files[-1].value
file = file_name(Regexp.new("#{icon_file}"))
else
nil
file = file_name(Regexp.new("Icon@2x"))
end
end

Expand All @@ -69,11 +84,66 @@ def bundle_identifier
def icon_prerendered
plist["UIPrerenderedIcon"] == true
end

def app_id
self.meta_plist["itemId"].to_s
end

def localized_names
names = {}
regex = /Payload\/[^\/]+.app\/(.+)\.lproj\/InfoPlist.strings/
Zip::ZipFile.foreach(self.file_path) do |f|
if f.name.match(regex)
file = f
cf_plist = CFPropertyList::List.new(:data => file.get_input_stream.read, :format => CFPropertyList::List::FORMAT_BINARY).value.to_rb
names[$1.to_sym] = cf_plist['CFBundleDisplayName']
end
end
names
end

def excutable_file
plist['CFBundleExecutable']
end

def genre
meta_plist['genre']
end

def genre_id
meta_plist['genreId'].to_s
end

def artist_id
meta_plist['artistId'].to_s
end

def artist_name
meta_plist['artistName']
end

def release_date
Date.parse meta_plist['releaseDate']
end

def device_family
plist['UIDeviceFamily']
end

def read_file(regex)
file = nil
Zip::ZipFile.foreach(self.file_path) { |f| file = f if f.name.match(regex) }
file.get_input_stream.read
if file
file.get_input_stream.read
end
end

def file_name(regex)
file = nil
Zip::ZipFile.foreach(self.file_path) { |f| file = f if f.name.match(regex) }
if file
file.name
end
end
end
end
Binary file added test/Find iPhone.ipa
Binary file not shown.
Binary file removed test/MultiG.ipa
Binary file not shown.
90 changes: 81 additions & 9 deletions test/test_ipa_reader.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,45 +3,117 @@

class IpaReaderTest < Test::Unit::TestCase
def setup
@ipa_file = IpaReader::IpaFile.new(File.dirname(__FILE__) + '/MultiG.ipa')
@ipa_file = IpaReader::IpaFile.new(File.dirname(__FILE__) + '/Find iPhone.ipa')
end

def test_parse
assert(@ipa_file.plist.keys.count > 0)
end

def test_version
assert_equal(@ipa_file.version, "1.2.2.4")
assert_equal(@ipa_file.version, "376")
end

def test_short_version
# asserting nil because the test file doesn't have this key
assert_nil(@ipa_file.short_version)
assert_equal(@ipa_file.short_version, "3.0")
end

def test_name
assert_equal(@ipa_file.name, "MultiG")
assert_equal(@ipa_file.name, "FindMyiPhone")
end

def test_target_os_version
assert_equal(@ipa_file.target_os_version, "4.1")
assert_equal(@ipa_file.target_os_version, "7.0")
end

def test_minimum_os_version
assert_equal(@ipa_file.minimum_os_version, "3.1")
assert_equal(@ipa_file.minimum_os_version, "7.0")
end

def test_url_schemes
assert_equal(@ipa_file.url_schemes, [])
assert_equal(@ipa_file.url_schemes, ['fmip1'])
end

def test_icon_file
assert_equal(@ipa_file.icon_file, 'Payload/FindMyiPhone.app/AppIcon60x60@2x.png')
end

def test_bundle_identifier
assert_equal("com.dcrails.multig", @ipa_file.bundle_identifier)
assert_equal("com.apple.mobileme.fmip1", @ipa_file.bundle_identifier)
end

def test_icon_prerendered
assert_equal(false, @ipa_file.icon_prerendered)
assert_equal(true, @ipa_file.icon_prerendered)
end

def test_app_id
assert_equal('376101648', @ipa_file.app_id)
end

def test_localized_names
assert_equal({:ar=>"عثور iPhone",
:ca=>"Buscar",
:cs=>"Najít iPhone",
:da=>"Find iPhone",
:de=>"Mein iPhone",
:el=>"Εύρεση",
:en=>"Find iPhone",
:en_GB=>"Find iPhone",
:es=>"Buscar",
:fi=>"Etsi iPhone",
:fr=>"Localiser",
:he=>"מצא iPhone",
:hr=>"Nađi iPhone",
:hu=>"Keresés",
:id=>"Cari iPhone",
:it=>"Trova iPhone",
:ja=>"Find iPhone",
:ko=>"iPhone 찾기",
:ms=>"Cari iPhone",
:nl=>"Zoek iPhone",
:no=>"Finn iPhone",
:pl=>"Znajdź",
:pt=>"Buscar",
:pt_PT=>"Encontrar",
:ro=>"Găsire iPhone",
:ru=>"Найти iPhone",
:sk=>"Nájsť iPhone",
:sv=>"Hitta iPhone",
:th=>"ค้นหา iPhone",
:tr=>"iPhone'u Bul",
:uk=>"Де iPhone",
:vi=>"Tìm iPhone",
:zh_CN=>"查找 iPhone",
:zh_TW=>"尋找 iPhone"}, @ipa_file.localized_names)
end

def test_excutable_file
assert_equal(@ipa_file.excutable_file, "FindMyiPhone")
end

def test_genre
assert_equal(@ipa_file.genre, "Utilities")
end

def test_genre_id
assert_equal(@ipa_file.genre_id, "6002")
end

def test_artist_id
assert_equal(@ipa_file.artist_id, "284417353")
end

def test_artist_name
assert_equal(@ipa_file.artist_name, "Apple")
end

def test_release_date
assert_equal(@ipa_file.release_date.to_s, "2010-06-18")
end

def test_device_family
assert_equal(@ipa_file.device_family, [DeviceFamily::IPhone, DeviceFamily::IPad])
end

end