rcs-common 9.6.0

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.
Files changed (116) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +49 -0
  3. data/Gemfile +4 -0
  4. data/LICENSE.txt +1 -0
  5. data/Rakefile +27 -0
  6. data/lib/rcs-common.rb +21 -0
  7. data/lib/rcs-common/binary.rb +64 -0
  8. data/lib/rcs-common/cgi.rb +7 -0
  9. data/lib/rcs-common/component.rb +87 -0
  10. data/lib/rcs-common/crypt.rb +71 -0
  11. data/lib/rcs-common/deploy.rb +96 -0
  12. data/lib/rcs-common/diagnosticable.rb +136 -0
  13. data/lib/rcs-common/evidence.rb +261 -0
  14. data/lib/rcs-common/evidence/addressbook.rb +173 -0
  15. data/lib/rcs-common/evidence/application.rb +59 -0
  16. data/lib/rcs-common/evidence/calendar.rb +62 -0
  17. data/lib/rcs-common/evidence/call.rb +185 -0
  18. data/lib/rcs-common/evidence/camera.rb +25 -0
  19. data/lib/rcs-common/evidence/chat.rb +272 -0
  20. data/lib/rcs-common/evidence/clibpoard.rb +58 -0
  21. data/lib/rcs-common/evidence/command.rb +50 -0
  22. data/lib/rcs-common/evidence/common.rb +78 -0
  23. data/lib/rcs-common/evidence/content/camera/001.jpg +0 -0
  24. data/lib/rcs-common/evidence/content/coin/wallet_bit.dat +0 -0
  25. data/lib/rcs-common/evidence/content/coin/wallet_lite.dat +0 -0
  26. data/lib/rcs-common/evidence/content/file/Einstein.docx +0 -0
  27. data/lib/rcs-common/evidence/content/file/arabic.docx +0 -0
  28. data/lib/rcs-common/evidence/content/mouse/001.jpg +0 -0
  29. data/lib/rcs-common/evidence/content/mouse/002.jpg +0 -0
  30. data/lib/rcs-common/evidence/content/mouse/003.jpg +0 -0
  31. data/lib/rcs-common/evidence/content/mouse/004.jpg +0 -0
  32. data/lib/rcs-common/evidence/content/print/001.jpg +0 -0
  33. data/lib/rcs-common/evidence/content/screenshot/001.jpg +0 -0
  34. data/lib/rcs-common/evidence/content/screenshot/002.jpg +0 -0
  35. data/lib/rcs-common/evidence/content/screenshot/003.jpg +0 -0
  36. data/lib/rcs-common/evidence/content/url/001.jpg +0 -0
  37. data/lib/rcs-common/evidence/content/url/002.jpg +0 -0
  38. data/lib/rcs-common/evidence/content/url/003.jpg +0 -0
  39. data/lib/rcs-common/evidence/device.rb +23 -0
  40. data/lib/rcs-common/evidence/download.rb +54 -0
  41. data/lib/rcs-common/evidence/exec.rb +0 -0
  42. data/lib/rcs-common/evidence/file.rb +129 -0
  43. data/lib/rcs-common/evidence/filesystem.rb +71 -0
  44. data/lib/rcs-common/evidence/info.rb +24 -0
  45. data/lib/rcs-common/evidence/keylog.rb +84 -0
  46. data/lib/rcs-common/evidence/mail.rb +237 -0
  47. data/lib/rcs-common/evidence/mic.rb +39 -0
  48. data/lib/rcs-common/evidence/mms.rb +36 -0
  49. data/lib/rcs-common/evidence/money.rb +676 -0
  50. data/lib/rcs-common/evidence/mouse.rb +62 -0
  51. data/lib/rcs-common/evidence/password.rb +60 -0
  52. data/lib/rcs-common/evidence/photo.rb +80 -0
  53. data/lib/rcs-common/evidence/position.rb +303 -0
  54. data/lib/rcs-common/evidence/print.rb +50 -0
  55. data/lib/rcs-common/evidence/screenshot.rb +53 -0
  56. data/lib/rcs-common/evidence/sms.rb +91 -0
  57. data/lib/rcs-common/evidence/url.rb +133 -0
  58. data/lib/rcs-common/fixnum.rb +48 -0
  59. data/lib/rcs-common/gridfs.rb +294 -0
  60. data/lib/rcs-common/heartbeat.rb +96 -0
  61. data/lib/rcs-common/keywords.rb +50 -0
  62. data/lib/rcs-common/mime.rb +65 -0
  63. data/lib/rcs-common/mongoid.rb +19 -0
  64. data/lib/rcs-common/pascalize.rb +62 -0
  65. data/lib/rcs-common/path_utils.rb +67 -0
  66. data/lib/rcs-common/resolver.rb +40 -0
  67. data/lib/rcs-common/rest.rb +17 -0
  68. data/lib/rcs-common/sanitize.rb +42 -0
  69. data/lib/rcs-common/serializer.rb +404 -0
  70. data/lib/rcs-common/signature.rb +141 -0
  71. data/lib/rcs-common/stats.rb +94 -0
  72. data/lib/rcs-common/symbolize.rb +10 -0
  73. data/lib/rcs-common/systemstatus.rb +136 -0
  74. data/lib/rcs-common/temporary.rb +13 -0
  75. data/lib/rcs-common/time.rb +24 -0
  76. data/lib/rcs-common/trace.rb +138 -0
  77. data/lib/rcs-common/trace.yaml +42 -0
  78. data/lib/rcs-common/updater/client.rb +354 -0
  79. data/lib/rcs-common/updater/dsl.rb +178 -0
  80. data/lib/rcs-common/updater/payload.rb +79 -0
  81. data/lib/rcs-common/updater/server.rb +126 -0
  82. data/lib/rcs-common/updater/shared_key.rb +55 -0
  83. data/lib/rcs-common/updater/tmp_dir.rb +13 -0
  84. data/lib/rcs-common/utf16le.rb +83 -0
  85. data/lib/rcs-common/version.rb +5 -0
  86. data/lib/rcs-common/winfirewall.rb +235 -0
  87. data/rcs-common.gemspec +64 -0
  88. data/spec/gridfs_spec.rb +637 -0
  89. data/spec/mongoid.yaml +6 -0
  90. data/spec/signature_spec.rb +105 -0
  91. data/spec/spec_helper.rb +22 -0
  92. data/spec/updater_spec.rb +80 -0
  93. data/tasks/deploy.rake +21 -0
  94. data/tasks/protect.rake +90 -0
  95. data/test/helper.rb +17 -0
  96. data/test/test_binary.rb +107 -0
  97. data/test/test_cgi.rb +14 -0
  98. data/test/test_crypt.rb +125 -0
  99. data/test/test_evidence.rb +52 -0
  100. data/test/test_evidence_manager.rb +119 -0
  101. data/test/test_fixnum.rb +35 -0
  102. data/test/test_keywords.rb +137 -0
  103. data/test/test_mime.rb +49 -0
  104. data/test/test_pascalize.rb +100 -0
  105. data/test/test_path_utils.rb +24 -0
  106. data/test/test_rcs-common.rb +7 -0
  107. data/test/test_sanitize.rb +40 -0
  108. data/test/test_serialization.rb +20 -0
  109. data/test/test_stats.rb +90 -0
  110. data/test/test_symbolize.rb +20 -0
  111. data/test/test_systemstatus.rb +35 -0
  112. data/test/test_time.rb +56 -0
  113. data/test/test_trace.rb +25 -0
  114. data/test/test_utf16le.rb +71 -0
  115. data/test/test_winfirewall.rb +68 -0
  116. metadata +423 -0
@@ -0,0 +1,94 @@
1
+ #
2
+ # Class to keep statistics by minute, hour, day, week and so on...
3
+ # to be subclassed and customized
4
+ #
5
+
6
+ module RCS
7
+
8
+ class Stats
9
+
10
+ def initialize
11
+ @stats = {}
12
+
13
+ # the template can be provided by the subclass
14
+ @template ||= Hash.new(0)
15
+
16
+ # total statistics ever
17
+ @stats[:total] = @template.dup
18
+
19
+ # remember the time when the total count was started
20
+ @stats[:total][:start] = Time.now.getutc
21
+
22
+ # sections to keep stats for
23
+ # the values are the tipping point
24
+ @sections ||= {:minutes => 0, :hours => 60, :days => 24, :weeks => 7}
25
+
26
+ # create the templates for each section
27
+ @sections.each_key do |section|
28
+ @stats[section] = {}
29
+ @stats[section][:last] = Array.new(5) { @template.dup }
30
+ @stats[section][:average] = @template.dup
31
+ @stats[section][:average][:samples] = 0
32
+ end
33
+
34
+ end
35
+
36
+ def stats(section = nil)
37
+ section ? @stats[section] : @stats
38
+ end
39
+
40
+ def add(hash)
41
+ # for each key sum up the counters in the total and in the current minute
42
+ hash.each_pair do |k, v|
43
+ next if @stats[:total][k].nil? or v.nil?
44
+ @stats[:total][k] += v
45
+ @sections.keys.each do |section|
46
+ add_to_section section, k, v
47
+ end
48
+ end
49
+ end
50
+
51
+ def add_to_section(section, k, v)
52
+ @stats[section][:last][0][k] ||= 0
53
+ @stats[section][:last][0][k] += v
54
+ end
55
+
56
+ def calculate
57
+ calculate_section @sections.keys.first
58
+
59
+ # each value in the @sections is the number of element of the previous section
60
+ # needed to form the current section
61
+ @sections.keys.each_with_index do |section, index|
62
+ calculate_section(section) if sample_limit(index)
63
+ end
64
+ end
65
+
66
+ def calculate_section(section)
67
+ # calculate the average for this section
68
+ @stats[section][:last].first.each_pair do |k, v|
69
+ @stats[section][:average][k] = ((@stats[section][:average][k].to_f * @stats[section][:average][:samples] + v) / (@stats[section][:average][:samples] + 1)).round(2)
70
+ end
71
+ @stats[section][:average][:samples] += 1
72
+ # initialize a new element for the current section
73
+ @stats[section][:last].insert(0, @template.dup)
74
+ # remove the last one
75
+ @stats[section][:last].pop
76
+ end
77
+
78
+ def sample_limit(index)
79
+ # tipping point of 0 means never tip
80
+ return false if @sections[@sections.keys[index]] == 0
81
+
82
+ # all the previous must be on the tipping point
83
+ values = []
84
+ index.downto(1) do |i|
85
+ prev = @sections.keys[i - 1]
86
+ values[i] = @stats[prev][:average][:samples] != 0 && @stats[prev][:average][:samples] % @sections[@sections.keys[i]] == 0
87
+ end
88
+
89
+ values.compact.inject(:&)
90
+ end
91
+
92
+ end
93
+
94
+ end #RCS
@@ -0,0 +1,10 @@
1
+ # here we are re-opening the ruby Hash class,
2
+ # the namespace must not be specified
3
+
4
+ class Hash
5
+
6
+ def symbolize
7
+ self.inject({}){|out,(k,v)| out[(k.class.eql? String) ? k.to_sym : k] = v; out}
8
+ end
9
+
10
+ end
@@ -0,0 +1,136 @@
1
+ require 'sys/filesystem'
2
+ require 'sys/cpu'
3
+
4
+ include Sys
5
+
6
+ module RCS
7
+ module SystemStatusCodes
8
+ OK = "OK"
9
+ WARN = "WARN"
10
+ ERROR = "ERROR"
11
+ end
12
+
13
+ module SystemStatusMixin
14
+ def self.included(base)
15
+ base.extend(ClassMethods)
16
+ end
17
+
18
+ module ClassMethods
19
+ def change_status(*args); SystemStatus.set(*args); end
20
+ end
21
+
22
+ def change_status(*args); SystemStatus.set(*args); end
23
+ end
24
+
25
+ # Status of the process and system
26
+ class SystemStatus
27
+ include SystemStatusCodes
28
+
29
+ DEFAULT = {status: OK, message: "Idle"}
30
+
31
+ @@prev_cpu = {}
32
+ @@prev_time = {}
33
+ @@current = DEFAULT
34
+ @@windowsOS = RUBY_PLATFORM.downcase.include?("mingw")
35
+ @@filesystem_stat_path = nil
36
+
37
+ def self.reset
38
+ @@current = DEFAULT
39
+ end
40
+
41
+ def self.set(status, message)
42
+ @@current = {status: status.to_s.upcase, message: message}
43
+ end
44
+
45
+ def self.status
46
+ @@current[:status]
47
+ end
48
+
49
+ def self.message
50
+ @@current[:message]
51
+ end
52
+
53
+ def self.windows?
54
+ @@windowsOS
55
+ end
56
+
57
+ def self.filesystem_stat(path)
58
+ Filesystem.stat(path) rescue nil
59
+ end
60
+
61
+ def self.filesystem_stat_path
62
+ return @@filesystem_stat_path if @@filesystem_stat_path
63
+
64
+ pwd = Dir.pwd
65
+
66
+ if !windows?
67
+ return @@filesystem_stat_path = pwd
68
+ end
69
+
70
+ loop do
71
+ stat = filesystem_stat(pwd+"\\")
72
+ return @@filesystem_stat_path = stat.path if stat
73
+ pwd = File.dirname(pwd.gsub('\\', '/')).gsub('/', '\\')
74
+ raise "Unable to find a valid mount point" if pwd == "."
75
+ end
76
+ end
77
+
78
+ # returns the percentage of free space
79
+ def self.disk_free
80
+ stat = Filesystem.stat(filesystem_stat_path)
81
+ # get the free and total blocks
82
+ free = stat.blocks_free.to_f
83
+ total = stat.blocks.to_f
84
+ # return the percentage (pessimistic)
85
+ return (free / total * 100).floor
86
+ end
87
+
88
+ # returns an indicator of the CPU usage in the last minute
89
+ # not exactly the CPU usage percentage, but very close to it
90
+ def self.cpu_load
91
+ # cpu load in the last minute
92
+ avg = CPU.load_avg
93
+ if avg.is_a? Array
94
+ # under unix like, there are 3 values (1, 15 and 15 minutes)
95
+ load_last_minute = avg.first
96
+ # default values for systems where the number is not reported (linux)
97
+ num_cpu = 1
98
+ num_cpu = CPU.num_cpu if CPU.num_cpu
99
+ # on multi core systems we have to divide by the number of CPUs
100
+ percentage = (load_last_minute / num_cpu * 100).floor
101
+ else
102
+ # under windows there is only one value that is the percentage
103
+ percentage = avg
104
+ # sometimes it returns nil under windows
105
+ percentage ||= 0
106
+ end
107
+
108
+ return percentage
109
+ end
110
+
111
+ # returns the CPU usage of the current process
112
+ def self.my_cpu_load(me)
113
+
114
+ # the first call to it, keep track of different thread calling the method
115
+ @@prev_cpu[me] ||= Process.times
116
+ @@prev_time[me] ||= Time.now
117
+
118
+ # calculate the current cpu time
119
+ current_cpu = Process.times
120
+
121
+ # diff them and divide by the call interval
122
+ cpu_time = (current_cpu.utime + current_cpu.stime) - (@@prev_cpu[me].utime + @@prev_cpu[me].stime)
123
+ time_diff = Time.now - @@prev_time[me]
124
+ # prevent division by zero on low res systems
125
+ time_diff = (time_diff == 0) ? 1 : time_diff
126
+ # calculate the percentage
127
+ cpu_percent = cpu_time / time_diff
128
+
129
+ # remember it for the next iteration
130
+ @@prev_cpu[me] = Process.times
131
+ @@prev_time[me] = Time.now
132
+
133
+ return cpu_percent.ceil
134
+ end
135
+ end
136
+ end
@@ -0,0 +1,13 @@
1
+
2
+ module RCS
3
+
4
+ class Temporary
5
+ def self.file(dir, filename)
6
+ Dir.mkdir(dir) unless Dir.exists? dir
7
+ tempfilename = File.join(dir, filename)
8
+ f = File.new(tempfilename, 'wb+')
9
+ return f
10
+ end
11
+ end
12
+
13
+ end # ::RCS
@@ -0,0 +1,24 @@
1
+ #
2
+ # Helper methods for decoding Windows FILETIME structs.
3
+ #
4
+
5
+ class Time
6
+ # Convert the time to the FILETIME format, a 64-bit value representing the
7
+ # number of 100-nanosecond intervals since January 1, 1601 (UTC).
8
+ def to_filetime
9
+ t = self.to_f + 11644473600
10
+ t *= 10000000
11
+ t = t.to_i
12
+ return (t & 0xFFFFFFFF), (t & 0xFFFFFFFF00000000) >> 32
13
+ end
14
+
15
+ # Create a time object from the FILETIME format, a 64-bit value representing
16
+ # the number of 100-nanosecond intervals since January 1, 1601 (UTC).
17
+ def self.from_filetime(high, low)
18
+ wtime = Float((high << 32) | low)
19
+ unix_hundreds_nanosec = wtime - 116_444_736_000_000_000
20
+ seconds_with_frac = unix_hundreds_nanosec / 10_000_000
21
+
22
+ return Time.at(seconds_with_frac).getutc
23
+ end
24
+ end
@@ -0,0 +1,138 @@
1
+ #
2
+ # The logging module
3
+ #
4
+
5
+ # System
6
+ require 'log4r'
7
+ require 'log4r/yamlconfigurator'
8
+ require 'log4r/outputter/datefileoutputter'
9
+
10
+ module RCS
11
+ module Tracer
12
+ include Log4r
13
+
14
+ TRACE_YAML_NAME = 'trace.yaml'
15
+
16
+ # Ensures that the log directories exists
17
+ def trace_ensure_log_folders
18
+ pwd = File.expand_path(Dir.pwd)
19
+
20
+ ["#{pwd}/log", "#{pwd}/log/err"].each do |path|
21
+ Dir.mkdir(path) unless File.directory?(path)
22
+ end
23
+ end
24
+
25
+ def trace_setup
26
+ pwd = File.expand_path(Dir.pwd)
27
+
28
+ raise "FATAL: Invalid execution directory." unless File.directory?("#{pwd}/lib")
29
+
30
+ trace_file_path = File.exist?(TRACE_YAML_NAME) ? TRACE_YAML_NAME : "#{pwd}/config/#{TRACE_YAML_NAME}"
31
+ raise "FATAL: Unable to find #{TRACE_YAML_NAME} file" unless File.exist?(trace_file_path)
32
+
33
+ trace_ensure_log_folders
34
+
35
+ trace_cfg = YamlConfigurator
36
+
37
+ # the only parameter in the YAML, our HOME directory
38
+ trace_cfg['HOME'] = pwd
39
+
40
+ # load the YAML file with this
41
+ trace_cfg.load_yaml_file(trace_file_path)
42
+ rescue Exception => ex
43
+ raise "FATAL: Unable to load #{TRACE_YAML_NAME}: #{ex.message}"
44
+ end
45
+
46
+ # needed to initialize the trace subsystem.
47
+ # the path provided is the path where the 'trace.yaml' resides
48
+ # the configuration inside the yaml can be changed at will
49
+ # and the trace system will reflect it
50
+ #
51
+ # @deprecated Please use {#trace_setup} instead
52
+ def trace_init(path = '.', file = 'trace.yaml')
53
+ # the configuration file is YAML
54
+ # the file must be called trace.yaml and put in the working directory
55
+ # of the module that wants to use the 'trace' function
56
+ trace_cfg = YamlConfigurator
57
+
58
+ # the only parameter in the YAML, our HOME directory
59
+ trace_cfg['HOME'] = path
60
+
61
+ # load the YAML file with this
62
+ begin
63
+ trace_cfg.load_yaml_file(file)
64
+ rescue
65
+ raise "FATAL: cannot find trace.yaml file. aborting."
66
+ end
67
+
68
+ end
69
+
70
+ # http://log4r.rubyforge.org/manual.html#ndc
71
+ def trace_nested_push(msg)
72
+ # push the context
73
+ # the %x tag should appear in the YAML file if you want to see this traces
74
+ NDC.push(msg)
75
+ end
76
+
77
+ def trace_nested_pop
78
+ # pop the last context
79
+ NDC.pop
80
+ end
81
+
82
+ # http://log4r.rubyforge.org/manual.html#mdc
83
+ def trace_named_put(name, msg)
84
+ # create the named context
85
+ # the %X{name} tag should appear in the YAML file if you want to see this traces
86
+ MDC.put(name, msg)
87
+ end
88
+
89
+ def trace_named_remove(name)
90
+ # remove the specified context
91
+ MDC.remove(name)
92
+ end
93
+
94
+ def thread_name
95
+ (Thread.current[:name] || Thread.current.object_id.to_s(32)).to_s
96
+ end
97
+
98
+ # the actual method used to output a trace
99
+ def trace(level, msg)
100
+ thread_info = "[Thread:#{thread_name}] " if ENV['TRACE_SHOW_THREAD_NAME']
101
+ msg = "#{thread_info}#{msg}"
102
+
103
+ log = Logger['rcslogger']
104
+ log.send(level, "#{msg}") unless log.nil?
105
+
106
+ # fallback if the logger is not initialized
107
+ puts "#{Time.now} [#{level.to_s.upcase}]: #{msg}" if log.nil? and not ENV['no_trace']
108
+ end
109
+
110
+ end # Tracer::
111
+ end # RCS::
112
+
113
+ if __FILE__ == $0
114
+ include RCS::Tracer
115
+
116
+ trace_init Dir.pwd
117
+
118
+ [:debug, :info, :warn, :error, :fatal].each do |level|
119
+ trace level, "this is a test"
120
+ end
121
+
122
+ trace_nested_push("level1")
123
+ trace :info, "test string"
124
+
125
+ trace_nested_push("level2")
126
+ trace :info, "test string"
127
+
128
+ trace_nested_pop
129
+ trace_nested_pop
130
+ trace :info, "test string"
131
+
132
+ trace_named_put(:test, "named tag")
133
+ trace :info, "test string"
134
+
135
+ trace_named_remove(:test)
136
+ trace :info, "test string"
137
+
138
+ end
@@ -0,0 +1,42 @@
1
+
2
+ # *** YAML2LOG4R ***
3
+ log4r_config:
4
+ # define all pre config ...
5
+ pre_config:
6
+ global:
7
+ level: DEBUG
8
+ root :
9
+ level: DEBUG
10
+
11
+ # define all loggers ...
12
+ loggers:
13
+ - name : rcslogger
14
+ level : DEBUG
15
+ additive : 'false'
16
+ trace : 'false'
17
+ outputters:
18
+ - stderr
19
+ # - logfile
20
+
21
+ # define all outputters (incl. formatters)
22
+ outputters:
23
+ - type : StderrOutputter
24
+ name : stderr
25
+ level : DEBUG
26
+ formatter:
27
+ # take a look at this: http://log4r.rubyforge.org/rdoc/Log4r/PatternFormatter.html
28
+ date_pattern: '%Y-%m-%d %H:%M:%S'
29
+ pattern : '%d [%l]: %X{:test} %x\t %m '
30
+ type : PatternFormatter
31
+
32
+ # - type : DateFileOutputter
33
+ # name : logfile
34
+ # level : DEBUG
35
+ # date_pattern: '%Y-%m-%d'
36
+ # trunc : 'false'
37
+ # dirname : "#{HOME}/logs"
38
+ # formatter :
39
+ # date_pattern: '%Y-%m-%d %H:%M:%S'
40
+ # pattern : '%d [%l]: %x %m'
41
+ # type : PatternFormatter
42
+