tiebreaker 0.0.2

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.
@@ -0,0 +1,789 @@
1
+ #============================================================#
2
+ # #
3
+ # $ID:$ #
4
+ # #
5
+ # NaServer.rb #
6
+ # #
7
+ # Client-side interface to ONTAP and DataFabric Manager APIs.#
8
+ # #
9
+ # Copyright (c) 2011 NetApp, Inc. All rights reserved. #
10
+ # Specifications subject to change without notice. #
11
+ # #
12
+ #============================================================#
13
+
14
+ require 'net/http'
15
+ require 'net/https'
16
+ require 'rexml/document'
17
+ require 'rexml/streamlistener'
18
+ include REXML
19
+ require 'stringio'
20
+ include StreamListener
21
+ require 'NaElement'
22
+ require 'pathname'
23
+
24
+ # Official NMSDK release version
25
+ $NMSDK_VERSION = '5.4'
26
+
27
+ # This method return the platform information of unix systems.
28
+ # This method is used internally for NMSDK/API Usage Tracking.
29
+ # NOTE: DO NOT REMOVE/MODIFY THIS METHOD.
30
+ # NOTE: DO NOT USE THIS METHOD EXTERNALLY.
31
+ def get_unix_info()
32
+ v = $VERBOSE
33
+ $VERBOSE = nil
34
+ sysname = `uname -s`
35
+ $VERBOSE = v
36
+ sysname = sysname.chomp
37
+
38
+ if(sysname.include?("Linux")) # for linux (rhel, suse, oel)
39
+ # check if it is SUSE
40
+ filepath = Pathname.new("/etc/SuSE-release")
41
+ if(filepath.exist?())
42
+ release_file = '/etc/SuSE-release'
43
+ else # for RHEL, OEL, etc.
44
+ release_file = '/etc/issue'
45
+ end
46
+
47
+ $VERBOSE = nil
48
+ flavor = `head -n 1 #{release_file}`
49
+ $VERBOSE = v
50
+ # Remove the string within parentheses
51
+ sysname = flavor.sub(/\(\w+\)/, '').chomp
52
+ sysname = sysname.sub(/\s+\Z/, "")
53
+
54
+ else # for other unix platforms (solaris, aix, hpux)
55
+ $VERBOSE = nil
56
+ if(sysname.eql?("AIX"))
57
+ version = `oslevel`
58
+ else
59
+ version = `uname -r`
60
+ end
61
+ $VERBOSE = v
62
+ sysname = sysname + " " + version.chomp
63
+ end
64
+
65
+ $VERBOSE = nil
66
+ if(sysname.eql?("HP-UX"))
67
+ processor = `uname -m`
68
+ else
69
+ processor = `uname -p`
70
+ end
71
+
72
+ if(sysname.include?("SunOS"))
73
+ isainfo = `isainfo -b`
74
+ isainfo = isainfo.chomp
75
+ bitinfo = " " + isainfo + "-bit"
76
+ else
77
+ bitinfo = ""
78
+ end
79
+ $VERBOSE = v
80
+
81
+ os_info = sysname + " " + processor.chomp + bitinfo
82
+ return os_info
83
+ end
84
+
85
+
86
+ # This method return the platform information of windows systems.
87
+ # This method is used internally for NMSDK/API Usage Tracking.
88
+ # NOTE: DO NOT REMOVE/MODIFY THIS METHOD.
89
+ # NOTE: DO NOT USE THIS METHOD EXTERNALLY.
90
+ def get_windows_info()
91
+ sysname = ""
92
+ processor = ""
93
+ os_info = ""
94
+
95
+ require 'win32/registry'
96
+
97
+ Win32::Registry::HKEY_LOCAL_MACHINE.open('SOFTWARE\Microsoft\Windows NT\CurrentVersion') do |reg|
98
+ type, sysname = reg.read('ProductName')
99
+ end
100
+
101
+ Win32::Registry::HKEY_LOCAL_MACHINE.open('SYSTEM\ControlSet001\Control\Session Manager\Environment') do |reg|
102
+ type, processor = reg.read('PROCESSOR_ARCHITECTURE')
103
+ end
104
+
105
+ os_info = sysname + " " + processor
106
+ return os_info
107
+ end
108
+
109
+ # The client platform information string.
110
+ # NOTE: DO NOT REMOVE/MODIFY THIS VARIABLE.
111
+ $NMSDK_PLATFORM = ""
112
+ platform = RUBY_PLATFORM
113
+ if (platform.include?("mingw") )
114
+ $NMSDK_PLATFORM = get_windows_info()
115
+ else
116
+ $NMSDK_PLATFORM = get_unix_info()
117
+ end
118
+
119
+
120
+ # Class for managing Network Appliance(r) Storage System
121
+ # using ONTAPI(tm) and DataFabric Manager API(tm).
122
+ #
123
+ # An NaServer encapsulates an administrative connection to
124
+ # a NetApp Storage Systems running Data ONTAP 6.4 or later.
125
+ # NaServer can also be used to establish connection with
126
+ # OnCommand Unified Manager (OCUM). You construct NaElement objects
127
+ # that represent queries or commands, and use invoke_elem()
128
+ # to send them to the storage systems or OCUM server. Also,
129
+ # a convenience routine called invoke() can be used to bypass
130
+ # the element construction step. The return from the call is
131
+ # another NaElement which either has children containing the
132
+ # command results, or an error indication.
133
+ #
134
+ # The following routines are available for setting up
135
+ # administrative connections to a storage system or OCUM server.
136
+ #
137
+
138
+ $ZAPI_stack = []
139
+ $ZAPI_atts = {}
140
+ $tag_element_stack = []
141
+
142
+ class NaServer
143
+
144
+ #dtd files
145
+ FILER_dtd = 'file:/etc/netapp_filer.dtd'
146
+ DFM_dtd = 'file:/etc/netapp_dfm.dtd'
147
+ AGENT_dtd = 'file:/etc/netapp_agent.dtd'
148
+
149
+ #URLs
150
+ AGENT_URL = '/apis/XMLrequest'
151
+ FILER_URL = '/servlets/netapp.servlets.admin.XMLrequest_filer'
152
+ NETCACHE_URL = '/servlets/netapp.servlets.admin.XMLrequest'
153
+ DFM_URL = '/apis/XMLrequest'
154
+
155
+ ZAPI_xmlns = 'http://www.netapp.com/filer/admin'
156
+
157
+ # Create a new connection to server 'server'. Before use,
158
+ # you either need to set the style to "hosts.equiv" or set
159
+ # the username (always "root" at present) and password with
160
+ # set_admin_user().
161
+
162
+ def initialize(server, major_version, minor_version)
163
+ @server = server
164
+ @major_version = major_version
165
+ @minor_version = minor_version
166
+ @transport_type = "HTTP"
167
+ @port = 80
168
+ @user = "root"
169
+ @password = ""
170
+ @style = "LOGIN"
171
+ @timeout = 0
172
+ @vfiler = ""
173
+ @server_type = "FILER"
174
+ @debug_style = ""
175
+ @xml = ""
176
+ @originator_id = ""
177
+ @enable_server_cert_verification = false
178
+ @enable_hostname_verification = false
179
+ @cert_file = nil
180
+ @key_file = nil
181
+ @key_passwd = nil
182
+ @ca_file = nil
183
+ @url = FILER_URL
184
+ @dtd = FILER_dtd
185
+
186
+ # Following parameters are used for NMSDK/API Usage Tracking.
187
+ # NOTE: DO NOT REMOVE/MODIFY THESE VARIABLES.
188
+ @nmsdk_version = $NMSDK_VERSION
189
+ @nmsdk_platform = $NMSDK_PLATFORM
190
+ @nmsdk_language = "Ruby"
191
+ @nmsdk_app = ""
192
+ end
193
+
194
+
195
+ # Set the client application name.
196
+ def set_application_name(app_name)
197
+ @nmsdk_app = app_name
198
+ end
199
+
200
+
201
+ # Get the client application name.
202
+ def get_application_name()
203
+ return @nmsdk_app
204
+ end
205
+
206
+
207
+ # Pass in 'LOGIN' to cause the server to use HTTP simple
208
+ # authentication with a username and password. Pass in 'HOSTS'
209
+ # to use the hosts.equiv file on the filer to determine access
210
+ # rights (the username must be root in that case). Pass in
211
+ # 'CERTIFICATE' to use certificate based authentication with the
212
+ # DataFabric Manager server.
213
+ #
214
+ # If $style = CERTIFICATE, you can use certificates to authenticate
215
+ # clients who attempt to connect to a server without the need of
216
+ # username and password. This style will internally set the transport
217
+ # type to HTTPS. Verification of the server's certificate is required
218
+ # in order to properly authenticate the identity of the server.
219
+ # Server certificate verification will be enabled by default using this
220
+ # style and Server certificate verification will always enable hostname
221
+ # verification. You can disable server certificate (with hostname)
222
+ # verification using set_server_cert_verification().
223
+
224
+ def set_style(style)
225
+ if(!style.eql?("HOSTS") and !style.eql?("LOGIN") and !style.eql?("CERTIFICATE"))
226
+ return fail_response(13001, "NaServer::set_style: bad style \"" + style + "\"")
227
+ end
228
+ if (style.eql?("CERTIFICATE"))
229
+ ret = set_transport_type("HTTPS")
230
+ if (ret)
231
+ return ret
232
+ end
233
+ @enable_server_cert_verification = true
234
+ @enable_hostname_verification = true
235
+ else
236
+ @enable_server_cert_verification = false
237
+ @enable_hostname_verification = false
238
+ end
239
+ @style = style
240
+ return nil
241
+ end
242
+
243
+
244
+ # Get the authentication style
245
+
246
+ def get_style()
247
+ return @style
248
+ end
249
+
250
+
251
+ # Set the admin username and password. At present 'user' must always be 'root'.
252
+
253
+ def set_admin_user(user, password)
254
+ @user = user
255
+ @password = password
256
+ end
257
+
258
+
259
+
260
+ # Pass in one of these keywords: 'FILER' or 'DFM' or 'OCUM' to indicate
261
+ # whether the server is a storage system (filer) or a OCUM server.
262
+ #
263
+ # If you also use set_port(), call set_port() AFTER calling this routine.
264
+ #
265
+ # The default is 'FILER'.
266
+
267
+ def set_server_type(server_type)
268
+ if (server_type.casecmp('filer') == 0)
269
+ @url = FILER_URL
270
+ @dtd = FILER_dtd
271
+ elsif (server_type.casecmp('netcache') == 0)
272
+ @url = NETCACHE_URL
273
+ @port = 80
274
+ elsif (server_type.casecmp('agent') == 0)
275
+ @url = AGENT_URL
276
+ @port = 4092
277
+ @dtd = AGENT_dtd
278
+ elsif (server_type.casecmp('dfm') == 0)
279
+ @url = DFM_URL
280
+ @port = 8088
281
+ @dtd = DFM_dtd
282
+ if(@transport_type == "HTTPS")
283
+ @port = 8488
284
+ end
285
+ elsif (server_type.casecmp('ocum') == 0)
286
+ @url = DFM_URL
287
+ @port = 443
288
+ @transport_type = "HTTPS"
289
+ @dtd = DFM_dtd
290
+ else
291
+ return fail_response(13001, "NaServer::set_server_type: bad type \"" + server_type + "\"")
292
+ end
293
+ @server_type = server_type
294
+ return nil
295
+ end
296
+
297
+
298
+ # Get the type of server this server connection applies to.
299
+
300
+ def get_server_type()
301
+ return @server_type
302
+ end
303
+
304
+
305
+ # Override the default transport type. The valid transport
306
+ # type are currently 'HTTP' and 'HTTPS'.
307
+
308
+ def set_transport_type(scheme)
309
+ if(!scheme.eql?("HTTP") and !scheme.eql?("HTTPS"))
310
+ return fail_response(13001, "NaServer::set_transport_type: bad type \" " + scheme + "\"")
311
+ end
312
+ if(scheme.eql?("HTTP"))
313
+ if(@server_type.eql?("OCUM"))
314
+ return fail_response(13001, "Server type '" + @server_type + "' does not support '" + scheme + "' transport type")
315
+ end
316
+
317
+ @transport_type = "HTTP"
318
+ if(@server_type.eql?("DFM"))
319
+ @port = 8088
320
+ else
321
+ @port = 80
322
+ end
323
+ elsif(scheme.eql?("HTTPS"))
324
+ @transport_type = "HTTPS"
325
+ if(@server_type.eql?("DFM"))
326
+ @port = 8488
327
+ else
328
+ @port = 443
329
+ end
330
+ end
331
+ return nil
332
+ end
333
+
334
+
335
+ # Retrieve the transport used for this connection.
336
+
337
+ def get_transport_type()
338
+ return @transport_type
339
+ end
340
+
341
+
342
+ # Set the style of debug.
343
+
344
+ def set_debug_style(debug_style)
345
+ if(!debug_style.eql?("NA_PRINT_DONT_PARSE"))
346
+ return fail_response(13001, "NaServer::set_debug_style: bad style \"" + debug_style + "\"")
347
+ else
348
+ @debug_style = debug_style
349
+ end
350
+ end
351
+
352
+
353
+ # Override the default port for this server. If you
354
+ # also call set_server_type(), you must call it before
355
+ # calling set_port().
356
+
357
+ def set_port(port)
358
+ @port = port
359
+ end
360
+
361
+
362
+ # Retrieve the port used for the remote server.
363
+
364
+ def get_port()
365
+ return @port
366
+ end
367
+
368
+
369
+ # Check the type of debug style and return the
370
+ # value for different needs. Return true if debug style
371
+ # is NA_PRINT_DONT_PARSE, else return false.
372
+
373
+ def is_debugging()
374
+ if(@debug_style.eql?("NA_PRINT_DONT_PARSE"))
375
+ return true
376
+ else
377
+ return false
378
+ end
379
+ end
380
+
381
+
382
+ # Return the raw XML output.
383
+
384
+ def get_raw_xml_output()
385
+ return @xml
386
+ end
387
+
388
+
389
+ # Save the raw XML output.
390
+
391
+ def set_raw_xml_output(xml)
392
+ @xml = xml
393
+ end
394
+
395
+
396
+ # Determines whether https is enabled.
397
+
398
+ def use_https()
399
+ if(@transport_type.eql?("HTTPS"))
400
+ return true
401
+ else
402
+ return false
403
+ end
404
+ end
405
+
406
+
407
+ def parse_raw_xml(xmlresponse)
408
+ xml_response = StringIO.new(xmlresponse)
409
+ Document.parse_stream(xml_response, MyListener.new)
410
+ if($tag_element_stack.length > 0)
411
+ print("\nError : No corresponding end tag for the element \"" + $tag_element_stack.pop() + "\"\n")
412
+ exit
413
+ end
414
+ stack_len = $ZAPI_stack.length
415
+ if(stack_len <= 0)
416
+ return fail_response(13001, "Zapi::parse_xml-no elements on stack")
417
+ end
418
+ r = $ZAPI_stack.pop()
419
+ return r
420
+ end
421
+
422
+
423
+
424
+ def parse_xml(xmlresponse)
425
+ xml_response = StringIO.new(xmlresponse)
426
+ Document.parse_stream(xml_response, MyListener.new)
427
+ if($tag_element_stack.length > 0)
428
+ print("\nError : No corresponding end tag for the element \"" + $tag_element_stack.pop() + "\"\n")
429
+ exit
430
+ end
431
+ stack_len = $ZAPI_stack.length
432
+ if(stack_len <= 0)
433
+ return fail_response(13001, "Zapi::parse_xml-no elements on stack")
434
+ end
435
+ r = $ZAPI_stack.pop()
436
+ if (r.name != "netapp")
437
+ return fail_response(13001, "Zapi::parse_xml - Expected <netapp> element but got" + r.name)
438
+ end
439
+ results = r.child_get("results")
440
+ unless(results)
441
+ return fail_response(13001, "Zapi::parse_xml - No results element in output!")
442
+ end
443
+ return results
444
+ end
445
+
446
+
447
+ # Submit an XML request already encapsulated as
448
+ # an NaElement and return the result in another
449
+ # NaElement.
450
+
451
+ def invoke_elem(req)
452
+ xmlrequest = req.toEncodedString()
453
+ vfiler_req = ""
454
+ originator_id_req = ""
455
+ if(!@vfiler.eql?(""))
456
+ vfiler_req = " vfiler=\"" + @vfiler + "\""
457
+ end
458
+ if(!@originator_id.eql?(""))
459
+ originator_id_req = " originator_id=\"" + @originator_id + "\""
460
+ end
461
+
462
+ app_name_req = ""
463
+ if(!@nmsdk_app.eql?(""))
464
+ app_name_req = " nmsdk_app='" + @nmsdk_app + "'"
465
+ end
466
+
467
+ content = "<?xml version=\'1.0\' encoding=\'utf-8\'?>" +
468
+ "\n" +
469
+ "<!DOCTYPE netapp SYSTEM \'" + @dtd + "\'>" +
470
+ "\n" +
471
+ "<netapp" +
472
+ vfiler_req +
473
+ originator_id_req +
474
+ " version='" + @major_version.to_s() + "." + @minor_version.to_s() + "' xmlns='" + ZAPI_xmlns + "'" +
475
+ " nmsdk_version='" + @nmsdk_version + "'" +
476
+ " nmsdk_platform='" + @nmsdk_platform + "'" +
477
+ " nmsdk_language='" + @nmsdk_language + "'" +
478
+ app_name_req +
479
+ ">" +
480
+ xmlrequest +
481
+ "</netapp>"
482
+
483
+ if(@debug_style.eql?("NA_PRINT_DONT_PARSE"))
484
+ print("INPUT \n " + content)
485
+ end
486
+
487
+ begin
488
+ http = Net::HTTP.new(@server, @port)
489
+ if(@transport_type.eql?("HTTPS"))
490
+ http.use_ssl = true
491
+ http.verify_mode = OpenSSL::SSL::VERIFY_NONE
492
+ # Server Certificate Verification
493
+ if(@enable_server_cert_verification.eql?(true))
494
+ http.ca_file = @ca_file
495
+ http.verify_mode = OpenSSL::SSL::VERIFY_PEER | OpenSSL::SSL::VERIFY_FAIL_IF_NO_PEER_CERT
496
+ unless(@enable_hostname_verification)
497
+ OpenSSL::SSL.module_eval do
498
+ verify_method = method(:verify_certificate_identity)
499
+ metaclass = class << OpenSSL::SSL; self; end
500
+ metaclass.send :define_method, :verify_certificate_identity do |cert, hostname|
501
+ true
502
+ end
503
+ end
504
+ end
505
+ end
506
+ # Client Certificate Verification
507
+ if(@cert_file != nil)
508
+ pem = File.read(@cert_file)
509
+ http.cert = OpenSSL::X509::Certificate.new(pem)
510
+ # @key_file is nil when the certificate and key are in the same file (@cert_file)
511
+ if(@key_file == nil)
512
+ http.key = OpenSSL::PKey::RSA.new(pem)
513
+ else
514
+ key = File.read(@key_file)
515
+ http.key = OpenSSL::PKey::RSA.new(key, @key_passwd)
516
+ end
517
+ end
518
+ end
519
+ if(@timeout > 0)
520
+ http.open_timeout = @timeout
521
+ http.read_timeout = @timeout
522
+ end
523
+ request = Net::HTTP::Post.new(@url)
524
+ if(!@style.eql?("HOSTS"))
525
+ request.basic_auth @user, @password
526
+ end
527
+ request.content_type = "text/xml; charset=\"UTF-8\""
528
+ request.body = content
529
+ response = http.start {|http| http.request(request)}
530
+ rescue Timeout::Error => msg
531
+ print("\nError : ")
532
+ return fail_response(13001, msg)
533
+ rescue Errno::ECONNREFUSED => msg
534
+ print("\nError : ")
535
+ return fail_response(111, msg)
536
+ rescue OpenSSL::SSL::SSLError => msg
537
+ return fail_response(13001, msg)
538
+ rescue => msg
539
+ print("\nError : ")
540
+ return fail_response(13001, msg)
541
+ end
542
+
543
+ if(!response)
544
+ return fail_response(13001,"No response received")
545
+ end
546
+ if(response.code.eql?("401"))
547
+ return fail_response(13002,"Authorization failed")
548
+ end
549
+ return parse_xml(response.body)
550
+ end
551
+
552
+
553
+ #A convenience routine which wraps invoke_elem().
554
+ #It constructs an NaElement with name $api, and for
555
+ #each argument name/value pair, adds a child element
556
+ #to it. It's an error to have an even number of
557
+ #arguments to this function.
558
+ #Example: myserver->invoke('snapshot-create',
559
+ # 'snapshot', 'mysnapshot',
560
+ # 'volume', 'vol0');
561
+ #
562
+
563
+ def invoke(api, *args)
564
+ num_parms = args.length
565
+ if ((num_parms & 1) != 0)
566
+ return self.fail_response(13001, "in Zapi::invoke, invalid number of parameters")
567
+ end
568
+ xi = NaElement.new(api)
569
+ i = 0
570
+ while(i < num_parms)
571
+ key = args[i]
572
+ i = i + 1
573
+ value = args[i]
574
+ i = i + 1
575
+ xi.child_add(NaElement.new(key, value))
576
+ end
577
+ return invoke_elem(xi)
578
+ end
579
+
580
+
581
+ #Sets the vfiler name. This function is used for vfiler-tunneling.
582
+
583
+ def set_vfiler(vfiler_name)
584
+ if(@major_version >= 1 and @minor_version >= 7)
585
+ @vfiler = vfiler_name
586
+ return 1
587
+ end
588
+ return 0
589
+ end
590
+
591
+
592
+ # Sets the vserver name. This function is used for vfiler-tunneling.
593
+ # However, vserver tunneling actually uses vfiler-tunneling.
594
+ # Hence this function internally sets the vfiler name.
595
+
596
+ def set_vserver(vserver_name)
597
+ if(@major_version >= 1 and @minor_version >= 15)
598
+ @vfiler = vserver_name
599
+ return 1
600
+ end
601
+ print("\nONTAPI version must be at least 1.15 to send API to a vserver\n")
602
+ return 0
603
+ end
604
+
605
+
606
+ # Gets the vserver name. This function is added for vserver-tunneling.
607
+ # However, vserver tunneling actually uses vfiler-tunneling. Hence this
608
+ # function actually returns the vfiler name.
609
+
610
+ def get_vserver()
611
+ return @vfiler
612
+ end
613
+
614
+
615
+ # Function to set the originator_id before executing any ONTAP API.
616
+
617
+ def set_originator_id(originator_id)
618
+ @originator_id = originator_id
619
+ return 1
620
+ end
621
+
622
+
623
+ # Gets the originator_id for the given server context on which the
624
+ # ONTAP API commands get invoked.
625
+
626
+ def get_originator_id()
627
+ return @originator_id
628
+ end
629
+
630
+ #Sets the connection timeout value, in seconds,for the given server context.
631
+
632
+ def set_timeout(timeout)
633
+ @timeout = timeout
634
+ end
635
+
636
+
637
+ #Retrieves the connection timeout value (in seconds) for the given server context.
638
+
639
+ def get_timeout()
640
+ return @timeout
641
+ end
642
+
643
+
644
+ # Enables or disables server certificate verification by the client.
645
+ # Server certificate verification is enabled by default when style
646
+ # is set to CERTIFICATE. Hostname (CN) verification is always enabled
647
+ # during server certificate verification.
648
+
649
+ def set_server_cert_verification(enable)
650
+ unless(enable.eql?(true) or enable.eql?(false))
651
+ return fail_response(13001, "NaServer::set_server_cert_verification: invalid argument " + enable + "specified");
652
+ end
653
+ unless (use_https())
654
+ return fail_response(13001, "NaServer::set_server_cert_verification: server certificate verification can only be enabled or disabled for HTTPS transport")
655
+ end
656
+ @enable_server_cert_verification = enable
657
+ @enable_hostname_verification = enable
658
+ return nil
659
+ end
660
+
661
+
662
+ # Determines whether server certificate verification is enabled or not.
663
+ # Returns true if it is enabled, else returns false.
664
+
665
+
666
+ def is_server_cert_verification_enabled()
667
+ return @enable_server_cert_verification
668
+ end
669
+
670
+
671
+ # Sets the client certificate and key files that are required for client authentication
672
+ # by the server using certificates. If key file is not defined, then the certificate file
673
+ # will be used as the key file.
674
+
675
+
676
+ def set_client_cert_and_key (cert_file, key_file = nil, key_passwd = nil)
677
+ unless(cert_file)
678
+ return fail_response(13001, "NaServer::set_client_cert_and_key: certificate file not specified")
679
+ end
680
+ @cert_file = cert_file
681
+ @key_file = key_file
682
+ if(key_passwd == nil)
683
+ @key_passwd = ""
684
+ else
685
+ @key_passwd = key_passwd
686
+ end
687
+
688
+ return nil
689
+ end
690
+
691
+
692
+ # Specifies the certificates of the Certificate Authorities (CAs) that are
693
+ # trusted by this application and that will be used to verify the server certificate.
694
+
695
+
696
+ def set_ca_certs (ca_file)
697
+ if(ca_file == nil)
698
+ return fail_response(13001, "NaServer::set_ca_certs: missing CA certificate file")
699
+ end
700
+ @ca_file = ca_file
701
+
702
+ return nil
703
+ end
704
+
705
+
706
+ # Enables or disables hostname verification by the client during server certificate the
707
+ # server certificate.
708
+
709
+
710
+ def set_hostname_verification (enable)
711
+ unless(enable.eql?(true) or enable.eql?(false))
712
+ return fail_response(13001, "NaServer::set_hostname_verification: invalid argument " + enable + "specified");
713
+ end
714
+ unless (@enable_server_cert_verification)
715
+ return fail_response(13001, "NaServer::set_hostname_verification: server certificate verification is not enabled")
716
+ end
717
+ @enable_hostname_verification = enable
718
+ return nil
719
+ end
720
+
721
+
722
+ # Determines whether hostname verification is enabled or not.
723
+ # Returns true if it is enabled, else returns false
724
+
725
+
726
+ def is_hostname_verification_enabled ()
727
+ return @enable_hostname_verification
728
+ end
729
+
730
+
731
+
732
+
733
+
734
+
735
+ # "private" subroutines for use by the public routines
736
+ # This is a private function, not to be called from outside NaServer
737
+ # This is used when the transmission path fails, and we don't actually
738
+ # get back any XML from the server.
739
+
740
+ def fail_response(errno, reason)
741
+ n = NaElement.new("results")
742
+ n.attr_set("status", "failed")
743
+ n.attr_set("reason", reason)
744
+ n.attr_set("errno", errno)
745
+ return n
746
+ end
747
+ end
748
+
749
+
750
+ class MyListener
751
+
752
+ def tag_start(element, attributes)
753
+ n = NaElement.new(element)
754
+ $tag_element_stack.push(element)
755
+ $ZAPI_stack.push(n)
756
+ attributes.each { |key, value| $ZAPI_atts[key] = value ; n.attr_set(key, value) }
757
+ end
758
+
759
+ def tag_end(element)
760
+ stack_len = $ZAPI_stack.length
761
+ if($tag_element_stack.length <= 0)
762
+ print("\nError : Missing start tag for " + element + "\n")
763
+ exit
764
+ end
765
+ tag_element = $tag_element_stack.pop()
766
+ if(not tag_element.eql?(element))
767
+ print("\nError : Missing start tag for " + element + "\n")
768
+ exit
769
+ end
770
+ if(stack_len > 1)
771
+ n = $ZAPI_stack.pop()
772
+ i = $ZAPI_stack.length
773
+ if(i != stack_len - 1)
774
+ print("pop did not work!!!!\n")
775
+ end
776
+ $ZAPI_stack[i-1].child_add(n)
777
+ end
778
+ end
779
+
780
+ def text(text)
781
+ text = text.chomp
782
+ i = $ZAPI_stack.length
783
+ if(text.length > 0 and i > 0)
784
+ text = NaElement.escapeHTML(text)
785
+ $ZAPI_stack[i-1].add_content(text)
786
+ end
787
+ end
788
+ end
789
+