exchange-offline-address-book 0.0.17 → 0.0.18
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 +4 -4
- data/Gemfile.lock +3 -1
- data/exchange-offline-address-book.gemspec +1 -0
- data/lib/exchange-offline-address-book.rb +68 -50
- data/lib/exchange-offline-address-book/parser.rb +6 -6
- data/lib/exchange-offline-address-book/version.rb +1 -1
- data/test/test_exchange-offline-address-book.rb +14 -10
- metadata +16 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: c55abcbbc07e7d39590701b7f2ec5709be800391
|
4
|
+
data.tar.gz: 3ab636736cfbc68dd0a59e1adc43773f5a4e91f6
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: fbc1e9847734ae88a8692439e50609e3b4942f598be4f541a5340e058c54641d133ffd56df926d8d7fc8f7220b0f72f7b6e4458e4aed76f38cd67d50dfb2a5ae
|
7
|
+
data.tar.gz: 896827f3141bf08128b62eacf10a90226f0de383f10e9497e4d49e8d1e3cd75de996dbe3bf311e0fc0799354d5e5c1e3f335dba02b362d70942944ce9c698dd0
|
data/Gemfile.lock
CHANGED
@@ -1,9 +1,10 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
exchange-offline-address-book (0.0.
|
4
|
+
exchange-offline-address-book (0.0.18)
|
5
5
|
autodiscover (~> 1)
|
6
6
|
curb (~> 0.9)
|
7
|
+
hashie
|
7
8
|
libmspack (~> 0.1)
|
8
9
|
nokogiri (~> 1.8)
|
9
10
|
|
@@ -23,6 +24,7 @@ GEM
|
|
23
24
|
ffi (>= 1.0.0)
|
24
25
|
rake
|
25
26
|
gem-release (1.0.0)
|
27
|
+
hashie (3.5.5)
|
26
28
|
httpclient (2.8.3)
|
27
29
|
libmspack (0.1.0)
|
28
30
|
ffi
|
@@ -7,14 +7,25 @@ require 'autodiscover'
|
|
7
7
|
require "autodiscover/debug" if ENV['DEBUG']
|
8
8
|
require 'yaml'
|
9
9
|
require 'nokogiri'
|
10
|
-
require 'tempfile'
|
11
10
|
require 'json'
|
12
|
-
require '
|
11
|
+
require 'hashie'
|
13
12
|
require 'shellwords'
|
13
|
+
require 'tmpdir'
|
14
14
|
|
15
15
|
require_relative 'exchange-offline-address-book/parser'
|
16
16
|
require_relative 'exchange-offline-address-book/mspack'
|
17
17
|
|
18
|
+
# https://github.com/intridea/hashie/pull/416
|
19
|
+
if Hashie::VERSION == '3.5.5'
|
20
|
+
module Hashie
|
21
|
+
class Mash
|
22
|
+
def self.disable_warnings?
|
23
|
+
@disable_warnings ||= false
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
18
29
|
class OfflineAddressBook
|
19
30
|
def initialize(email: nil, password: nil, username: nil, cachedir: nil, baseurl: nil, update: true)
|
20
31
|
@email = email
|
@@ -23,20 +34,16 @@ class OfflineAddressBook
|
|
23
34
|
@cachedir = cachedir
|
24
35
|
@update = update
|
25
36
|
@baseurl = baseurl
|
26
|
-
end
|
27
|
-
|
28
|
-
def path(name)
|
29
|
-
@files ||= {}
|
30
|
-
@files[name] ||= (@cachedir ? File.join(@cachedir, name) : Tempfile.new(name).path)
|
31
|
-
end
|
32
37
|
|
33
|
-
|
34
|
-
|
35
|
-
|
38
|
+
if cachedir
|
39
|
+
fetch_to(cachedir)
|
40
|
+
else
|
41
|
+
Dir.mktmpdir{|dir| fetch_to(dir) }
|
36
42
|
end
|
37
|
-
return path(name)
|
38
43
|
end
|
39
44
|
|
45
|
+
attr_reader :records
|
46
|
+
|
40
47
|
def baseurl
|
41
48
|
@baseurl ||= begin
|
42
49
|
client = Autodiscover::Client.new(email: @email, password: @password, username: @username)
|
@@ -46,59 +53,70 @@ class OfflineAddressBook
|
|
46
53
|
end
|
47
54
|
end
|
48
55
|
|
49
|
-
def
|
50
|
-
@
|
51
|
-
|
52
|
-
|
53
|
-
oab = Dir[File.join(@cachedir, '*.oab')][0]
|
54
|
-
lzx = File.basename(oab, File.extname(oab)) + '.lzx' if oab
|
55
|
-
end
|
56
|
+
def header
|
57
|
+
@parsed ||= Parser.new(addressbook)
|
58
|
+
@parsed.header
|
59
|
+
end
|
56
60
|
|
57
|
-
|
58
|
-
|
61
|
+
def fetch_to(dir)
|
62
|
+
begin
|
63
|
+
@dir = dir
|
59
64
|
|
60
|
-
if
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
}
|
65
|
-
end
|
65
|
+
if File.file?(cache)
|
66
|
+
@records = JSON.parse(open(cache).read, object_class: Hashie::Mash)
|
67
|
+
return
|
68
|
+
end
|
66
69
|
|
70
|
+
if !File.file?(addressbook)
|
71
|
+
%w{json oab lzx}.each{|ext|
|
72
|
+
Dir[File.join(@dir, "*.#{ext}")].each{|f| File.delete(f) }
|
73
|
+
}
|
74
|
+
lzx = File.basename(addressbook, File.extname(addressbook)) + '.lzx'
|
75
|
+
puts "OfflineAddressBook: Downloading #{lzx}" if ENV['DEBUG']
|
67
76
|
download(lzx)
|
68
|
-
|
77
|
+
puts "OfflineAddressBook: Decompressing #{lzx} to #{addressbook}" if ENV['DEBUG']
|
78
|
+
LibMsPack.oab_decompress(File.join(@dir, lzx), addressbook)
|
69
79
|
end
|
80
|
+
puts "OfflineAddressBook: Addressbook ready at #{addressbook}" if ENV['DEBUG']
|
70
81
|
|
71
|
-
|
82
|
+
parsed = Parser.new(addressbook)
|
83
|
+
@records = parsed.records.collect{|record|
|
84
|
+
record.to_h.each_pair{|k, v|
|
85
|
+
record[k] = v[0] if v.length == 1
|
86
|
+
}
|
87
|
+
# no idea what's going on here
|
88
|
+
record.AddressBookObjectGuid = record.AddressBookObjectGuid.inspect if record.AddressBookObjectGuid
|
89
|
+
record
|
90
|
+
}
|
91
|
+
open(cache, 'w'){|f| f.write(JSON.pretty_generate(@records.collect{|r| r.to_h}))} if @cachedir # this can ditch the collect with hashie
|
92
|
+
ensure
|
93
|
+
@dir = nil
|
72
94
|
end
|
73
95
|
end
|
74
96
|
|
75
|
-
|
76
|
-
@cache ||= path(File.basename(addressbook, File.extname(addressbook)) + '.json')
|
77
|
-
end
|
97
|
+
private
|
78
98
|
|
79
|
-
def
|
80
|
-
@
|
81
|
-
@
|
99
|
+
def download(name)
|
100
|
+
puts "curl --#{ENV['DEBUG'] ? 'verbose' : 'silent'} --ntlm --user #{[@username, @password].join(':').shellescape} #{[baseurl, name].join('').shellescape} -o #{File.join(@dir, name).shellescape}" if ENV['DEBUG']
|
101
|
+
system "curl --#{ENV['DEBUG'] ? 'verbose' : 'silent'} --ntlm --user #{[@username, @password].join(':').shellescape} #{[baseurl, name].join('').shellescape} -o #{File.join(@dir, name).shellescape}"
|
102
|
+
return File.join(@dir, name)
|
82
103
|
end
|
83
104
|
|
84
|
-
def
|
85
|
-
@
|
86
|
-
if File.
|
87
|
-
|
105
|
+
def addressbook
|
106
|
+
@addressbook ||= begin
|
107
|
+
if !@update && Dir[File.join(@dir, '*.oab')].length > 0
|
108
|
+
oab = File.basename(Dir[File.join(@dir, '*.oab')][0])
|
109
|
+
puts "OfflineAddressBook: Reusing #{oab}" if ENV['DEBUG']
|
88
110
|
else
|
89
|
-
|
90
|
-
|
91
|
-
record.to_h.each_pair{|k, v|
|
92
|
-
record[k] = v[0] if v.length == 1
|
93
|
-
}
|
94
|
-
# no idea what's going on here
|
95
|
-
record.AddressBookObjectGuid = record.AddressBookObjectGuid.inspect if record.AddressBookObjectGuid
|
96
|
-
record
|
97
|
-
}
|
98
|
-
open(cache, 'w'){|f| f.write(JSON.pretty_generate(parsed.collect{|r| r.to_h}))} if @cachedir
|
111
|
+
lzx = Nokogiri::XML(open(download('oab.xml'))).at('//Full').inner_text
|
112
|
+
oab = File.basename(lzx, File.extname(lzx)) + '.oab'
|
99
113
|
end
|
100
114
|
|
101
|
-
|
115
|
+
File.join(@dir, oab)
|
102
116
|
end
|
103
117
|
end
|
118
|
+
|
119
|
+
def cache
|
120
|
+
@cache ||= File.join(@dir, File.basename(addressbook, File.extname(addressbook)) + '.json')
|
121
|
+
end
|
104
122
|
end
|
@@ -1,8 +1,8 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
2
|
|
3
|
-
require '
|
3
|
+
require 'hashie'
|
4
4
|
|
5
|
-
MapiPropertyDataType =
|
5
|
+
MapiPropertyDataType = Hashie::Mash.new({
|
6
6
|
Unspecified: 0,
|
7
7
|
Null: 1,
|
8
8
|
Short: 2,
|
@@ -648,7 +648,7 @@ class OfflineAddressBook
|
|
648
648
|
def _propertyTypes
|
649
649
|
n = _uint32
|
650
650
|
return 1.upto(n).collect{|i|
|
651
|
-
prop =
|
651
|
+
prop = Hashie::Mash.new
|
652
652
|
prop.pos = pos
|
653
653
|
|
654
654
|
id = _uint32
|
@@ -689,12 +689,12 @@ class OfflineAddressBook
|
|
689
689
|
else
|
690
690
|
value = _scalar(prop.type)
|
691
691
|
end
|
692
|
-
p =
|
692
|
+
p = Hashie::Mash.new(type: prop.type, id: prop.id, name: prop.name, value: value)
|
693
693
|
return p
|
694
694
|
end
|
695
695
|
|
696
696
|
def _scalar(type)
|
697
|
-
case type
|
697
|
+
case type.to_sym
|
698
698
|
when :Long then return _integer
|
699
699
|
when :Boolean then return (_ubyte > 0)
|
700
700
|
when :Binary then return @oab.read(_integer)
|
@@ -713,7 +713,7 @@ class OfflineAddressBook
|
|
713
713
|
def _record(headerRecord = false)
|
714
714
|
initialPosition = @oab.pos
|
715
715
|
recordSize = 0
|
716
|
-
record =
|
716
|
+
record = Hashie::Mash.new
|
717
717
|
begin
|
718
718
|
properties = headerRecord ? @headerProperties : @oabProperties
|
719
719
|
recordSize = _uint32
|
@@ -4,16 +4,20 @@ require 'minitest/autorun'
|
|
4
4
|
require 'exchange-offline-address-book'
|
5
5
|
|
6
6
|
class EOABTest < Minitest::Test
|
7
|
-
def test_downlod
|
7
|
+
# def test_downlod
|
8
|
+
# oab = OfflineAddressBook.new(username: ENV['EWS_USERNAME'], password: ENV['EWS_PASSWORD'], email: ENV['EWS_EMAIL'])
|
9
|
+
# puts oab.addressbook
|
10
|
+
# end
|
11
|
+
# def test_baseurl
|
12
|
+
# oab = OfflineAddressBook.new(username: ENV['EWS_USERNAME'], password: ENV['EWS_PASSWORD'], email: ENV['EWS_EMAIL'])
|
13
|
+
# puts oab.baseurl
|
14
|
+
# end
|
15
|
+
# def test_given_baseurl
|
16
|
+
# oab = OfflineAddressBook.new(username: ENV['EWS_USERNAME'], password: ENV['EWS_PASSWORD'], email: ENV['EWS_EMAIL'], baseurl: ENV['EWS_BASEURL'])
|
17
|
+
# puts oab.addressbook
|
18
|
+
# end
|
19
|
+
def test_records
|
8
20
|
oab = OfflineAddressBook.new(username: ENV['EWS_USERNAME'], password: ENV['EWS_PASSWORD'], email: ENV['EWS_EMAIL'])
|
9
|
-
puts oab.
|
10
|
-
end
|
11
|
-
def test_baseurl
|
12
|
-
oab = OfflineAddressBook.new(username: ENV['EWS_USERNAME'], password: ENV['EWS_PASSWORD'], email: ENV['EWS_EMAIL'])
|
13
|
-
puts oab.baseurl
|
14
|
-
end
|
15
|
-
def test_given_baseurl
|
16
|
-
oab = OfflineAddressBook.new(username: ENV['EWS_USERNAME'], password: ENV['EWS_PASSWORD'], email: ENV['EWS_EMAIL'], baseurl: ENV['EWS_BASEURL'])
|
17
|
-
puts oab.addressbook
|
21
|
+
puts oab.records.length
|
18
22
|
end
|
19
23
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: exchange-offline-address-book
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.18
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Emiliano Heyns
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2017-06-
|
11
|
+
date: 2017-06-29 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -136,6 +136,20 @@ dependencies:
|
|
136
136
|
- - "~>"
|
137
137
|
- !ruby/object:Gem::Version
|
138
138
|
version: '0.9'
|
139
|
+
- !ruby/object:Gem::Dependency
|
140
|
+
name: hashie
|
141
|
+
requirement: !ruby/object:Gem::Requirement
|
142
|
+
requirements:
|
143
|
+
- - ">="
|
144
|
+
- !ruby/object:Gem::Version
|
145
|
+
version: '0'
|
146
|
+
type: :runtime
|
147
|
+
prerelease: false
|
148
|
+
version_requirements: !ruby/object:Gem::Requirement
|
149
|
+
requirements:
|
150
|
+
- - ">="
|
151
|
+
- !ruby/object:Gem::Version
|
152
|
+
version: '0'
|
139
153
|
description: Get Exchange Offline Address Book
|
140
154
|
email:
|
141
155
|
- Emiliano.Heyns@iris-advies.com
|