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.
- data/lib/nosy/hunter.rb +16 -0
- data/lib/nosy/parser.rb +110 -0
- data/lib/nosy/searcher.rb +35 -0
- data/lib/nosy.rb +22 -0
- metadata +84 -0
data/lib/nosy/hunter.rb
ADDED
@@ -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
|
data/lib/nosy/parser.rb
ADDED
@@ -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:
|