dbus/bus signals.c,1.1,1.2 signals.h,1.1,1.2 Makefile.am,1.27,1.28 activation.c,1.27,1.28 bus.c,1.38,1.39 bus.h,1.18,1.19 config-parser.c,1.21,1.22 connection.c,1.43,1.44 connection.h,1.15,1.16 dbus-daemon-1.1.in,1.3,1.4 desktop-file.c,1.7,1.8 dispatch.c,1.50,1.51 dispatch.h,1.3,1.4 driver.c,1.41,1.42 policy.c,1.13,1.14 policy.h,1.9,1.10 services.c,1.15,1.16 session.conf.in,1.5,1.6 system.conf.in,1.10,1.11 test-main.c,1.12,1.13 test.c,1.21,1.22 test.h,1.10,1.11

Havoc Pennington hp@pdx.freedesktop.org
Mon, 29 Sep 2003 19:33:23 -0700


Update of /cvs/dbus/dbus/bus
In directory pdx:/tmp/cvs-serv18265/bus

Modified Files:
	Makefile.am activation.c bus.c bus.h config-parser.c 
	connection.c connection.h dbus-daemon-1.1.in desktop-file.c 
	dispatch.c dispatch.h driver.c policy.c policy.h services.c 
	session.conf.in system.conf.in test-main.c test.c test.h 
Added Files:
	signals.c signals.h 
Log Message:
2003-09-29  Havoc Pennington  <hp@pobox.com>

	* Merge dbus-object-names branch. To see the entire patch 
	do cvs diff -r DBUS_OBJECT_NAMES_BRANCHPOINT -r dbus-object-names,
	it's huuuuge though.
	To revert, I tagged DBUS_BEFORE_OBJECT_NAMES_MERGE.
	
2003-09-28  Havoc Pennington  <hp@pobox.com>

	* HACKING: update to reflect new server

2003-09-26  Seth Nickell  <seth@gnome.org>

	* python/dbus.py:
	* python/examples/example-signals.py:

	Start implementing some notions of signals. The API
	is really terrible, but they sort of work (with the
	exception of being able to filter by service, and to
	transmit signals *as* a particular service). Need to
	figure out how to make messages come from the service
	we registered :-(
	
	* python/dbus_bindings.pyx.in:

	Removed duplicate message_handler callbacks.
	
2003-09-25  Havoc Pennington  <hp@redhat.com>

	* bus/session.conf.in: fix my mess

2003-09-25  Havoc Pennington  <hp@pobox.com>

	* bus/session.conf.in: fix security policy, reported by Seth Nickell

2003-09-25  Seth Nickell  <seth@gnome.org>

	* python/examples/example-service.py:

	Johan notices complete wrong code in example-service, but
	completely wrong in a way that works exactly the same (!).
	Johan is confused, how could this possibly work? Example
	code fails to serve purpose of making things clear.
	Seth fixes.

2003-09-25  Mark McLoughlin  <mark@skynet.ie>

	* doc/dbus-specification.sgml: don't require header fields
	to be 4-byte aligned and specify that fields should be
	distinguished from padding by the fact that zero is not
	a valid field name.
	
	* doc/TODO: remove re-alignment item and add item to doc
	the OBJECT_PATH type.
	
	* dbus/dbus-message.c:
	(HeaderField): rename the original member to value_offset
	and introduce a name_offset member to keep track of where
	the field actually begins.
	(adjust_field_offsets): remove.
	(append_int_field), (append_uint_field),
	(append_string_field): don't align the start of the header
	field to a 4-byte boundary.
	(get_next_field): impl finding the next marhsalled field
	after a given field.
	(re_align_field_recurse): impl re-aligning a number of
	already marshalled fields.
	(delete_field): impl deleting a field of any type and
	re-aligning any following fields.
	(delete_int_or_uint_field), (delete_string_field): remove.
	(set_int_field), (set_uint_field): no need to re-check
	that we have the correct type for the field.
	(set_string_field): ditto and impl re-aligning any
	following fields.
	(decode_header_data): update to take into account that
	the fields aren't 4-byte aligned any more and the new
	way to distinguish padding from header fields. Also,
	don't exit when there is too much header padding.
	(process_test_subdir): print the directory.
	(_dbus_message_test): add test to make sure a following
	field is re-aligned correctly after field deletion.
	
	* dbus/dbus-string.[ch]:
	(_dbus_string_insert_bytes): rename from insert_byte and
	allow the insert of multiple bytes.
	(_dbus_string_test): test inserting multiple bytes.

	* dbus/dbus-marshal.c: (_dbus_marshal_set_string): add
	warning note to docs about having to re-align any
	marshalled values following the string.
	
	* dbus/dbus-message-builder.c:
	(append_string_field), (_dbus_message_data_load):
	don't align the header field.
	
	* dbus/dbus-auth.c: (process_test_subdir): print the
	directory.
	
	* test/break-loader.c: (randomly_add_one_byte): upd. for
	insert_byte change.
	
	* test/data/invalid-messages/bad-header-field-alignment.message:
	new test case.
	
	* test/data/valid-messages/unknown-header-field.message: shove
	a dict in the unknown field.

2003-09-25  Seth Nickell  <seth@gnome.org>

	* python/dbus.py:
	* python/dbus_bindings.pyx.in:

	Handle return values.
	
	* python/examples/example-client.py:
	* python/examples/example-service.py:

	Pass back return values from the service to the client.
	
2003-09-24  Seth Nickell  <seth@gnome.org>

	* python/dbus.py:

	Connect Object methods (when you are sharing an object) up... pass
	in a list of methods to be shared. Sharing all the methods just
	worked out too weird. You can now create nice Services over the
	DBus in Python. :-)
	
	* python/dbus_bindings.pyx.in:

	Keep references to user_data tuples passed into C functions so 
	Python doesn't garbage collect on us.

	Implement MethodReturn and Error subclasses of Message for creating
	DBusMessage's of those types.
	
	* python/examples/example-client.py:
	* python/examples/example-service.py:

	Simple example code showing both how create DBus services and objects,
	and how to use them.

2003-09-23  Havoc Pennington  <hp@pobox.com>

	* glib/dbus-gproxy.c (dbus_gproxy_manager_filter): implement

2003-09-23  Havoc Pennington  <hp@redhat.com>

	* glib/dbus-gproxy.c (dbus_gproxy_connect_signal): implement
	(dbus_gproxy_disconnect_signal): implement
	(dbus_gproxy_manager_remove_signal_match): implement
	(dbus_gproxy_manager_add_signal_match): implement
	(dbus_gproxy_oneway_call): implement

2003-09-23  Havoc Pennington  <hp@pobox.com>

	* glib/dbus-gproxy.c (struct DBusGProxy): convert to a GObject
	subclass. This means dropping the transparent thread safety of the
	proxy; you now need a separate proxy per-thread, or your own
	locking on the proxy. Probably right anyway.
	(dbus_gproxy_ref, dbus_gproxy_unref): nuke, just use g_object_ref

2003-09-22  Havoc Pennington  <hp@redhat.com>

	* glib/dbus-gproxy.c (dbus_gproxy_manager_get): implement

2003-09-21  Seth Nickell  <seth@gnome.org>

        First checkin of the Python bindings.
	
	* python/.cvsignore:
	* python/Makefile.am:
	* python/dbus_bindings.pyx.in:
	* python/dbus_h_wrapper.h:

	Pieces for Pyrex to operate on, building a dbus_bindings.so
	python module for low-level access to the DBus APIs.
	
	* python/dbus.py:

	High-level Python module for accessing DBus objects.

	* configure.in:
	* Makefile.am:

	Build stuff for the python bindings.

	* acinclude.m4:

	Extra macro needed for finding the Python C header files.

2003-09-21  Havoc Pennington  <hp@pobox.com>

	* glib/dbus-gproxy.c (dbus_gproxy_manager_new): start
	implementing the proxy manager, didn't get very far.

	* dbus/dbus-bus.c (dbus_bus_add_match): new
	(dbus_bus_remove_match): new

	* glib/dbus-gproxy.c (dbus_gproxy_new_for_service): add a
	path_name argument; adjust the other not-yet-implemented 
	gproxy constructors to be what I think they should be.

2003-09-21  Havoc Pennington  <hp@pobox.com>

	* dbus/dbus-bus.c (dbus_bus_get): set exit_on_disconnect to TRUE
	by default for message bus connections.

	* dbus/dbus-connection.c (dbus_connection_dispatch): exit if
	exit_on_disconnect flag is set and we process the disconnected
	signal.
	(dbus_connection_set_exit_on_disconnect): new function

2003-09-21  Havoc Pennington  <hp@pobox.com>

	Get matching rules mostly working in the bus; only actually
	parsing the rule text remains. However, the client side of
	"signal connections" hasn't been started, this patch is only the
	bus side.
	
	* dbus/dispatch.c: fix for the matching rules changes
	
	* bus/driver.c (bus_driver_handle_remove_match)
	(bus_driver_handle_add_match): send an ack reply from these
	method calls

	* glib/dbus-gproxy.c (dbus_gproxy_begin_call): fix order of
	arguments, reported by Seth Nickell

	* bus/config-parser.c (append_rule_from_element): support
	eavesdrop=true|false attribute on policies so match rules 
	can be prevented from snooping on the system bus.

	* bus/dbus-daemon-1.1.in: consistently use terminology "sender"
	and "destination" in attribute names; fix some docs bugs; 
	add eavesdrop=true|false attribute

	* bus/driver.c (bus_driver_handle_add_match)
	(bus_driver_handle_remove_match): handle AddMatch, RemoveMatch
	messages

	* dbus/dbus-protocol.h (DBUS_SERVICE_ORG_FREEDESKTOP_BROADCAST): get
	rid of broadcast service concept, signals are just always broadcast

	* bus/signals.c, bus/dispatch.c, bus/connection.c, bus/bus.c:
	mostly implement matching rules stuff (currently only exposed as signal
	connections)

2003-09-21  Mark McLoughlin  <mark@skynet.ie>

	* doc/dbus-specification.sgml: Change the header field name
	to be an enum and update the rest of the spec to reference
	the fields using the conventinal name.

	* dbus/dbus-protocol.h: update to reflect the spec.

	* doc/TODO: add item to remove the 4 byte alignment requirement.
	
	* dbus/dbus-message.c: Remove the code to generalise the
	header/body length and serial number header fields as named
	header fields so we can reference field names using the 
	protocol values.
	(append_int_field), (append_uint_field), (append_string_field):
	Append the field name as a byte rather than four chars.
	(delete_int_or_uint_field), (delete_string_field): reflect the
	fact that the field name and typecode now occupy 4 bytes instead
	of 8.
	(decode_string_field), (decode_header_data): update to reflect
	protocol changes and move the field specific encoding from
	decode_string_field() back into decode_header_data().
	
	* dbus/dbus-internals.[ch]: (_dbus_header_field_to_string):
	Add utility to aid debugging.
	
	* dbus/dbus-message-builder.c:
	(append_string_field), (_dbus_message_data_load): Update to
	reflect protocol changes; Change the FIELD_NAME directive
	to HEADER_FIELD and allow it to take the field's conventional
	name rather than the actual value.
	
	* test/data/*/*.message: Update to use HEADER_FIELD instead
	of FIELD_NAME; Always align the header on an 8 byte boundary
	*before* updating the header length.

2003-09-15  Havoc Pennington  <hp@pobox.com>

	* dbus/dbus-pending-call.c: add the get/set object data
	boilerplate as for DBusConnection, etc. Use generic object data
	for the notify callback.

	* glib/dbus-gparser.c (parse_node): parse child nodes

	* tools/dbus-viewer.c: more hacking on the dbus-viewer
	
	* glib/dbus-gutils.c (_dbus_gutils_split_path): add a file to
	contain functions shared between the convenience lib and the
	installed lib

	* glib/Makefile.am (libdbus_glib_1_la_LDFLAGS): add
	-export-symbols-regex to the GLib library

	* dbus/dbus-object-tree.c (_dbus_object_tree_dispatch_and_unlock):
	fix the locking in here, and add a default handler for
	Introspect() that just returns sub-nodes.

2003-09-14  Havoc Pennington  <hp@pobox.com>

	* glib/dbus-gthread.c (dbus_g_thread_init): rename to make g_foo
	rather than gfoo consistent

	* glib/dbus-gproxy.h: delete for now, move contents to
	dbus-glib.h, because the include files don't work right since we
	aren't in the dbus/ subdir.
	
	* glib/dbus-gproxy.c (dbus_gproxy_send): finish implementing
	(dbus_gproxy_end_call): finish
	(dbus_gproxy_begin_call): finish

	* glib/dbus-gmain.c (dbus_set_g_error): new

	* glib/dbus-gobject.c (handle_introspect): include information
	about child nodes in the introspection

	* dbus/dbus-connection.c (dbus_connection_list_registered): new
	function to help in implementation of introspection

	* dbus/dbus-object-tree.c
	(_dbus_object_tree_list_registered_and_unlock): new function

2003-09-12  Havoc Pennington  <hp@pobox.com>

	* glib/dbus-gidl.h: add common base class for all the foo_info
	types

        * tools/dbus-viewer.c: add GTK-based introspection UI thingy
	similar to kdcop

	* test/Makefile.am: try test srcdir -ef . in addition to test
	srcdir = ., one of them should work (yeah lame)
	
        * glib/Makefile.am: build the "idl" parser stuff as a convenience
	library
	
	* glib/dbus-gparser.h: make description_load routines return
	NodeInfo* not Parser*

	* Makefile.am (SUBDIRS): build test dir after all library dirs

	* configure.in: add GTK+ detection

2003-09-07  Havoc Pennington  <hp@pobox.com>

	* Make Doxygen contented.

2003-09-07  Havoc Pennington  <hp@pobox.com>

	* doc/dbus-specification.sgml: more updates

2003-09-06  Havoc Pennington  <hp@pobox.com>

	* doc/dbus-specification.sgml: partial updates

	* bus/dbus-daemon-1.1.in: fix the config file docs for the
	zillionth time; hopefully I edited the right file this time.

	* bus/config-parser.c (append_rule_from_element): support
	send_type, send_path, receive_type, receive_path

	* bus/policy.c: add message type and path to the list of things
	that can be "firewalled"

2003-09-06  Havoc Pennington  <hp@pobox.com>

	* dbus/dbus-connection.c (dbus_connection_register_fallback): add this
	(dbus_connection_register_object_path): make this not handle
	messages to paths below the given path

2003-09-03  Havoc Pennington  <hp@pobox.com>

	* test/glib/Makefile.am: add this with random glib-linked test
	programs

	* glib/Makefile.am: remove the random test programs from here,
	leave only the unit tests

	* glib/dbus-gobject.c (_dbus_gobject_test): add test for 
	uscore/javacaps conversion, and fix	
	(get_object_property, set_object_property): change to .NET
	convention for mapping props to methods, set_FooBar/get_FooBar, 
	since one language has such a convention we may as well copy it. 
	Plus real methods in either getFooBar or get_foo_bar style won't 
	collide with this convention.

2003-09-01  Havoc Pennington  <hp@pobox.com>

	* glib/dbus-gparser.c: implement

	* glib/dbus-gobject.c: start implementing skeletons support

	* configure.in: when disabling checks/assert, also define
	G_DISABLE_ASSERT and G_DISABLE_CHECKS

2003-09-01  Havoc Pennington  <hp@pobox.com>

	* glib/Makefile.am: rearrange a bunch of files and get "make
	check" framework set up

2003-08-31  Havoc Pennington  <hp@pobox.com>

	* fix build with --disable-tests

2003-08-30  Havoc Pennington  <hp@pobox.com>

	* dbus/dbus-connection.c: purge DBusMessageHandler

	* dbus/dbus-message-handler.c: remove DBusMessageHandler, just 
	use callbacks everywhere

2003-08-30  Havoc Pennington  <hp@pobox.com>

	* test/data/valid-config-files/system.d/test.conf: change to 
	root for the user so warnings don't get printed

	* dbus/dbus-message.c: add dbus_message_get_path,
	dbus_message_set_path
	
	* dbus/dbus-object-tree.c (do_test_dispatch): add test of
	dispatching to a path

	* dbus/dbus-string.c (_dbus_string_validate_path): add

	* dbus/dbus-marshal.c (_dbus_demarshal_object_path): implement
	(_dbus_marshal_object_path): implement

	* dbus/dbus-protocol.h (DBUS_HEADER_FIELD_PATH): new header field 
	to contain the path to the target object
	(DBUS_HEADER_FIELD_SENDER_SERVICE): rename
	DBUS_HEADER_FIELD_SENDER to explicitly say it's the sender service

2003-08-30  Havoc Pennington  <hp@pobox.com>

	* dbus/dbus-object-tree.c: write tests and fix the discovered bugs

2003-08-29  Havoc Pennington  <hp@pobox.com>

	* dbus/dbus-object-tree.c: modify to allow overlapping paths to be
	registered
	(struct DBusObjectSubtree): shrink this
	a lot, since we may have a lot of them
	(_dbus_object_tree_free_all_unlocked): implement
	(_dbus_object_tree_dispatch_and_unlock): implement

2003-08-29  Havoc Pennington  <hp@pobox.com>

	* dbus/dbus-internals.h: fix _DBUS_N_GLOBAL_LOCKS

2003-08-28  Havoc Pennington  <hp@pobox.com>

	purge DBusObjectID
	
	* dbus/dbus-connection.c: port to no ObjectID, create a
	DBusObjectTree, rename ObjectTree to ObjectPath in public API

	* dbus/dbus-connection.h (struct DBusObjectTreeVTable): delete 
	everything except UnregisterFunction and MessageFunction
	
	* dbus/dbus-marshal.c: port away from DBusObjectID, 
	add DBUS_TYPE_OBJECT_PATH
	
	* dbus/dbus-object-registry.[hc], dbus/dbus-object.[hc], 
	dbus/dbus-objectid.[hc]: remove these, we are moving to 
	path-based object IDs

2003-08-25  Havoc Pennington  <hp@pobox.com>

        Just noticed that dbus_message_test is hosed, I wonder when I
	broke that. I thought make check was passing earlier...
	
	* dbus/dbus-object-tree.c: add new "object tree" to match DCOP 
	container tree, will replace most of dbus-object-registry

	* dbus/dbus-string.c (_dbus_string_append_printf_valist): fix C99
	screwup

2003-08-19  Havoc Pennington  <hp@pobox.com>

	* dbus/dbus-message.c (decode_string_field): support FIELD_SENDER
	(dbus_message_is_error): fix this function

	* bus/dbus-daemon-1.1: clarify logic on when <deny>/<allow> rules
	match

	* bus/policy.c (bus_client_policy_check_can_receive): fix code to
	reflect clarified man page
	(bus_client_policy_check_can_send): ditto
	
	* bus/session.conf.in: fixup

	* bus/system.conf.in: fixup

2003-08-18  Havoc Pennington  <hp@redhat.com>

	* dbus/dbus-hash.c (_dbus_hash_table_insert_two_strings): fix

	* dbus/dbus-message.c (_dbus_message_loader_queue_messages): fix
	dumb bug created earlier (wrong order of args to
	decode_header_data())
	
	* tools/dbus-send.c: port

	* tools/dbus-print-message.c (print_message): port

        * test/data/*messages: port all messages over
	
        * dbus/dbus-message-builder.c: support including 
	message type
	
        * bus/driver.c: port over
	
	* bus/dispatch.c: port over to new stuff

	* dbus/dbus-connection.c (_dbus_connection_new_for_transport):
	rename disconnect signal to "Disconnected"

2003-08-17  Havoc Pennington  <hp@pobox.com>

	This doesn't compile yet, but syncing up so I can hack on it from
	work. What are branches for if not broken code? ;-)
	
	* dbus/dbus-protocol.h: remove DBUS_HEADER_FIELD_NAME, add
	DBUS_HEADER_FIELD_INTERFACE, DBUS_HEADER_FIELD_MEMBER,
	DBUS_HEADER_FIELD_ERROR_NAME
	
	* dbus/dbus-hash.c: Introduce DBUS_HASH_TWO_STRINGS as hack to use
	for the interface+member pairs
	(string_hash): change to use g_str_hash algorithm
	(find_direct_function, find_string_function): refactor these to
	share most code.
	
	* dbus/dbus-message.c: port all of this over to support 
	interface/member fields instead of name field

	* dbus/dbus-object-registry.c: port over
	
	* dbus/dbus-string.c (_dbus_string_validate_interface): rename
	from _dbus_string_validate_name

	* bus/dbus-daemon-1.1: change file format for the 
	<deny>/<allow> stuff to match new message naming scheme

	* bus/policy.c: port over

	* bus/config-parser.c: parse new format
	
2003-08-16  Havoc Pennington  <hp@pobox.com>

	* dbus/dbus-object-registry.c (add_and_remove_objects): remove
	broken assertion

	* glib/dbus-gproxy.c: some hacking

2003-08-15  Havoc Pennington  <hp@redhat.com>

	* dbus/dbus-pending-call.c (dbus_pending_call_block): implement

	* dbus/dbus-connection.c
	(dbus_connection_send_with_reply_and_block): factor out internals;
	change to convert any error replies to DBusError instead of 
	returning them as a message

2003-08-15  Havoc Pennington  <hp@pobox.com>

	* dbus/dbus-connection.c, 
	dbus/dbus-pending-call.c: Finish the pending call stuff

2003-08-14  Havoc Pennington  <hp@redhat.com>

	* dbus/dbus-pending-call.c: start on new object that will replace
	DBusMessageHandler and ReplyHandlerData for tracking outstanding
	replies

	* dbus/dbus-gproxy.c: start on proxy object used to communicate
	with remote interfaces

	* dbus/dbus-gidl.c: do the boring boilerplate in here
	
2003-08-12  Havoc Pennington  <hp@pobox.com>

	* bus/dispatch.c (bus_dispatch): make this return proper 
	DBusHandlerResult to avoid DBUS_ERROR_UNKNOWN_METHOD

	* dbus/dbus-errors.c (dbus_set_error): use
	_dbus_string_append_printf_valist

	* dbus/dbus-string.c (_dbus_string_append_printf_valist)
	(_dbus_string_append_printf): new

	* dbus/dbus-errors.h (DBUS_ERROR_UNKNOWN_MESSAGE): change to
	UNKNOWN_METHOD

	* dbus/dbus-connection.c (dbus_connection_dispatch): handle
	DBUS_HANDLER_RESULT_NEED_MEMORY; send default error reply if a
	message is unhandled.

2003-08-11  Havoc Pennington  <hp@pobox.com>

	* bus/test.c (client_disconnect_handler): change to return
	HANDLED (would have been REMOVE_MESSAGE)

	* dbus/dbus-object.h (enum DBusHandlerResult): rename to
	HANDLED/NOT_YET_HANDLED instead of
	REMOVE_MESSAGE/ALLOW_MORE_HANDLERS to make it clearer how it 
	should be used.

2003-08-10  Havoc Pennington  <hp@pobox.com>

	* tools/dbus-send.c (main): add --type argument, for now
	supporting only method_call and signal types.

	* tools/dbus-print-message.c: print message type

	* dbus/dbus-connection.c (_dbus_connection_new_for_transport):
	init connection->objects

	* doc/dbus-specification.sgml: fix sgml

	* bus/*.c: port over to object-instance API changes

	* test/test-service.c: ditto
	
	* dbus/dbus-message.c (dbus_message_create_header): allow #NULL
	name, we will have to fix up the rest of the code to also handle
	this
	(dbus_message_new): generic message-creation call
	(set_string_field): allow appending name field

2003-08-06  Havoc Pennington  <hp@pobox.com>

	* dbus/dbus-object-registry.c: implement signal connection 
	and dispatch

	* dbus/dbus-connection.c (_dbus_connection_unref_unlocked): new

	* dbus/dbus-internals.c (_dbus_memdup): new function

2003-08-02  Havoc Pennington  <hp@pobox.com>

	* dbus/dbus-message.c (dbus_message_get_no_reply)
	(dbus_message_set_no_reply): add these and remove
	set_is_error/get_is_error

	* dbus/dbus-protocol.h, doc/dbus-specification.sgml: 
	remove the ERROR flag, since there's now an ERROR type

2003-08-01  Havoc Pennington  <hp@pobox.com>

	* dbus/dbus-object-registry.c (_dbus_object_registry_handle_and_unlock):
	implement

	* dbus/dbus-message.c (dbus_message_get_type): new function

	* doc/dbus-specification.sgml: add "type" byte to messages

2003-08-01  Havoc Pennington  <hp@pobox.com>

	* dbus/dbus-protocol.h (DBUS_MESSAGE_TYPE_*): introduce
	a message type enum to distinguish kinds of message
	(DBUS_HEADER_FLAG_NO_REPLY_EXPECTED): flag for a message 
	that need not be replied to

2003-08-01  Havoc Pennington  <hp@pobox.com>

	* dbus/dbus-marshal.c: adapt to DBusObjectID changes
	(unpack_8_octets): fix no-64-bit-int bug

	* dbus/dbus-object-registry.c (validate_id): validate the 
	connection ID bits, not just the instance ID.

	* dbus/dbus-connection.c (_dbus_connection_init_id): initialize
	the connection-global 33 bits of the object ID

	* dbus/dbus-object-registry.c (info_from_entry): fill in 
	object ID in the new way

	* dbus/dbus-objectid.h: rather than high/low bits, specifically 
	define server/client/instance bits.

2003-07-30  Havoc Pennington  <hp@pobox.com>

	* dbus/dbus-connection.c (dbus_connection_register_object): fix
	build

2003-07-13  Havoc Pennington  <hp@pobox.com>

	* dbus/dbus-object.h (struct DBusObjectVTable): add padding
	fields to DBusObjectVTable and DBusObjectInfo

2003-07-12  Havoc Pennington  <hp@pobox.com>

	* dbus/dbus-object-registry.c: implement unit test,
	fix bugs discovered in process

	* dbus/dbus-connection.c: remove handler_table and
	register_handler(), add DBusObjectRegistry usage

	* dbus/dbus-objectid.c (dbus_object_id_is_null)
	(dbus_object_id_set_null): new functions

2003-07-08  Havoc Pennington  <hp@pobox.com>

	* dbus/dbus-object.c: implement some of this

	* dbus/dbus-object-registry.c
	(_dbus_object_registry_add_and_unlock): fill in the object_id out
	param
	(_dbus_object_registry_new): handle OOM

2003-07-08  Havoc Pennington  <hp@pobox.com>

	* dbus/dbus-object.h: sketch out an API for registering objects
	with a connection, that allows us to use as little as 24 bytes
	per object and lets application code represent an object in 
	any conceivable way.

	* dbus/dbus-object-registry.c: implement the hard bits of the
	DBusConnection aspect of object API. Not yet wired up.
	
2003-07-06  Havoc Pennington  <hp@pobox.com>

	* dbus/dbus-marshal.c (_dbus_marshal_set_object_id): new function
	(_dbus_marshal_object_id): new
	(_dbus_demarshal_object_id): new
	(_dbus_marshal_get_arg_end_pos): support object ID type, and
	consolidate identical switch cases. Don't conditionalize handling
	of DBUS_TYPE_UINT64, need to handle the type always.
	(_dbus_marshal_validate_arg): consolidate identical cases, and
	handle DBUS_TYPE_OBJECT_ID

	* dbus/dbus-objectid.c: new file with DBusObjectID data type.

	* dbus/dbus-protocol.h: add DBUS_TYPE_OBJECT_ID

2003-09-28  Havoc Pennington  <hp@pobox.com>

	* real 0.13 release

2003-09-28  Havoc Pennington  <hp@pobox.com>

	* doc/Makefile.am (dbus-specification.html): testing a funky hack
	to work with Debian db2html

2003-09-28  Havoc Pennington  <hp@pobox.com>

	* configure.in: 0.13

	* doc/Makefile.am (dbus-test-plan.html): accept nonexistence of
	stylesheet-images for benefit of Debian
	
	Change back to using filesystem-linked sockets for the system
	bus, so only root can create the default system bus address.
	
	* bus/system.conf.in: change to use
	DBUS_SYSTEM_BUS_DEFAULT_ADDRESS

	* dbus/Makefile.am (INCLUDES): remove DBUS_SYSTEM_BUS_PATH define
	from here.

	* configure.in: define DBUS_SYSTEM_BUS_DEFAULT_ADDRESS
	here, and AC_DEFINE DBUS_SYSTEM_PATH

2003-08-09  Anders Carlsson  <andersca@codefactory.se>

	* doc/TODO:
	* doc/busconfig.dtd:
	Add busconfig DTD.
	
2003-08-09  Anders Carlsson  <andersca@codefactory.se>

	* doc/dbus-specification.sgml:
	Add activation reply values.
	
2003-08-05  Havoc Pennington  <hp@redhat.com>

	* configure.in: 0.12

2003-08-05  Anders Carlsson  <andersca@codefactory.se>

	* glib/dbus-gmain.c: (watch_fd_new), (watch_fd_ref),
	(watch_fd_unref), (dbus_gsource_check), (dbus_gsource_dispatch),
	(add_watch), (remove_watch), (create_source):
	Refcount fds, fixes some reentrancy issues.
	
2003-07-30  Havoc Pennington  <hp@redhat.com>

	* dbus/dbus-bus.c (init_connections_unlocked): fix default system
	bus address to be abstract if we have abstract sockets

	* NEWS: update

2003-07-28  Havoc Pennington  <hp@redhat.com>

	* bus/messagebus.in: fix to avoid processname/servicename 
	confusion, from Michael Kearey
	https://bugzilla.redhat.com/bugzilla/show_bug.cgi?id=100965
	
2003-07-23  Havoc Pennington  <hp@pobox.com>

	* dbus/dbus-message.c (dbus_message_iter_get_named): 
	fix from Andy Hanton to remove broken "+1"

2003-07-16  Havoc Pennington  <hp@pobox.com>

	* tools/dbus-launch.c (babysit): close stdout/stderr in the
	babysitter process, as suggested by Thomas Leonard, so 
	an "eval `dbus-launch --exit-with-session`" will actually 
	return

2003-07-16  Havoc Pennington  <hp@pobox.com>

	* configure.in: print out EXPANDED_* variables in the summary at
	the end; clean up the code that computes EXPANDED_ variables and
	get the ones using exec_prefix right. Should make things work
	when you build without --prefix






Index: Makefile.am
===================================================================
RCS file: /cvs/dbus/dbus/bus/Makefile.am,v
retrieving revision 1.27
retrieving revision 1.28
diff -u -d -r1.27 -r1.28
--- Makefile.am	16 May 2003 16:01:56 -0000	1.27
+++ Makefile.am	30 Sep 2003 02:32:50 -0000	1.28
@@ -44,6 +44,8 @@
 	policy.h				\
 	services.c				\
 	services.h				\
+	signals.c				\
+	signals.h				\
 	test.c					\
 	test.h					\
 	utils.c					\

Index: activation.c
===================================================================
RCS file: /cvs/dbus/dbus/bus/activation.c,v
retrieving revision 1.27
retrieving revision 1.28
diff -u -d -r1.27 -r1.28
--- activation.c	14 May 2003 02:40:41 -0000	1.27
+++ activation.c	30 Sep 2003 02:32:50 -0000	1.28
@@ -586,7 +586,7 @@
       
       if (dbus_connection_get_is_connected (entry->connection))
 	{
-	  message = dbus_message_new_reply (entry->activation_message);
+	  message = dbus_message_new_method_return (entry->activation_message);
 	  if (!message)
 	    {
 	      BUS_SET_OOM (error);
@@ -866,7 +866,7 @@
     {
       _dbus_verbose ("Service \"%s\" is already active\n", service_name);
       
-      message = dbus_message_new_reply (activation_message);
+      message = dbus_message_new_method_return (activation_message);
 
       if (!message)
 	{

Index: bus.c
===================================================================
RCS file: /cvs/dbus/dbus/bus/bus.c,v
retrieving revision 1.38
retrieving revision 1.39
diff -u -d -r1.38 -r1.39
--- bus.c	22 Jun 2003 19:39:46 -0000	1.38
+++ bus.c	30 Sep 2003 02:32:50 -0000	1.39
@@ -28,6 +28,7 @@
 #include "utils.h"
 #include "policy.h"
 #include "config-parser.h"
+#include "signals.h"
 #include <dbus/dbus-list.h>
 #include <dbus/dbus-hash.h>
 #include <dbus/dbus-internals.h>
@@ -44,6 +45,7 @@
   BusActivation *activation;
   BusRegistry *registry;
   BusPolicy *policy;
+  BusMatchmaker *matchmaker;
   DBusUserDatabase *user_database;
   BusLimits limits;
 };
@@ -505,6 +507,13 @@
       goto failed;
     }
 
+  context->matchmaker = bus_matchmaker_new ();
+  if (context->matchmaker == NULL)
+    {
+      BUS_SET_OOM (error);
+      goto failed;
+    }
+  
   context->policy = bus_config_parser_steal_policy (parser);
   _dbus_assert (context->policy != NULL);
   
@@ -715,6 +724,12 @@
           _dbus_loop_unref (context->loop);
           context->loop = NULL;
         }
+
+      if (context->matchmaker)
+        {
+          bus_matchmaker_unref (context->matchmaker);
+          context->matchmaker = NULL;
+        }
       
       dbus_free (context->type);
       dbus_free (context->address);
@@ -771,6 +786,12 @@
   return context->activation;
 }
 
+BusMatchmaker*
+bus_context_get_matchmaker (BusContext  *context)
+{
+  return context->matchmaker;
+}
+
 DBusLoop*
 bus_context_get_loop (BusContext *context)
 {
@@ -845,18 +866,33 @@
   return context->limits.max_services_per_connection;
 }
 
+int
+bus_context_get_max_match_rules_per_connection (BusContext *context)
+{
+  return context->limits.max_match_rules_per_connection;
+}
+
 dbus_bool_t
 bus_context_check_security_policy (BusContext     *context,
                                    DBusConnection *sender,
-                                   DBusConnection *recipient,
+                                   DBusConnection *addressed_recipient,
+                                   DBusConnection *proposed_recipient,
                                    DBusMessage    *message,
                                    DBusError      *error)
 {
   BusClientPolicy *sender_policy;
   BusClientPolicy *recipient_policy;
 
-  /* NULL sender/receiver means the bus driver */
+  /* NULL sender, proposed_recipient means the bus driver.  NULL
+   * addressed_recipient means the message didn't specify an explicit
+   * target. If proposed_recipient is NULL, then addressed_recipient
+   * is also NULL but is implicitly the bus driver.
+   */
 
+  _dbus_assert (proposed_recipient == NULL ||
+                (dbus_message_get_destination (message) == NULL ||
+                 addressed_recipient != NULL));
+  
   if (sender != NULL)
     {
       if (bus_connection_is_active (sender))
@@ -869,21 +905,23 @@
           /* Policy for inactive connections is that they can only send
            * the hello message to the bus driver
            */
-          if (recipient == NULL &&
-              dbus_message_has_name (message, DBUS_MESSAGE_HELLO))
+          if (proposed_recipient == NULL &&
+              dbus_message_is_method_call (message,
+                                           DBUS_INTERFACE_ORG_FREEDESKTOP_DBUS,
+                                           "Hello"))
             {
               _dbus_verbose ("security check allowing %s message\n",
-                             DBUS_MESSAGE_HELLO);
+                             "Hello");
               return TRUE;
             }
           else
             {
               _dbus_verbose ("security check disallowing non-%s message\n",
-                             DBUS_MESSAGE_HELLO);
+                             "Hello");
 
               dbus_set_error (error, DBUS_ERROR_ACCESS_DENIED,
                               "Client tried to send a message other than %s without being registered",
-                              DBUS_MESSAGE_HELLO);
+                              "Hello");
               
               return FALSE;
             }
@@ -895,15 +933,15 @@
   _dbus_assert ((sender != NULL && sender_policy != NULL) ||
                 (sender == NULL && sender_policy == NULL));
   
-  if (recipient != NULL)
+  if (proposed_recipient != NULL)
     {
       /* only the bus driver can send to an inactive recipient (as it
        * owns no services, so other apps can't address it). Inactive
        * recipients can receive any message.
        */
-      if (bus_connection_is_active (recipient))
+      if (bus_connection_is_active (proposed_recipient))
         {
-          recipient_policy = bus_connection_get_policy (recipient);
+          recipient_policy = bus_connection_get_policy (proposed_recipient);
           _dbus_assert (recipient_policy != NULL);
         }
       else if (sender == NULL)
@@ -920,13 +958,13 @@
   else
     recipient_policy = NULL;
   
-  _dbus_assert ((recipient != NULL && recipient_policy != NULL) ||
-                (recipient != NULL && sender == NULL && recipient_policy == NULL) ||
-                (recipient == NULL && recipient_policy == NULL));
+  _dbus_assert ((proposed_recipient != NULL && recipient_policy != NULL) ||
+                (proposed_recipient != NULL && sender == NULL && recipient_policy == NULL) ||
+                (proposed_recipient == NULL && recipient_policy == NULL));
   
   if (sender_policy &&
       !bus_client_policy_check_can_send (sender_policy,
-                                         context->registry, recipient,
+                                         context->registry, proposed_recipient,
                                          message))
     {
       const char *dest = dbus_message_get_destination (message);
@@ -934,9 +972,14 @@
                       "A security policy in place prevents this sender "
                       "from sending this message to this recipient, "
                       "see message bus configuration file (rejected message "
-                      "had name \"%s\" destination \"%s\")",
-                      dbus_message_get_name (message),
-                      dest ? dest : DBUS_SERVICE_DBUS);
+                      "had interface \"%s\" member \"%s\" error name \"%s\" destination \"%s\")",
+                      dbus_message_get_interface (message) ?
+                      dbus_message_get_interface (message) : "(unset)",
+                      dbus_message_get_member (message) ?
+                      dbus_message_get_member (message) : "(unset)",
+                      dbus_message_get_error_name (message) ?
+                      dbus_message_get_error_name (message) : "(unset)",
+                      dest ? dest : DBUS_SERVICE_ORG_FREEDESKTOP_DBUS);
       _dbus_verbose ("security policy disallowing message due to sender policy\n");
       return FALSE;
     }
@@ -944,6 +987,7 @@
   if (recipient_policy &&
       !bus_client_policy_check_can_receive (recipient_policy,
                                             context->registry, sender,
+                                            addressed_recipient, proposed_recipient,
                                             message))
     {
       const char *dest = dbus_message_get_destination (message);
@@ -951,22 +995,29 @@
                       "A security policy in place prevents this recipient "
                       "from receiving this message from this sender, "
                       "see message bus configuration file (rejected message "
-                      "had name \"%s\" destination \"%s\")",
-                      dbus_message_get_name (message),
-                      dest ? dest : DBUS_SERVICE_DBUS);
+                      "had interface \"%s\" member \"%s\" error name \"%s\" destination \"%s\")",
+                      dbus_message_get_interface (message) ?
+                      dbus_message_get_interface (message) : "(unset)",
+                      dbus_message_get_member (message) ?
+                      dbus_message_get_member (message) : "(unset)",
+                      dbus_message_get_error_name (message) ?
+                      dbus_message_get_error_name (message) : "(unset)",
+                      dest ? dest : DBUS_SERVICE_ORG_FREEDESKTOP_DBUS);
       _dbus_verbose ("security policy disallowing message due to recipient policy\n");
       return FALSE;
     }
 
   /* See if limits on size have been exceeded */
-  if (recipient &&
-      dbus_connection_get_outgoing_size (recipient) >
+  if (proposed_recipient &&
+      dbus_connection_get_outgoing_size (proposed_recipient) >
       context->limits.max_outgoing_bytes)
     {
       const char *dest = dbus_message_get_destination (message);
       dbus_set_error (error, DBUS_ERROR_LIMITS_EXCEEDED,
                       "The destination service \"%s\" has a full message queue",
-                      dest ? dest : DBUS_SERVICE_DBUS);
+                      dest ? dest : (proposed_recipient ?
+                                     bus_connection_get_name (proposed_recipient) : 
+                                     DBUS_SERVICE_ORG_FREEDESKTOP_DBUS));
       _dbus_verbose ("security policy disallowing message due to full message queue\n");
       return FALSE;
     }

Index: bus.h
===================================================================
RCS file: /cvs/dbus/dbus/bus/bus.h,v
retrieving revision 1.18
retrieving revision 1.19
diff -u -d -r1.18 -r1.19
--- bus.h	4 May 2003 08:54:24 -0000	1.18
+++ bus.h	30 Sep 2003 02:32:50 -0000	1.19
@@ -40,7 +40,8 @@
 typedef struct BusRegistry      BusRegistry;
 typedef struct BusService       BusService;
 typedef struct BusTransaction   BusTransaction;
-
+typedef struct BusMatchmaker    BusMatchmaker;
+typedef struct BusMatchRule     BusMatchRule;
 
 typedef struct
 {
@@ -54,40 +55,44 @@
   int max_connections_per_user;     /**< Max number of connections auth'd as same user */
   int max_pending_activations;      /**< Max number of pending activations for the entire bus */
   int max_services_per_connection;  /**< Max number of owned services for a single connection */
+  int max_match_rules_per_connection; /**< Max number of match rules for a single connection */
 } BusLimits;
 
-BusContext*       bus_context_new                             (const DBusString *config_file,
-                                                               dbus_bool_t       force_fork,
-                                                               int               print_addr_fd,
-                                                               int               print_pid_fd,
-                                                               DBusError        *error);
-void              bus_context_shutdown                        (BusContext       *context);
-void              bus_context_ref                             (BusContext       *context);
-void              bus_context_unref                           (BusContext       *context);
-const char*       bus_context_get_type                        (BusContext       *context);
-const char*       bus_context_get_address                     (BusContext       *context);
-BusRegistry*      bus_context_get_registry                    (BusContext       *context);
-BusConnections*   bus_context_get_connections                 (BusContext       *context);
-BusActivation*    bus_context_get_activation                  (BusContext       *context);
-DBusLoop*         bus_context_get_loop                        (BusContext       *context);
-DBusUserDatabase* bus_context_get_user_database               (BusContext       *context);
-dbus_bool_t       bus_context_allow_user                      (BusContext       *context,
-                                                               unsigned long     uid);
-BusClientPolicy*  bus_context_create_client_policy            (BusContext       *context,
-                                                               DBusConnection   *connection,
-                                                               DBusError        *error);
+BusContext*       bus_context_new                                (const DBusString *config_file,
+                                                                  dbus_bool_t       force_fork,
+                                                                  int               print_addr_fd,
+                                                                  int               print_pid_fd,
+                                                                  DBusError        *error);
+void              bus_context_shutdown                           (BusContext       *context);
+void              bus_context_ref                                (BusContext       *context);
+void              bus_context_unref                              (BusContext       *context);
+const char*       bus_context_get_type                           (BusContext       *context);
+const char*       bus_context_get_address                        (BusContext       *context);
+BusRegistry*      bus_context_get_registry                       (BusContext       *context);
+BusConnections*   bus_context_get_connections                    (BusContext       *context);
+BusActivation*    bus_context_get_activation                     (BusContext       *context);
+BusMatchmaker*    bus_context_get_matchmaker                     (BusContext       *context);
+DBusLoop*         bus_context_get_loop                           (BusContext       *context);
+DBusUserDatabase* bus_context_get_user_database                  (BusContext       *context);
+dbus_bool_t       bus_context_allow_user                         (BusContext       *context,
+                                                                  unsigned long     uid);
+BusClientPolicy*  bus_context_create_client_policy               (BusContext       *context,
+                                                                  DBusConnection   *connection,
+                                                                  DBusError        *error);
+int               bus_context_get_activation_timeout             (BusContext       *context);
+int               bus_context_get_auth_timeout                   (BusContext       *context);
+int               bus_context_get_max_completed_connections      (BusContext       *context);
+int               bus_context_get_max_incomplete_connections     (BusContext       *context);
+int               bus_context_get_max_connections_per_user       (BusContext       *context);
+int               bus_context_get_max_pending_activations        (BusContext       *context);
+int               bus_context_get_max_services_per_connection    (BusContext       *context);
+int               bus_context_get_max_match_rules_per_connection (BusContext       *context);
+dbus_bool_t       bus_context_check_security_policy              (BusContext       *context,
+                                                                  DBusConnection   *sender,
+                                                                  DBusConnection   *addressed_recipient,
+                                                                  DBusConnection   *proposed_recipient,
+                                                                  DBusMessage      *message,
+                                                                  DBusError        *error);
 
-int               bus_context_get_activation_timeout          (BusContext       *context);
-int               bus_context_get_auth_timeout                (BusContext       *context);
-int               bus_context_get_max_completed_connections   (BusContext       *context);
-int               bus_context_get_max_incomplete_connections  (BusContext       *context);
-int               bus_context_get_max_connections_per_user    (BusContext       *context);
-int               bus_context_get_max_pending_activations     (BusContext       *context);
-int               bus_context_get_max_services_per_connection (BusContext       *context);
-dbus_bool_t       bus_context_check_security_policy           (BusContext       *context,
-                                                               DBusConnection   *sender,
-                                                               DBusConnection   *recipient,
-                                                               DBusMessage      *message,
-                                                               DBusError        *error);
 
 #endif /* BUS_BUS_H */

Index: config-parser.c
===================================================================
RCS file: /cvs/dbus/dbus/bus/config-parser.c,v
retrieving revision 1.21
retrieving revision 1.22
diff -u -d -r1.21 -r1.22
--- config-parser.c	17 May 2003 17:53:16 -0000	1.21
+++ config-parser.c	30 Sep 2003 02:32:50 -0000	1.22
@@ -88,9 +88,12 @@
 
 } Element;
 
+/**
+ * Parser for bus configuration file. 
+ */
 struct BusConfigParser
 {
-  int refcount;
+  int refcount;        /**< Reference count */
 
   DBusString basedir;  /**< Directory we resolve paths relative to */
   
@@ -331,6 +334,8 @@
 
   parser->limits.max_pending_activations = 256;
   parser->limits.max_services_per_connection = 256;
+
+  parser->limits.max_match_rules_per_connection = 128;
   
   parser->refcount = 1;
 
@@ -808,6 +813,21 @@
     }
 }
 
+static int
+message_type_from_string (const char *type_str)
+{
+  if (strcmp (type_str, "method_call") == 0)
+    return DBUS_MESSAGE_TYPE_METHOD_CALL;
+  if (strcmp (type_str, "method_return") == 0)
+    return DBUS_MESSAGE_TYPE_METHOD_RETURN;
+  else if (strcmp (type_str, "signal") == 0)
+    return DBUS_MESSAGE_TYPE_SIGNAL;
+  else if (strcmp (type_str, "error") == 0)
+    return DBUS_MESSAGE_TYPE_ERROR;
+  else
+    return DBUS_MESSAGE_TYPE_INVALID;
+}
+
 static dbus_bool_t
 append_rule_from_element (BusConfigParser   *parser,
                           const char        *element_name,
@@ -816,11 +836,20 @@
                           dbus_bool_t        allow,
                           DBusError         *error)
 {
-  const char *send;
-  const char *receive;
+  const char *send_interface;
+  const char *send_member;
+  const char *send_error;
+  const char *send_destination;
+  const char *send_path;
+  const char *send_type;
+  const char *receive_interface;
+  const char *receive_member;
+  const char *receive_error;
+  const char *receive_sender;
+  const char *receive_path;
+  const char *receive_type;
+  const char *eavesdrop;
   const char *own;
-  const char *send_to;
-  const char *receive_from;
   const char *user;
   const char *group;
   BusPolicyRule *rule;
@@ -829,57 +858,147 @@
                           attribute_names,
                           attribute_values,
                           error,
-                          "send", &send,
-                          "receive", &receive,
+                          "send_interface", &send_interface,
+                          "send_member", &send_member,
+                          "send_error", &send_error,
+                          "send_destination", &send_destination,
+                          "send_path", &send_path,
+                          "send_type", &send_type,
+                          "receive_interface", &receive_interface,
+                          "receive_member", &receive_member,
+                          "receive_error", &receive_error,
+                          "receive_sender", &receive_sender,
+                          "receive_path", &receive_path,
+                          "receive_type", &receive_type,
+                          "eavesdrop", &eavesdrop,
                           "own", &own,
-                          "send_to", &send_to,
-                          "receive_from", &receive_from,
                           "user", &user,
                           "group", &group,
                           NULL))
     return FALSE;
 
-  if (!(send || receive || own || send_to || receive_from ||
-        user || group))
+  if (!(send_interface || send_member || send_error || send_destination ||
+        send_type || send_path ||
+        receive_interface || receive_member || receive_error || receive_sender ||
+        receive_type || receive_path || eavesdrop ||
+        own || user || group))
     {
       dbus_set_error (error, DBUS_ERROR_FAILED,
                       "Element <%s> must have one or more attributes",
                       element_name);
       return FALSE;
     }
+
+  if ((send_member && (send_interface == NULL && send_path == NULL)) ||
+      (receive_member && (receive_interface == NULL && receive_path == NULL)))
+    {
+      dbus_set_error (error, DBUS_ERROR_FAILED,
+                      "On element <%s>, if you specify a member you must specify an interface or a path. Keep in mind that not all messages have an interface field.",
+                      element_name);
+      return FALSE;
+    }
   
-  if (((send && own) ||
-       (send && receive) ||
-       (send && receive_from) ||
-       (send && user) ||
-       (send && group)) ||
+  /* Allowed combinations of elements are:
+   *
+   *   base, must be all send or all receive:
+   *     nothing
+   *     interface
+   *     interface + member
+   *     error
+   * 
+   *   base send_ can combine with send_destination, send_path, send_type
+   *   base receive_ with receive_sender, receive_path, receive_type, eavesdrop
+   *
+   *   user, group, own must occur alone
+   *
+   * Pretty sure the below stuff is broken, FIXME think about it more.
+   */
 
-      ((receive && own) ||
-       (receive && send_to) ||
-       (receive && user) ||
-       (receive && group)) ||
+  if (((send_interface && send_error) ||
+       (send_interface && receive_interface) ||
+       (send_interface && receive_member) ||
+       (send_interface && receive_error) ||
+       (send_interface && receive_sender) ||
+       (send_interface && eavesdrop) ||
+       (send_interface && own) ||
+       (send_interface && user) ||
+       (send_interface && group)) ||
 
-      ((own && send_to) ||
-       (own && receive_from) ||
-       (own && user) ||
-       (own && group)) ||
+      ((send_member && send_error) ||
+       (send_member && receive_interface) ||
+       (send_member && receive_member) ||
+       (send_member && receive_error) ||
+       (send_member && receive_sender) ||
+       (send_member && eavesdrop) ||
+       (send_member && own) ||
+       (send_member && user) ||
+       (send_member && group)) ||
+      
+      ((send_error && receive_interface) ||
+       (send_error && receive_member) ||
+       (send_error && receive_error) ||
+       (send_error && receive_sender) ||
+       (send_error && eavesdrop) ||
+       (send_error && own) ||
+       (send_error && user) ||
+       (send_error && group)) ||
 
-      ((send_to && receive_from) ||
-       (send_to && user) ||
-       (send_to && group)) ||
+      ((send_destination && receive_interface) ||
+       (send_destination && receive_member) ||
+       (send_destination && receive_error) ||
+       (send_destination && receive_sender) ||
+       (send_destination && eavesdrop) ||
+       (send_destination && own) ||
+       (send_destination && user) ||
+       (send_destination && group)) ||
 
-      ((receive_from && user) ||
-       (receive_from && group)) ||
+      ((send_type && receive_interface) ||
+       (send_type && receive_member) ||
+       (send_type && receive_error) ||
+       (send_type && receive_sender) ||
+       (send_type && eavesdrop) ||
+       (send_type && own) ||
+       (send_type && user) ||
+       (send_type && group)) ||
 
-      (user && group))
+      ((send_path && receive_interface) ||
+       (send_path && receive_member) ||
+       (send_path && receive_error) ||
+       (send_path && receive_sender) ||
+       (send_path && eavesdrop) ||
+       (send_path && own) ||
+       (send_path && user) ||
+       (send_path && group)) ||
+      
+      ((receive_interface && receive_error) ||
+       (receive_interface && own) ||
+       (receive_interface && user) ||
+       (receive_interface && group)) ||
+
+      ((receive_member && receive_error) ||
+       (receive_member && own) ||
+       (receive_member && user) ||
+       (receive_member && group)) ||
+      
+      ((receive_error && own) ||
+       (receive_error && user) ||
+       (receive_error && group)) ||
+
+      ((eavesdrop && own) ||
+       (eavesdrop && user) ||
+       (eavesdrop && group)) ||
+      
+      ((own && user) ||
+       (own && group)) ||
+
+      ((user && group)))
     {
       dbus_set_error (error, DBUS_ERROR_FAILED,
-                      "Invalid combination of attributes on element <%s>, "
-                      "only send/send_to or receive/receive_from may be paired",
+                      "Invalid combination of attributes on element <%s>",
                       element_name);
       return FALSE;
     }
-
+  
   rule = NULL;
 
   /* In BusPolicyRule, NULL represents wildcard.
@@ -887,41 +1006,122 @@
    */
 #define IS_WILDCARD(str) ((str) && ((str)[0]) == '*' && ((str)[1]) == '\0')
 
-  if (send || send_to)
+  if (send_interface || send_member || send_error || send_destination ||
+      send_path || send_type)
     {
+      int message_type;
+      
+      if (IS_WILDCARD (send_interface))
+        send_interface = NULL;
+      if (IS_WILDCARD (send_member))
+        send_member = NULL;
+      if (IS_WILDCARD (send_error))
+        send_error = NULL;
+      if (IS_WILDCARD (send_destination))
+        send_destination = NULL;
+      if (IS_WILDCARD (send_path))
+        send_path = NULL;
+      if (IS_WILDCARD (send_type))
+        send_type = NULL;
+
+      message_type = DBUS_MESSAGE_TYPE_INVALID;
+      if (send_type != NULL)
+        {
+          message_type = message_type_from_string (send_type);
+          if (message_type == DBUS_MESSAGE_TYPE_INVALID)
+            {
+              dbus_set_error (error, DBUS_ERROR_FAILED,
+                              "Bad message type \"%s\"",
+                              send_type);
+              return FALSE;
+            }
+        }
+      
       rule = bus_policy_rule_new (BUS_POLICY_RULE_SEND, allow); 
       if (rule == NULL)
         goto nomem;
-
-      if (IS_WILDCARD (send))
-        send = NULL;
-      if (IS_WILDCARD (send_to))
-        send_to = NULL;
       
-      rule->d.send.message_name = _dbus_strdup (send);
-      rule->d.send.destination = _dbus_strdup (send_to);
-      if (send && rule->d.send.message_name == NULL)
+      rule->d.send.message_type = message_type;
+      rule->d.send.path = _dbus_strdup (send_path);
+      rule->d.send.interface = _dbus_strdup (send_interface);
+      rule->d.send.member = _dbus_strdup (send_member);
+      rule->d.send.error = _dbus_strdup (send_error);
+      rule->d.send.destination = _dbus_strdup (send_destination);
+      if (send_path && rule->d.send.path == NULL)
         goto nomem;
-      if (send_to && rule->d.send.destination == NULL)
+      if (send_interface && rule->d.send.interface == NULL)
+        goto nomem;
+      if (send_member && rule->d.send.member == NULL)
+        goto nomem;
+      if (send_error && rule->d.send.error == NULL)
+        goto nomem;
+      if (send_destination && rule->d.send.destination == NULL)
         goto nomem;
     }
-  else if (receive || receive_from)
+  else if (receive_interface || receive_member || receive_error || receive_sender ||
+           receive_path || receive_type || eavesdrop)
     {
+      int message_type;
+      
+      if (IS_WILDCARD (receive_interface))
+        receive_interface = NULL;
+      if (IS_WILDCARD (receive_member))
+        receive_member = NULL;
+      if (IS_WILDCARD (receive_error))
+        receive_error = NULL;
+      if (IS_WILDCARD (receive_sender))
+        receive_sender = NULL;
+      if (IS_WILDCARD (receive_path))
+        receive_path = NULL;
+      if (IS_WILDCARD (receive_type))
+        receive_type = NULL;
+
+      message_type = DBUS_MESSAGE_TYPE_INVALID;
+      if (receive_type != NULL)
+        {
+          message_type = message_type_from_string (receive_type);
+          if (message_type == DBUS_MESSAGE_TYPE_INVALID)
+            {
+              dbus_set_error (error, DBUS_ERROR_FAILED,
+                              "Bad message type \"%s\"",
+                              receive_type);
+              return FALSE;
+            }
+        }
+
+
+      if (eavesdrop &&
+          !(strcmp (eavesdrop, "true") == 0 ||
+            strcmp (eavesdrop, "false") == 0))
+        {
+          dbus_set_error (error, DBUS_ERROR_FAILED,
+                          "Bad value \"%s\" for eavesdrop attribute, must be true or false",
+                          eavesdrop);
+          return FALSE;
+        }
+      
       rule = bus_policy_rule_new (BUS_POLICY_RULE_RECEIVE, allow); 
       if (rule == NULL)
         goto nomem;
 
-      if (IS_WILDCARD (receive))
-        receive = NULL;
-
-      if (IS_WILDCARD (receive_from))
-        receive_from = NULL;
+      if (eavesdrop)
+        rule->d.receive.eavesdrop = (strcmp (eavesdrop, "true") == 0);
       
-      rule->d.receive.message_name = _dbus_strdup (receive);
-      rule->d.receive.origin = _dbus_strdup (receive_from);
-      if (receive && rule->d.receive.message_name == NULL)
+      rule->d.receive.message_type = message_type;
+      rule->d.receive.path = _dbus_strdup (receive_path);
+      rule->d.receive.interface = _dbus_strdup (receive_interface);
+      rule->d.receive.member = _dbus_strdup (receive_member);
+      rule->d.receive.error = _dbus_strdup (receive_error);
+      rule->d.receive.origin = _dbus_strdup (receive_sender);
+      if (receive_path && rule->d.receive.path == NULL)
         goto nomem;
-      if (receive_from && rule->d.receive.origin == NULL)
+      if (receive_interface && rule->d.receive.interface == NULL)
+        goto nomem;
+      if (receive_member && rule->d.receive.member == NULL)
+        goto nomem;
+      if (receive_error && rule->d.receive.error == NULL)
+        goto nomem;
+      if (receive_sender && rule->d.receive.origin == NULL)
         goto nomem;
     }
   else if (own)

Index: connection.c
===================================================================
RCS file: /cvs/dbus/dbus/bus/connection.c,v
retrieving revision 1.43
retrieving revision 1.44
diff -u -d -r1.43 -r1.44
--- connection.c	22 Jun 2003 19:39:47 -0000	1.43
+++ connection.c	30 Sep 2003 02:32:50 -0000	1.44
@@ -25,6 +25,7 @@
 #include "policy.h"
 #include "services.h"
 #include "utils.h"
+#include "signals.h"
 #include <dbus/dbus-list.h>
 #include <dbus/dbus-hash.h>
 #include <dbus/dbus-timeout.h>
@@ -41,6 +42,7 @@
   BusContext *context;
   DBusHashTable *completed_by_user; /**< Number of completed connections for each UID */
   DBusTimeout *expire_timeout; /**< Timeout for expiring incomplete connections. */
+  int stamp;            /**< Incrementing number */
 };
 
 static dbus_int32_t connection_data_slot = -1;
@@ -52,6 +54,8 @@
   DBusConnection *connection;
   DBusList *services_owned;
   int n_services_owned;
+  DBusList *match_rules;
+  int n_match_rules;
   char *name;
   DBusList *transaction_messages; /**< Stuff we need to send as part of a transaction */
   DBusMessage *oom_message;
@@ -60,6 +64,7 @@
 
   long connection_tv_sec;  /**< Time when we connected (seconds component) */
   long connection_tv_usec; /**< Time when we connected (microsec component) */
+  int stamp;               /**< connections->stamp last time we were traversed */
 } BusConnectionData;
 
 static dbus_bool_t expire_incomplete_timeout (void *data);
@@ -140,12 +145,20 @@
 {
   BusConnectionData *d;
   BusService *service;
-
+  BusMatchmaker *matchmaker;
+  
   d = BUS_CONNECTION_DATA (connection);
   _dbus_assert (d != NULL);
 
   _dbus_verbose ("%s disconnected, dropping all service ownership and releasing\n",
                  d->name ? d->name : "(inactive)");
+
+  /* Delete our match rules */
+  if (d->n_match_rules > 0)
+    {
+      matchmaker = bus_context_get_matchmaker (d->connections->context);
+      bus_matchmaker_disconnected (matchmaker, connection);
+    }
   
   /* Drop any service ownership. FIXME Unfortunately, this requires
    * memory allocation and there doesn't seem to be a good way to
@@ -881,6 +894,40 @@
   return connections->context;
 }
 
+/*
+ * This is used to avoid covering the same connection twice when
+ * traversing connections. Note that it assumes we will
+ * bus_connection_mark_stamp() each connection at least once per
+ * INT_MAX increments of the global stamp, or wraparound would break
+ * things.
+ */
+void
+bus_connections_increment_stamp (BusConnections *connections)
+{
+  connections->stamp += 1;
+}
+
+/* Mark connection with current stamp, return TRUE if it
+ * didn't already have that stamp
+ */
+dbus_bool_t
+bus_connection_mark_stamp (DBusConnection *connection)
+{
+  BusConnectionData *d;
+  
+  d = BUS_CONNECTION_DATA (connection);
+  
+  _dbus_assert (d != NULL);
+
+  if (d->stamp == d->connections->stamp)
+    return FALSE;
+  else
+    {
+      d->stamp = d->connections->stamp;
+      return TRUE;
+    }
+}
+
 BusContext*
 bus_connection_get_context (DBusConnection *connection)
 {
@@ -929,6 +976,18 @@
   return bus_context_get_activation (d->connections->context);
 }
 
+BusMatchmaker*
+bus_connection_get_matchmaker (DBusConnection *connection)
+{
+  BusConnectionData *d;
+
+  d = BUS_CONNECTION_DATA (connection);
+
+  _dbus_assert (d != NULL);
+
+  return bus_context_get_matchmaker (d->connections->context);
+}
+
 /**
  * Checks whether the connection is registered with the message bus.
  *
@@ -963,19 +1022,19 @@
   if (preallocated == NULL)
     return FALSE;
 
-  /* d->name may be NULL, but that is OK */
-  message = dbus_message_new (DBUS_ERROR_NO_MEMORY,
-                              d->name);
+  message = dbus_message_new (DBUS_MESSAGE_TYPE_ERROR);
+
   if (message == NULL)
     {
       dbus_connection_free_preallocated_send (connection, preallocated);
       return FALSE;
     }
 
-  dbus_message_set_is_error (message, TRUE);
-
-  if (!dbus_message_set_sender (message,
-                                DBUS_SERVICE_DBUS))
+  /* d->name may be NULL, but that is OK */
+  if (!dbus_message_set_error_name (message, DBUS_ERROR_NO_MEMORY) ||
+      !dbus_message_set_destination (message, d->name) ||
+      !dbus_message_set_sender (message,
+                                DBUS_SERVICE_ORG_FREEDESKTOP_DBUS))
     {
       dbus_connection_free_preallocated_send (connection, preallocated);
       dbus_message_unref (message);
@@ -1025,6 +1084,62 @@
 }
 
 void
+bus_connection_add_match_rule_link (DBusConnection *connection,
+                                    DBusList       *link)
+{
+  BusConnectionData *d;
+
+  d = BUS_CONNECTION_DATA (connection);
+  _dbus_assert (d != NULL);
+
+  _dbus_list_append_link (&d->match_rules, link);
+
+  d->n_match_rules += 1;
+}
+
+dbus_bool_t
+bus_connection_add_match_rule (DBusConnection *connection,
+                               BusMatchRule   *rule)
+{
+    DBusList *link;
+
+  link = _dbus_list_alloc_link (rule);
+
+  if (link == NULL)
+    return FALSE;
+
+  bus_connection_add_match_rule_link (connection, link);
+
+  return TRUE;
+}
+
+void
+bus_connection_remove_match_rule (DBusConnection *connection,
+                                  BusMatchRule   *rule)
+{
+  BusConnectionData *d;
+
+  d = BUS_CONNECTION_DATA (connection);
+  _dbus_assert (d != NULL);
+
+  _dbus_list_remove_last (&d->match_rules, rule);
+
+  d->n_match_rules -= 1;
+  _dbus_assert (d->n_match_rules >= 0);
+}
+
+int
+bus_connection_get_n_match_rules (DBusConnection *connection)
+{
+  BusConnectionData *d;
+
+  d = BUS_CONNECTION_DATA (connection);
+  _dbus_assert (d != NULL);
+  
+  return d->n_match_rules;
+}
+
+void
 bus_connection_add_owned_service_link (DBusConnection *connection,
                                        DBusList       *link)
 {
@@ -1092,6 +1207,8 @@
   _dbus_assert (d != NULL);
   _dbus_assert (d->name == NULL);
   _dbus_assert (d->policy == NULL);
+
+  _dbus_assert (!bus_connection_is_active (connection));
   
   if (!_dbus_string_copy_data (name, &d->name))
     {
@@ -1147,6 +1264,8 @@
 
   /* See if we can remove the timeout */
   bus_connections_expire_incomplete (d->connections);
+
+  _dbus_assert (bus_connection_is_active (connection));
   
   return TRUE;
 }
@@ -1312,17 +1431,22 @@
    * to check security policy since it was not done in
    * dispatch.c
    */
-  _dbus_verbose ("Sending %s from driver\n",
-                 dbus_message_get_name (message));
-  
-  if (!dbus_message_set_sender (message, DBUS_SERVICE_DBUS))
+  _dbus_verbose ("Sending %s %s %s from driver\n",
+                 dbus_message_get_interface (message) ?
+                 dbus_message_get_interface (message) : "(no interface)",
+                 dbus_message_get_member (message) ?
+                 dbus_message_get_member (message) : "(no member)",
+                 dbus_message_get_error_name (message) ?
+                 dbus_message_get_error_name (message) : "(no error name)");
+                 
+  if (!dbus_message_set_sender (message, DBUS_SERVICE_ORG_FREEDESKTOP_DBUS))
     return FALSE;
 
   /* If security policy doesn't allow the message, we silently
    * eat it; the driver doesn't care about getting a reply.
    */
   if (!bus_context_check_security_policy (bus_transaction_get_context (transaction),
-                                          NULL, connection, message, NULL))
+                                          NULL, connection, connection, message, NULL))
     return TRUE;
 
   return bus_transaction_send (transaction, connection, message);
@@ -1337,11 +1461,16 @@
   BusConnectionData *d;
   DBusList *link;
 
-  _dbus_verbose ("  trying to add %s %s to transaction%s\n",
-                 dbus_message_get_is_error (message) ? "error" :
+  _dbus_verbose ("  trying to add %s interface=%s member=%s error=%s to transaction%s\n",
+                 dbus_message_get_type (message) == DBUS_MESSAGE_TYPE_ERROR ? "error" :
                  dbus_message_get_reply_serial (message) != 0 ? "reply" :
                  "message",
-                 dbus_message_get_name (message),
+                 dbus_message_get_interface (message) ?
+                 dbus_message_get_interface (message) : "(unset)",
+                 dbus_message_get_member (message) ?
+                 dbus_message_get_member (message) : "(unset)",
+                 dbus_message_get_error_name (message) ?
+                 dbus_message_get_error_name (message) : "(unset)",
                  dbus_connection_get_is_connected (connection) ?
                  "" : " (disconnected)");
 
@@ -1550,13 +1679,13 @@
   
   _dbus_assert (error != NULL);
   _DBUS_ASSERT_ERROR_IS_SET (error);
-
+  
   _dbus_verbose ("Sending error reply %s \"%s\"\n",
                  error->name, error->message);
 
-  reply = dbus_message_new_error_reply (in_reply_to,
-                                        error->name,
-                                        error->message);
+  reply = dbus_message_new_error (in_reply_to,
+                                  error->name,
+                                  error->message);
   if (reply == NULL)
     return FALSE;
 

Index: connection.h
===================================================================
RCS file: /cvs/dbus/dbus/bus/connection.h,v
retrieving revision 1.15
retrieving revision 1.16
diff -u -d -r1.15 -r1.16
--- connection.h	27 Apr 2003 06:25:42 -0000	1.15
+++ connection.h	30 Sep 2003 02:32:50 -0000	1.16
@@ -44,16 +44,18 @@
                                                    BusConnectionForeachFunction  function,
                                                    void                         *data);
 BusContext*     bus_connections_get_context       (BusConnections               *connections);
+void            bus_connections_increment_stamp   (BusConnections               *connections);
 BusContext*     bus_connection_get_context        (DBusConnection               *connection);
 BusConnections* bus_connection_get_connections    (DBusConnection               *connection);
 BusRegistry*    bus_connection_get_registry       (DBusConnection               *connection);
 BusActivation*  bus_connection_get_activation     (DBusConnection               *connection);
+BusMatchmaker*  bus_connection_get_matchmaker     (DBusConnection               *connection);
 dbus_bool_t     bus_connections_check_limits      (BusConnections               *connections,
                                                    DBusConnection               *requesting_completion,
                                                    DBusError                    *error);
 void            bus_connections_expire_incomplete (BusConnections               *connections);
 
-
+dbus_bool_t     bus_connection_mark_stamp         (DBusConnection               *connection);
 
 dbus_bool_t bus_connection_is_active (DBusConnection *connection);
 const char *bus_connection_get_name  (DBusConnection *connection);
@@ -62,6 +64,15 @@
 void        bus_connection_send_oom_error        (DBusConnection *connection,
                                                   DBusMessage    *in_reply_to);
 
+/* called by signals.c */
+dbus_bool_t bus_connection_add_match_rule      (DBusConnection *connection,
+                                                BusMatchRule   *rule);
+void        bus_connection_add_match_rule_link (DBusConnection *connection,
+                                                DBusList       *link);
+void        bus_connection_remove_match_rule   (DBusConnection *connection,
+                                                BusMatchRule   *rule);
+int         bus_connection_get_n_match_rules   (DBusConnection *connection);
+
 
 /* called by services.c */
 dbus_bool_t bus_connection_add_owned_service      (DBusConnection *connection,

Index: dbus-daemon-1.1.in
===================================================================
RCS file: /cvs/dbus/dbus/bus/dbus-daemon-1.1.in,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -d -r1.3 -r1.4
--- dbus-daemon-1.1.in	4 May 2003 08:54:24 -0000	1.3
+++ dbus-daemon-1.1.in	30 Sep 2003 02:32:50 -0000	1.4
@@ -328,16 +328,33 @@
 
 .TP
 .I "<deny>"
+.I "<allow>"
 
 .PP
-A <deny> element appears below a <policy> element and prohibits 
-some action. The possible attributes of a <deny> element are:
+A <deny> element appears below a <policy> element and prohibits some
+action. The <allow> element makes an exception to previous <deny>
+statements, and works just like <deny> but with the inverse meaning.
+
+.PP
+The possible attributes of these elements are:
 .nf
-   send="messagename"
-   receive="messagename"
+   send_interface="interface_name"
+   send_member="method_or_signal_name" 
+   send_error="error_name" 
+   send_destination="service_name" 
+   send_type="method_call" | "method_return" | "signal" | "error" 
+   send_path="/path/name"
+
+   receive_interface="interface_name"
+   receive_member="method_or_signal_name" 
+   receive_error="error_name" 
+   receive_sender="service_name" 
+   receive_type="method_call" | "method_return" | "signal" | "error"
+   receive_path="/path/name"
+   
+   eavesdrop="true" | "false"
+
    own="servicename"
-   send_to="servicename"
-   receive_from="servicename"
    user="username"
    group="groupname"
 .fi
@@ -345,11 +362,11 @@
 .PP
 Examples:
 .nf
-   <deny send="org.freedesktop.System.Reboot"/> 
-   <deny receive="org.freedesktop.System.Reboot"/>
+   <deny send_interface="org.freedesktop.System" send_member="Reboot"/> 
+   <deny receive_interface="org.freedesktop.System" receive_member="Reboot"/>
    <deny own="org.freedesktop.System"/>
-   <deny send_to="org.freedesktop.System"/>
-   <deny receive_from="org.freedesktop.System"/>
+   <deny send_destination="org.freedesktop.System"/>
+   <deny receive_sender="org.freedesktop.System"/>
    <deny user="john"/>
    <deny group="enemies"/>
 .fi
@@ -360,18 +377,38 @@
 rules in the config file allow it).
 
 .PP
-send_to and receive_from mean that messages may not be sent to or
-received from the *owner* of the given service, not that they may not
-be sent *to that service name*. That is, if a connection owns services
-A, B, C, and sending to A is denied, sending to B or C will not work
-either.
+send_destination and receive_sender rules mean that messages may not be
+sent to or received from the *owner* of the given service, not that
+they may not be sent *to that service name*. That is, if a connection
+owns services A, B, C, and sending to A is denied, sending to B or C
+will not work either.
+
+.PP
+The other send_* and receive_* attributes are purely textual/by-value
+matches against the given field in the message header.
+
+.PP
+"Eavesdropping" occurs when an application receives a message that
+was explicitly addressed to a service the application does not own.
+Eavesdropping thus only applies to messages that are addressed to
+services (i.e. it does not apply to signals).
+
+.PP
+For <allow>, eavesdrop="true" indicates that the rule matches even 
+when eavesdropping. eavesdrop="false" is the default and means that 
+the rule only allows messages to go to their specified recipient.
+For <deny>, eavesdrop="true" indicates that the rule matches 
+only when eavesdropping. eavesdrop="false" is the default for <deny>
+also, but here it means that the rule applies always, even when 
+not eavesdropping. The eavesdrop attribute can only be combined with
+receive rules (with receive_* attributes).
 
 .PP
 user and group denials mean that the given user or group may 
 not connect to the message bus.
 
 .PP
-For "servicename" or "messagename" or "username" or "groupname"
+For "service_name", "username", "groupname", etc.
 the character "*" can be substituted, meaning "any." Complex globs
 like "foo.bar.*" aren't allowed for now because they'd be work to
 implement and maybe encourage sloppy security anyway.
@@ -382,18 +419,21 @@
 context="default" or context="mandatory" policies.
 
 .PP
-A single <deny> rule may specify both send and send_to, OR both
-receive and receive_from. In this case, the denial applies only if
-both attributes match the message being denied.
-e.g. <deny send="foo.bar" send_to="foo.blah"/> would deny 
-messages of the given name AND to the given service.
+A single <deny> rule may specify combinations of attributes such as
+send_service and send_interface and send_type. In this case, the
+denial applies only if both attributes match the message being denied.
+e.g. <deny send_interface="foo.bar" send_service="foo.blah"/> would
+deny messages of the given interface AND to the given service.
+To get an OR effect you specify multiple <deny> rules.
 
-.TP
-.I "<allow>"
+.PP
+You can't include both send_ and receive_ attributes on the same
+rule, since "whether the message can be sent" and "whether it can be
+received" are evaluated separately.
 
 .PP
-Makes an exception to previous <deny> statements. Works 
-just like <deny> but with the inverse meaning.
+Be careful with send_interface/receive_interface, because the 
+interface field in messages is optional.
 
 .SH AUTHOR
 See http://www.freedesktop.org/software/dbus/doc/AUTHORS

Index: desktop-file.c
===================================================================
RCS file: /cvs/dbus/dbus/bus/desktop-file.c,v
retrieving revision 1.7
retrieving revision 1.8
diff -u -d -r1.7 -r1.8
--- desktop-file.c	31 Mar 2003 20:56:29 -0000	1.7
+++ desktop-file.c	30 Sep 2003 02:32:50 -0000	1.8
@@ -48,15 +48,19 @@
   int n_allocated_sections;
 };
 
+/**
+ * Parser for service files.
+ */
 typedef struct
 {
-  DBusString data;
+  DBusString data; /**< The data from the file */
 
-  BusDesktopFile *desktop_file;
-  int current_section;
+  BusDesktopFile *desktop_file; /**< The resulting object */
+  int current_section;    /**< The current section being parsed */
   
-  int pos, len;
-  int line_num;
+  int pos;          /**< Current position */
+  int len;          /**< Length */
+  int line_num;     /**< Current line number */
   
 } BusDesktopFileParser;
 

Index: dispatch.c
===================================================================
RCS file: /cvs/dbus/dbus/bus/dispatch.c,v
retrieving revision 1.50
retrieving revision 1.51
diff -u -d -r1.50 -r1.51
--- dispatch.c	22 Jun 2003 19:39:47 -0000	1.50
+++ dispatch.c	30 Sep 2003 02:32:50 -0000	1.51
@@ -28,38 +28,33 @@
 #include "services.h"
 #include "utils.h"
 #include "bus.h"
+#include "signals.h"
 #include "test.h"
 #include <dbus/dbus-internals.h>
 #include <string.h>
 
-static dbus_int32_t message_handler_slot = -1;
-
-typedef struct
-{
-  BusContext     *context;
-  DBusConnection *sender;
-  DBusMessage    *message;
-  BusTransaction *transaction;
-  DBusError      *error;
-} SendMessageData;
-
 static dbus_bool_t
-send_one_message (DBusConnection *connection, void *data)
+send_one_message (DBusConnection *connection,
+                  BusContext     *context,
+                  DBusConnection *sender,
+                  DBusConnection *addressed_recipient,
+                  DBusMessage    *message,
+                  BusTransaction *transaction,
+                  DBusError      *error)
 {
-  SendMessageData *d = data;
-
-  if (!bus_context_check_security_policy (d->context,
-                                          d->sender,
+  if (!bus_context_check_security_policy (context,
+                                          sender,
+                                          addressed_recipient,
                                           connection,
-                                          d->message,
+                                          message,
                                           NULL))
     return TRUE; /* silently don't send it */
   
-  if (!bus_transaction_send (d->transaction,
+  if (!bus_transaction_send (transaction,
                              connection,
-                             d->message))
+                             message))
     {
-      BUS_SET_OOM (d->error);
+      BUS_SET_OOM (error);
       return FALSE;
     }
 
@@ -67,30 +62,60 @@
 }
 
 dbus_bool_t
-bus_dispatch_broadcast_message (BusTransaction *transaction,
-                                DBusConnection *sender,
-                                DBusMessage    *message,
-                                DBusError      *error)
+bus_dispatch_matches (BusTransaction *transaction,
+                      DBusConnection *sender,
+                      DBusConnection *addressed_recipient,
+                      DBusMessage    *message,
+                      DBusError      *error)
 {
   DBusError tmp_error;
-  SendMessageData d;
   BusConnections *connections;
+  DBusList *recipients;
+  BusMatchmaker *matchmaker;
+  DBusList *link;
+  BusContext *context;
 
   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
-  
+
+  /* sender and recipient can both be NULL for the bus driver,
+   * or for signals with no particular recipient
+   */
+
+  _dbus_assert (sender == NULL || bus_connection_is_active (sender));
   _dbus_assert (dbus_message_get_sender (message) != NULL);
 
   connections = bus_transaction_get_connections (transaction);
   
   dbus_error_init (&tmp_error);
-  d.sender = sender;
-  d.context = bus_transaction_get_context (transaction);
-  d.message = message;
-  d.transaction = transaction;
-  d.error = &tmp_error;
-  
-  bus_connections_foreach_active (connections, send_one_message, &d);
+  context = bus_transaction_get_context (transaction);
+  matchmaker = bus_context_get_matchmaker (context);
+
+  recipients = NULL;
+  if (!bus_matchmaker_get_recipients (matchmaker,
+                                      bus_context_get_connections (context),
+                                      sender, addressed_recipient, message,
+                                      &recipients))
+    {
+      BUS_SET_OOM (error);
+      return FALSE;
+    }
+
+  link = _dbus_list_get_first_link (&recipients);
+  while (link != NULL)
+    {
+      DBusConnection *dest;
 
+      dest = link->data;
+
+      if (!send_one_message (dest, context, sender, addressed_recipient,
+                             message, transaction, &tmp_error))
+        break;
+
+      link = _dbus_list_get_next_link (&recipients, link);
+    }
+
+  _dbus_list_clear (&recipients);
+  
   if (dbus_error_is_set (&tmp_error))
     {
       dbus_move_error (&tmp_error, error);
@@ -100,16 +125,21 @@
     return TRUE;
 }
 
-static void
+static DBusHandlerResult
 bus_dispatch (DBusConnection *connection,
               DBusMessage    *message)
 {
-  const char *sender, *service_name, *message_name;
+  const char *sender, *service_name;
   DBusError error;
   BusTransaction *transaction;
   BusContext *context;
+  DBusHandlerResult result;
+  DBusConnection *addressed_recipient;
+  
+  result = DBUS_HANDLER_RESULT_HANDLED;
   
   transaction = NULL;
+  addressed_recipient = NULL;
   dbus_error_init (&error);
   
   context = bus_connection_get_context (connection);
@@ -123,32 +153,50 @@
   
   /* Ref connection in case we disconnect it at some point in here */
   dbus_connection_ref (connection);
-
+  
   service_name = dbus_message_get_destination (message);
-  message_name = dbus_message_get_name (message);
 
-  _dbus_assert (message_name != NULL); /* DBusMessageLoader is supposed to check this */
+#ifdef DBUS_ENABLE_VERBOSE_MODE
+  {
+    const char *interface_name, *member_name, *error_name;
 
-  _dbus_verbose ("DISPATCH: %s to %s\n",
-                 message_name, service_name ? service_name : "peer");
+    interface_name = dbus_message_get_interface (message);
+    member_name = dbus_message_get_member (message);
+    error_name = dbus_message_get_error_name (message);
+    
+    _dbus_verbose ("DISPATCH: %s %s %s to %s\n",
+                   interface_name ? interface_name : "(no interface)",
+                   member_name ? member_name : "(no member)",
+                   error_name ? error_name : "(no error name)",
+                   service_name ? service_name : "peer");
+  }
+#endif /* DBUS_ENABLE_VERBOSE_MODE */
   
-  /* If service_name is NULL, this is a message to the bus daemon, not
-   * intended to actually go "on the bus"; e.g. a peer-to-peer
+  /* If service_name is NULL, if it's a signal we send it to all
+   * connections with a match rule. If it's not a signal, it goes to
+   * the bus daemon but doesn't go "on the bus"; e.g. a peer-to-peer
    * ping. Handle these immediately, especially disconnection
    * messages. There are no security policy checks on these.
    */
   if (service_name == NULL)
-    {      
-      if (strcmp (message_name, DBUS_MESSAGE_LOCAL_DISCONNECT) == 0)
-        bus_connection_disconnected (connection);
+    {
+      if (dbus_message_is_signal (message,
+                                  DBUS_INTERFACE_ORG_FREEDESKTOP_LOCAL,
+                                  "Disconnected"))
+        {
+          bus_connection_disconnected (connection);
+          goto out;
+        }
 
-      /* DBusConnection also handles some of these automatically, we leave
-       * it to do so.
-       */
-      goto out;
+      if (dbus_message_get_type (message) != DBUS_MESSAGE_TYPE_SIGNAL)
+        {
+          /* DBusConnection also handles some of these automatically, we leave
+           * it to do so.
+           */
+          result = DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+          goto out;
+        }
     }
-
-  _dbus_assert (service_name != NULL); /* this message is intended for bus routing */
   
   /* Create our transaction */
   transaction = bus_transaction_new (context);
@@ -177,17 +225,18 @@
        */
       service_name = dbus_message_get_destination (message);
     }
-
-  if (strcmp (service_name, DBUS_SERVICE_DBUS) == 0) /* to bus driver */
+  
+  if (service_name &&
+      strcmp (service_name, DBUS_SERVICE_ORG_FREEDESKTOP_DBUS) == 0) /* to bus driver */
     {
       if (!bus_context_check_security_policy (context,
-                                              connection, NULL, message, &error))
+                                              connection, NULL, NULL, message, &error))
         {
           _dbus_verbose ("Security policy rejected message\n");
           goto out;
         }
 
-      _dbus_verbose ("Giving message to %s\n", DBUS_SERVICE_DBUS);
+      _dbus_verbose ("Giving message to %s\n", DBUS_SERVICE_ORG_FREEDESKTOP_DBUS);
       if (!bus_driver_handle_message (connection, transaction, message, &error))
         goto out;
     }
@@ -195,22 +244,16 @@
     {
       _dbus_verbose ("Received message from non-registered client. Disconnecting.\n");
       dbus_connection_disconnect (connection);
+      goto out;
     }
-  /* FIXME what if we un-special-case this service and just have a flag
-   * on services that all service owners will get messages to it, not just
-   * the primary owner.
-   */
-  else if (strcmp (service_name, DBUS_SERVICE_BROADCAST) == 0) /* spam! */
-    {
-      if (!bus_dispatch_broadcast_message (transaction, connection, message, &error))
-        goto out;
-    }
-  else  /* route to named service */
+  else if (service_name != NULL) /* route to named service */
     {
       DBusString service_string;
       BusService *service;
       BusRegistry *registry;
 
+      _dbus_assert (service_name != NULL);
+      
       registry = bus_connection_get_registry (connection);
       
       _dbus_string_init_const (&service_string, service_name);
@@ -225,24 +268,30 @@
           goto out;
         }
       else
-        {
-          DBusConnection *recipient;
-          
-          recipient = bus_service_get_primary_owner (service);
-          _dbus_assert (recipient != NULL);
+        {          
+          addressed_recipient = bus_service_get_primary_owner (service);
+          _dbus_assert (addressed_recipient != NULL);
           
           if (!bus_context_check_security_policy (context,
-                                                  connection, recipient, message, &error))
+                                                  connection, addressed_recipient,
+                                                  addressed_recipient,
+                                                  message, &error))
             goto out;
           
           /* Dispatch the message */
-          if (!bus_transaction_send (transaction, recipient, message))
+          if (!bus_transaction_send (transaction, addressed_recipient, message))
             {
               BUS_SET_OOM (&error);
               goto out;
             }
         }
     }
+
+  /* Now match the messages against any match rules, which will send
+   * out signals and such. addressed_recipient may == NULL.
+   */
+  if (!bus_dispatch_matches (transaction, connection, addressed_recipient, message, &error))
+    goto out;
   
  out:
   if (dbus_error_is_set (&error))
@@ -295,66 +344,26 @@
     }
 
   dbus_connection_unref (connection);
-}
 
-static DBusHandlerResult
-bus_dispatch_message_handler (DBusMessageHandler *handler,
-			      DBusConnection     *connection,
-			      DBusMessage        *message,
-			      void               *user_data)
-{
-  bus_dispatch (connection, message);
-  
-  return DBUS_HANDLER_RESULT_ALLOW_MORE_HANDLERS;
+  return result;
 }
 
-static void
-free_message_handler (void *data)
+static DBusHandlerResult
+bus_dispatch_message_filter (DBusConnection     *connection,
+                             DBusMessage        *message,
+                             void               *user_data)
 {
-  DBusMessageHandler *handler = data;
-  
-  _dbus_assert (message_handler_slot >= 0);
-  
-  dbus_message_handler_unref (handler);
-  dbus_connection_free_data_slot (&message_handler_slot);
+  return bus_dispatch (connection, message);
 }
 
 dbus_bool_t
 bus_dispatch_add_connection (DBusConnection *connection)
-{
-  DBusMessageHandler *handler;
-
-  if (!dbus_connection_allocate_data_slot (&message_handler_slot))
+{  
+  if (!dbus_connection_add_filter (connection,
+                                   bus_dispatch_message_filter,
+                                   NULL, NULL))
     return FALSE;
   
-  handler = dbus_message_handler_new (bus_dispatch_message_handler, NULL, NULL);  
-  if (handler == NULL)
-    {
-      dbus_connection_free_data_slot (&message_handler_slot);
-      return FALSE;
-    }    
-  
-  if (!dbus_connection_add_filter (connection, handler))
-    {
-      dbus_message_handler_unref (handler);
-      dbus_connection_free_data_slot (&message_handler_slot);
-      
-      return FALSE;
-    }
-
-  _dbus_assert (message_handler_slot >= 0);
-  
-  if (!dbus_connection_set_data (connection,
-				 message_handler_slot,
-				 handler,
-                                 free_message_handler))
-    {
-      dbus_message_handler_unref (handler);
-      dbus_connection_free_data_slot (&message_handler_slot);
-
-      return FALSE;
-    }
-
   return TRUE;
 }
 
@@ -364,9 +373,9 @@
   /* Here we tell the bus driver that we want to get off. */
   bus_driver_remove_connection (connection);
 
-  dbus_connection_set_data (connection,
-			    message_handler_slot,
-			    NULL, NULL);
+  dbus_connection_remove_filter (connection,
+                                 bus_dispatch_message_filter,
+                                 NULL);
 }
 
 #ifdef DBUS_BUILD_TESTS
@@ -401,6 +410,42 @@
   return dbus_connection_pop_message (connection);
 }
 
+static void
+warn_unexpected_real (DBusConnection *connection,
+                      DBusMessage    *message,
+                      const char     *expected,
+                      const char     *function,
+                      int             line)
+{
+  _dbus_warn ("%s:%d received message interface \"%s\" member \"%s\" error name \"%s\" on %p, expecting %s\n",
+              function, line,
+              dbus_message_get_interface (message) ?
+              dbus_message_get_interface (message) : "(unset)",
+              dbus_message_get_member (message) ?
+              dbus_message_get_member (message) : "(unset)",
+              dbus_message_get_error_name (message) ?
+              dbus_message_get_error_name (message) : "(unset)",
+              connection,
+              expected);
+}
+
+#define warn_unexpected(connection, message, expected) \
+  warn_unexpected_real (connection, message, expected, _DBUS_FUNCTION_NAME, __LINE__)
+
+static void
+verbose_message_received (DBusConnection *connection,
+                          DBusMessage    *message)
+{
+  _dbus_verbose ("Received message interface \"%s\" member \"%s\" error name \"%s\" on %p\n",
+                 dbus_message_get_interface (message) ?
+                 dbus_message_get_interface (message) : "(unset)",
+                 dbus_message_get_member (message) ?
+                 dbus_message_get_member (message) : "(unset)",
+                 dbus_message_get_error_name (message) ?
+                 dbus_message_get_error_name (message) : "(unset)",
+                 connection);
+}
+
 typedef struct
 {
   const char *expected_service_name;
@@ -424,14 +469,15 @@
   if (message == NULL)
     {
       _dbus_warn ("Did not receive a message on %p, expecting %s\n",
-                  connection, DBUS_MESSAGE_SERVICE_DELETED);
+                  connection, "ServiceDeleted");
       goto out;
     }
-  else if (!dbus_message_has_name (message, DBUS_MESSAGE_SERVICE_DELETED))
+  else if (!dbus_message_is_signal (message,
+                                    DBUS_INTERFACE_ORG_FREEDESKTOP_DBUS,
+                                    "ServiceDeleted"))
     {
-      _dbus_warn ("Received message %s on %p, expecting %s\n",
-                  dbus_message_get_name (message),
-                  connection, DBUS_MESSAGE_SERVICE_DELETED);
+      warn_unexpected (connection, message, "ServiceDeleted");
+
       goto out;
     }
   else
@@ -554,8 +600,8 @@
   message = pop_message_waiting_for_memory (connection);
   if (message != NULL)
     {
-      _dbus_warn ("Received message %s on %p, expecting no messages\n",
-                  dbus_message_get_name (message), connection);
+      warn_unexpected (connection, message, "no messages");
+
       d->failed = TRUE;
     }
 
@@ -591,14 +637,14 @@
   if (message == NULL)
     {
       _dbus_warn ("Did not receive a message on %p, expecting %s\n",
-                  connection, DBUS_MESSAGE_SERVICE_CREATED);
+                  connection, "ServiceCreated");
       goto out;
     }
-  else if (!dbus_message_has_name (message, DBUS_MESSAGE_SERVICE_CREATED))
+  else if (!dbus_message_is_signal (message,
+                                    DBUS_INTERFACE_ORG_FREEDESKTOP_DBUS,
+                                    "ServiceCreated"))
     {
-      _dbus_warn ("Received message %s on %p, expecting %s\n",
-                  dbus_message_get_name (message),
-                  connection, DBUS_MESSAGE_SERVICE_CREATED);
+      warn_unexpected (connection, message, "ServiceCreated");
       goto out;
     }
   else
@@ -662,7 +708,7 @@
                      DBusConnection *connection)
 {
   DBusMessage *message;
-  dbus_int32_t serial;
+  dbus_uint32_t serial;
   dbus_bool_t retval;
   DBusError error;
   char *name;
@@ -673,9 +719,13 @@
   name = NULL;
   acquired = NULL;
   message = NULL;
+
+  _dbus_verbose ("check_hello_message for %p\n", connection);
   
-  message = dbus_message_new (DBUS_MESSAGE_HELLO,
-                              DBUS_SERVICE_DBUS);
+  message = dbus_message_new_method_call (DBUS_SERVICE_ORG_FREEDESKTOP_DBUS,
+                                          DBUS_PATH_ORG_FREEDESKTOP_DBUS,
+                                          DBUS_INTERFACE_ORG_FREEDESKTOP_DBUS,
+                                          "Hello");
 
   if (message == NULL)
     return TRUE;
@@ -710,14 +760,13 @@
   if (message == NULL)
     {
       _dbus_warn ("Did not receive a reply to %s %d on %p\n",
-                  DBUS_MESSAGE_HELLO, serial, connection);
+                  "Hello", serial, connection);
       goto out;
     }
 
-  _dbus_verbose ("Received %s on %p\n",
-                 dbus_message_get_name (message), connection);
+  verbose_message_received (connection, message);
 
-  if (!dbus_message_has_sender (message, DBUS_SERVICE_DBUS))
+  if (!dbus_message_has_sender (message, DBUS_SERVICE_ORG_FREEDESKTOP_DBUS))
     {
       _dbus_warn ("Message has wrong sender %s\n",
                   dbus_message_get_sender (message) ?
@@ -725,17 +774,17 @@
       goto out;
     }
   
-  if (dbus_message_get_is_error (message))
+  if (dbus_message_get_type (message) == DBUS_MESSAGE_TYPE_ERROR)
     {
-      if (dbus_message_has_name (message,
+      if (dbus_message_is_error (message,
                                  DBUS_ERROR_NO_MEMORY))
         {
           ; /* good, this is a valid response */
         }
       else
         {
-          _dbus_warn ("Did not expect error %s\n",
-                      dbus_message_get_name (message));
+          warn_unexpected (connection, message, "not this error");
+
           goto out;
         }
     }
@@ -743,15 +792,14 @@
     {
       CheckServiceCreatedData scd;
       
-      if (dbus_message_has_name (message,
-                                 DBUS_MESSAGE_HELLO))
+      if (dbus_message_get_type (message) == DBUS_MESSAGE_TYPE_METHOD_RETURN)
         {
           ; /* good, expected */
         }
       else
         {
-          _dbus_warn ("Did not expect reply %s\n",
-                      dbus_message_get_name (message));
+          warn_unexpected (connection, message, "method return for Hello");
+
           goto out;
         }
 
@@ -780,7 +828,7 @@
       while (!dbus_bus_set_base_service (connection, name))
         _dbus_wait_for_memory ();
       
-      scd.skip_connection = NULL;
+      scd.skip_connection = connection; /* we haven't done AddMatch so won't get it ourselves */
       scd.failed = FALSE;
       scd.expected_service_name = name;
       bus_test_clients_foreach (check_service_created_foreach,
@@ -795,7 +843,7 @@
       if (message == NULL)
         {
           _dbus_warn ("Expecting %s, got nothing\n",
-                      DBUS_MESSAGE_SERVICE_ACQUIRED);
+                      "ServiceAcquired");
           goto out;
         }
       
@@ -850,6 +898,126 @@
  * but the correct thing may include OOM errors.
  */
 static dbus_bool_t
+check_add_match_all (BusContext     *context,
+                     DBusConnection *connection)
+{
+  DBusMessage *message;
+  dbus_bool_t retval;
+  dbus_uint32_t serial;
+  DBusError error;
+
+  retval = FALSE;
+  dbus_error_init (&error);
+  message = NULL;
+
+  _dbus_verbose ("check_add_match_all for %p\n", connection);
+  
+  message = dbus_message_new_method_call (DBUS_SERVICE_ORG_FREEDESKTOP_DBUS,
+                                          DBUS_PATH_ORG_FREEDESKTOP_DBUS,
+                                          DBUS_INTERFACE_ORG_FREEDESKTOP_DBUS,
+                                          "AddMatch");
+
+  if (message == NULL)
+    return TRUE;
+
+  if (!dbus_message_append_args (message, DBUS_TYPE_STRING, "", /* FIXME */
+                                 DBUS_TYPE_INVALID))
+    {
+      dbus_message_unref (message);
+      return TRUE;
+    }
+  
+  if (!dbus_connection_send (connection, message, &serial))
+    {
+      dbus_message_unref (message);
+      return TRUE;
+    }
+
+  dbus_message_unref (message);
+  message = NULL;
+
+  /* send our message */
+  bus_test_run_clients_loop (TRUE);
+
+  dbus_connection_ref (connection); /* because we may get disconnected */
+  block_connection_until_message_from_bus (context, connection);
+
+  if (!dbus_connection_get_is_connected (connection))
+    {
+      _dbus_verbose ("connection was disconnected\n");
+      
+      dbus_connection_unref (connection);
+      
+      return TRUE;
+    }
+
+  dbus_connection_unref (connection);
+  
+  message = pop_message_waiting_for_memory (connection);
+  if (message == NULL)
+    {
+      _dbus_warn ("Did not receive a reply to %s %d on %p\n",
+                  "AddMatch", serial, connection);
+      goto out;
+    }
+
+  verbose_message_received (connection, message);
+
+  if (!dbus_message_has_sender (message, DBUS_SERVICE_ORG_FREEDESKTOP_DBUS))
+    {
+      _dbus_warn ("Message has wrong sender %s\n",
+                  dbus_message_get_sender (message) ?
+                  dbus_message_get_sender (message) : "(none)");
+      goto out;
+    }
+  
+  if (dbus_message_get_type (message) == DBUS_MESSAGE_TYPE_ERROR)
+    {
+      if (dbus_message_is_error (message,
+                                 DBUS_ERROR_NO_MEMORY))
+        {
+          ; /* good, this is a valid response */
+        }
+      else
+        {
+          warn_unexpected (connection, message, "not this error");
+
+          goto out;
+        }
+    }
+  else
+    {
+      if (dbus_message_get_type (message) == DBUS_MESSAGE_TYPE_METHOD_RETURN)
+        {
+          ; /* good, expected */
+          _dbus_assert (dbus_message_get_reply_serial (message) == serial);
+        }
+      else
+        {
+          warn_unexpected (connection, message, "method return for AddMatch");
+
+          goto out;
+        }
+    }
+
+  if (!check_no_leftovers (context))
+    goto out;
+  
+  retval = TRUE;
+  
+ out:
+  dbus_error_free (&error);
+  
+  if (message)
+    dbus_message_unref (message);
+  
+  return retval;
+}
+
+/* returns TRUE if the correct thing happens,
+ * but the correct thing may include OOM errors.
+ */
+static dbus_bool_t
 check_hello_connection (BusContext *context)
 {
   DBusConnection *connection;
@@ -874,7 +1042,7 @@
 
   if (!check_hello_message (context, connection))
     return FALSE;
-
+  
   if (dbus_bus_get_base_service (connection) == NULL)
     {
       /* We didn't successfully register, so we can't
@@ -884,6 +1052,9 @@
     }
   else
     {
+      if (!check_add_match_all (context, connection))
+        return FALSE;
+      
       kill_client_connection (context, connection);
     }
 
@@ -900,14 +1071,16 @@
                                       DBusConnection *connection)
 {
   DBusMessage *message;
-  dbus_int32_t serial;
+  dbus_uint32_t serial;
   dbus_bool_t retval;
   DBusError error;
   
   dbus_error_init (&error);
   
-  message = dbus_message_new (DBUS_MESSAGE_ACTIVATE_SERVICE,
-                              DBUS_SERVICE_DBUS);
+  message = dbus_message_new_method_call (DBUS_SERVICE_ORG_FREEDESKTOP_DBUS,
+                                          DBUS_PATH_ORG_FREEDESKTOP_DBUS,
+                                          DBUS_INTERFACE_ORG_FREEDESKTOP_DBUS,
+                                          "ActivateService");
 
   if (message == NULL)
     return TRUE;
@@ -946,16 +1119,15 @@
   if (message == NULL)
     {
       _dbus_warn ("Did not receive a reply to %s %d on %p\n",
-                  DBUS_MESSAGE_ACTIVATE_SERVICE, serial, connection);
+                  "ActivateService", serial, connection);
       goto out;
     }
 
-  _dbus_verbose ("Received %s on %p\n",
-                 dbus_message_get_name (message), connection);
+  verbose_message_received (connection, message);
 
-  if (dbus_message_get_is_error (message))
+  if (dbus_message_get_type (message) == DBUS_MESSAGE_TYPE_ERROR)
     {
-      if (!dbus_message_has_sender (message, DBUS_SERVICE_DBUS))
+      if (!dbus_message_has_sender (message, DBUS_SERVICE_ORG_FREEDESKTOP_DBUS))
         {
           _dbus_warn ("Message has wrong sender %s\n",
                       dbus_message_get_sender (message) ?
@@ -963,20 +1135,19 @@
           goto out;
         }
       
-      if (dbus_message_has_name (message,
+      if (dbus_message_is_error (message,
                                  DBUS_ERROR_NO_MEMORY))
         {
           ; /* good, this is a valid response */
         }
-      else if (dbus_message_has_name (message,
+      else if (dbus_message_is_error (message,
                                       DBUS_ERROR_ACTIVATE_SERVICE_NOT_FOUND))
         {
           ; /* good, this is expected also */
         }
       else
         {
-          _dbus_warn ("Did not expect error %s\n",
-                      dbus_message_get_name (message));
+          warn_unexpected (connection, message, "not this error");
           goto out;
         }
     }
@@ -1015,7 +1186,9 @@
   message = initial_message;
   dbus_message_ref (message);  
 
-  if (dbus_message_has_name (message, DBUS_MESSAGE_SERVICE_CREATED))
+  if (dbus_message_is_signal (message,
+                              DBUS_INTERFACE_ORG_FREEDESKTOP_DBUS,
+                              "ServiceCreated"))
     {
       char *service_name;
       CheckServiceCreatedData scd;
@@ -1034,7 +1207,7 @@
           else
             {
               _dbus_warn ("Message %s doesn't have a service name: %s\n",
-                          dbus_message_get_name (message),
+                          "ServiceCreated",
                           error.message);
               dbus_error_free (&error);
               goto out;
@@ -1062,8 +1235,8 @@
     }
   else
     {
-      _dbus_warn ("Expected to get base service ServiceCreated, instead got %s\n",
-                  dbus_message_get_name (message));
+      warn_unexpected (connection, message, "ServiceCreated for base service");
+
       goto out;
     }
 
@@ -1104,7 +1277,9 @@
   message = initial_message;
   dbus_message_ref (message);
 
-  if (dbus_message_has_name (message, DBUS_MESSAGE_SERVICE_CREATED))
+  if (dbus_message_is_signal (message,
+                              DBUS_INTERFACE_ORG_FREEDESKTOP_DBUS,
+                              "ServiceCreated"))
     {
       char *service_name;
       CheckServiceCreatedData scd;
@@ -1123,7 +1298,7 @@
           else
             {
               _dbus_warn ("Message %s doesn't have a service name: %s\n",
-                          dbus_message_get_name (message),
+                          "ServiceCreated",
                           error.message);
               dbus_error_free (&error);
               goto out;
@@ -1154,22 +1329,21 @@
       if (message == NULL)
         {
           _dbus_warn ("Expected a reply to %s, got nothing\n",
-                      DBUS_MESSAGE_ACTIVATE_SERVICE);
+                      "ActivateService");
           goto out;
         }
     }
   else
     {
-      _dbus_warn ("Expected to get service %s ServiceCreated, instead got %s\n",
-                  activated_name, dbus_message_get_name (message));
+      warn_unexpected (connection, message, "ServiceCreated for the activated name");
+      
       goto out;
     }
   
-  if (!dbus_message_has_name (message, DBUS_MESSAGE_ACTIVATE_SERVICE))
+  if (dbus_message_get_type (message) != DBUS_MESSAGE_TYPE_METHOD_RETURN)
     {
-      _dbus_warn ("Expected reply to %s, got message %s instead\n",
-                  DBUS_MESSAGE_ACTIVATE_SERVICE,
-                  dbus_message_get_name (message));
+      warn_unexpected (connection, message, "reply to ActivateService");
+
       goto out;
     }
 
@@ -1181,7 +1355,7 @@
       if (!dbus_error_has_name (&error, DBUS_ERROR_NO_MEMORY))
         {
           _dbus_warn ("Did not have activation result first argument to %s: %s\n",
-                      DBUS_MESSAGE_ACTIVATE_SERVICE, error.message);
+                      "ActivateService", error.message);
           dbus_error_free (&error);
           goto out;
         }
@@ -1279,7 +1453,7 @@
 {
   dbus_bool_t got_error;
   DBusMessage *message;
-  dbus_int32_t serial;
+  dbus_uint32_t serial;
   dbus_bool_t retval;
   
   _dbus_verbose ("Sending exit message to the test service\n");
@@ -1287,8 +1461,10 @@
   retval = FALSE;
   
   /* Kill off the test service by sending it a quit message */
-  message = dbus_message_new ("org.freedesktop.DBus.TestSuiteExit",
-                              service_name);
+  message = dbus_message_new_method_call (service_name,
+                                          "/org/freedesktop/TestSuite",
+                                          "org.freedesktop.TestSuite",
+                                          "Exit");
       
   if (message == NULL)
     {
@@ -1324,7 +1500,7 @@
   /* see if we got an error during message bus dispatching */
   bus_test_run_clients_loop (FALSE);
   message = dbus_connection_borrow_message (connection);
-  got_error = message != NULL && dbus_message_get_is_error (message);
+  got_error = message != NULL && dbus_message_get_type (message) == DBUS_MESSAGE_TYPE_ERROR;
   if (message)
     {
       dbus_connection_return_message (connection, message);
@@ -1344,21 +1520,16 @@
       message = pop_message_waiting_for_memory (connection);
       _dbus_assert (message != NULL);
 
-      if (!dbus_message_get_is_error (message))
-        {
-          _dbus_warn ("expecting an error reply to asking test service to exit, got %s\n",
-                      dbus_message_get_name (message));
-          goto out;
-        }
-      else if (!dbus_message_has_name (message, DBUS_ERROR_NO_MEMORY))
+      if (!dbus_message_is_error (message,
+                                  DBUS_ERROR_NO_MEMORY))
         {
-          _dbus_warn ("not expecting error %s when asking test service to exit\n",
-                      dbus_message_get_name (message));
+          warn_unexpected (connection, message,
+                           "a no memory error from asking test service to exit");
           goto out;
         }
 
       _dbus_verbose ("Got error %s when asking test service to exit\n",
-                     dbus_message_get_name (message));
+                     dbus_message_get_error_name (message));
 
       /* Do this again; we still need the service to exit... */
       if (!check_send_exit_to_service (context, connection,
@@ -1402,10 +1573,10 @@
       goto out;
     }
 
-  if (!dbus_message_get_is_error (message))
+  if (dbus_message_get_type (message) != DBUS_MESSAGE_TYPE_ERROR)
     {
-      _dbus_warn ("Expected an error, got %s\n",
-                  dbus_message_get_name (message));
+      warn_unexpected (connection, message, "an error");
+
       goto out;
     }
 
@@ -1415,7 +1586,7 @@
   error_name = first_error_name;
   while (error_name != NULL)
     {
-      if (dbus_message_has_name (message, error_name))
+      if (dbus_message_is_error (message, error_name))
         {
           error_found = TRUE;
           break;
@@ -1428,7 +1599,7 @@
     {
       _dbus_warn ("Expected error %s or other, got %s instead\n",
                   first_error_name,
-                  dbus_message_get_name (message));
+                  dbus_message_get_error_name (message));
       goto out;
     }
 
@@ -1451,7 +1622,7 @@
                                    DBusConnection *connection)
 {
   DBusMessage *message;
-  dbus_int32_t serial;
+  dbus_uint32_t serial;
   dbus_bool_t retval;
   DBusError error;
   char *base_service;
@@ -1460,8 +1631,10 @@
   
   dbus_error_init (&error);
   
-  message = dbus_message_new (DBUS_MESSAGE_ACTIVATE_SERVICE,
-                              DBUS_SERVICE_DBUS);
+  message = dbus_message_new_method_call (DBUS_SERVICE_ORG_FREEDESKTOP_DBUS,
+                                          DBUS_PATH_ORG_FREEDESKTOP_DBUS,
+                                          DBUS_INTERFACE_ORG_FREEDESKTOP_DBUS,
+                                          "ActivateService");
 
   if (message == NULL)
     return TRUE;
@@ -1505,17 +1678,16 @@
   if (message == NULL)
     {
       _dbus_warn ("Did not receive any messages after %s %d on %p\n",
-                  DBUS_MESSAGE_ACTIVATE_SERVICE, serial, connection);
+                  "ActivateService", serial, connection);
       goto out;
     }
 
-  _dbus_verbose ("Received %s on %p after sending %s\n",
-                 dbus_message_get_name (message), connection,
-                 DBUS_MESSAGE_ACTIVATE_SERVICE);
+  verbose_message_received (connection, message);
+  _dbus_verbose ("  (after sending %s)\n", "ActivateService");
 
-  if (dbus_message_get_is_error (message))
+  if (dbus_message_get_type (message) == DBUS_MESSAGE_TYPE_ERROR)
     {
-      if (!dbus_message_has_sender (message, DBUS_SERVICE_DBUS))
+      if (!dbus_message_has_sender (message, DBUS_SERVICE_ORG_FREEDESKTOP_DBUS))
         {
           _dbus_warn ("Message has wrong sender %s\n",
                       dbus_message_get_sender (message) ?
@@ -1523,12 +1695,12 @@
           goto out;
         }
       
-      if (dbus_message_has_name (message,
+      if (dbus_message_is_error (message,
                                  DBUS_ERROR_NO_MEMORY))
         {
           ; /* good, this is a valid response */
         }
-      else if (dbus_message_has_name (message,
+      else if (dbus_message_is_error (message,
                                       DBUS_ERROR_SPAWN_CHILD_EXITED))
         {
           ; /* good, this is expected also */
@@ -1536,7 +1708,7 @@
       else
         {
           _dbus_warn ("Did not expect error %s\n",
-                      dbus_message_get_name (message));
+                      dbus_message_get_error_name (message));
           goto out;
         }
     }
@@ -1562,8 +1734,10 @@
           goto out;
         }
 
-      got_service_deleted = dbus_message_has_name (message, DBUS_MESSAGE_SERVICE_DELETED);
-      got_error = dbus_message_get_is_error (message);
+      got_service_deleted = dbus_message_is_signal (message,
+                                                    DBUS_INTERFACE_ORG_FREEDESKTOP_DBUS,
+                                                    "ServiceDeleted");
+      got_error = dbus_message_get_type (message) == DBUS_MESSAGE_TYPE_ERROR;
       
       dbus_connection_return_message (connection, message);
       message = NULL;
@@ -1662,14 +1836,16 @@
                                    DBusConnection *connection)
 {
   DBusMessage *message;
-  dbus_int32_t serial;
+  dbus_uint32_t serial;
   dbus_bool_t retval;
   DBusError error;
   
   dbus_error_init (&error);
   
-  message = dbus_message_new (DBUS_MESSAGE_ACTIVATE_SERVICE,
-                              DBUS_SERVICE_DBUS);
+  message = dbus_message_new_method_call (DBUS_SERVICE_ORG_FREEDESKTOP_DBUS,
+                                          DBUS_PATH_ORG_FREEDESKTOP_DBUS,
+                                          DBUS_INTERFACE_ORG_FREEDESKTOP_DBUS,
+                                          "ActivateService");
 
   if (message == NULL)
     return TRUE;
@@ -1709,16 +1885,15 @@
   if (message == NULL)
     {
       _dbus_warn ("Did not receive a reply to %s %d on %p\n",
-                  DBUS_MESSAGE_ACTIVATE_SERVICE, serial, connection);
+                  "ActivateService", serial, connection);
       goto out;
     }
 
-  _dbus_verbose ("Received %s on %p\n",
-                 dbus_message_get_name (message), connection);
+  verbose_message_received (connection, message);
 
-  if (dbus_message_get_is_error (message))
+  if (dbus_message_get_type (message) == DBUS_MESSAGE_TYPE_ERROR)
     {
-      if (!dbus_message_has_sender (message, DBUS_SERVICE_DBUS))
+      if (!dbus_message_has_sender (message, DBUS_SERVICE_ORG_FREEDESKTOP_DBUS))
         {
           _dbus_warn ("Message has wrong sender %s\n",
                       dbus_message_get_sender (message) ?
@@ -1726,20 +1901,20 @@
           goto out;
         }
       
-      if (dbus_message_has_name (message,
-                                DBUS_ERROR_NO_MEMORY))
+      if (dbus_message_is_error (message,
+                                 DBUS_ERROR_NO_MEMORY))
         {
           ; /* good, this is a valid response */
         }
-      else if (dbus_message_has_name (message,
-                                     DBUS_ERROR_SPAWN_CHILD_SIGNALED))
+      else if (dbus_message_is_error (message,
+                                      DBUS_ERROR_SPAWN_CHILD_SIGNALED))
         {
           ; /* good, this is expected also */
         }
       else
         {
-          _dbus_warn ("Did not expect error %s\n",
-                      dbus_message_get_name (message));
+          warn_unexpected (connection, message, "not this error");
+
           goto out;
         }
     }
@@ -1862,6 +2037,9 @@
 
   if (!check_hello_message (context, foo))
     _dbus_assert_not_reached ("hello message failed");
+
+  if (!check_add_match_all (context, foo))
+    _dbus_assert_not_reached ("AddMatch message failed");
   
   bar = dbus_connection_open ("debug-pipe:name=test-server", &error);
   if (bar == NULL)
@@ -1872,6 +2050,9 @@
 
   if (!check_hello_message (context, bar))
     _dbus_assert_not_reached ("hello message failed");
+
+  if (!check_add_match_all (context, bar))
+    _dbus_assert_not_reached ("AddMatch message failed");
   
   baz = dbus_connection_open ("debug-pipe:name=test-server", &error);
   if (baz == NULL)
@@ -1883,6 +2064,9 @@
   if (!check_hello_message (context, baz))
     _dbus_assert_not_reached ("hello message failed");
 
+  if (!check_add_match_all (context, baz))
+    _dbus_assert_not_reached ("AddMatch message failed");
+  
   if (!check_no_leftovers (context))
     {
       _dbus_warn ("Messages were left over after setting up initial connections");
@@ -1939,6 +2123,9 @@
   if (!check_hello_message (context, foo))
     _dbus_assert_not_reached ("hello message failed");
 
+  if (!check_add_match_all (context, foo))
+    _dbus_assert_not_reached ("addmatch message failed");
+  
   if (!check_no_leftovers (context))
     {
       _dbus_warn ("Messages were left over after setting up initial SHA-1 connection\n");

Index: dispatch.h
===================================================================
RCS file: /cvs/dbus/dbus/bus/dispatch.h,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -d -r1.3 -r1.4
--- dispatch.h	14 Apr 2003 02:29:21 -0000	1.3
+++ dispatch.h	30 Sep 2003 02:32:50 -0000	1.4
@@ -29,8 +29,9 @@
 
 dbus_bool_t bus_dispatch_add_connection    (DBusConnection *connection);
 void        bus_dispatch_remove_connection (DBusConnection *connection);
-dbus_bool_t bus_dispatch_broadcast_message (BusTransaction *transaction,
+dbus_bool_t bus_dispatch_matches           (BusTransaction *transaction,
                                             DBusConnection *sender,
+                                            DBusConnection *recipient,
                                             DBusMessage    *message,
                                             DBusError      *error);
 

Index: driver.c
===================================================================
RCS file: /cvs/dbus/dbus/bus/driver.c,v
retrieving revision 1.41
retrieving revision 1.42
diff -u -d -r1.41 -r1.42
--- driver.c	14 May 2003 02:40:41 -0000	1.41
+++ driver.c	30 Sep 2003 02:32:50 -0000	1.42
@@ -27,6 +27,7 @@
 #include "driver.h"
 #include "dispatch.h"
 #include "services.h"
+#include "signals.h"
 #include "utils.h"
 #include <dbus/dbus-string.h>
 #include <dbus/dbus-internals.h>
@@ -49,15 +50,17 @@
   
   _dbus_verbose ("sending service deleted: %s\n", service_name);
 
-  message = dbus_message_new (DBUS_MESSAGE_SERVICE_DELETED,
-                              DBUS_SERVICE_BROADCAST);
+  message = dbus_message_new_signal (DBUS_PATH_ORG_FREEDESKTOP_DBUS,
+                                     DBUS_INTERFACE_ORG_FREEDESKTOP_DBUS,
+                                     "ServiceDeleted");
+  
   if (message == NULL)
     {
       BUS_SET_OOM (error);
       return FALSE;
     }
   
-  if (!dbus_message_set_sender (message, DBUS_SERVICE_DBUS) ||
+  if (!dbus_message_set_sender (message, DBUS_SERVICE_ORG_FREEDESKTOP_DBUS) ||
       !dbus_message_append_args (message,
                                  DBUS_TYPE_STRING, service_name,
                                  DBUS_TYPE_INVALID))
@@ -67,7 +70,7 @@
       return FALSE;
     }
 
-  retval = bus_dispatch_broadcast_message (transaction, NULL, message, error);
+  retval = bus_dispatch_matches (transaction, NULL, NULL, message, error);
   dbus_message_unref (message);
 
   return retval;
@@ -83,15 +86,17 @@
 
   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
   
-  message = dbus_message_new (DBUS_MESSAGE_SERVICE_CREATED,
-                              DBUS_SERVICE_BROADCAST);
+  message = dbus_message_new_signal (DBUS_PATH_ORG_FREEDESKTOP_DBUS,
+                                     DBUS_INTERFACE_ORG_FREEDESKTOP_DBUS,
+                                     "ServiceCreated");
+  
   if (message == NULL)
     {
       BUS_SET_OOM (error);
       return FALSE;
     }
   
-  if (!dbus_message_set_sender (message, DBUS_SERVICE_DBUS))
+  if (!dbus_message_set_sender (message, DBUS_SERVICE_ORG_FREEDESKTOP_DBUS))
     {
       dbus_message_unref (message);
       BUS_SET_OOM (error);
@@ -107,7 +112,7 @@
       return FALSE;
     }
   
-  retval = bus_dispatch_broadcast_message (transaction, NULL, message, error);
+  retval = bus_dispatch_matches (transaction, NULL, NULL, message, error);
   dbus_message_unref (message);
 
   return retval;
@@ -123,15 +128,18 @@
 
   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
   
-  message = dbus_message_new (DBUS_MESSAGE_SERVICE_LOST,
-                              bus_connection_get_name (connection));
+  message = dbus_message_new_signal (DBUS_PATH_ORG_FREEDESKTOP_DBUS,
+                                     DBUS_INTERFACE_ORG_FREEDESKTOP_DBUS,
+                                     "ServiceLost");
+  
   if (message == NULL)
     {
       BUS_SET_OOM (error);
       return FALSE;
     }
   
-  if (!dbus_message_append_args (message,
+  if (!dbus_message_set_destination (message, bus_connection_get_name (connection)) ||
+      !dbus_message_append_args (message,
                                  DBUS_TYPE_STRING, service_name,
                                  DBUS_TYPE_INVALID))
     {
@@ -163,8 +171,9 @@
 
   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
   
-  message = dbus_message_new (DBUS_MESSAGE_SERVICE_ACQUIRED,
-                              bus_connection_get_name (connection));
+  message = dbus_message_new_signal (DBUS_PATH_ORG_FREEDESKTOP_DBUS,
+                                     DBUS_INTERFACE_ORG_FREEDESKTOP_DBUS,
+                                     "ServiceAcquired");
 
   if (message == NULL)
     {
@@ -172,7 +181,8 @@
       return FALSE;
     }
   
-  if (!dbus_message_append_args (message,
+  if (!dbus_message_set_destination (message, bus_connection_get_name (connection)) ||
+      !dbus_message_append_args (message,
                                  DBUS_TYPE_STRING, service_name,
                                  DBUS_TYPE_INVALID))
     {
@@ -322,6 +332,7 @@
   
   bus_service_set_prohibit_replacement (service, TRUE);
 
+  _dbus_assert (bus_connection_is_active (connection));
   retval = TRUE;
   
  out_0:
@@ -343,7 +354,7 @@
   name = bus_connection_get_name (connection);
   _dbus_assert (name != NULL);
   
-  welcome = dbus_message_new_reply (hello_message);
+  welcome = dbus_message_new_method_return (hello_message);
   if (welcome == NULL)
     {
       BUS_SET_OOM (error);
@@ -387,7 +398,7 @@
   
   registry = bus_connection_get_registry (connection);
   
-  reply = dbus_message_new_reply (message);
+  reply = dbus_message_new_method_return (message);
   if (reply == NULL)
     {
       BUS_SET_OOM (error);
@@ -463,7 +474,7 @@
                                      error))
     goto out;
   
-  reply = dbus_message_new_reply (message);
+  reply = dbus_message_new_method_return (message);
   if (reply == NULL)
     {
       BUS_SET_OOM (error);
@@ -518,7 +529,7 @@
   _dbus_string_init_const (&service_name, name);
   service = bus_registry_lookup (registry, &service_name);
  
-  reply = dbus_message_new_reply (message);
+  reply = dbus_message_new_method_return (message);
   if (reply == NULL)
     {
       BUS_SET_OOM (error);
@@ -591,6 +602,160 @@
   return retval;
 }
 
+static dbus_bool_t
+send_ack_reply (DBusConnection *connection,
+                BusTransaction *transaction,
+                DBusMessage    *message,
+                DBusError      *error)
+{
+  DBusMessage *reply;
+
+  reply = dbus_message_new_method_return (message);
+  if (reply == NULL)
+    {
+      BUS_SET_OOM (error);
+      return FALSE;
+    }
+
+  if (!bus_transaction_send_from_driver (transaction, connection, reply))
+    {
+      BUS_SET_OOM (error);
+      dbus_message_unref (reply);
+      return FALSE;
+    }
+
+  dbus_message_unref (reply);
+  
+  return TRUE;
+}
+
+static dbus_bool_t
+bus_driver_handle_add_match (DBusConnection *connection,
+                             BusTransaction *transaction,
+                             DBusMessage    *message,
+                             DBusError      *error)
+{
+  BusMatchRule *rule;
+  char *text;
+  DBusString str;
+  BusMatchmaker *matchmaker;
+  
+  _DBUS_ASSERT_ERROR_IS_CLEAR (error);
+
+  text = NULL;
+  rule = NULL;
+
+  if (bus_connection_get_n_match_rules (connection) >=
+      bus_context_get_max_match_rules_per_connection (bus_transaction_get_context (transaction)))
+    {
+      dbus_set_error (error, DBUS_ERROR_LIMITS_EXCEEDED,
+                      "Connection \"%s\" is not allowed to add more match rules "
+                      "(increase limits in configuration file if required)",
+                      bus_connection_is_active (connection) ?
+                      bus_connection_get_name (connection) :
+                      "(inactive)");
+      goto failed;
+    }
+  
+  if (!dbus_message_get_args (message, error,
+                              DBUS_TYPE_STRING, &text,
+                              DBUS_TYPE_INVALID))
+    {
+      _dbus_verbose ("No memory to get arguments to AddMatch\n");
+      goto failed;
+    }
+
+  _dbus_string_init_const (&str, text);
+
+  rule = bus_match_rule_parse (connection, &str, error);
+  if (rule == NULL)
+    goto failed;
+
+  matchmaker = bus_connection_get_matchmaker (connection);
+
+  if (!bus_matchmaker_add_rule (matchmaker, rule))
+    {
+      BUS_SET_OOM (error);
+      goto failed;
+    }
+
+  if (!send_ack_reply (connection, transaction,
+                       message, error))
+    {
+      bus_matchmaker_remove_rule (matchmaker, rule);
+      goto failed;
+    }
+  
+  bus_match_rule_unref (rule);
+  dbus_free (text);
+  
+  return TRUE;
+
+ failed:
+  _DBUS_ASSERT_ERROR_IS_SET (error);
+  if (rule)
+    bus_match_rule_unref (rule);
+  if (text)
+    dbus_free (text);
+  return FALSE;
+}
+
+static dbus_bool_t
+bus_driver_handle_remove_match (DBusConnection *connection,
+                                BusTransaction *transaction,
+                                DBusMessage    *message,
+                                DBusError      *error)
+{
+  BusMatchRule *rule;
+  char *text;
+  DBusString str;
+  BusMatchmaker *matchmaker;
+  
+  _DBUS_ASSERT_ERROR_IS_CLEAR (error);
+
+  text = NULL;
+  rule = NULL;
+  
+  if (!dbus_message_get_args (message, error,
+                              DBUS_TYPE_STRING, &text,
+                              DBUS_TYPE_INVALID))
+    {
+      _dbus_verbose ("No memory to get arguments to RemoveMatch\n");
+      goto failed;
+    }
+
+  _dbus_string_init_const (&str, text);
+
+  rule = bus_match_rule_parse (connection, &str, error);
+  if (rule == NULL)
+    goto failed;
+
+  /* Send the ack before we remove the rule, since the ack is undone
+   * on transaction cancel, but rule removal isn't.
+   */
+  if (!send_ack_reply (connection, transaction,
+                       message, error))
+    goto failed;
+  
+  matchmaker = bus_connection_get_matchmaker (connection);
+
+  if (!bus_matchmaker_remove_rule_by_value (matchmaker, rule, error))
+    goto failed;
+
+  bus_match_rule_unref (rule);
+  dbus_free (text);
+  
+  return TRUE;
+
+ failed:
+  _DBUS_ASSERT_ERROR_IS_SET (error);
+  if (rule)
+    bus_match_rule_unref (rule);
+  if (text)
+    dbus_free (text);
+  return FALSE;
+}
+
 /* For speed it might be useful to sort this in order of
  * frequency of use (but doesn't matter with only a few items
  * anyhow)
@@ -603,11 +768,13 @@
                            DBusMessage    *message,
                            DBusError      *error);
 } message_handlers[] = {
-  { DBUS_MESSAGE_ACQUIRE_SERVICE, bus_driver_handle_acquire_service },
-  { DBUS_MESSAGE_ACTIVATE_SERVICE, bus_driver_handle_activate_service },
-  { DBUS_MESSAGE_HELLO, bus_driver_handle_hello },
-  { DBUS_MESSAGE_SERVICE_EXISTS, bus_driver_handle_service_exists },
-  { DBUS_MESSAGE_LIST_SERVICES, bus_driver_handle_list_services }
+  { "AcquireService", bus_driver_handle_acquire_service },
+  { "ActivateService", bus_driver_handle_activate_service },
+  { "Hello", bus_driver_handle_hello },
+  { "ServiceExists", bus_driver_handle_service_exists },
+  { "ListServices", bus_driver_handle_list_services },
+  { "AddMatch", bus_driver_handle_add_match },
+  { "RemoveMatch", bus_driver_handle_remove_match }
 };
 
 dbus_bool_t
@@ -620,15 +787,32 @@
   int i;
 
   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
+
+  if (dbus_message_get_type (message) != DBUS_MESSAGE_TYPE_METHOD_CALL)
+    {
+      _dbus_verbose ("Driver got a non-method-call message, ignoring\n");
+      return TRUE; /* we just ignore this */
+    }
+
+  _dbus_assert (dbus_message_get_interface (message) != NULL);
+  _dbus_assert (dbus_message_get_member (message) != NULL);
+
+  name = dbus_message_get_member (message);
+  sender = dbus_message_get_sender (message);
   
-  _dbus_verbose ("Driver got a message: %s\n",
-		 dbus_message_get_name (message));
+  if (strcmp (dbus_message_get_interface (message),
+              DBUS_INTERFACE_ORG_FREEDESKTOP_DBUS) != 0)
+    {
+      _dbus_verbose ("Driver got message to unknown interface \"%s\"\n",
+                     dbus_message_get_interface (message));
+      goto unknown;
+    }
+  
+  _dbus_verbose ("Driver got a method call: %s\n",
+		 dbus_message_get_member (message));
   
-  name = dbus_message_get_name (message);
-  sender = dbus_message_get_sender (message);
-
   /* security checks should have kept this from getting here */
-  _dbus_assert (sender != NULL || strcmp (name, DBUS_MESSAGE_HELLO) == 0);
+  _dbus_assert (sender != NULL || strcmp (name, "Hello") == 0);
 
   if (dbus_message_get_reply_serial (message) == 0)
     {
@@ -659,11 +843,13 @@
       ++i;
     }
 
-  _dbus_verbose ("No driver handler for %s\n", name);
+ unknown:
+  _dbus_verbose ("No driver handler for message \"%s\"\n",
+                 name);
 
-  dbus_set_error (error, DBUS_ERROR_UNKNOWN_MESSAGE,
+  dbus_set_error (error, DBUS_ERROR_UNKNOWN_METHOD,
                   "%s does not understand message %s",
-                  DBUS_SERVICE_DBUS, name);
+                  DBUS_SERVICE_ORG_FREEDESKTOP_DBUS, name);
   
   return FALSE;
 }

Index: policy.c
===================================================================
RCS file: /cvs/dbus/dbus/bus/policy.c,v
retrieving revision 1.13
retrieving revision 1.14
diff -u -d -r1.13 -r1.14
--- policy.c	17 May 2003 17:53:16 -0000	1.13
+++ policy.c	30 Sep 2003 02:32:50 -0000	1.14
@@ -52,7 +52,11 @@
       rule->d.group.gid = DBUS_GID_UNSET;
       break;
     case BUS_POLICY_RULE_SEND:
+      rule->d.send.message_type = DBUS_MESSAGE_TYPE_INVALID;
+      break;
     case BUS_POLICY_RULE_RECEIVE:
+      rule->d.receive.message_type = DBUS_MESSAGE_TYPE_INVALID;
+      break;
     case BUS_POLICY_RULE_OWN:
       break;
     }
@@ -80,11 +84,17 @@
       switch (rule->type)
         {
         case BUS_POLICY_RULE_SEND:
-          dbus_free (rule->d.send.message_name);
+          dbus_free (rule->d.send.path);
+          dbus_free (rule->d.send.interface);
+          dbus_free (rule->d.send.member);
+          dbus_free (rule->d.send.error);
           dbus_free (rule->d.send.destination);
           break;
         case BUS_POLICY_RULE_RECEIVE:
-          dbus_free (rule->d.receive.message_name);
+          dbus_free (rule->d.receive.path);
+          dbus_free (rule->d.receive.interface);
+          dbus_free (rule->d.receive.member);
+          dbus_free (rule->d.receive.error);
           dbus_free (rule->d.receive.origin);
           break;
         case BUS_POLICY_RULE_OWN:
@@ -680,8 +690,8 @@
 
   /* The idea here is that if we have:
    * 
-   * <allow send="foo"/>
-   * <deny send="*"/>
+   * <allow send_interface="foo.bar"/>
+   * <deny send_interface="*"/>
    *
    * (for example) the deny will always override the allow.  So we
    * delete the allow. Ditto for deny followed by allow, etc. This is
@@ -713,12 +723,20 @@
         {
         case BUS_POLICY_RULE_SEND:
           remove_preceding =
-            rule->d.send.message_name == NULL &&
+            rule->d.send.message_type == DBUS_MESSAGE_TYPE_INVALID &&
+            rule->d.send.path == NULL &&
+            rule->d.send.interface == NULL &&
+            rule->d.send.member == NULL &&
+            rule->d.send.error == NULL &&
             rule->d.send.destination == NULL;
           break;
         case BUS_POLICY_RULE_RECEIVE:
           remove_preceding =
-            rule->d.receive.message_name == NULL &&
+            rule->d.receive.message_type == DBUS_MESSAGE_TYPE_INVALID &&
+            rule->d.receive.path == NULL &&
+            rule->d.receive.interface == NULL &&
+            rule->d.receive.member == NULL &&
+            rule->d.receive.error == NULL &&
             rule->d.receive.origin == NULL;
           break;
         case BUS_POLICY_RULE_OWN:
@@ -791,16 +809,59 @@
           continue;
         }
 
-      if (rule->d.send.message_name != NULL)
+      if (rule->d.send.message_type != DBUS_MESSAGE_TYPE_INVALID)
         {
-          if (!dbus_message_has_name (message,
-                                      rule->d.send.message_name))
+          if (dbus_message_get_type (message) != rule->d.send.message_type)
             {
-              _dbus_verbose ("  (policy) skipping rule for different message name\n");
+              _dbus_verbose ("  (policy) skipping rule for different message type\n");
+              continue;
+            }
+        }
+      
+      if (rule->d.send.path != NULL)
+        {
+          if (dbus_message_get_path (message) != NULL &&
+              strcmp (dbus_message_get_path (message),
+                      rule->d.send.path) != 0)
+            {
+              _dbus_verbose ("  (policy) skipping rule for different path\n");
+              continue;
+            }
+        }
+      
+      if (rule->d.send.interface != NULL)
+        {
+          if (dbus_message_get_interface (message) != NULL &&
+              strcmp (dbus_message_get_interface (message),
+                      rule->d.send.interface) != 0)
+            {
+              _dbus_verbose ("  (policy) skipping rule for different interface\n");
+              continue;
+            }
+        }
+
+      if (rule->d.send.member != NULL)
+        {
+          if (dbus_message_get_member (message) != NULL &&
+              strcmp (dbus_message_get_member (message),
+                      rule->d.send.member) != 0)
+            {
+              _dbus_verbose ("  (policy) skipping rule for different member\n");
               continue;
             }
         }
 
+      if (rule->d.send.error != NULL)
+        {
+          if (dbus_message_get_error_name (message) != NULL &&
+              strcmp (dbus_message_get_error_name (message),
+                      rule->d.send.error) != 0)
+            {
+              _dbus_verbose ("  (policy) skipping rule for different error name\n");
+              continue;
+            }
+        }
+      
       if (rule->d.send.destination != NULL)
         {
           /* receiver can be NULL for messages that are sent to the
@@ -856,16 +917,33 @@
 bus_client_policy_check_can_receive (BusClientPolicy *policy,
                                      BusRegistry     *registry,
                                      DBusConnection  *sender,
+                                     DBusConnection  *addressed_recipient,
+                                     DBusConnection  *proposed_recipient,
                                      DBusMessage     *message)
 {
   DBusList *link;
   dbus_bool_t allowed;
+  dbus_bool_t eavesdropping;
+  
+  /* NULL sender, proposed_recipient means the bus driver.  NULL
+   * addressed_recipient means the message didn't specify an explicit
+   * target. If proposed_recipient is NULL, then addressed_recipient
+   * is also NULL but is implicitly the bus driver.
+   */
+
+  _dbus_assert (proposed_recipient == NULL ||
+                (dbus_message_get_destination (message) == NULL ||
+                 addressed_recipient != NULL));
+  
+  eavesdropping =
+    (proposed_recipient == NULL || /* explicitly to bus driver */
+     (addressed_recipient && addressed_recipient != proposed_recipient)); /* explicitly to a different recipient */
   
   /* policy->rules is in the order the rules appeared
    * in the config file, i.e. last rule that applies wins
    */
 
-  _dbus_verbose ("  (policy) checking receive rules\n");
+  _dbus_verbose ("  (policy) checking receive rules, eavesdropping = %d\n", eavesdropping);
   
   allowed = FALSE;
   link = _dbus_list_get_first_link (&policy->rules);
@@ -873,12 +951,7 @@
     {
       BusPolicyRule *rule = link->data;
 
-      link = _dbus_list_get_next_link (&policy->rules, link);
-      
-      /* Rule is skipped if it specifies a different
-       * message name from the message, or a different
-       * origin from the message
-       */
+      link = _dbus_list_get_next_link (&policy->rules, link);      
       
       if (rule->type != BUS_POLICY_RULE_RECEIVE)
         {
@@ -886,16 +959,77 @@
           continue;
         }
 
-      if (rule->d.receive.message_name != NULL)
+      if (rule->d.receive.message_type != DBUS_MESSAGE_TYPE_INVALID)
         {
-          if (!dbus_message_has_name (message,
-                                      rule->d.receive.message_name))
+          if (dbus_message_get_type (message) != rule->d.receive.message_type)
             {
-              _dbus_verbose ("  (policy) skipping rule for different message name\n");
+              _dbus_verbose ("  (policy) skipping rule for different message type\n");
               continue;
             }
         }
 
+      /* for allow, eavesdrop=false means the rule doesn't apply when
+       * eavesdropping. eavesdrop=true means always allow.
+       */
+      if (eavesdropping && rule->allow && !rule->d.receive.eavesdrop)
+        {
+          _dbus_verbose ("  (policy) skipping allow rule since it doesn't apply to eavesdropping\n");
+          continue;
+        }
+
+      /* for deny, eavesdrop=true means the rule applies only when
+       * eavesdropping; eavesdrop=false means always deny.
+       */
+      if (!eavesdropping && !rule->allow && rule->d.receive.eavesdrop)
+        {
+          _dbus_verbose ("  (policy) skipping deny rule since it only applies to eavesdropping\n");
+          continue;
+        }
+      
+      if (rule->d.receive.path != NULL)
+        {
+          if (dbus_message_get_path (message) != NULL &&
+              strcmp (dbus_message_get_path (message),
+                      rule->d.receive.path) != 0)
+            {
+              _dbus_verbose ("  (policy) skipping rule for different path\n");
+              continue;
+            }
+        }
+      
+      if (rule->d.receive.interface != NULL)
+        {
+          if (dbus_message_get_interface (message) != NULL &&
+              strcmp (dbus_message_get_interface (message),
+                      rule->d.receive.interface) != 0)
+            {
+              _dbus_verbose ("  (policy) skipping rule for different interface\n");
+              continue;
+            }
+        }      
+
+      if (rule->d.receive.member != NULL)
+        {
+          if (dbus_message_get_member (message) != NULL &&
+              strcmp (dbus_message_get_member (message),
+                      rule->d.receive.member) != 0)
+            {
+              _dbus_verbose ("  (policy) skipping rule for different member\n");
+              continue;
+            }
+        }
+
+      if (rule->d.receive.error != NULL)
+        {
+          if (dbus_message_get_error_name (message) != NULL &&
+              strcmp (dbus_message_get_error_name (message),
+                      rule->d.receive.error) != 0)
+            {
+              _dbus_verbose ("  (policy) skipping rule for different error name\n");
+              continue;
+            }
+        }
+      
       if (rule->d.receive.origin != NULL)
         {          
           /* sender can be NULL for messages that originate from the
@@ -937,7 +1071,7 @@
                 }
             }
         }
-
+      
       /* Use this rule */
       allowed = rule->allow;
 

Index: policy.h
===================================================================
RCS file: /cvs/dbus/dbus/bus/policy.h,v
retrieving revision 1.9
retrieving revision 1.10
diff -u -d -r1.9 -r1.10
--- policy.h	17 May 2003 17:53:16 -0000	1.9
+++ policy.h	30 Sep 2003 02:32:50 -0000	1.10
@@ -54,16 +54,27 @@
   {
     struct
     {
-      /* either can be NULL meaning "any" */
-      char *message_name;
+      /* message type can be DBUS_MESSAGE_TYPE_INVALID meaning "any" */
+      int   message_type;
+      /* any of these can be NULL meaning "any" */
+      char *path;
+      char *interface;
+      char *member;
+      char *error;
       char *destination;
     } send;
 
     struct
     {
-      /* either can be NULL meaning "any" */
-      char *message_name;
+      /* message type can be DBUS_MESSAGE_TYPE_INVALID meaning "any" */
+      int   message_type;
+      /* any of these can be NULL meaning "any" */
+      char *path;
+      char *interface;
+      char *member;
+      char *error;
       char *origin;
+      unsigned int eavesdrop : 1;
     } receive;
 
     struct
@@ -124,6 +135,8 @@
 dbus_bool_t      bus_client_policy_check_can_receive (BusClientPolicy  *policy,
                                                       BusRegistry      *registry,
                                                       DBusConnection   *sender,
+                                                      DBusConnection   *addressed_recipient,
+                                                      DBusConnection   *proposed_recipient,
                                                       DBusMessage      *message);
 dbus_bool_t      bus_client_policy_check_can_own     (BusClientPolicy  *policy,
                                                       DBusConnection   *connection,

Index: services.c
===================================================================
RCS file: /cvs/dbus/dbus/bus/services.c,v
retrieving revision 1.15
retrieving revision 1.16
diff -u -d -r1.15 -r1.16
--- services.c	27 Apr 2003 06:25:42 -0000	1.15
+++ services.c	30 Sep 2003 02:32:50 -0000	1.16
@@ -417,10 +417,14 @@
   bus_service_ref (service);
 }
 
+/**
+ * Data used to represent an ownership cancellation in
+ * a bus transaction.
+ */
 typedef struct
 {
-  DBusConnection *connection;
-  BusService *service;
+  DBusConnection *connection; /**< the connection */
+  BusService *service;        /**< service to cancel ownership of */
 } OwnershipCancelData;
 
 static void

Index: session.conf.in
===================================================================
RCS file: /cvs/dbus/dbus/bus/session.conf.in,v
retrieving revision 1.5
retrieving revision 1.6
diff -u -d -r1.5 -r1.6
--- session.conf.in	14 May 2003 02:40:41 -0000	1.5
+++ session.conf.in	30 Sep 2003 02:32:50 -0000	1.6
@@ -13,11 +13,14 @@
   <servicedir>@EXPANDED_LIBDIR@/dbus-1.0/services</servicedir>
 
   <policy context="default">
-    <!-- Allow everything -->
-    <allow send="*"/>
-    <allow receive="*"/>
+    <!-- Allow everything to be sent -->
+    <allow send_destination="*"/>
+    <!-- Allow everything to be received -->
+    <allow eavesdrop="true"/>
+    <!-- Allow anyone to own anything -->
     <allow own="*"/>
-    <allow user="*"/>  
+    <!-- Allow any user to connect -->
+    <allow user="*"/>
   </policy>
 
   <!-- This is included last so local configuration can override what's 

Index: system.conf.in
===================================================================
RCS file: /cvs/dbus/dbus/bus/system.conf.in,v
retrieving revision 1.10
retrieving revision 1.11
diff -u -d -r1.10 -r1.11
--- system.conf.in	29 Sep 2003 01:43:52 -0000	1.10
+++ system.conf.in	30 Sep 2003 02:32:50 -0000	1.11
@@ -34,16 +34,16 @@
 
   <policy context="default">
     <!-- Deny everything then punch holes -->
-    <deny send="*"/>
-    <deny receive="*"/>
+    <deny send_interface="*"/>
+    <deny receive_interface="*"/>
     <deny own="*"/>
     <!-- But allow all users to connect -->
     <allow user="*"/>
     <!-- Allow anyone to talk to the message bus -->
     <!-- FIXME I think currently these allow rules are always implicit 
          even if they aren't in here -->
-    <allow send_to="org.freedesktop.DBus"/>
-    <allow receive_from="org.freedesktop.DBus"/>
+    <allow send_destination="org.freedesktop.DBus"/>
+    <allow receive_sender="org.freedesktop.DBus"/>
   </policy>
 
   <!-- Config files are placed here that among other things, punch 

Index: test-main.c
===================================================================
RCS file: /cvs/dbus/dbus/bus/test-main.c,v
retrieving revision 1.12
retrieving revision 1.13
diff -u -d -r1.12 -r1.13
--- test-main.c	14 Apr 2003 23:52:40 -0000	1.12
+++ test-main.c	30 Sep 2003 02:32:50 -0000	1.13
@@ -89,6 +89,12 @@
 
   check_memleaks (argv[0]);
 
+  printf ("%s: Running signals test\n", argv[0]);
+  if (!bus_signals_test (&test_data_dir))
+    die ("signals");
+
+  check_memleaks (argv[0]);
+  
   printf ("%s: Running SHA1 connection test\n", argv[0]);
   if (!bus_dispatch_sha1_test (&test_data_dir))
     die ("sha1");

Index: test.c
===================================================================
RCS file: /cvs/dbus/dbus/bus/test.c,v
retrieving revision 1.21
retrieving revision 1.22
diff -u -d -r1.21 -r1.22
--- test.c	22 Jun 2003 19:39:47 -0000	1.21
+++ test.c	30 Sep 2003 02:32:50 -0000	1.22
@@ -102,11 +102,15 @@
 }
 
 static DBusHandlerResult
-client_disconnect_handler (DBusMessageHandler *handler,
-                           DBusConnection     *connection,
-                           DBusMessage        *message,
-                           void               *user_data)
+client_disconnect_filter (DBusConnection     *connection,
+                          DBusMessage        *message,
+                          void               *user_data)
 {
+  if (!dbus_message_is_signal (message,
+                               DBUS_INTERFACE_ORG_FREEDESKTOP_LOCAL,
+                               "Disconnected"))
+    return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+    
   _dbus_verbose ("Removing client %p in disconnect handler\n",
                  connection);
   
@@ -120,42 +124,19 @@
       client_loop = NULL;
     }
   
-  return DBUS_HANDLER_RESULT_ALLOW_MORE_HANDLERS;
-}
-
-static dbus_int32_t handler_slot = -1;
-
-static void
-free_handler (void *data)
-{
-  DBusMessageHandler *handler = data;
-
-  dbus_message_handler_unref (handler);
-  dbus_connection_free_data_slot (&handler_slot);
+  return DBUS_HANDLER_RESULT_HANDLED;
 }
 
 dbus_bool_t
 bus_setup_debug_client (DBusConnection *connection)
 {
-  DBusMessageHandler *disconnect_handler;
-  const char *to_handle[] = { DBUS_MESSAGE_LOCAL_DISCONNECT };
-  dbus_bool_t retval;
-  
-  disconnect_handler = dbus_message_handler_new (client_disconnect_handler,
-                                                 NULL, NULL);
+  dbus_bool_t retval;  
 
-  if (disconnect_handler == NULL)
+  if (!dbus_connection_add_filter (connection,
+                                   client_disconnect_filter,
+                                   NULL, NULL))
     return FALSE;
 
-  if (!dbus_connection_register_handler (connection,
-                                         disconnect_handler,
-                                         to_handle,
-                                         _DBUS_N_ELEMENTS (to_handle)))
-    {
-      dbus_message_handler_unref (disconnect_handler);
-      return FALSE;
-    }
-
   retval = FALSE;
 
   if (client_loop == NULL)
@@ -182,25 +163,15 @@
 
   if (!_dbus_list_append (&clients, connection))
     goto out;
-
-  if (!dbus_connection_allocate_data_slot (&handler_slot))
-    goto out;
-
-  /* Set up handler to be destroyed */  
-  if (!dbus_connection_set_data (connection, handler_slot,
-                                 disconnect_handler,
-                                 free_handler))
-    {
-      dbus_connection_free_data_slot (&handler_slot);
-      goto out;
-    }
   
   retval = TRUE;
   
  out:
   if (!retval)
     {
-      dbus_message_handler_unref (disconnect_handler); /* unregisters it */
+      dbus_connection_remove_filter (connection,
+                                     client_disconnect_filter,
+                                     NULL);
       
       dbus_connection_set_watch_functions (connection,
                                            NULL, NULL, NULL, NULL, NULL);

Index: test.h
===================================================================
RCS file: /cvs/dbus/dbus/bus/test.h,v
retrieving revision 1.10
retrieving revision 1.11
diff -u -d -r1.10 -r1.11
--- test.h	14 Apr 2003 23:52:40 -0000	1.10
+++ test.h	30 Sep 2003 02:32:50 -0000	1.11
@@ -36,6 +36,7 @@
 dbus_bool_t bus_dispatch_sha1_test    (const DBusString             *test_data_dir);
 dbus_bool_t bus_policy_test           (const DBusString             *test_data_dir);
 dbus_bool_t bus_config_parser_test    (const DBusString             *test_data_dir);
+dbus_bool_t bus_signals_test          (const DBusString             *test_data_dir);
 dbus_bool_t bus_setup_debug_client    (DBusConnection               *connection);
 void        bus_test_clients_foreach  (BusConnectionForeachFunction  function,
                                        void                         *data);