passivedns-client 1.0.1 → 1.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/README.md +3 -3
- data/bin/pdnstool +3 -3
- data/lib/passivedns/client/{isc.rb → dnsdb.rb} +9 -9
- data/lib/passivedns/client/version.rb +1 -1
- data/lib/passivedns/client.rb +5 -3
- data/test/test_passivedns-client.rb +5 -5
- data.tar.gz.sig +0 -0
- metadata +118 -120
- metadata.gz.sig +2 -1
data/README.md
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
# PassiveDNS::Client
|
2
2
|
|
3
|
-
This rubygem queries 5 major Passive DNS databases: BFK, CERTEE, DNSParse,
|
3
|
+
This rubygem queries 5 major Passive DNS databases: BFK, CERTEE, DNSParse, DNSDB, and VirusTotal.
|
4
4
|
Passive DNS is a technique where IP to hostname mappings are made by recording the answers of other people's queries.
|
5
5
|
|
6
6
|
There is a tool included, pdnstool, that wraps a lot of the functionality that you would need.
|
@@ -27,7 +27,7 @@ Or install it yourself as:
|
|
27
27
|
|
28
28
|
require 'passivedns-client'
|
29
29
|
|
30
|
-
c = PassiveDNS::Client.new(['bfk','
|
30
|
+
c = PassiveDNS::Client.new(['bfk','dnsdb']) # providers: bfk, dnsparse, certee, dnsdb, virustotal
|
31
31
|
results = c.query("example.com")
|
32
32
|
|
33
33
|
Or use the included tool!
|
@@ -37,7 +37,7 @@ Or use the included tool!
|
|
37
37
|
-b only use BFK
|
38
38
|
-e only use CERT-EE
|
39
39
|
-d only use DNSParse (default)
|
40
|
-
-i only use ISC
|
40
|
+
-i only use DNSDB (formerly ISC)
|
41
41
|
-V only use VirusTotal
|
42
42
|
|
43
43
|
-g outputs a link-nodal GDF visualization definition
|
data/bin/pdnstool
CHANGED
@@ -55,7 +55,7 @@ require 'yaml'
|
|
55
55
|
puts " -b only use BFK"
|
56
56
|
puts " -e only use CERT-EE"
|
57
57
|
puts " -d only use DNSParse (default)"
|
58
|
-
puts " -i only use ISC"
|
58
|
+
puts " -i only use DNSDB (formerly ISC)"
|
59
59
|
puts " -V only use VirusTotal"
|
60
60
|
puts ""
|
61
61
|
puts " -g outputs a link-nodal GDF visualization definition"
|
@@ -121,7 +121,7 @@ require 'yaml'
|
|
121
121
|
pdnsdbs << "bfk"
|
122
122
|
pdnsdbs << "certee"
|
123
123
|
pdnsdbs << "dnsparse"
|
124
|
-
pdnsdbs << "
|
124
|
+
pdnsdbs << "dnsdb"
|
125
125
|
pdnsdbs << "virustotal"
|
126
126
|
when '--bfk'
|
127
127
|
pdnsdbs << "bfk"
|
@@ -130,7 +130,7 @@ require 'yaml'
|
|
130
130
|
when '--dnsparse'
|
131
131
|
pdnsdbs << "dnsparse"
|
132
132
|
when '--isc'
|
133
|
-
pdnsdbs << "
|
133
|
+
pdnsdbs << "dnsdb"
|
134
134
|
when '--virustotal'
|
135
135
|
pdnsdbs << "virustotal"
|
136
136
|
when '--gdf'
|
@@ -1,13 +1,13 @@
|
|
1
|
-
# DESCRIPTION: this is a module for pdns.rb, primarily used by pdnstool.rb, to query the
|
1
|
+
# DESCRIPTION: this is a module for pdns.rb, primarily used by pdnstool.rb, to query the Farsight Security passive DNS database
|
2
2
|
# details on the API are at https://dnsdb.isc.org/doc/isc-dnsdb-api.html
|
3
3
|
# to request an API key, please email dnsdb@isc.org
|
4
4
|
require 'net/http'
|
5
5
|
require 'net/https'
|
6
6
|
|
7
7
|
module PassiveDNS
|
8
|
-
class
|
8
|
+
class DNSDB
|
9
9
|
attr_accessor :debug
|
10
|
-
@@base="https://
|
10
|
+
@@base="https://api.dnsdb.info/lookup"
|
11
11
|
|
12
12
|
def initialize(config="#{ENV['HOME']}/.isc-dnsdb-query.conf")
|
13
13
|
@debug = false
|
@@ -21,7 +21,7 @@ module PassiveDNS
|
|
21
21
|
raise "Format of configuration file (default: #{ENV['HOME']}/.isc-dnsdb-query.conf) is:\nAPIKEY=\"<key>\"\nE.g.,\nAPIKEY=\"d41d8cd98f00b204e9800998ecf8427ed41d8cd98f00b204e9800998ecf8427e\"\n"
|
22
22
|
end
|
23
23
|
else
|
24
|
-
raise "Configuration file for
|
24
|
+
raise "Configuration file for DNSDB is required for intialization\nFormat of configuration file (default: #{ENV['HOME']}/.isc-dnsdb-query.conf) is:\nAPIKEY=\"<key>\"\nE.g.,\nAPIKEY=\"d41d8cd98f00b204e9800998ecf8427ed41d8cd98f00b204e9800998ecf8427e\"\n"
|
25
25
|
end
|
26
26
|
end
|
27
27
|
|
@@ -35,21 +35,21 @@ module PassiveDNS
|
|
35
35
|
record['rdata'] = [record['rdata']] if record['rdata'].class == String
|
36
36
|
record['rdata'].each do |rdata|
|
37
37
|
if record['time_first']
|
38
|
-
res << PDNSResult.new('
|
38
|
+
res << PDNSResult.new('DNSDB',response_time,record['rrname'],rdata,record['rrtype'],0,Time.at(record['time_first'].to_i).utc.strftime("%Y-%m-%dT%H:%M:%SZ"),Time.at(record['time_last'].to_i).utc.strftime("%Y-%m-%dT%H:%M:%SZ"),record['count'])
|
39
39
|
else
|
40
|
-
res << PDNSResult.new('
|
40
|
+
res << PDNSResult.new('DNSDB',response_time,record['rrname'],rdata,record['rrtype'])
|
41
41
|
end
|
42
42
|
end
|
43
43
|
end
|
44
44
|
res
|
45
45
|
rescue Exception => e
|
46
|
-
$stderr.puts "
|
46
|
+
$stderr.puts "DNSDB Exception: #{e}"
|
47
47
|
$stderr.puts page
|
48
48
|
raise e
|
49
49
|
end
|
50
50
|
|
51
51
|
def lookup(label)
|
52
|
-
$stderr.puts "DEBUG:
|
52
|
+
$stderr.puts "DEBUG: DNSDB.lookup(#{label})" if @debug
|
53
53
|
Timeout::timeout(240) {
|
54
54
|
url = nil
|
55
55
|
if label =~ /^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}(\/\d{1,2})?$/
|
@@ -74,7 +74,7 @@ module PassiveDNS
|
|
74
74
|
parse_json(response.body,t2-t1)
|
75
75
|
}
|
76
76
|
rescue Timeout::Error => e
|
77
|
-
$stderr.puts "
|
77
|
+
$stderr.puts "DNSDB lookup timed out: #{label}"
|
78
78
|
end
|
79
79
|
end
|
80
80
|
end
|
data/lib/passivedns/client.rb
CHANGED
@@ -6,7 +6,7 @@ require "passivedns/client/version"
|
|
6
6
|
require 'passivedns/client/bfk.rb'
|
7
7
|
require 'passivedns/client/certee.rb'
|
8
8
|
require 'passivedns/client/dnsparse.rb'
|
9
|
-
require 'passivedns/client/
|
9
|
+
require 'passivedns/client/dnsdb.rb'
|
10
10
|
require 'passivedns/client/virustotal.rb'
|
11
11
|
require 'passivedns/client/state.rb'
|
12
12
|
|
@@ -15,7 +15,7 @@ module PassiveDNS
|
|
15
15
|
class PDNSResult < Struct.new(:source, :response_time, :query, :answer, :rrtype, :ttl, :firstseen, :lastseen, :count); end
|
16
16
|
|
17
17
|
class Client
|
18
|
-
def initialize(pdns=['bfk','certee','dnsparse','
|
18
|
+
def initialize(pdns=['bfk','certee','dnsparse','dnsdb','virustotal'])
|
19
19
|
@pdnsdbs = []
|
20
20
|
pdns.uniq.each do |pd|
|
21
21
|
case pd
|
@@ -25,8 +25,10 @@ module PassiveDNS
|
|
25
25
|
@pdnsdbs << PassiveDNS::CERTEE.new
|
26
26
|
when 'dnsparse'
|
27
27
|
@pdnsdbs << PassiveDNS::DNSParse.new
|
28
|
+
when 'dnsdb'
|
29
|
+
@pdnsdbs << PassiveDNS::DNSDB.new
|
28
30
|
when 'isc'
|
29
|
-
@pdnsdbs << PassiveDNS::
|
31
|
+
@pdnsdbs << PassiveDNS::DNSDB.new
|
30
32
|
when 'virustotal'
|
31
33
|
@pdnsdbs << PassiveDNS::VirusTotal.new
|
32
34
|
else
|
@@ -36,10 +36,10 @@ class TestPassiveDnsQuery < Test::Unit::TestCase
|
|
36
36
|
end
|
37
37
|
end
|
38
38
|
|
39
|
-
def
|
40
|
-
assert_not_nil(PassiveDNS::
|
39
|
+
def test_instantiate_DNSDB_Client
|
40
|
+
assert_not_nil(PassiveDNS::DNSDB.new)
|
41
41
|
assert_nothing_raised do
|
42
|
-
PassiveDNS::Client.new(['
|
42
|
+
PassiveDNS::Client.new(['dnsdb'])
|
43
43
|
end
|
44
44
|
end
|
45
45
|
|
@@ -97,8 +97,8 @@ class TestPassiveDnsQuery < Test::Unit::TestCase
|
|
97
97
|
assert_not_nil(rows.to_yaml)
|
98
98
|
end
|
99
99
|
|
100
|
-
def
|
101
|
-
rows = PassiveDNS::
|
100
|
+
def test_query_DNSDB
|
101
|
+
rows = PassiveDNS::DNSDB.new.lookup("example.org")
|
102
102
|
assert_not_nil(rows)
|
103
103
|
assert_not_nil(rows.to_s)
|
104
104
|
assert_not_nil(rows.to_xml)
|
data.tar.gz.sig
CHANGED
Binary file
|
metadata
CHANGED
@@ -1,135 +1,131 @@
|
|
1
|
-
--- !ruby/object:Gem::Specification
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
2
|
name: passivedns-client
|
3
|
-
version: !ruby/object:Gem::Version
|
4
|
-
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
hash: 19
|
5
5
|
prerelease:
|
6
|
+
segments:
|
7
|
+
- 1
|
8
|
+
- 1
|
9
|
+
- 0
|
10
|
+
version: 1.1.0
|
6
11
|
platform: ruby
|
7
|
-
authors:
|
12
|
+
authors:
|
8
13
|
- chrislee35
|
9
14
|
autorequire:
|
10
15
|
bindir: bin
|
11
|
-
cert_chain:
|
12
|
-
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
WStCNXFibwpqTFhNUXUyWmdJU1l3WE5qTmJHVkhlaHV0ODJVN1U5b2lIb1dj
|
39
|
-
ck9HYXphUlVtR085VFhQK2FKTEgwZ3cyZGNLCkFmTWdsWFBpCi0tLS0tRU5E
|
40
|
-
IENFUlRJRklDQVRFLS0tLS0K
|
41
|
-
date: 2013-06-02 00:00:00.000000000 Z
|
42
|
-
dependencies:
|
43
|
-
- !ruby/object:Gem::Dependency
|
16
|
+
cert_chain:
|
17
|
+
- |
|
18
|
+
-----BEGIN CERTIFICATE-----
|
19
|
+
MIIDYjCCAkqgAwIBAgIBADANBgkqhkiG9w0BAQUFADBXMREwDwYDVQQDDAhydWJ5
|
20
|
+
Z2VtczEYMBYGCgmSJomT8ixkARkWCGNocmlzbGVlMRMwEQYKCZImiZPyLGQBGRYD
|
21
|
+
ZGhzMRMwEQYKCZImiZPyLGQBGRYDb3JnMB4XDTEzMDUyMjEyNTk0N1oXDTE0MDUy
|
22
|
+
MjEyNTk0N1owVzERMA8GA1UEAwwIcnVieWdlbXMxGDAWBgoJkiaJk/IsZAEZFghj
|
23
|
+
aHJpc2xlZTETMBEGCgmSJomT8ixkARkWA2RoczETMBEGCgmSJomT8ixkARkWA29y
|
24
|
+
ZzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBANcPrx8BZiWIR9xWWG8I
|
25
|
+
tqR538tS1t+UJ4FZFl+1vrtU9TiuWX3Vj37TwUpa2fFkziK0n5KupVThyEhcem5m
|
26
|
+
OGRjvgrRFbWQJSSscIKOpwqURHVKRpV9gVz/Hnzk8S+xotUR1Buo3Ugr+I1jHewD
|
27
|
+
Cgr+y+zgZbtjtHsJtsuujkOcPhEjjUinj68L9Fz9BdeJQt+IacjwAzULix6jWCht
|
28
|
+
Uc+g+0z8Esryca2G6I1GsrgX6WHw8dykyQDT9dCtS2flCOwSC1R0K5T/xHW54f+5
|
29
|
+
wcw8mm53KLNe+tmgVC6ZHyME+qJsBnP6uxF0aTEnGA/jDBQDhQNTF0ZP/abzyTsL
|
30
|
+
zjUCAwEAAaM5MDcwCQYDVR0TBAIwADALBgNVHQ8EBAMCBLAwHQYDVR0OBBYEFO8w
|
31
|
+
+aeP7T6kVJblCg6eusOII9DfMA0GCSqGSIb3DQEBBQUAA4IBAQBCQyRJLXsBo2Fy
|
32
|
+
8W6e/W4RemQRrlAw9DK5O6U71JtedVob2oq+Ob+zmS+PifE2+L+3RiJ2H6VTlOzi
|
33
|
+
x+A061MUXhGraqVq4J2FC8kt4EQywAD0P0Ta5GU24CGSF08Y3GkJy1Sa4XqTC2YC
|
34
|
+
o51s7JP+tkCCtpVYSdzJhTllieRAWBpGV1dtaoeUKE6tYPMBkosxSRcVGczk/Sc3
|
35
|
+
7eQCpexYy9JlUBI9u3BqIY9E+l+MSn8ihXSPmyK0DgrhaCu+voaSFVOX6Y+B5qbo
|
36
|
+
jLXMQu2ZgISYwXNjNbGVHehut82U7U9oiHoWcrOGazaRUmGO9TXP+aJLH0gw2dcK
|
37
|
+
AfMglXPi
|
38
|
+
-----END CERTIFICATE-----
|
39
|
+
|
40
|
+
date: 2013-08-02 00:00:00 Z
|
41
|
+
dependencies:
|
42
|
+
- !ruby/object:Gem::Dependency
|
44
43
|
name: json
|
45
|
-
|
44
|
+
version_requirements: &id001 !ruby/object:Gem::Requirement
|
46
45
|
none: false
|
47
|
-
requirements:
|
48
|
-
- -
|
49
|
-
- !ruby/object:Gem::Version
|
46
|
+
requirements:
|
47
|
+
- - ">="
|
48
|
+
- !ruby/object:Gem::Version
|
49
|
+
hash: 1
|
50
|
+
segments:
|
51
|
+
- 1
|
52
|
+
- 4
|
53
|
+
- 3
|
50
54
|
version: 1.4.3
|
51
|
-
type: :runtime
|
52
55
|
prerelease: false
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
- - ! '>='
|
57
|
-
- !ruby/object:Gem::Version
|
58
|
-
version: 1.4.3
|
59
|
-
- !ruby/object:Gem::Dependency
|
56
|
+
type: :runtime
|
57
|
+
requirement: *id001
|
58
|
+
- !ruby/object:Gem::Dependency
|
60
59
|
name: sqlite3
|
61
|
-
|
60
|
+
version_requirements: &id002 !ruby/object:Gem::Requirement
|
62
61
|
none: false
|
63
|
-
requirements:
|
64
|
-
- -
|
65
|
-
- !ruby/object:Gem::Version
|
62
|
+
requirements:
|
63
|
+
- - ">="
|
64
|
+
- !ruby/object:Gem::Version
|
65
|
+
hash: 29
|
66
|
+
segments:
|
67
|
+
- 1
|
68
|
+
- 3
|
69
|
+
- 3
|
66
70
|
version: 1.3.3
|
67
|
-
type: :runtime
|
68
71
|
prerelease: false
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
- - ! '>='
|
73
|
-
- !ruby/object:Gem::Version
|
74
|
-
version: 1.3.3
|
75
|
-
- !ruby/object:Gem::Dependency
|
72
|
+
type: :runtime
|
73
|
+
requirement: *id002
|
74
|
+
- !ruby/object:Gem::Dependency
|
76
75
|
name: structformatter
|
77
|
-
|
76
|
+
version_requirements: &id003 !ruby/object:Gem::Requirement
|
78
77
|
none: false
|
79
|
-
requirements:
|
78
|
+
requirements:
|
80
79
|
- - ~>
|
81
|
-
- !ruby/object:Gem::Version
|
80
|
+
- !ruby/object:Gem::Version
|
81
|
+
hash: 29
|
82
|
+
segments:
|
83
|
+
- 0
|
84
|
+
- 0
|
85
|
+
- 1
|
82
86
|
version: 0.0.1
|
83
|
-
type: :runtime
|
84
87
|
prerelease: false
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
- - ~>
|
89
|
-
- !ruby/object:Gem::Version
|
90
|
-
version: 0.0.1
|
91
|
-
- !ruby/object:Gem::Dependency
|
88
|
+
type: :runtime
|
89
|
+
requirement: *id003
|
90
|
+
- !ruby/object:Gem::Dependency
|
92
91
|
name: bundler
|
93
|
-
|
92
|
+
version_requirements: &id004 !ruby/object:Gem::Requirement
|
94
93
|
none: false
|
95
|
-
requirements:
|
94
|
+
requirements:
|
96
95
|
- - ~>
|
97
|
-
- !ruby/object:Gem::Version
|
98
|
-
|
99
|
-
|
96
|
+
- !ruby/object:Gem::Version
|
97
|
+
hash: 9
|
98
|
+
segments:
|
99
|
+
- 1
|
100
|
+
- 3
|
101
|
+
version: "1.3"
|
100
102
|
prerelease: false
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
- - ~>
|
105
|
-
- !ruby/object:Gem::Version
|
106
|
-
version: '1.3'
|
107
|
-
- !ruby/object:Gem::Dependency
|
103
|
+
type: :development
|
104
|
+
requirement: *id004
|
105
|
+
- !ruby/object:Gem::Dependency
|
108
106
|
name: rake
|
109
|
-
|
107
|
+
version_requirements: &id005 !ruby/object:Gem::Requirement
|
110
108
|
none: false
|
111
|
-
requirements:
|
112
|
-
- -
|
113
|
-
- !ruby/object:Gem::Version
|
114
|
-
|
115
|
-
|
109
|
+
requirements:
|
110
|
+
- - ">="
|
111
|
+
- !ruby/object:Gem::Version
|
112
|
+
hash: 3
|
113
|
+
segments:
|
114
|
+
- 0
|
115
|
+
version: "0"
|
116
116
|
prerelease: false
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
- !ruby/object:Gem::Version
|
122
|
-
version: '0'
|
123
|
-
description: This provides interfaces to various passive DNS databases to do the query
|
124
|
-
and to normalize the responses. The query tool also allows for recursive queries,
|
125
|
-
using an SQLite3 database to keep state.
|
126
|
-
email:
|
117
|
+
type: :development
|
118
|
+
requirement: *id005
|
119
|
+
description: This provides interfaces to various passive DNS databases to do the query and to normalize the responses. The query tool also allows for recursive queries, using an SQLite3 database to keep state.
|
120
|
+
email:
|
127
121
|
- rubygems@chrislee.dhs.org
|
128
|
-
executables:
|
122
|
+
executables:
|
129
123
|
- pdnstool
|
130
124
|
extensions: []
|
125
|
+
|
131
126
|
extra_rdoc_files: []
|
132
|
-
|
127
|
+
|
128
|
+
files:
|
133
129
|
- .gitignore
|
134
130
|
- Gemfile
|
135
131
|
- LICENSE.txt
|
@@ -139,8 +135,8 @@ files:
|
|
139
135
|
- lib/passivedns/client.rb
|
140
136
|
- lib/passivedns/client/bfk.rb
|
141
137
|
- lib/passivedns/client/certee.rb
|
138
|
+
- lib/passivedns/client/dnsdb.rb
|
142
139
|
- lib/passivedns/client/dnsparse.rb
|
143
|
-
- lib/passivedns/client/isc.rb
|
144
140
|
- lib/passivedns/client/state.rb
|
145
141
|
- lib/passivedns/client/version.rb
|
146
142
|
- lib/passivedns/client/virustotal.rb
|
@@ -148,36 +144,38 @@ files:
|
|
148
144
|
- test/helper.rb
|
149
145
|
- test/test_passivedns-client.rb
|
150
146
|
homepage: https://github.com/chrislee35/passivedns-client
|
151
|
-
licenses:
|
147
|
+
licenses:
|
152
148
|
- MIT
|
153
149
|
post_install_message:
|
154
150
|
rdoc_options: []
|
155
|
-
|
151
|
+
|
152
|
+
require_paths:
|
156
153
|
- lib
|
157
|
-
required_ruby_version: !ruby/object:Gem::Requirement
|
154
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
158
155
|
none: false
|
159
|
-
requirements:
|
160
|
-
- -
|
161
|
-
- !ruby/object:Gem::Version
|
162
|
-
|
163
|
-
segments:
|
156
|
+
requirements:
|
157
|
+
- - ">="
|
158
|
+
- !ruby/object:Gem::Version
|
159
|
+
hash: 3
|
160
|
+
segments:
|
164
161
|
- 0
|
165
|
-
|
166
|
-
required_rubygems_version: !ruby/object:Gem::Requirement
|
162
|
+
version: "0"
|
163
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
167
164
|
none: false
|
168
|
-
requirements:
|
169
|
-
- -
|
170
|
-
- !ruby/object:Gem::Version
|
171
|
-
|
172
|
-
segments:
|
165
|
+
requirements:
|
166
|
+
- - ">="
|
167
|
+
- !ruby/object:Gem::Version
|
168
|
+
hash: 3
|
169
|
+
segments:
|
173
170
|
- 0
|
174
|
-
|
171
|
+
version: "0"
|
175
172
|
requirements: []
|
173
|
+
|
176
174
|
rubyforge_project:
|
177
175
|
rubygems_version: 1.8.25
|
178
176
|
signing_key:
|
179
177
|
specification_version: 3
|
180
178
|
summary: Query passive DNS databases
|
181
|
-
test_files:
|
179
|
+
test_files:
|
182
180
|
- test/helper.rb
|
183
181
|
- test/test_passivedns-client.rb
|
metadata.gz.sig
CHANGED
@@ -1 +1,2 @@
|
|
1
|
-
|
1
|
+
��S�5q�����4�Rv+����~5�l)��$��mڍ�s7�!A(�vb�6
|
2
|
+
@M�V���g}츇���!�mo+�-_�+��I��%�B=�����j� ��*�+6����"�'���T���=%ſ-{�C�0
|