ruby-dbus 0.7.2 → 0.8.0

Sign up to get free protection for your applications and to get access to all the features.
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