1package soap
2
3import (
4	"strconv"
5
6	"github.com/masterzen/simplexml/dom"
7)
8
9type HeaderOption struct {
10	key   string
11	value string
12}
13
14func NewHeaderOption(name string, value string) *HeaderOption {
15	return &HeaderOption{key: name, value: value}
16}
17
18type SoapHeader struct {
19	to              string
20	replyTo         string
21	maxEnvelopeSize string
22	timeout         string
23	locale          string
24	id              string
25	action          string
26	shellId         string
27	resourceURI     string
28	options         []HeaderOption
29	message         *SoapMessage
30}
31
32type HeaderBuilder interface {
33	To(string) *SoapHeader
34	ReplyTo(string) *SoapHeader
35	MaxEnvelopeSize(int) *SoapHeader
36	Timeout(string) *SoapHeader
37	Locale(string) *SoapHeader
38	Id(string) *SoapHeader
39	Action(string) *SoapHeader
40	ShellId(string) *SoapHeader
41	resourceURI(string) *SoapHeader
42	AddOption(*HeaderOption) *SoapHeader
43	Options([]HeaderOption) *SoapHeader
44	Build(*SoapMessage) *SoapMessage
45}
46
47func (self *SoapHeader) To(uri string) *SoapHeader {
48	self.to = uri
49	return self
50}
51
52func (self *SoapHeader) ReplyTo(uri string) *SoapHeader {
53	self.replyTo = uri
54	return self
55}
56
57func (self *SoapHeader) MaxEnvelopeSize(size int) *SoapHeader {
58	self.maxEnvelopeSize = strconv.Itoa(size)
59	return self
60}
61
62func (self *SoapHeader) Timeout(timeout string) *SoapHeader {
63	self.timeout = timeout
64	return self
65}
66
67func (self *SoapHeader) Id(id string) *SoapHeader {
68	self.id = id
69	return self
70}
71
72func (self *SoapHeader) Action(action string) *SoapHeader {
73	self.action = action
74	return self
75}
76
77func (self *SoapHeader) Locale(locale string) *SoapHeader {
78	self.locale = locale
79	return self
80}
81
82func (self *SoapHeader) ShellId(shellId string) *SoapHeader {
83	self.shellId = shellId
84	return self
85}
86
87func (self *SoapHeader) ResourceURI(resourceURI string) *SoapHeader {
88	self.resourceURI = resourceURI
89	return self
90}
91
92func (self *SoapHeader) AddOption(option *HeaderOption) *SoapHeader {
93	self.options = append(self.options, *option)
94	return self
95}
96
97func (self *SoapHeader) Options(options []HeaderOption) *SoapHeader {
98	self.options = options
99	return self
100}
101
102func (self *SoapHeader) Build() *SoapMessage {
103	header := self.createElement(self.message.envelope, "Header", DOM_NS_SOAP_ENV)
104
105	if self.to != "" {
106		to := self.createElement(header, "To", DOM_NS_ADDRESSING)
107		to.SetContent(self.to)
108	}
109
110	if self.replyTo != "" {
111		replyTo := self.createElement(header, "ReplyTo", DOM_NS_ADDRESSING)
112		a := self.createMUElement(replyTo, "Address", DOM_NS_ADDRESSING, true)
113		a.SetContent(self.replyTo)
114	}
115
116	if self.maxEnvelopeSize != "" {
117		envelope := self.createMUElement(header, "MaxEnvelopeSize", DOM_NS_WSMAN_DMTF, true)
118		envelope.SetContent(self.maxEnvelopeSize)
119	}
120
121	if self.timeout != "" {
122		timeout := self.createElement(header, "OperationTimeout", DOM_NS_WSMAN_DMTF)
123		timeout.SetContent(self.timeout)
124	}
125
126	if self.id != "" {
127		id := self.createElement(header, "MessageID", DOM_NS_ADDRESSING)
128		id.SetContent(self.id)
129	}
130
131	if self.locale != "" {
132		locale := self.createMUElement(header, "Locale", DOM_NS_WSMAN_DMTF, false)
133		locale.SetAttr("xml:lang", self.locale)
134		datalocale := self.createMUElement(header, "DataLocale", DOM_NS_WSMAN_MSFT, false)
135		datalocale.SetAttr("xml:lang", self.locale)
136	}
137
138	if self.action != "" {
139		action := self.createMUElement(header, "Action", DOM_NS_ADDRESSING, true)
140		action.SetContent(self.action)
141	}
142
143	if self.shellId != "" {
144		selectorSet := self.createElement(header, "SelectorSet", DOM_NS_WSMAN_DMTF)
145		selector := self.createElement(selectorSet, "Selector", DOM_NS_WSMAN_DMTF)
146		selector.SetAttr("Name", "ShellId")
147		selector.SetContent(self.shellId)
148	}
149
150	if self.resourceURI != "" {
151		resource := self.createMUElement(header, "ResourceURI", DOM_NS_WSMAN_DMTF, true)
152		resource.SetContent(self.resourceURI)
153	}
154
155	if len(self.options) > 0 {
156		set := self.createElement(header, "OptionSet", DOM_NS_WSMAN_DMTF)
157		for _, option := range self.options {
158			e := self.createElement(set, "Option", DOM_NS_WSMAN_DMTF)
159			e.SetAttr("Name", option.key)
160			e.SetContent(option.value)
161		}
162	}
163
164	return self.message
165}
166
167func (self *SoapHeader) createElement(parent *dom.Element, name string, ns dom.Namespace) (element *dom.Element) {
168	element = dom.CreateElement(name)
169	parent.AddChild(element)
170	ns.SetTo(element)
171	return
172}
173
174func (self *SoapHeader) createMUElement(parent *dom.Element, name string, ns dom.Namespace, mustUnderstand bool) (element *dom.Element) {
175	element = self.createElement(parent, name, ns)
176	value := "false"
177	if mustUnderstand {
178		value = "true"
179	}
180	element.SetAttr("mustUnderstand", value)
181	return
182}
183