zimbra-soap-api 0.0.7.9
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 +4 -0
- data/.irbrc +6 -0
- data/Gemfile +6 -0
- data/README +21 -0
- data/Rakefile +1 -0
- data/lib/zimbra.rb +94 -0
- data/lib/zimbra/account.rb +94 -0
- data/lib/zimbra/acl.rb +63 -0
- data/lib/zimbra/alias.rb +4 -0
- data/lib/zimbra/appointment.rb +274 -0
- data/lib/zimbra/appointment/alarm.rb +101 -0
- data/lib/zimbra/appointment/attendee.rb +97 -0
- data/lib/zimbra/appointment/invite.rb +360 -0
- data/lib/zimbra/appointment/recur_exception.rb +83 -0
- data/lib/zimbra/appointment/recur_rule.rb +184 -0
- data/lib/zimbra/appointment/reply.rb +91 -0
- data/lib/zimbra/auth.rb +46 -0
- data/lib/zimbra/base.rb +217 -0
- data/lib/zimbra/calendar.rb +27 -0
- data/lib/zimbra/common_elements.rb +51 -0
- data/lib/zimbra/cos.rb +124 -0
- data/lib/zimbra/delegate_auth_token.rb +49 -0
- data/lib/zimbra/directory.rb +175 -0
- data/lib/zimbra/distribution_list.rb +147 -0
- data/lib/zimbra/domain.rb +63 -0
- data/lib/zimbra/ext/handsoap_curb_driver.rb +21 -0
- data/lib/zimbra/ext/hash.rb +72 -0
- data/lib/zimbra/ext/string.rb +10 -0
- data/lib/zimbra/extra/date_helpers.rb +111 -0
- data/lib/zimbra/folder.rb +100 -0
- data/lib/zimbra/handsoap_account_service.rb +44 -0
- data/lib/zimbra/handsoap_service.rb +75 -0
- data/lib/zimbra/version.rb +3 -0
- data/spec/fixtures/xml_api_requests/appointments/create.xml +84 -0
- data/spec/fixtures/xml_api_responses/alarms/15_minutes_before.xml +26 -0
- data/spec/fixtures/xml_api_responses/alarms/using_all_intervals.xml +26 -0
- data/spec/fixtures/xml_api_responses/appointments/appointment_response_1.xml +40 -0
- data/spec/fixtures/xml_api_responses/attendees/one_attendee_and_one_reply.xml +27 -0
- data/spec/fixtures/xml_api_responses/attendees/three_attendees_response_1.xml +30 -0
- data/spec/fixtures/xml_api_responses/multiple_invites/recurring_with_exceptions.xml +109 -0
- data/spec/fixtures/xml_api_responses/recur_rules/day_27_of_every_2_months.xml +27 -0
- data/spec/fixtures/xml_api_responses/recur_rules/every_2_days.xml +26 -0
- data/spec/fixtures/xml_api_responses/recur_rules/every_3_weeks_on_tuesday_and_friday.xml +30 -0
- data/spec/fixtures/xml_api_responses/recur_rules/every_day_50_instances.xml +27 -0
- data/spec/fixtures/xml_api_responses/recur_rules/every_monday_wednesday_friday.xml +31 -0
- data/spec/fixtures/xml_api_responses/recur_rules/every_tuesday.xml +29 -0
- data/spec/fixtures/xml_api_responses/recur_rules/every_weekday_with_end_date.xml +34 -0
- data/spec/fixtures/xml_api_responses/recur_rules/every_year_on_february_2.xml +28 -0
- data/spec/fixtures/xml_api_responses/recur_rules/first_day_of_every_month.xml +36 -0
- data/spec/fixtures/xml_api_responses/recur_rules/first_monday_of_every_february.xml +31 -0
- data/spec/fixtures/xml_api_responses/recur_rules/first_weekend_day_of_every_month.xml +31 -0
- data/spec/fixtures/xml_api_responses/recur_rules/last_day_of_every_month.xml +36 -0
- data/spec/fixtures/xml_api_responses/recur_rules/second_day_of_every_2_months.xml +36 -0
- data/spec/fixtures/xml_api_responses/recur_rules/second_wednesday_of_every_month.xml +29 -0
- data/spec/fixtures/xml_api_responses/recur_rules/weekly_with_an_exception.xml +44 -0
- data/spec/spec_helper.rb +32 -0
- data/spec/zimbra/acl_spec.rb +11 -0
- data/spec/zimbra/appointment/alarm_spec.rb +33 -0
- data/spec/zimbra/appointment/invite_spec.rb +62 -0
- data/spec/zimbra/appointment/recur_rule_spec.rb +307 -0
- data/spec/zimbra/appointment_spec.rb +175 -0
- data/spec/zimbra/common_elements_spec.rb +33 -0
- data/spec/zimbra/distribution_list_spec.rb +54 -0
- data/zimbra.gemspec +28 -0
- metadata +197 -0
@@ -0,0 +1,63 @@
|
|
1
|
+
module Zimbra
|
2
|
+
class Domain < Zimbra::Base
|
3
|
+
class << self
|
4
|
+
def acl_name
|
5
|
+
'domain'
|
6
|
+
end
|
7
|
+
end
|
8
|
+
|
9
|
+
def count_accounts
|
10
|
+
DomainService.count_accounts(id)
|
11
|
+
end
|
12
|
+
|
13
|
+
def save
|
14
|
+
DomainService.modify(self)
|
15
|
+
end
|
16
|
+
|
17
|
+
end
|
18
|
+
|
19
|
+
class DomainService < HandsoapService
|
20
|
+
|
21
|
+
def count_accounts(id)
|
22
|
+
xml = invoke("n2:CountAccountRequest") do |message|
|
23
|
+
Builder.count_accounts(message, id)
|
24
|
+
end
|
25
|
+
Parser.count_accounts_response(xml)
|
26
|
+
end
|
27
|
+
|
28
|
+
def delete
|
29
|
+
xml = invoke("n2:DeleteDomainRequest") do |message|
|
30
|
+
Builder.delete(message, id)
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
class Builder
|
35
|
+
class << self
|
36
|
+
|
37
|
+
|
38
|
+
def count_accounts(message, id)
|
39
|
+
message.add 'domain', id do |c|
|
40
|
+
c.set_attr 'by', 'id'
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
def delete(message, id)
|
45
|
+
message.add 'id', id
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
class Parser
|
50
|
+
class << self
|
51
|
+
def count_accounts_response(response)
|
52
|
+
hash = {}
|
53
|
+
(response/"//n2:cos").map do |node|
|
54
|
+
cos_id = (node/'@id').to_s
|
55
|
+
hash[cos_id] = node.to_s.to_i
|
56
|
+
end
|
57
|
+
hash
|
58
|
+
end
|
59
|
+
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
class Handsoap::Http::Drivers::CurbDriver
|
2
|
+
def get_curl(url)
|
3
|
+
if @curl
|
4
|
+
@curl.url = url
|
5
|
+
else
|
6
|
+
@curl = ::Curl::Easy.new(url)
|
7
|
+
@curl.timeout = Handsoap.timeout
|
8
|
+
@curl.enable_cookies = @enable_cookies
|
9
|
+
|
10
|
+
# enables both deflate and gzip compression of responses
|
11
|
+
@curl.encoding = ''
|
12
|
+
|
13
|
+
if Handsoap.follow_redirects?
|
14
|
+
@curl.follow_location = true
|
15
|
+
@curl.max_redirects = Handsoap.max_redirects
|
16
|
+
end
|
17
|
+
end
|
18
|
+
@curl.ssl_verify_peer = false
|
19
|
+
@curl
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,72 @@
|
|
1
|
+
module Zimbra
|
2
|
+
class Hash < ::Hash
|
3
|
+
# Thanks to https://gist.github.com/dimus/335286 for this code
|
4
|
+
|
5
|
+
class << self
|
6
|
+
def symbolize_keys(hash, recursive = false)
|
7
|
+
hash.keys.each do |key|
|
8
|
+
value = hash.delete(key)
|
9
|
+
key = key.respond_to?(:to_sym) ? key.to_sym : key
|
10
|
+
hash[key] = (recursive && value.is_a?(::Hash)) ? symbolize_keys(value.dup, recursive) : value
|
11
|
+
end
|
12
|
+
hash
|
13
|
+
end
|
14
|
+
|
15
|
+
def from_xml(xml_io)
|
16
|
+
begin
|
17
|
+
result = Nokogiri::XML(xml_io)
|
18
|
+
return { result.root.name.to_sym => xml_node_to_hash(result.root)}
|
19
|
+
rescue Exception => e
|
20
|
+
# raise your custom exception here
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
def xml_node_to_hash(node)
|
25
|
+
# If we are at the root of the document, start the hash
|
26
|
+
if node.element?
|
27
|
+
result_hash = {}
|
28
|
+
if node.attributes != {}
|
29
|
+
result_hash[:attributes] = {}
|
30
|
+
node.attributes.keys.each do |key|
|
31
|
+
result_hash[:attributes][node.attributes[key].name.to_sym] = prepare(node.attributes[key].value)
|
32
|
+
end
|
33
|
+
end
|
34
|
+
if node.children.size > 0
|
35
|
+
node.children.each do |child|
|
36
|
+
result = xml_node_to_hash(child)
|
37
|
+
|
38
|
+
if child.name == "text"
|
39
|
+
unless child.next_sibling || child.previous_sibling
|
40
|
+
if result_hash[:attributes]
|
41
|
+
result_hash['value'] = prepare(result)
|
42
|
+
return result_hash
|
43
|
+
else
|
44
|
+
return prepare(result)
|
45
|
+
end
|
46
|
+
end
|
47
|
+
elsif result_hash[child.name.to_sym]
|
48
|
+
if result_hash[child.name.to_sym].is_a?(Object::Array)
|
49
|
+
result_hash[child.name.to_sym] << prepare(result)
|
50
|
+
else
|
51
|
+
result_hash[child.name.to_sym] = [result_hash[child.name.to_sym]] << prepare(result)
|
52
|
+
end
|
53
|
+
else
|
54
|
+
result_hash[child.name.to_sym] = prepare(result)
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
return result_hash
|
59
|
+
else
|
60
|
+
return result_hash
|
61
|
+
end
|
62
|
+
else
|
63
|
+
return prepare(node.content.to_s)
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
def prepare(data)
|
68
|
+
(data.class == String && data.to_i.to_s == data) ? data.to_i : data
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
@@ -0,0 +1,111 @@
|
|
1
|
+
module Zimbra
|
2
|
+
class DateHelpers
|
3
|
+
class Frequency
|
4
|
+
FREQUENCIES = [
|
5
|
+
{ name: :secondly, zimbra_name: 'SEC', abbreviations: [] },
|
6
|
+
{ name: :minutely, zimbra_name: 'MIN', abbreviations: [] },
|
7
|
+
{ name: :hourly, zimbra_name: 'HOU', abbreviations: [] },
|
8
|
+
{ name: :daily, zimbra_name: 'DAI', abbreviations: [] },
|
9
|
+
{ name: :weekly, zimbra_name: 'WEE', abbreviations: [] },
|
10
|
+
{ name: :monthly, zimbra_name: 'MON', abbreviations: [] },
|
11
|
+
{ name: :yearly, zimbra_name: 'YEA', abbreviations: [] }
|
12
|
+
]
|
13
|
+
|
14
|
+
class << self
|
15
|
+
def all
|
16
|
+
@all ||= FREQUENCIES.inject([]) do |frequencies, data|
|
17
|
+
frequencies << new(data)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
def find(name_or_abbreviation)
|
22
|
+
all.find { |frequency| frequency.match?(name_or_abbreviation) }
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
attr_accessor :name, :zimbra_name, :abbreviations
|
27
|
+
|
28
|
+
def initialize(args = {})
|
29
|
+
@name = args[:name]
|
30
|
+
@zimbra_name = args[:zimbra_name]
|
31
|
+
@abbreviations = args[:abbreviations]
|
32
|
+
end
|
33
|
+
|
34
|
+
def match?(name_or_abbreviation)
|
35
|
+
downcased_matcher = name_or_abbreviation.to_s.downcase
|
36
|
+
([name.to_s, zimbra_name.to_s] + abbreviations).map(&:downcase).include?(downcased_matcher)
|
37
|
+
end
|
38
|
+
|
39
|
+
def to_sym
|
40
|
+
name.downcase.to_sym
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
class WeekDay
|
45
|
+
WEEK_DAYS = [
|
46
|
+
{
|
47
|
+
id: 1, name: :Sunday, zimbra_name: 'SU',
|
48
|
+
abbreviations: ['su', 'sun']
|
49
|
+
},
|
50
|
+
{
|
51
|
+
id: 2, name: :Monday, zimbra_name: 'MO',
|
52
|
+
abbreviations: ['mo', 'mon']
|
53
|
+
},
|
54
|
+
{
|
55
|
+
id: 3, name: :Tuesday, zimbra_name: 'TU',
|
56
|
+
abbreviations: ['tu', 'tue']
|
57
|
+
},
|
58
|
+
{
|
59
|
+
id: 4, name: :Wednesday, zimbra_name: 'WE',
|
60
|
+
abbreviations: ['we', 'wed']
|
61
|
+
},
|
62
|
+
{
|
63
|
+
id: 5, name: :Thursday, zimbra_name: 'TH',
|
64
|
+
abbreviations: ['th', 'thu', 'thur', 'thurs']
|
65
|
+
},
|
66
|
+
{
|
67
|
+
id: 6, name: :Friday, zimbra_name: 'FR',
|
68
|
+
abbreviations: ['fr', 'fri']
|
69
|
+
},
|
70
|
+
{
|
71
|
+
id: 7, name: :Saturday, zimbra_name: 'SA',
|
72
|
+
abbreviations: ['sa', 'sat']
|
73
|
+
}
|
74
|
+
] unless const_defined?(:WEEK_DAYS)
|
75
|
+
|
76
|
+
class << self
|
77
|
+
def all
|
78
|
+
@all ||= WEEK_DAYS.inject([]) do |week_days, data|
|
79
|
+
week_days << new(data)
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
def find(id_name_or_abbreviation)
|
84
|
+
all.find { |week_day| week_day.match?(id_name_or_abbreviation) }
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
attr_accessor :id, :name, :abbreviations, :zimbra_name
|
89
|
+
|
90
|
+
def initialize(args = {})
|
91
|
+
@id = args[:id]
|
92
|
+
@name = args[:name]
|
93
|
+
@zimbra_name = args[:zimbra_name]
|
94
|
+
@abbreviations = args[:abbreviations]
|
95
|
+
end
|
96
|
+
|
97
|
+
def match?(id_name_or_abbreviation)
|
98
|
+
if id_name_or_abbreviation.is_a?(Fixnum)
|
99
|
+
id_name_or_abbreviation == id
|
100
|
+
else
|
101
|
+
downcased_matcher = id_name_or_abbreviation.to_s.downcase
|
102
|
+
([name.to_s, zimbra_name.to_s] + abbreviations).map(&:downcase).include?(downcased_matcher)
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
106
|
+
def to_sym
|
107
|
+
name.downcase.to_sym
|
108
|
+
end
|
109
|
+
end
|
110
|
+
end
|
111
|
+
end
|
@@ -0,0 +1,100 @@
|
|
1
|
+
# http://files.zimbra.com/docs/soap_api/8.0.4/soap-docs-804/api-reference/zimbraMail/GetFolder.html
|
2
|
+
module Zimbra
|
3
|
+
class Folder
|
4
|
+
class << self
|
5
|
+
def all
|
6
|
+
FolderService.all
|
7
|
+
end
|
8
|
+
|
9
|
+
def find_all_by_view(view)
|
10
|
+
FolderService.find_all_by_view(view)
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
ATTRS = [
|
15
|
+
:id, :uuid, :name, :view, :absolute_folder_path,
|
16
|
+
:parent_folder_id, :parent_folder_uuid,
|
17
|
+
:non_folder_item_count, :non_folder_item_size,
|
18
|
+
:revision, :imap_next_uid, :imap_modified_sequence, :modified_sequence, :activesync_disabled,
|
19
|
+
:modified_date
|
20
|
+
] unless const_defined?(:ATTRS)
|
21
|
+
|
22
|
+
attr_accessor *ATTRS
|
23
|
+
|
24
|
+
def initialize(args = {})
|
25
|
+
self.attributes = args
|
26
|
+
end
|
27
|
+
|
28
|
+
def attributes=(args = {})
|
29
|
+
ATTRS.each do |attr_name|
|
30
|
+
self.send(:"#{attr_name}=", (args[attr_name] || args[attr_name.to_s])) if args.has_key?(attr_name) || args.has_key?(attr_name.to_s)
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
class FolderService < HandsoapAccountService
|
36
|
+
def all
|
37
|
+
xml = invoke("n2:GetFolderRequest")
|
38
|
+
parse_xml_responses(xml)
|
39
|
+
end
|
40
|
+
|
41
|
+
def find_all_by_view(view)
|
42
|
+
xml = invoke("n2:GetFolderRequest") do |message|
|
43
|
+
Builder.find_all_by_view(message, view)
|
44
|
+
end
|
45
|
+
parse_xml_responses(xml)
|
46
|
+
end
|
47
|
+
|
48
|
+
def parse_xml_responses(xml)
|
49
|
+
Parser.get_all_response(xml)
|
50
|
+
end
|
51
|
+
|
52
|
+
class Builder
|
53
|
+
class << self
|
54
|
+
def find_all_by_view(message, view)
|
55
|
+
message.set_attr 'view', view
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
class Parser
|
61
|
+
ATTRIBUTE_MAPPING = {
|
62
|
+
:id => :id,
|
63
|
+
:uuid => :uuid,
|
64
|
+
:name => :name,
|
65
|
+
:view => :view,
|
66
|
+
:absFolderPath => :absolute_folder_path,
|
67
|
+
:l => :parent_folder_id,
|
68
|
+
:luuid => :parent_folder_uuid,
|
69
|
+
:n => :non_folder_item_count,
|
70
|
+
:s => :non_folder_item_size,
|
71
|
+
:rev => :revision,
|
72
|
+
:i4next => :imap_next_uid,
|
73
|
+
:i4ms => :imap_modified_sequence,
|
74
|
+
:ms => :modified_sequence,
|
75
|
+
:activesyncdisabled => :activesync_disabled,
|
76
|
+
:md => :modified_date
|
77
|
+
}
|
78
|
+
|
79
|
+
class << self
|
80
|
+
def get_all_response(response)
|
81
|
+
(response/"//n2:folder").map do |node|
|
82
|
+
folder_response(node)
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
def folder_response(node)
|
87
|
+
folder_attributes = ATTRIBUTE_MAPPING.inject({}) do |attrs, (xml_name, attr_name)|
|
88
|
+
attrs[attr_name] = (node/"@#{xml_name}").to_s
|
89
|
+
attrs
|
90
|
+
end
|
91
|
+
initialize_from_attributes(folder_attributes)
|
92
|
+
end
|
93
|
+
|
94
|
+
def initialize_from_attributes(folder_attributes)
|
95
|
+
Zimbra::Folder.new(folder_attributes)
|
96
|
+
end
|
97
|
+
end
|
98
|
+
end
|
99
|
+
end
|
100
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
require 'handsoap'
|
2
|
+
|
3
|
+
module Zimbra
|
4
|
+
module HandsoapAccountNamespaces
|
5
|
+
def request_namespaces(doc)
|
6
|
+
doc.alias 'n1', "urn:zimbra"
|
7
|
+
doc.alias 'n2', "urn:zimbraMail"
|
8
|
+
doc.alias 'env', 'http://schemas.xmlsoap.org/soap/envelope/'
|
9
|
+
end
|
10
|
+
def response_namespaces(doc)
|
11
|
+
doc.add_namespace 'n2', "urn:zimbraMail"
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
module HandsoapAccountUriOverrides
|
16
|
+
def uri
|
17
|
+
Zimbra.account_api_url
|
18
|
+
end
|
19
|
+
def envelope_namespace
|
20
|
+
'http://www.w3.org/2003/05/soap-envelope'
|
21
|
+
end
|
22
|
+
def request_content_type
|
23
|
+
"application/soap+xml"
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
class HandsoapAccountService < Handsoap::Service
|
28
|
+
include HandsoapErrors
|
29
|
+
include HandsoapAccountNamespaces
|
30
|
+
extend HandsoapAccountUriOverrides
|
31
|
+
|
32
|
+
def on_create_document(doc)
|
33
|
+
request_namespaces(doc)
|
34
|
+
header = doc.find("Header")
|
35
|
+
header.add "n1:context" do |s|
|
36
|
+
s.set_attr "env:mustUnderstand", "0"
|
37
|
+
s.add "n1:authToken", Zimbra.account_auth_token
|
38
|
+
end
|
39
|
+
end
|
40
|
+
def on_response_document(doc)
|
41
|
+
response_namespaces(doc)
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
@@ -0,0 +1,75 @@
|
|
1
|
+
require 'handsoap'
|
2
|
+
|
3
|
+
module Zimbra
|
4
|
+
module HandsoapErrors
|
5
|
+
class SOAPFault < StandardError; end
|
6
|
+
class NotFound < StandardError; end
|
7
|
+
class NotImplemented < StandardError; end
|
8
|
+
|
9
|
+
@@response = nil
|
10
|
+
|
11
|
+
def on_http_error(response)
|
12
|
+
@@response = response
|
13
|
+
return nil if soap_fault_not_found?
|
14
|
+
report_error(response) if http_error?
|
15
|
+
end
|
16
|
+
def report_error(response)
|
17
|
+
message = response.body.scan(/<faultstring>(.*)<\/faultstring>/).first.first
|
18
|
+
raise SOAPFault, message
|
19
|
+
end
|
20
|
+
def on_after_create_http_request(request)
|
21
|
+
@@response = nil
|
22
|
+
end
|
23
|
+
|
24
|
+
def soap_fault_not_found?
|
25
|
+
@@response && @@response.body =~ /no such/
|
26
|
+
end
|
27
|
+
def http_error?
|
28
|
+
@@response && (500..599).include?(@@response.status)
|
29
|
+
end
|
30
|
+
def http_not_found?
|
31
|
+
@@response && (400..499).include?(@@response.status)
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
module HandsoapNamespaces
|
36
|
+
def request_namespaces(doc)
|
37
|
+
doc.alias 'n1', "urn:zimbra"
|
38
|
+
doc.alias 'n2', "urn:zimbraAdmin"
|
39
|
+
doc.alias 'env', 'http://schemas.xmlsoap.org/soap/envelope/'
|
40
|
+
end
|
41
|
+
def response_namespaces(doc)
|
42
|
+
doc.add_namespace 'n2', "urn:zimbraAdmin"
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
module HandsoapUriOverrides
|
47
|
+
def uri
|
48
|
+
Zimbra.admin_api_url
|
49
|
+
end
|
50
|
+
def envelope_namespace
|
51
|
+
'http://www.w3.org/2003/05/soap-envelope'
|
52
|
+
end
|
53
|
+
def request_content_type
|
54
|
+
"application/soap+xml"
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
class HandsoapService < Handsoap::Service
|
59
|
+
include HandsoapErrors
|
60
|
+
include HandsoapNamespaces
|
61
|
+
extend HandsoapUriOverrides
|
62
|
+
|
63
|
+
def on_create_document(doc)
|
64
|
+
request_namespaces(doc)
|
65
|
+
header = doc.find("Header")
|
66
|
+
header.add "n1:context" do |s|
|
67
|
+
s.set_attr "env:mustUnderstand", "0"
|
68
|
+
s.add "n1:authToken", Zimbra.auth_token
|
69
|
+
end
|
70
|
+
end
|
71
|
+
def on_response_document(doc)
|
72
|
+
response_namespaces(doc)
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|