nosy 0.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,16 @@
1
+ require 'fileutils'
2
+
3
+ module Nosy
4
+
5
+ class Hunter
6
+
7
+ def hunt
8
+ if RUBY_PLATFORM =~ /darwin/
9
+ FileUtils.cp "#{Dir.home}/Library/Application Support/MobileSync/Backup/55e67384ae82dd8a317f29585e1d7b5884e43107/3d0d7e5fb2ce288813306e4d4636395e047a3d28", "#{FileUtils.pwd}/texts.sqlite"
10
+ "#{FileUtils.pwd}/texts.sqlite"
11
+ end
12
+ end
13
+
14
+ end
15
+
16
+ end
@@ -0,0 +1,110 @@
1
+ require 'sqlite3'
2
+
3
+ Message = Struct.new(:receiver, :sender, :message, :imessage, :date)
4
+
5
+ module Nosy
6
+
7
+ class Parser
8
+
9
+ def can_parse?(file)
10
+ begin
11
+ db = SQLite3::Database.new( file )
12
+ begin
13
+ results = db.execute2( "select * from message LIMIT 1" )
14
+ results.map do |header|
15
+ if ( header[0] == "ROWID" && header[1] == "address" && header[2] == "date" && header[3] == "text" && header[4] == "flags" && header[16] == "read")
16
+ return true
17
+ else
18
+ return false
19
+ end
20
+ end
21
+ rescue SQLite3::SQLException
22
+ return false
23
+ end
24
+ rescue SQLite3::NotADatabaseException
25
+ return false
26
+ end
27
+
28
+ end
29
+
30
+ def parse(file)
31
+ db = SQLite3::Database.new( file )
32
+ all_messages = db.execute( "select * from message" )
33
+
34
+ all_messages.map do |message|
35
+
36
+ # http://www.slideshare.net/hrgeeks/iphone-forensics-without-the-iphone
37
+ # http://www.scip.ch/?labs.20111103
38
+
39
+ parsed_message = Message.new("", "", message[3], "", "")
40
+
41
+ ## If it is an iMessage
42
+ if message[29] == 1
43
+ parsed_message.imessage = true
44
+ parsed_message.date = message[2] + 978307200
45
+
46
+ # Sent an iMessage
47
+ if message[25] == 36869
48
+ parsed_message.receiver = format_address(message[18])
49
+ parsed_message.sender = "me"
50
+
51
+ # Recieved an iMessage
52
+ elsif message[25] == 12289
53
+ parsed_message.receiver = "me"
54
+ parsed_message.sender = format_address(message[18])
55
+
56
+ # Sent a group iMessage
57
+ elsif message[25] == 32773
58
+ parsed_message.sender = "me"
59
+ parsed_message.receiver = "group"
60
+ end
61
+
62
+ ## It is an SMS
63
+ else
64
+
65
+ parsed_message.imessage = false
66
+ parsed_message.date = message[2]
67
+
68
+ # Sent SMS
69
+ if message[4] == 3
70
+ parsed_message.receiver = format_address(message[1])
71
+ parsed_message.sender = "me"
72
+
73
+ # Recieved an SMS
74
+ elsif message[4] == 2
75
+ parsed_message.receiver = "me"
76
+ parsed_message.sender = format_address(message[1])
77
+
78
+ # Sent SMS on retry
79
+ elsif message[4] == 35
80
+ parsed_message.receiver = format_address(message[1])
81
+ parsed_message.sender = "me"
82
+
83
+ # SMS Failed
84
+ elsif message[4] == 33
85
+ parsed_message.receiver = format_address(message[1])
86
+ parsed_message.sender = "me"
87
+
88
+ # iMessage Failed and sent as SMS
89
+ elsif message[4] == 16387
90
+ parsed_message.receiver = format_address(message[1])
91
+ parsed_message.sender = "me"
92
+ end
93
+
94
+ end
95
+
96
+ parsed_message
97
+ end
98
+ end
99
+
100
+ private
101
+ def format_address(address)
102
+ if !address.nil?
103
+ address = address.gsub(/\s+|[()-]/, "")
104
+ address =~ /^[0-9]+$/ ? "+"+address : address
105
+ end
106
+ end
107
+
108
+ end
109
+
110
+ end
@@ -0,0 +1,35 @@
1
+ module Nosy
2
+
3
+ class Searcher
4
+ attr_accessor :texts
5
+
6
+ def initialize( file )
7
+ @texts = Parser.new.parse( file )
8
+ end
9
+
10
+ def search(filters={})
11
+
12
+ @texts.select do |text|
13
+ filters.all?{ |key, value| key == :date ? filter_dates(key, value, text) : text[key] == value }
14
+ end
15
+ end
16
+
17
+ private
18
+
19
+ def filter_dates( key, value, text )
20
+ if value[1] == "="
21
+ value[0] == ">" ? Time.at(text[key]) >= Time.at(value[2..-1].to_i) : Time.at(text[key]) <= Time.at(value[2..-1].to_i)
22
+ else
23
+ if value[0] == ">"
24
+ Time.at(text[key]) > Time.at(value[1..-1].to_i)
25
+ elsif value[0] == "<"
26
+ Time.at(text[key]) < Time.at(value[1..-1].to_i)
27
+ else
28
+ Time.at(text[key]) == Time.at(value.to_i)
29
+ end
30
+ end
31
+ end
32
+
33
+ end
34
+
35
+ end
data/lib/nosy.rb ADDED
@@ -0,0 +1,22 @@
1
+ require "nosy/hunter"
2
+ require "nosy/parser"
3
+ require "nosy/searcher"
4
+
5
+ module Nosy
6
+
7
+ def self.hunt
8
+ Hunter.new.hunt
9
+ end
10
+
11
+ def self.new(file)
12
+ Searcher.new(file)
13
+ end
14
+
15
+ def self.can_parse?(file)
16
+ Parser.new.can_parse?(file)
17
+ end
18
+
19
+ def self.parse(file)
20
+ Parser.new.parse(file)
21
+ end
22
+ end
metadata ADDED
@@ -0,0 +1,84 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: nosy
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.2
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Philip Dudley
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2011-11-24 00:00:00.000000000Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: sqlite3
16
+ requirement: &70094878998840 !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ~>
20
+ - !ruby/object:Gem::Version
21
+ version: 1.3.4
22
+ type: :runtime
23
+ prerelease: false
24
+ version_requirements: *70094878998840
25
+ - !ruby/object:Gem::Dependency
26
+ name: fileutils
27
+ requirement: &70094878998360 !ruby/object:Gem::Requirement
28
+ none: false
29
+ requirements:
30
+ - - ~>
31
+ - !ruby/object:Gem::Version
32
+ version: '0.7'
33
+ type: :runtime
34
+ prerelease: false
35
+ version_requirements: *70094878998360
36
+ - !ruby/object:Gem::Dependency
37
+ name: rspec
38
+ requirement: &70094878997900 !ruby/object:Gem::Requirement
39
+ none: false
40
+ requirements:
41
+ - - ~>
42
+ - !ruby/object:Gem::Version
43
+ version: 2.6.0
44
+ type: :development
45
+ prerelease: false
46
+ version_requirements: *70094878997900
47
+ description: Nosy fetches, parses and searches the iPhone's SMS database that is created
48
+ on your machine each time you make a backup.
49
+ email: pdudley89@gmail.com
50
+ executables: []
51
+ extensions: []
52
+ extra_rdoc_files: []
53
+ files:
54
+ - lib/nosy.rb
55
+ - lib/nosy/hunter.rb
56
+ - lib/nosy/parser.rb
57
+ - lib/nosy/searcher.rb
58
+ homepage: http://phildudley.com
59
+ licenses: []
60
+ post_install_message:
61
+ rdoc_options: []
62
+ require_paths:
63
+ - lib
64
+ required_ruby_version: !ruby/object:Gem::Requirement
65
+ none: false
66
+ requirements:
67
+ - - ! '>='
68
+ - !ruby/object:Gem::Version
69
+ version: '0'
70
+ required_rubygems_version: !ruby/object:Gem::Requirement
71
+ none: false
72
+ requirements:
73
+ - - ! '>='
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ requirements: []
77
+ rubyforge_project:
78
+ rubygems_version: 1.8.10
79
+ signing_key:
80
+ specification_version: 3
81
+ summary: Nosy fetches, parses and searches the iPhone's SMS database that is created
82
+ on your machine each time you make a backup.
83
+ test_files: []
84
+ has_rdoc: