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.
- 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,96 @@
|
|
|
1
|
+
require 'rcs-common/trace'
|
|
2
|
+
require 'rcs-common/systemstatus'
|
|
3
|
+
require 'socket'
|
|
4
|
+
|
|
5
|
+
module RCS::HeartBeat
|
|
6
|
+
class Base
|
|
7
|
+
extend RCS::Tracer
|
|
8
|
+
include RCS::Tracer
|
|
9
|
+
include RCS::SystemStatusCodes
|
|
10
|
+
|
|
11
|
+
# Declare the component
|
|
12
|
+
# To use as an helper in the subclasses
|
|
13
|
+
def self.component(component_name, component_fullname = nil)
|
|
14
|
+
@component_name = component_name
|
|
15
|
+
@component_fullname = component_fullname
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
# This method is called from outside
|
|
19
|
+
def self.perform
|
|
20
|
+
heartbeat = new(@component_name, component_fullname: @component_fullname)
|
|
21
|
+
status, message = *heartbeat.perform
|
|
22
|
+
if status
|
|
23
|
+
heartbeat.update(status, message)
|
|
24
|
+
else
|
|
25
|
+
# trace(:warn, "heartbeat prevented")
|
|
26
|
+
end
|
|
27
|
+
rescue Interrupt
|
|
28
|
+
trace :fatal, "Heartbeat was interrupted because of a term signal"
|
|
29
|
+
rescue Exception => ex
|
|
30
|
+
trace :fatal, "Cannot perform heartbeat: #{ex.message}"
|
|
31
|
+
trace :fatal, ex.backtrace
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
def initialize(component_name, component_fullname: nil)
|
|
36
|
+
raise("Undefined component version") unless version
|
|
37
|
+
raise("Undefined component name") unless component_name
|
|
38
|
+
|
|
39
|
+
@component_name = component_name.to_s.downcase
|
|
40
|
+
@component_fullname = component_fullname || "RCS::#{component_name.to_s.capitalize}"
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
def update(status, message)
|
|
44
|
+
system_status, system_message = *system_status_and_message
|
|
45
|
+
|
|
46
|
+
if status == OK and system_status != OK
|
|
47
|
+
status, message = system_status, system_message
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
attributes = [@component_fullname, hostname, status, message, machine_stats, @component_name, version]
|
|
51
|
+
|
|
52
|
+
if defined?(::Status)
|
|
53
|
+
# Db
|
|
54
|
+
::Status.status_update(*attributes)
|
|
55
|
+
else
|
|
56
|
+
# Collector
|
|
57
|
+
db_class = Object.const_get(@component_fullname)::DB
|
|
58
|
+
attributes[1] = ''
|
|
59
|
+
db_class.instance.update_status(*attributes)
|
|
60
|
+
end
|
|
61
|
+
ensure
|
|
62
|
+
reset_system_status_and_message
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
# Override this method
|
|
66
|
+
def perform
|
|
67
|
+
system_status_and_message
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
private
|
|
71
|
+
|
|
72
|
+
def hostname
|
|
73
|
+
@hostname ||= Socket.gethostname rescue 'unknown'
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
def reset_system_status_and_message
|
|
77
|
+
RCS::SystemStatus.reset
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
def system_status_and_message
|
|
81
|
+
[RCS::SystemStatus.status, RCS::SystemStatus.message]
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
def version
|
|
85
|
+
$version
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
def machine_stats
|
|
89
|
+
{
|
|
90
|
+
disk: RCS::SystemStatus.disk_free,
|
|
91
|
+
cpu: RCS::SystemStatus.cpu_load,
|
|
92
|
+
pcpu: RCS::SystemStatus.my_cpu_load(@component_fullname)
|
|
93
|
+
}
|
|
94
|
+
end
|
|
95
|
+
end
|
|
96
|
+
end
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
# encoding: utf-8
|
|
2
|
+
|
|
3
|
+
# here we are re-opening the ruby String class,
|
|
4
|
+
# the namespace must not be specified
|
|
5
|
+
|
|
6
|
+
require_relative 'sanitize'
|
|
7
|
+
|
|
8
|
+
class String
|
|
9
|
+
|
|
10
|
+
def keywords
|
|
11
|
+
|
|
12
|
+
# make a copy of itself to preserve the original
|
|
13
|
+
keywords = self.dup
|
|
14
|
+
|
|
15
|
+
# sanitize the input UTF-8
|
|
16
|
+
keywords.force_utf8!
|
|
17
|
+
|
|
18
|
+
# remove everything that is not alphanumeric
|
|
19
|
+
keywords.gsub!(/([^[:alnum:]])+/u, ' ')
|
|
20
|
+
#keywords.gsub!(/[(,%&@_":;!\#\-\*\[\]\{\}\?\\\+\'\.\/)]/, ' ')
|
|
21
|
+
|
|
22
|
+
# returns a copy of str with leading and trailing whitespace removed.
|
|
23
|
+
keywords.strip!
|
|
24
|
+
|
|
25
|
+
# convert to lowercase
|
|
26
|
+
keywords.downcase!
|
|
27
|
+
|
|
28
|
+
# split on spaces
|
|
29
|
+
keywords = keywords.split " "
|
|
30
|
+
|
|
31
|
+
# remove too long words
|
|
32
|
+
# it is with a very high probability a meaningless word (like encoded or something)
|
|
33
|
+
keywords.delete_if {|w| w.size > 25}
|
|
34
|
+
|
|
35
|
+
# remove duplicate words
|
|
36
|
+
keywords.uniq!
|
|
37
|
+
|
|
38
|
+
# sort the array
|
|
39
|
+
keywords.sort!
|
|
40
|
+
|
|
41
|
+
keywords
|
|
42
|
+
rescue Exception => e
|
|
43
|
+
#puts e.message if debug
|
|
44
|
+
#puts e.backtrace.first if debug
|
|
45
|
+
# fallback case
|
|
46
|
+
[]
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
end
|
|
50
|
+
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
#
|
|
2
|
+
# Mime Types handling module
|
|
3
|
+
#
|
|
4
|
+
|
|
5
|
+
# system
|
|
6
|
+
require 'mime/types'
|
|
7
|
+
|
|
8
|
+
# reopen the original class in order to add our specific mime types
|
|
9
|
+
module MIME
|
|
10
|
+
class Types
|
|
11
|
+
# rename the original method to be used in our wrapper
|
|
12
|
+
alias mime_type_for type_for
|
|
13
|
+
|
|
14
|
+
# our wrapper which adds our types
|
|
15
|
+
def type_for(filename, platform = false)
|
|
16
|
+
# call the original method
|
|
17
|
+
type = mime_type_for(filename, platform)
|
|
18
|
+
|
|
19
|
+
if type.empty? then
|
|
20
|
+
case File.extname(filename)
|
|
21
|
+
when '.cod'
|
|
22
|
+
type = MIME::Type.from_array('application/vnd.rim.cod', 'cod', '8bit', 'linux')
|
|
23
|
+
when '.apk'
|
|
24
|
+
type = MIME::Type.from_array('application/vnd.android.package-archive', 'apk', '8bit', 'linux')
|
|
25
|
+
when '.aetx'
|
|
26
|
+
type = MIME::Type.from_array('application/x-aetx', 'aetx', '8bit', 'linux')
|
|
27
|
+
when '.xap'
|
|
28
|
+
type = MIME::Type.from_array('application/x-silverlight-app', 'xap', '8bit', 'linux')
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
return type
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
module RCS
|
|
37
|
+
|
|
38
|
+
class MimeType
|
|
39
|
+
|
|
40
|
+
def self.get(file)
|
|
41
|
+
begin
|
|
42
|
+
# ask for the mime type
|
|
43
|
+
type = MIME::Types.type_for(file)
|
|
44
|
+
|
|
45
|
+
# if there are multiple choices, get the first one
|
|
46
|
+
type = type.first if type.is_a?(Array)
|
|
47
|
+
rescue Exception => e
|
|
48
|
+
type = nil
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
# special case for IE mobile not understanding this
|
|
52
|
+
if File.extname(file) == '.cab' then
|
|
53
|
+
type = MIME::Type.new('binary/octet-stream')
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
# default if none is found
|
|
57
|
+
type = MIME::Type.new('binary/octet-stream') if type.nil?
|
|
58
|
+
|
|
59
|
+
# convert from MIME::Type to String
|
|
60
|
+
return type.to_s
|
|
61
|
+
end
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
end #RCS::
|
|
65
|
+
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
require 'mongoid'
|
|
2
|
+
|
|
3
|
+
# Monkey path serialization of BSON::ObjectId
|
|
4
|
+
module BSON
|
|
5
|
+
class ObjectId
|
|
6
|
+
def as_json(*args)
|
|
7
|
+
to_s
|
|
8
|
+
end
|
|
9
|
+
end
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
# Fix #symbolize_key called on BSON::Document
|
|
13
|
+
module BSON
|
|
14
|
+
class Document < ::Hash
|
|
15
|
+
def symbolize_keys
|
|
16
|
+
to_h.symbolize_keys
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
end
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
# here we are re-opening the ruby String class,
|
|
2
|
+
# the namespace must not be specified
|
|
3
|
+
|
|
4
|
+
class String
|
|
5
|
+
|
|
6
|
+
# returns a string encoded into a pascalized form
|
|
7
|
+
def pascalize
|
|
8
|
+
# the pascalized version is composed as follow:
|
|
9
|
+
# - 4 bytes len in front
|
|
10
|
+
# - UTF-16LE encoded string
|
|
11
|
+
# - UTF-16LE null terminator
|
|
12
|
+
pascalized = [self.encode('UTF-16LE').bytesize + 2].pack('I')
|
|
13
|
+
pascalized += self.encode('UTF-16LE').unpack('H*').pack('H*')
|
|
14
|
+
pascalized += "\x00\x00"
|
|
15
|
+
|
|
16
|
+
# BINARY is an alias for ASCII-8BIT
|
|
17
|
+
return pascalized.encode!('ASCII-8BIT')
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
# returns a string decoded from its pascalized form
|
|
21
|
+
def unpascalize
|
|
22
|
+
begin
|
|
23
|
+
# get the len (unsigned int 4 bytes)
|
|
24
|
+
len = self.unpack('I')
|
|
25
|
+
# sanity check to avoid
|
|
26
|
+
return nil unless len.first <= self.length - 4
|
|
27
|
+
# get the string
|
|
28
|
+
unpascalized = self.slice(4, len.first).force_encoding('UTF-16LE')
|
|
29
|
+
# convert to UTF-8
|
|
30
|
+
unpascalized.encode!('UTF-8')
|
|
31
|
+
# remove the trailing zero
|
|
32
|
+
unpascalized.chop!
|
|
33
|
+
|
|
34
|
+
return unpascalized
|
|
35
|
+
rescue
|
|
36
|
+
return nil
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
# returns an array containing all the concatenated pascalized strings
|
|
41
|
+
def unpascalize_ary
|
|
42
|
+
many = []
|
|
43
|
+
buffer = self
|
|
44
|
+
len = 0
|
|
45
|
+
|
|
46
|
+
begin
|
|
47
|
+
# len of the current token
|
|
48
|
+
len += buffer.unpack('I').first + 4
|
|
49
|
+
# unpascalize the token
|
|
50
|
+
str = buffer.unpascalize
|
|
51
|
+
# add to the result array
|
|
52
|
+
many << str unless str.nil?
|
|
53
|
+
# move the pointer after the token
|
|
54
|
+
buffer = self.slice(len, self.length)
|
|
55
|
+
# sanity check
|
|
56
|
+
break if buffer.nil?
|
|
57
|
+
end while buffer.length != 0
|
|
58
|
+
|
|
59
|
+
return many
|
|
60
|
+
end
|
|
61
|
+
end
|
|
62
|
+
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
module RCS
|
|
2
|
+
module Common
|
|
3
|
+
module PathUtils
|
|
4
|
+
# Requires and rcs module. Sarch for a folder named rcs-NAME, where NAME is
|
|
5
|
+
# the given name, and requires a script named NAME.rb
|
|
6
|
+
#
|
|
7
|
+
# @note The current directory is changed (chdir command)
|
|
8
|
+
def require_component(name, opts = {})
|
|
9
|
+
$invocation_directory = Dir.pwd
|
|
10
|
+
$invocation_directory = ENV['CWD'] if ENV['CWD']
|
|
11
|
+
|
|
12
|
+
init_script = caller[0].scan(/^(.+)\:\d+\:.+$/)[0][0]
|
|
13
|
+
|
|
14
|
+
if init_script !~ /(bin|lib)\/rcs\-#{name}/
|
|
15
|
+
raise "Invalid execution directory"
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
$execution_directory = File.expand_path('../..', init_script)
|
|
19
|
+
|
|
20
|
+
#puts "WARN: chdir to #{$execution_directory}"
|
|
21
|
+
Dir.chdir($execution_directory)
|
|
22
|
+
|
|
23
|
+
require_release("#{$execution_directory}/lib/rcs-#{name}-release/#{name}.rb", warn: true)
|
|
24
|
+
|
|
25
|
+
rescue LoadError => error
|
|
26
|
+
puts "FATAL: cannot load component rcs-#{name}: #{error.message}"
|
|
27
|
+
puts error.backtrace.join(", ") if error.backtrace.respond_to?(:join)
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
# Requires an encrypted ruby script (rcs-XXX-releases folders) when
|
|
31
|
+
# available, otherwise requires the clean version of it (rcs-XXX folders)
|
|
32
|
+
def require_release(path, warn: false, required: true)
|
|
33
|
+
if path.include?("-release")
|
|
34
|
+
new_path = path
|
|
35
|
+
else
|
|
36
|
+
new_path = path.gsub(/(.*)rcs-([^\/]+)/, '\1rcs-\2-release')
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
if warn and !new_path.include?('-release') and File.exists?(new_path)
|
|
40
|
+
puts "WARNING: Executing clear text code... (debug only)"
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
begin
|
|
44
|
+
require(new_path)
|
|
45
|
+
return
|
|
46
|
+
rescue LoadError => error
|
|
47
|
+
# In this case, raise the LoadError only if it's caused
|
|
48
|
+
# by another #require inside the required script, otherwise
|
|
49
|
+
# go on and try to require the clean version
|
|
50
|
+
raise(error) if error.path != new_path
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
begin
|
|
54
|
+
new_path.gsub!('-release', '')
|
|
55
|
+
require(new_path)
|
|
56
|
+
rescue LoadError => error
|
|
57
|
+
raise(error) if required
|
|
58
|
+
end
|
|
59
|
+
end
|
|
60
|
+
end
|
|
61
|
+
end
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
unless Kernel.respond_to?(:require_release)
|
|
65
|
+
Kernel.__send__(:include, RCS::Common::PathUtils)
|
|
66
|
+
Object.__send__(:include, Kernel)
|
|
67
|
+
end
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
require 'resolv'
|
|
2
|
+
require 'timeout'
|
|
3
|
+
|
|
4
|
+
module RCS
|
|
5
|
+
module Resolver
|
|
6
|
+
def resolved_dns_cache
|
|
7
|
+
@@dns_cache ||= {}
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
def resolve_dns(dns, use_cache: false)
|
|
11
|
+
if use_cache and resolved_dns_cache[dns]
|
|
12
|
+
return resolved_dns_cache[dns]
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
ip = nil
|
|
16
|
+
|
|
17
|
+
Timeout::timeout(8) do
|
|
18
|
+
ip = Resolv.getaddress(dns).to_s rescue nil
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
if ip.nil? and defined?(Win32)
|
|
22
|
+
Timeout::timeout(10) do
|
|
23
|
+
info = Win32::Resolv.get_resolv_info
|
|
24
|
+
resolver = Resolv::DNS.new(nameserver: info[1], search: info[0])
|
|
25
|
+
ip = resolver.getaddress(dns).to_s rescue nil
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
raise("Cannot resolve DNS #{dns.inspect}: unknown host") unless ip
|
|
30
|
+
|
|
31
|
+
resolved_dns_cache[dns] = ip
|
|
32
|
+
|
|
33
|
+
return ip
|
|
34
|
+
rescue Timeout::Error
|
|
35
|
+
raise("Cannot resolve DNS #{dns.inspect}: timeout")
|
|
36
|
+
rescue Exception => ex
|
|
37
|
+
raise("Cannot resolve DNS #{dns.inspect}: #{ex.message}")
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
end
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
require 'rcs-common/trace'
|
|
2
|
+
|
|
3
|
+
module RCS
|
|
4
|
+
module Common
|
|
5
|
+
module Rest
|
|
6
|
+
STATUS_OK = 200
|
|
7
|
+
STATUS_REDIRECT = 302
|
|
8
|
+
STATUS_BAD_REQUEST = 400
|
|
9
|
+
STATUS_AUTH_REQUIRED = 401
|
|
10
|
+
STATUS_NOT_FOUND = 404
|
|
11
|
+
STATUS_NOT_AUTHORIZED = 403
|
|
12
|
+
STATUS_METHOD_NOT_ALLOWED = 405
|
|
13
|
+
STATUS_CONFLICT = 409
|
|
14
|
+
STATUS_SERVER_ERROR = 500
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
end
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
# encoding: utf-8
|
|
2
|
+
|
|
3
|
+
# here we are re-opening the ruby String class,
|
|
4
|
+
# the namespace must not be specified
|
|
5
|
+
|
|
6
|
+
class String
|
|
7
|
+
REMOVE_INVALID_CHARS_REGEXP = Regexp.new(/([^[:alnum:][:graph:]\n\r])+/u)
|
|
8
|
+
|
|
9
|
+
def remove_invalid_chars
|
|
10
|
+
self.force_utf8.gsub(REMOVE_INVALID_CHARS_REGEXP, ' ')
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def force_utf8(modify_self = false)
|
|
14
|
+
src_encoding = valid_encoding? ? encoding.to_s : 'BINARY'
|
|
15
|
+
dst_encoding = 'UTF-8'
|
|
16
|
+
|
|
17
|
+
args = [dst_encoding, src_encoding, {:invalid => :replace, :undef => :replace, replace: ''}]
|
|
18
|
+
|
|
19
|
+
modify_self ? encode!(*args) : encode(*args)
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def force_utf8!
|
|
23
|
+
force_utf8(true)
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def strip_html_tags
|
|
27
|
+
copy = self.dup
|
|
28
|
+
|
|
29
|
+
# Strip HTML tags
|
|
30
|
+
copy.gsub!(/<[^>]*>/, '')
|
|
31
|
+
|
|
32
|
+
# Strip encoded & repetitively encoded HTML tags
|
|
33
|
+
copy.gsub!(/&(amp;)*lt;.*?&(amp;)*gt;/im, '')
|
|
34
|
+
|
|
35
|
+
# Strip HTML entities and repetitively encoded entities
|
|
36
|
+
# Or decode with http://htmlentities.rubyforge.org/
|
|
37
|
+
copy.gsub!(/&(amp;)*((#x?)?[a-f0-9]+|[a-z]+);/i, ' ')
|
|
38
|
+
|
|
39
|
+
copy
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
end
|