ruby-dbus 0.7.2 → 0.8.0

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.
data/NEWS CHANGED
@@ -5,6 +5,25 @@ Note about bug numbers:
5
5
  Issue#1 - http://github.com/mvidner/ruby-dbus/issues#issue/1
6
6
  bnc#1 - https://bugzilla.novell.com/show_bug.cgi?id=1
7
7
 
8
+ == Ruby D-Bus 0.8.0 - 2012-09-20
9
+
10
+ Features:
11
+ * Add Anonymous authentication (Issue#27, by Walter Brebels).
12
+ * Use Nokogiri for XML parsing when available (Issue#24, by Geoff Youngs).
13
+
14
+ Bug fixes:
15
+ * Use SCM_CREDS authentication only on FreeBSD, not on OpenBSD (Issue#21,
16
+ reported by Adde Nilsson).
17
+ * Recognize signature "h" (UNIX_FD) used eg. by Upstart (Issue#23,
18
+ by Bernd Ahlers).
19
+ * Find the session bus also via launchd, on OS X (Issue#20, reported
20
+ by Paul Sturgess).
21
+
22
+ Other:
23
+ * Now doing continuous integration with Travis:
24
+ http://travis-ci.org/#!/mvidner/ruby-dbus
25
+
26
+
8
27
  == Ruby D-Bus 0.7.2 - 2012-04-05
9
28
 
10
29
  A brown-paper-bag release.
data/Rakefile CHANGED
@@ -28,7 +28,7 @@ end
28
28
  desc "Run bare:#{tname} in the proper environment"
29
29
  task tname do |t|
30
30
  cd "test" do
31
- system "./test_env rake bare:#{tname}"
31
+ sh "./test_env rake bare:#{tname}"
32
32
  end
33
33
  end
34
34
  end
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.7.2
1
+ 0.8.0
@@ -17,6 +17,7 @@ require 'dbus/marshall'
17
17
  require 'dbus/message'
18
18
  require 'dbus/matchrule'
19
19
  require 'dbus/auth'
20
+ require 'dbus/xml'
20
21
 
21
22
  require 'socket'
22
23
  require 'thread'
@@ -23,6 +23,13 @@ module DBus
23
23
  end
24
24
  end
25
25
 
26
+ # = Anonymous authentication class
27
+ class Anonymous < Authenticator
28
+ def authenticate
29
+ '527562792044427573' # Hex encoded version of "Ruby DBus"
30
+ end
31
+ end
32
+
26
33
  # = External authentication class
27
34
  #
28
35
  # Class for 'external' type authentication.
@@ -115,12 +122,12 @@ module DBus
115
122
  def initialize(socket)
116
123
  @socket = socket
117
124
  @state = nil
118
- @auth_list = [External,DBusCookieSHA1]
125
+ @auth_list = [External,DBusCookieSHA1,Anonymous]
119
126
  end
120
127
 
121
128
  # Start the authentication process.
122
129
  def authenticate
123
- if (RbConfig::CONFIG["target_os"] =~ /bsd/)
130
+ if (RbConfig::CONFIG["target_os"] =~ /freebsd/)
124
131
  @socket.sendmsg(0.chr, 0, nil, [:SOCKET, :SCM_CREDS, ""])
125
132
  else
126
133
  @socket.write(0.chr)
@@ -225,6 +225,8 @@ module DBus
225
225
  connect_to_unix kv_hash
226
226
  when "tcp"
227
227
  connect_to_tcp kv_hash
228
+ when "launchd"
229
+ connect_to_launchd kv_hash
228
230
  else
229
231
  # ignore, report?
230
232
  end
@@ -271,6 +273,12 @@ module DBus
271
273
  init_connection
272
274
  end
273
275
 
276
+ def connect_to_launchd(params)
277
+ socket_var = params['env']
278
+ socket = `launchctl getenv #{socket_var}`.chomp
279
+ connect_to_unix 'path' => socket
280
+ end
281
+
274
282
  # Send the buffer _buf_ to the bus using Connection#writel.
275
283
  def send(buf)
276
284
  @socket.write(buf) unless @socket.nil?
@@ -510,7 +518,7 @@ module DBus
510
518
  begin
511
519
  ret, size = Message.new.unmarshall_buffer(@buffer)
512
520
  @buffer.slice!(0, size)
513
- rescue IncompleteBufferException => e
521
+ rescue IncompleteBufferException
514
522
  # fall through, let ret be null
515
523
  end
516
524
  ret
@@ -531,7 +539,6 @@ module DBus
531
539
  # Update the buffer and retrieve all messages using Connection#messages.
532
540
  # Return the messages.
533
541
  def poll_messages
534
- ret = nil
535
542
  r, d, d = IO.select([@socket], nil, nil, 0)
536
543
  if r and r.size > 0
537
544
  update_buffer
@@ -719,7 +726,7 @@ module DBus
719
726
  class ASessionBus < Connection
720
727
  # Get the the default session bus.
721
728
  def initialize
722
- super(ENV["DBUS_SESSION_BUS_ADDRESS"] || address_from_file)
729
+ super(ENV["DBUS_SESSION_BUS_ADDRESS"] || address_from_file || "launchd:env=DBUS_LAUNCHD_SESSION_BUS_SOCKET")
723
730
  connect
724
731
  send_hello
725
732
  end
@@ -734,6 +741,8 @@ module DBus
734
741
  return $1
735
742
  end
736
743
  end
744
+ rescue Errno::ENOENT
745
+ nil
737
746
  end
738
747
  end
739
748
 
@@ -8,9 +8,6 @@
8
8
  # License, version 2.1 as published by the Free Software Foundation.
9
9
  # See the file "COPYING" for the exact licensing terms.
10
10
 
11
- # TODO check if it is slow, make replaceable
12
- require 'rexml/document'
13
-
14
11
  module DBus
15
12
  # Regular expressions that should match all method names.
16
13
  MethodSignalRE = /^[A-Za-z][A-Za-z0-9_]*$/
@@ -219,82 +216,6 @@ module DBus
219
216
  end
220
217
  end # class Signal
221
218
 
222
- # = D-Bus introspect XML parser class
223
- #
224
- # This class parses introspection XML of an object and constructs a tree
225
- # of Node, Interface, Method, Signal instances.
226
- class IntrospectXMLParser
227
- # Creates a new parser for XML data in string _xml_.
228
- def initialize(xml)
229
- @xml = xml
230
- end
231
-
232
- # return the names of direct subnodes
233
- def parse_subnodes
234
- subnodes = Array.new
235
- d = REXML::Document.new(@xml)
236
- d.elements.each("node/node") do |e|
237
- subnodes << e.attributes["name"]
238
- end
239
- subnodes
240
- end
241
-
242
- # return a pair: [list of Interfaces, list of direct subnode names]
243
- def parse
244
- interfaces = Array.new
245
- subnodes = Array.new
246
- t = Time.now
247
- d = REXML::Document.new(@xml)
248
- d.elements.each("node/node") do |e|
249
- subnodes << e.attributes["name"]
250
- end
251
- d.elements.each("node/interface") do |e|
252
- i = Interface.new(e.attributes["name"])
253
- e.elements.each("method") do |me|
254
- m = Method.new(me.attributes["name"])
255
- parse_methsig(me, m)
256
- i << m
257
- end
258
- e.elements.each("signal") do |se|
259
- s = Signal.new(se.attributes["name"])
260
- parse_methsig(se, s)
261
- i << s
262
- end
263
- interfaces << i
264
- end
265
- d = Time.now - t
266
- if d > 2
267
- puts "Some XML took more that two secs to parse. Optimize me!" if $DEBUG
268
- end
269
- [interfaces, subnodes]
270
- end
271
-
272
- ######################################################################
273
- private
274
-
275
- # Parses a method signature XML element _e_ and initialises
276
- # method/signal _m_.
277
- def parse_methsig(e, m)
278
- e.elements.each("arg") do |ae|
279
- name = ae.attributes["name"]
280
- dir = ae.attributes["direction"]
281
- sig = ae.attributes["type"]
282
- if m.is_a?(DBus::Signal)
283
- m.add_fparam(name, sig)
284
- elsif m.is_a?(DBus::Method)
285
- case dir
286
- when "in"
287
- m.add_fparam(name, sig)
288
- when "out"
289
- m.add_return(name, sig)
290
- end
291
- else
292
- raise NotImplementedError, dir
293
- end
294
- end
295
- end
296
- end # class IntrospectXMLParser
297
-
298
219
  # = D-Bus proxy object interface class
299
220
  #
300
221
  # A class similar to the normal Interface used as a proxy for remote
@@ -146,7 +146,7 @@ module DBus
146
146
  if (packet & 0x8000) != 0
147
147
  packet -= 0x10000
148
148
  end
149
- when Type::UINT32
149
+ when Type::UINT32, Type::UNIX_FD
150
150
  align(4)
151
151
  packet = get(4).unpack(@uint32)[0]
152
152
  when Type::INT32
@@ -317,7 +317,7 @@ module DBus
317
317
  case type.sigtype
318
318
  when Type::BYTE
319
319
  @packet += val.chr
320
- when Type::UINT32
320
+ when Type::UINT32, Type::UNIX_FD
321
321
  align(4)
322
322
  @packet += [val].pack("L")
323
323
  when Type::UINT64
@@ -240,7 +240,7 @@ module DBus
240
240
  end
241
241
  pu = PacketUnmarshaller.new(buf, endianness)
242
242
  mdata = pu.unmarshall(MESSAGE_SIGNATURE)
243
- dummy, @message_type, @flags, @protocol, @body_length, @serial,
243
+ _, @message_type, @flags, @protocol, @body_length, @serial,
244
244
  headers = mdata
245
245
 
246
246
  headers.each do |struct|
@@ -274,7 +274,7 @@ module DBus
274
274
  # Message#unmarshall_buf.
275
275
  # Return the message.
276
276
  def unmarshall(buf)
277
- ret, size = unmarshall_buffer(buf)
277
+ ret, _ = unmarshall_buffer(buf)
278
278
  ret
279
279
  end
280
280
  end # class Message
@@ -33,6 +33,7 @@ module Type
33
33
  STRING = ?s
34
34
  SIGNATURE = ?g
35
35
  DICT_ENTRY = ?e
36
+ UNIX_FD = ?h
36
37
 
37
38
  # Mapping from type number to name.
38
39
  TypeName = {
@@ -52,7 +53,8 @@ module Type
52
53
  OBJECT_PATH => "OBJECT_PATH",
53
54
  STRING => "STRING",
54
55
  SIGNATURE => "SIGNATURE",
55
- DICT_ENTRY => "DICT_ENTRY"
56
+ DICT_ENTRY => "DICT_ENTRY",
57
+ UNIX_FD => "UNIX_FD"
56
58
  }
57
59
 
58
60
  # Exception raised when an unknown/incorrect type is encountered.
@@ -96,6 +98,7 @@ module Type
96
98
  OBJECT_PATH => 4,
97
99
  STRING => 4,
98
100
  SIGNATURE => 1,
101
+ UNIX_FD => 4,
99
102
  }[@sigtype]
100
103
  end
101
104
 
@@ -0,0 +1,156 @@
1
+ # dbus/xml.rb - introspection parser, rexml/nokogiri abstraction
2
+ #
3
+ # This file is part of the ruby-dbus project
4
+ # Copyright (C) 2007 Arnaud Cornet and Paul van Tilburg
5
+ # Copyright (C) 2012 Geoff Youngs
6
+ #
7
+ # This library is free software; you can redistribute it and/or
8
+ # modify it under the terms of the GNU Lesser General Public
9
+ # License, version 2.1 as published by the Free Software Foundation.
10
+ # See the file "COPYING" for the exact licensing terms.
11
+
12
+ # TODO check if it is slow, make replaceable
13
+ require 'rexml/document'
14
+ begin
15
+ require 'nokogiri'
16
+ rescue LoadError
17
+ end
18
+
19
+ module DBus
20
+ # = D-Bus introspect XML parser class
21
+ #
22
+ # This class parses introspection XML of an object and constructs a tree
23
+ # of Node, Interface, Method, Signal instances.
24
+ class IntrospectXMLParser
25
+ class << self
26
+ attr_accessor :backend
27
+ end
28
+ # Creates a new parser for XML data in string _xml_.
29
+ def initialize(xml)
30
+ @xml = xml
31
+ end
32
+
33
+ class AbstractXML
34
+ def self.have_nokogiri?
35
+ Object.const_defined?('Nokogiri')
36
+ end
37
+ class Node
38
+ def initialize(node)
39
+ @node = node
40
+ end
41
+ # required methods
42
+ # returns node attribute value
43
+ def [](key)
44
+ end
45
+ # yields child nodes which match xpath of type AbstractXML::Node
46
+ def each(xpath)
47
+ end
48
+ end
49
+ # required methods
50
+ # initialize parser with xml string
51
+ def initialize(xml)
52
+ end
53
+ # yields nodes which match xpath of type AbstractXML::Node
54
+ def each(xpath)
55
+ end
56
+ end
57
+
58
+ class NokogiriParser < AbstractXML
59
+ class NokogiriNode < AbstractXML::Node
60
+ def [](key)
61
+ @node[key]
62
+ end
63
+ def each(path, &block)
64
+ @node.search(path).each { |node| block.call NokogiriNode.new(node) }
65
+ end
66
+ end
67
+ def initialize(xml)
68
+ @doc = Nokogiri.XML(xml)
69
+ end
70
+ def each(path, &block)
71
+ @doc.search("//#{path}").each { |node| block.call NokogiriNode.new(node) }
72
+ end
73
+ end
74
+
75
+ class REXMLParser < AbstractXML
76
+ class REXMLNode < AbstractXML::Node
77
+ def [](key)
78
+ @node.attributes[key]
79
+ end
80
+ def each(path, &block)
81
+ @node.elements.each(path) { |node| block.call REXMLNode.new(node) }
82
+ end
83
+ end
84
+ def initialize(xml)
85
+ @doc = REXML::Document.new(xml)
86
+ end
87
+ def each(path, &block)
88
+ @doc.elements.each(path) { |node| block.call REXMLNode.new(node) }
89
+ end
90
+ end
91
+
92
+ if AbstractXML.have_nokogiri?
93
+ @backend = NokogiriParser
94
+ else
95
+ @backend = REXMLParser
96
+ end
97
+
98
+ # return a pair: [list of Interfaces, list of direct subnode names]
99
+ def parse
100
+ interfaces = Array.new
101
+ subnodes = Array.new
102
+ t = Time.now
103
+
104
+
105
+ d = IntrospectXMLParser.backend.new(@xml)
106
+ d.each("node/node") do |e|
107
+ subnodes << e["name"]
108
+ end
109
+ d.each("node/interface") do |e|
110
+ i = Interface.new(e["name"])
111
+ e.each("method") do |me|
112
+ m = Method.new(me["name"])
113
+ parse_methsig(me, m)
114
+ i << m
115
+ end
116
+ e.each("signal") do |se|
117
+ s = Signal.new(se["name"])
118
+ parse_methsig(se, s)
119
+ i << s
120
+ end
121
+ interfaces << i
122
+ end
123
+ d = Time.now - t
124
+ if d > 2
125
+ puts "Some XML took more that two secs to parse. Optimize me!" if $DEBUG
126
+ end
127
+ [interfaces, subnodes]
128
+ end
129
+
130
+ ######################################################################
131
+ private
132
+
133
+ # Parses a method signature XML element _e_ and initialises
134
+ # method/signal _m_.
135
+ def parse_methsig(e, m)
136
+ e.each("arg") do |ae|
137
+ name = ae["name"]
138
+ dir = ae["direction"]
139
+ sig = ae["type"]
140
+ if m.is_a?(DBus::Signal)
141
+ m.add_fparam(name, sig)
142
+ elsif m.is_a?(DBus::Method)
143
+ case dir
144
+ when "in"
145
+ m.add_fparam(name, sig)
146
+ when "out"
147
+ m.add_return(name, sig)
148
+ end
149
+ else
150
+ raise NotImplementedError, dir
151
+ end
152
+ end
153
+ end
154
+ end # class IntrospectXMLParser
155
+ end # module DBus
156
+
@@ -0,0 +1,42 @@
1
+ #!/usr/bin/env ruby
2
+ # Test the bus class
3
+ require "test/unit"
4
+ require 'rubygems'
5
+ require 'nokogiri'
6
+ require "dbus"
7
+
8
+ class BusAndXmlBackendTest < Test::Unit::TestCase
9
+ def setup
10
+ @bus = DBus::ASessionBus.new
11
+ end
12
+
13
+ def test_introspection_reading_rexml
14
+ DBus::IntrospectXMLParser.backend = DBus::IntrospectXMLParser::REXMLParser
15
+ @svc = @bus.service("org.ruby.service")
16
+ obj = @svc.object("/org/ruby/MyInstance")
17
+ obj.default_iface = 'org.ruby.SampleInterface'
18
+ obj.introspect
19
+ assert_nothing_raised do
20
+ assert_equal 42, obj.the_answer[0], "should respond to :the_answer"
21
+ end
22
+ assert_nothing_raised do
23
+ assert_equal "oof", obj["org.ruby.AnotherInterface"].Reverse('foo')[0], "should work with multiple interfaces"
24
+ end
25
+ end
26
+
27
+ def test_introspection_reading_nokogiri
28
+ # peek inside the object to see if a cleanup step worked or not
29
+ DBus::IntrospectXMLParser.backend = DBus::IntrospectXMLParser::NokogiriParser
30
+ @svc = @bus.service("org.ruby.service")
31
+ obj = @svc.object("/org/ruby/MyInstance")
32
+ obj.default_iface = 'org.ruby.SampleInterface'
33
+ obj.introspect
34
+ assert_nothing_raised do
35
+ assert_equal 42, obj.the_answer[0], "should respond to :the_answer"
36
+ end
37
+ assert_nothing_raised do
38
+ assert_equal "oof", obj["org.ruby.AnotherInterface"].Reverse('foo')[0], "should work with multiple interfaces"
39
+ end
40
+ end
41
+
42
+ end
@@ -10,7 +10,7 @@ class Foo < DBus::Object
10
10
  end
11
11
 
12
12
  dbus_signal :signal_without_interface
13
- rescue DBus::Object::UndefinedInterface => e
13
+ rescue DBus::Object::UndefinedInterface
14
14
  # raised by the preceding signal declaration
15
15
  end
16
16
 
@@ -46,6 +46,7 @@ class SignalHandlerTest < Test::Unit::TestCase
46
46
  @loop.quit
47
47
  end
48
48
  @loop.run
49
+ quitter.join
49
50
 
50
51
  assert_equal 1, counter
51
52
  end
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ruby-dbus
3
3
  version: !ruby/object:Gem::Version
4
- hash: 7
4
+ hash: 63
5
5
  prerelease:
6
6
  segments:
7
7
  - 0
8
- - 7
9
- - 2
10
- version: 0.7.2
8
+ - 8
9
+ - 0
10
+ version: 0.8.0
11
11
  platform: ruby
12
12
  authors:
13
13
  - Ruby DBus Team
@@ -15,7 +15,7 @@ autorequire:
15
15
  bindir: bin
16
16
  cert_chain: []
17
17
 
18
- date: 2012-04-05 00:00:00 Z
18
+ date: 2012-09-20 00:00:00 Z
19
19
  dependencies: []
20
20
 
21
21
  description:
@@ -54,9 +54,11 @@ files:
54
54
  - lib/dbus/matchrule.rb
55
55
  - lib/dbus/message.rb
56
56
  - lib/dbus/type.rb
57
+ - lib/dbus/xml.rb
57
58
  - ruby-dbus.gemspec
58
59
  - test/async_test.rb
59
60
  - test/binding_test.rb
61
+ - test/bus_and_xml_backend_test.rb
60
62
  - test/bus_driver_test.rb
61
63
  - test/bus_test.rb
62
64
  - test/dbus-launch-simple