initscript \
avahi-dnsconfd \
avahi-utils \
+ avahi-python \
examples \
man \
tests \
--- /dev/null
+# $Id$
+
+# This file is part of avahi.
+#
+# avahi is free software; you can redistribute it and/or modify it
+# under the terms of the GNU Lesser General Public License as
+# published by the Free Software Foundation; either version 2 of the
+# License, or (at your option) any later version.
+#
+# avahi is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
+# License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with avahi; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+# USA.
+
+AM_CFLAGS=-I$(top_srcdir)
+
+# This cool debug trap works on i386/gcc only
+AM_CFLAGS+='-DDEBUG_TRAP=__asm__("int $$3")'
+
+EXTRA_DIST = \
+ avahi-publish-address.in \
+ avahi-publish-service.in \
+ avahi-bookmarks.in \
+ avahi-discover.in \
+ avahi-discover.desktop.in
+
+SUBDIRS=avahi
+
+if HAVE_PYTHON
+if HAVE_PYTHON_DBUS
+if HAVE_PYGTK
+
+pythonscripts = \
+ avahi-publish-address \
+ avahi-publish-service \
+ avahi-bookmarks \
+ avahi-discover
+
+desktopdir = $(datadir)/applications
+desktop_DATA = avahi-discover.desktop
+
+avahi-discover.desktop: avahi-discover.desktop.in
+ sed -e 's,@bindir\@,$(bindir),g' $< > $@
+ chmod +x $@
+
+avahi-discover: avahi-discover.in
+ sed -e 's,@PYTHON\@,$(PYTHON),g' \
+ -e 's,@interfacesdir\@,$(interfacesdir),g' $< > $@
+ chmod +x $@
+
+avahi-publish-address: avahi-publish-address.in
+ sed -e 's,@PYTHON\@,$(PYTHON),g' $< > $@
+ chmod +x $@
+
+avahi-publish-service: avahi-publish-service.in
+ sed -e 's,@PYTHON\@,$(PYTHON),g' $< > $@
+ chmod +x $@
+
+avahi-bookmarks: avahi-bookmarks.in
+ sed -e 's,@PYTHON\@,$(PYTHON),g' $< > $@
+ chmod +x $@
+
+bin_SCRIPTS = $(pythonscripts)
+CLEANFILES = $(pythonscripts) $(desktop_DATA)
+
+endif
+endif
+endif
--- /dev/null
+#!@PYTHON@
+# -*-python-*-
+# $Id$
+
+# This file is part of avahi.
+#
+# avahi is free software; you can redistribute it and/or modify it
+# under the terms of the GNU Lesser General Public License as
+# published by the Free Software Foundation; either version 2 of the
+# License, or (at your option) any later version.
+#
+# avahi is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
+# License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with avahi; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+# USA.
+
+import sys, getopt
+
+try:
+ import avahi, gobject, dbus
+except ImportError:
+ print "Sorry, to use this tool you need to install Avahi, pygtk and python-dbus."
+ sys.exit(1)
+
+try:
+ import dbus.glib
+except ImportError:
+ pass
+
+try:
+ from twisted.internet import gtk2reactor
+ gtk2reactor.install()
+ from twisted.internet import reactor
+ from twisted.web import server, resource
+except ImportError:
+ print "Sorry, to use this tool you need to install twisted and twisted.web."
+ sys.exit(1)
+
+urlproto = { "_http._tcp" : "http", "_https._tcp" : "https", "_ftp._tcp" : "ftp" }
+
+port = 8080
+address = "127.0.0.1"
+use_host_names = False
+domain = "local"
+
+class AvahiBookmarks(resource.Resource):
+ isLeaf = True
+
+ services = {}
+
+ def __init__(self):
+ resource.Resource.__init__(self)
+
+ self.bus = dbus.SystemBus()
+ self.server = dbus.Interface(self.bus.get_object(avahi.DBUS_NAME, avahi.DBUS_PATH_SERVER), avahi.DBUS_INTERFACE_SERVER)
+
+ self.version_string = self.server.GetVersionString()
+
+ self.browse_service_type("_http._tcp")
+
+ # Hurrah! if I enable one of the following lines, python segfaults.
+ #self.browse_service_type("_https._tcp")
+ #self.browse_service_type("_ftp._tcp")
+
+ def browse_service_type(self, stype):
+
+ global domain
+
+ browser = dbus.Interface(self.bus.get_object(avahi.DBUS_NAME, self.server.ServiceBrowserNew(avahi.IF_UNSPEC, avahi.PROTO_UNSPEC, stype, domain, dbus.UInt32(0))), avahi.DBUS_INTERFACE_SERVICE_BROWSER)
+ browser.connect_to_signal('ItemNew', self.new_service)
+ browser.connect_to_signal('ItemRemove', self.remove_service)
+
+ def find_path(self, txt):
+
+ l = avahi.txt_array_to_string_array(txt)
+
+ for k in l:
+ if k[:5] == "path=":
+ if k[5:].startswith("/"):
+ return k[5:]
+ else:
+ return "/" + k[5:]
+
+ return "/"
+
+ def render_GET(self, request):
+
+ t = '<html><head><title>Zeroconf Bookmarks</title></head><body><h1>Zeroconf Bookmarks</h1>'
+
+ if len(self.services) == 0:
+ t += '<p>Sorry, no web services have been registered on the local LAN.</p>'
+ else:
+ t += '<ul style="padding: 0px; margin: 20px; list-style-type: none">'
+
+ for k, v in self.services.iteritems():
+
+ if v[3] == 80:
+ port = ''
+ else:
+ port = ':%i' % v[3]
+
+ path = self.find_path(v[4])
+ t += '<li><a href="%s://%s%s%s">%s</a></li>' % (urlproto[k[3]], v[2], port, path, k[2])
+
+ t += '</ul>'
+
+ t += '<hr noshade/><p style="font-size: 8; font-family: sans-serif">Served by %s</p></body></html>' % self.version_string
+
+ return t
+
+
+ def new_service(self, interface, protocol, name, type, domain, flags):
+
+ interface, protocol, name, type, domain, host, aprotocol, address, port, txt, flags = self.server.ResolveService(interface, protocol, name, type, domain, avahi.PROTO_UNSPEC, dbus.UInt32(0))
+
+ if use_host_names:
+ h = host
+ else:
+ if aprotocol == avahi.PROTO_INET6:
+ h = "[" + address + "]"
+ else:
+ h = address
+
+ self.services[(interface, protocol, name, type, domain)] = (host, aprotocol, h, port, txt)
+
+ def remove_service(self, interface, protocol, name, type, domain):
+ del self.services[(interface, protocol, name, type, domain)]
+
+
+def usage(retval = 0):
+ print "%s [options]\n" % sys.argv[0]
+ print " -h --help Show this help"
+ print " -p --port PORT Specify the port to use (default %u)" % port
+ print " -a --address ADDRESS Specify the address to bind to (default %s)" % address
+ print " -H --host-names Show all services, regardless of the type"
+ print " -d --domain DOMAIN Specify the domain to browse"
+ sys.exit(retval)
+
+try:
+ opts, args = getopt.getopt(sys.argv[1:], "hp:a:Hd:", ["help", "port=", "address=", "host-names", "domain="])
+except getopt.GetoptError:
+ usage(2)
+
+for o, a in opts:
+ if o in ("-h", "--help"):
+ usage()
+
+ if o in ("-p", "--port"):
+ port = int(a)
+
+ if o in ("-a", "--address"):
+ address = a
+
+ if o in ("-H", "--host-names"):
+ use_host_names = True
+
+ if o in ("-d", "--domain"):
+ domain = a
+
+site = server.Site(AvahiBookmarks())
+reactor.listenTCP(port, site, interface=address)
+
+print "Now point your web browser to http://%s:%u/!" % (address, port)
+
+try:
+ reactor.run()
+except KeyboardInterrupt, k:
+ pass
--- /dev/null
+[Desktop Entry]
+Encoding=UTF-8
+Name=Avahi Zeroconf Browser
+Comment=Browse for Zeroconf services available on your network
+Exec=@bindir@/avahi-discover
+Terminal=false
+Type=Application
+Icon=gnome-nettool.png
+Categories=GNOME;Application;System;Utility
+StartupNotify=false
--- /dev/null
+#!@PYTHON@
+# -*-python-*-
+# $Id$
+
+# This file is part of avahi.
+#
+# avahi is free software; you can redistribute it and/or modify it
+# under the terms of the GNU Lesser General Public License as
+# published by the Free Software Foundation; either version 2 of the
+# License, or (at your option) any later version.
+#
+# avahi is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
+# License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with avahi; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+# USA.
+
+import os, sys
+
+try:
+ import avahi, gtk, gobject, dbus, avahi.ServiceTypeDatabase
+ from avahi.SimpleGladeApp import SimpleGladeApp
+except ImportError:
+ print "Sorry, to use this tool you need to install Avahi, pygtk and python-dbus."
+ sys.exit(1)
+
+try:
+ import dbus.glib
+except ImportError, e:
+ pass
+
+service_type_browsers = {}
+service_browsers = {}
+
+glade_dir = "@interfacesdir@"
+
+service_type_db = avahi.ServiceTypeDatabase.ServiceTypeDatabase()
+
+class Main_window(SimpleGladeApp):
+ def __init__(self, path="avahi-discover.glade", root="main_window", domain=None, **kwargs):
+ path = os.path.join(glade_dir, path)
+ SimpleGladeApp.__init__(self, path, root, domain, **kwargs)
+
+ def on_tree_view_cursor_changed(self, widget, *args):
+ (model, iter) = widget.get_selection().get_selected()
+ (name,interface,protocol,stype,domain) = self.treemodel.get(iter,1,2,3,4,5)
+ if stype == None:
+ self.info_label.set_markup("<i>No service currently selected.</i>")
+ return
+ #Asynchronous resolving
+ self.server.ResolveService( int(interface), int(protocol), name, stype, domain, avahi.PROTO_UNSPEC, dbus.UInt32(0), reply_handler=self.service_resolved, error_handler=self.print_error)
+
+
+ def protoname(self,protocol):
+ if protocol == avahi.PROTO_INET:
+ return "IPv4"
+ if protocol == avahi.PROTO_INET6:
+ return "IPv6"
+
+
+ def siocgifname(self, interface):
+ if interface <= 0:
+ return "any"
+ else:
+ return self.server.GetNetworkInterfaceNameByIndex(interface)
+
+ def service_resolved(self, interface, protocol, name, stype, domain, host, aprotocol, address, port, txt, flags):
+ print "Service data for service '%s' of type '%s' in domain '%s' on %i.%i:" % (name, stype, domain, interface, protocol)
+
+ print "\tHost %s (%s), port %i, TXT data: %s" % (host, address, port, str(avahi.txt_array_to_string_array(txt)))
+
+ self.update_label(interface, protocol, name, stype, domain, host, aprotocol, address, port, avahi.txt_array_to_string_array(txt))
+
+ def print_error(self, err):
+ error_label = "<b>Error:</b> %s" % (err)
+ self.info_label.set_markup(error_label)
+ print "Error:", str(err)
+
+ def lookup_type(self, stype):
+ global service_type_db
+
+ try:
+ return service_type_db[stype]
+ except KeyError:
+ return stype
+
+ def new_service(self, interface, protocol, name, stype, domain, flags):
+ print "Found service '%s' of type '%s' in domain '%s' on %i.%i." % (name, stype, domain, interface, protocol)
+ if self.zc_ifaces.has_key((interface,protocol)) == False:
+ self.zc_ifaces[(interface,protocol)] = self.insert_row(self.treemodel, None, str(self.siocgifname(interface))+" "+str(self.protoname(protocol)),None,interface,protocol,None,domain)
+ if self.zc_domains.has_key((interface,protocol,domain)) == False:
+ self.zc_domains[(interface,protocol,domain)] = self.insert_row(self.treemodel, self.zc_ifaces[(interface,protocol)], domain,None,interface,protocol,None,domain)
+ if self.zc_types.has_key((interface,protocol,stype,domain)) == False:
+ thisDomain = self.zc_domains[(interface,protocol,domain)]
+ self.zc_types[(interface,protocol,stype,domain)] = self.insert_row(self.treemodel, thisDomain, self.lookup_type(stype), name, interface,None,None,None)
+ treeiter = self.insert_row(self.treemodel,self.zc_types[(interface,protocol,stype,domain)], name, name, interface,protocol,stype,domain)
+ self.services_browsed[(interface, protocol, name, stype, domain)] = treeiter
+ # expand the tree of this path
+ self.tree_view.expand_to_path(self.treemodel.get_path(treeiter))
+
+
+ def remove_service(self, interface, protocol, name, stype, domain, flags):
+ print "Service '%s' of type '%s' in domain '%s' on %i.%i disappeared." % (name, stype, domain, interface, protocol)
+ self.info_label.set_markup("")
+ treeiter=self.services_browsed[(interface, protocol, name, stype, domain)]
+ parent = self.treemodel.iter_parent(treeiter)
+ self.treemodel.remove(treeiter)
+ del self.services_browsed[(interface, protocol, name, stype, domain)]
+ if self.treemodel.iter_has_child(parent) == False:
+ treeiter=self.zc_types[(interface,protocol,stype,domain)]
+ parent = self.treemodel.iter_parent(treeiter)
+ self.treemodel.remove(treeiter)
+ del self.zc_types[(interface,protocol,stype,domain)]
+ if self.treemodel.iter_has_child(parent) == False:
+ treeiter=self.zc_domains[(interface,protocol,domain)]
+ parent = self.treemodel.iter_parent(treeiter)
+ self.treemodel.remove(treeiter)
+ del self.zc_domains[(interface,protocol,domain)]
+ if self.treemodel.iter_has_child(parent) == False:
+ treeiter=self.zc_ifaces[(interface,protocol)]
+ parent = self.treemodel.iter_parent(treeiter)
+ self.treemodel.remove(treeiter)
+ del self.zc_ifaces[(interface,protocol)]
+
+
+ def new_service_type(self, interface, protocol, stype, domain, flags):
+ global service_browsers
+
+ # Are we already browsing this domain for this type?
+ if service_browsers.has_key((interface, protocol, stype, domain)):
+ return
+
+ print "Browsing for services of type '%s' in domain '%s' on %i.%i ..." % (stype, domain, interface, protocol)
+
+ b = dbus.Interface(self.bus.get_object(avahi.DBUS_NAME, self.server.ServiceBrowserNew(interface, protocol, stype, domain, dbus.UInt32(0))), avahi.DBUS_INTERFACE_SERVICE_BROWSER)
+ b.connect_to_signal('ItemNew', self.new_service)
+ b.connect_to_signal('ItemRemove', self.remove_service)
+
+ service_browsers[(interface, protocol, stype, domain)] = b
+
+ def browse_domain(self, interface, protocol, domain):
+ global service_type_browsers
+
+ # Are we already browsing this domain?
+ if service_type_browsers.has_key((interface, protocol, domain)):
+ return
+
+ if self.stype is None:
+ print "Browsing domain '%s' on %i.%i ..." % (domain, interface, protocol)
+
+ b = dbus.Interface(self.bus.get_object(avahi.DBUS_NAME, self.server.ServiceTypeBrowserNew(interface, protocol, domain, dbus.UInt32(0))), avahi.DBUS_INTERFACE_SERVICE_TYPE_BROWSER)
+ b.connect_to_signal('ItemNew', self.new_service_type)
+
+ service_type_browsers[(interface, protocol, domain)] = b
+ else:
+ new_service_type(interface, protocol, stype, domain)
+
+ def new_domain(self,interface, protocol, domain, flags):
+ if self.zc_ifaces.has_key((interface,protocol)) == False:
+ self.zc_ifaces[(interface,protocol)] = self.insert_row(self.treemodel, None, str(self.siocgifname(interface))+" "+str(self.protoname(protocol)),None,interface,protocol,None,domain)
+ if self.zc_domains.has_key((interface,protocol,domain)) == False:
+ self.zc_domains[(interface,protocol,domain)] = self.insert_row(self.treemodel, self.zc_ifaces[(interface,protocol)], domain,None,interface,protocol,None,domain)
+ if domain != "local":
+ self.browse_domain(interface, protocol, domain)
+
+ def pair_to_dict(self, l):
+ res = dict()
+ for el in l:
+ if "=" not in el:
+ res[el]=''
+ else:
+ tmp = el.split('=',1)
+ if len(tmp[0]) > 0:
+ res[tmp[0]] = tmp[1]
+ return res
+
+
+ def update_label(self,interface, protocol, name, stype, domain, host, aprotocol, address, port, txt):
+ if len(txt) != 0:
+ txts = ""
+ txtd = self.pair_to_dict(txt)
+ for k,v in txtd.items():
+ txts+="<b>TXT <i>%s</i></b> = %s\n" % (k,v)
+ else:
+ txts = "<b>TXT Data:</b> <i>empty</i>"
+
+ infos = "<b>Service Type:</b> %s\n<b>Service Name:</b> %s\n<b>Domain Name:</b> %s\n<b>Interface:</b> %s %s\n<b>Address:</b> %s/%s:%i\n%s" % (stype, name, domain, self.siocgifname(interface), self.protoname(protocol), host, address, port, txts.strip())
+ self.info_label.set_markup(infos)
+
+ def insert_row(self, model,parent,
+ content, name, interface,protocol,stype,domain):
+ myiter=model.insert_after(parent,None)
+ model.set(myiter,0,content,1,name,2,interface,3,protocol,4,stype,5,domain)
+ return myiter
+
+ def new(self):
+ print "A new main_window has been created"
+ self.treemodel=gtk.TreeStore(gobject.TYPE_STRING, gobject.TYPE_STRING, gobject.TYPE_STRING, gobject.TYPE_STRING, gobject.TYPE_STRING, gobject.TYPE_STRING)
+ self.tree_view.set_model(self.treemodel)
+
+ #creating the columns headers
+ self.tree_view.set_headers_visible(False)
+ renderer=gtk.CellRendererText()
+ column=gtk.TreeViewColumn("",renderer, text=0)
+ column.set_resizable(True)
+ column.set_sizing("GTK_TREE_VIEW_COLUMN_GROW_ONLY");
+ column.set_expand(True);
+ self.tree_view.append_column(column)
+
+ self.domain = None
+ self.stype = None
+ self.zc_ifaces = {}
+ self.zc_domains = {}
+ self.zc_types = {}
+ self.services_browsed = {}
+
+ self.bus = dbus.SystemBus()
+ self.server = dbus.Interface(self.bus.get_object(avahi.DBUS_NAME, avahi.DBUS_PATH_SERVER), avahi.DBUS_INTERFACE_SERVER)
+
+ if self.domain is None:
+ # Explicitly browse .local
+ self.browse_domain(avahi.IF_UNSPEC, avahi.PROTO_UNSPEC, "local")
+
+ # Browse for other browsable domains
+ db = dbus.Interface(self.bus.get_object(avahi.DBUS_NAME, self.server.DomainBrowserNew(avahi.IF_UNSPEC, avahi.PROTO_UNSPEC, "", avahi.DOMAIN_BROWSER_BROWSE, dbus.UInt32(0))), avahi.DBUS_INTERFACE_DOMAIN_BROWSER)
+ db.connect_to_signal('ItemNew', self.new_domain)
+ else:
+ # Just browse the domain the user wants us to browse
+ self.browse_domain(avahi.IF_UNSPEC, avahi.PROTO_UNSPEC, domain)
+
+
+def main():
+ main_window = Main_window()
+
+ main_window.run()
+
+if __name__ == "__main__":
+ main()
+
+
--- /dev/null
+#!@PYTHON@
+# -*-python-*-
+# $Id$
+
+# This file is part of avahi.
+#
+# avahi is free software; you can redistribute it and/or modify it
+# under the terms of the GNU Lesser General Public License as
+# published by the Free Software Foundation; either version 2 of the
+# License, or (at your option) any later version.
+#
+# avahi is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
+# License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with avahi; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+# USA.
+
+import sys, getopt, string
+
+try:
+ import avahi, gobject, dbus
+except ImportError:
+ print "Sorry, to use this tool you need to install Avahi, pygtk and python-dbus."
+ sys.exit(1)
+
+try:
+ import dbus.glib
+except ImportError, e:
+ pass
+
+def usage(retval = 0):
+ print "%s <name> <address>" % sys.argv[0]
+ sys.exit(retval)
+
+if len(sys.argv) != 3:
+ usage(2)
+
+name = sys.argv[1]
+address = sys.argv[2]
+
+group = None
+n_rename = 0
+
+def remove_address():
+ global group
+
+ if not (group is None):
+ group.Free()
+ group = None
+
+def add_address():
+ global server, group, name, address
+ assert group is None
+
+ print "Adding address '%s' for '%s' ..." % (name, address)
+ group = dbus.Interface(bus.get_object(avahi.DBUS_NAME, server.EntryGroupNew()), avahi.DBUS_INTERFACE_ENTRY_GROUP)
+ group.connect_to_signal('StateChanged', entry_group_state_changed)
+ group.AddAddress(avahi.IF_UNSPEC, avahi.PROTO_UNSPEC, dbus.UInt32(0), name, address)
+ group.Commit()
+
+def entry_group_state_changed(state):
+ global name, server, n_rename, main_loop
+
+ if state == avahi.ENTRY_GROUP_ESTABLISHED:
+ print "Address established."
+ elif state == avahi.ENTRY_GROUP_COLLISION:
+
+ n_rename = n_rename + 1
+ if n_rename >= 12:
+ print "ERROR: No suitable name found after %i retries, exiting." % n_rename
+ main_loop.quit()
+ else:
+ hn = name.split('.')
+ hn[0] = server.GetAlternativeHostName(hn[0])
+ name = string.join(hn, '.')
+ print "WARNING: Address/host name collision, changing name to '%s' ..." % name
+ remove_address()
+ add_address()
+
+main_loop = gobject.MainLoop()
+
+bus = dbus.SystemBus()
+server = dbus.Interface(bus.get_object(avahi.DBUS_NAME, avahi.DBUS_PATH_SERVER), avahi.DBUS_INTERFACE_SERVER)
+
+add_address()
+
+try:
+ main_loop.run()
+except KeyboardInterrupt, k:
+ pass
+
+remove_address()
--- /dev/null
+#!@PYTHON@
+# -*-python-*-
+# $Id$
+
+# This file is part of avahi.
+#
+# avahi is free software; you can redistribute it and/or modify it
+# under the terms of the GNU Lesser General Public License as
+# published by the Free Software Foundation; either version 2 of the
+# License, or (at your option) any later version.
+#
+# avahi is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
+# License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with avahi; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+# USA.
+
+import sys, getopt
+
+try:
+ import avahi, gobject, dbus
+except ImportError:
+ print "Sorry, to use this tool you need to install Avahi, pygtk and python-dbus."
+ sys.exit(1)
+
+try:
+ import dbus.glib
+except ImportError, e:
+ pass
+
+def usage(retval = 0):
+ print "%s [options] <name> <type> <port> [<txt> ...]\n" % sys.argv[0]
+ print " -h --help Show this help"
+ print " -d --domain Domain where to register this service"
+ print " -H --host Host where this service resides"
+ sys.exit(retval)
+
+try:
+ opts, args = getopt.getopt(sys.argv[1:], "hd:H:", ["help", "domain=", "host="])
+except getopt.GetoptError:
+ usage(2)
+
+domain = ""
+host = ""
+
+for o, a in opts:
+ if o in ("-h", "--help"):
+ usage()
+
+ if o in ("-d", "--domain"):
+ domain = a
+
+ if o in ("-H", "--host"):
+ host = a
+
+if len(args) < 3:
+ usage(2)
+
+name = args[0]
+stype = args[1]
+port = int(args[2])
+txt = args[3:]
+
+# python-dbus doesn't allow transmission of empty arrays, therefore we "fix" it with a bogus entry
+if len(txt) == 0:
+ txt.append("python-dbus=brain-damage")
+
+group = None
+n_rename = 0
+
+def remove_service():
+ global group
+
+ if not group is None:
+ group.Reset()
+
+def add_service():
+ global server, group, name, stype, domain, host, port, txt
+
+ if group is None:
+ group = dbus.Interface(bus.get_object(avahi.DBUS_NAME, server.EntryGroupNew()), avahi.DBUS_INTERFACE_ENTRY_GROUP)
+ group.connect_to_signal('StateChanged', entry_group_state_changed)
+
+ assert group.IsEmpty()
+
+ print "Adding service '%s' of type '%s' ..." % (name, stype)
+
+ group.AddService(avahi.IF_UNSPEC, avahi.PROTO_UNSPEC, dbus.UInt32(0), name, stype, domain, host, dbus.UInt16(port), avahi.string_array_to_txt_array(txt))
+ group.Commit()
+
+def entry_group_state_changed(state):
+ global name, server, n_rename
+
+# print "state change: %i" % state
+
+ if state == avahi.ENTRY_GROUP_ESTABLISHED:
+ print "Service established."
+ elif state == avahi.ENTRY_GROUP_COLLISION:
+
+ n_rename = n_rename + 1
+ if n_rename >= 12:
+ print "ERROR: No suitable service name found after %i retries, exiting." % n_rename
+ main_loop.quit()
+ else:
+ name = server.GetAlternativeServiceName(name)
+ print "WARNING: Service name collision, changing name to '%s' ..." % name
+ remove_service()
+ add_service()
+
+def server_state_changed(state):
+ if state == avahi.SERVER_COLLISION:
+ print "WARNING: Server name collision"
+ remove_service()
+ elif state == avahi.SERVER_RUNNING:
+ add_service()
+
+main_loop = gobject.MainLoop()
+
+bus = dbus.SystemBus()
+server = dbus.Interface(bus.get_object(avahi.DBUS_NAME, avahi.DBUS_PATH_SERVER), avahi.DBUS_INTERFACE_SERVER)
+server.connect_to_signal("StateChanged", server_state_changed)
+server_state_changed(server.GetState())
+
+try:
+ main_loop.run()
+except KeyboardInterrupt, k:
+ pass
+
+if not group is None:
+ group.Free()
--- /dev/null
+# $Id$
+
+# This file is part of avahi.
+#
+# avahi is free software; you can redistribute it and/or modify it
+# under the terms of the GNU Lesser General Public License as
+# published by the Free Software Foundation; either version 2 of the
+# License, or (at your option) any later version.
+#
+# avahi is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
+# License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with avahi; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+# USA.
+
+EXTRA_DIST = __init__.py SimpleGladeApp.py ServiceTypeDatabase.py.in
+
+if HAVE_PYTHON
+
+avahidir = $(pythondir)/avahi
+
+avahi_SCRIPTS = ServiceTypeDatabase.py
+
+ServiceTypeDatabase.py: ServiceTypeDatabase.py.in
+ sed -e 's,@PYTHON\@,$(PYTHON),g' \
+ -e 's,@pkgdatadir\@,$(pkgdatadir),g' $< > $@
+ chmod +x $@
+
+if HAVE_PYGTK
+if HAVE_PYTHON_DBUS
+
+avahi_PYTHON = __init__.py SimpleGladeApp.py
+
+endif
+endif
+endif
+
+CLEANFILES=*.pyc *.pyo ServiceTypeDatabase.py
+
+
--- /dev/null
+#!@PYTHON@
+# -*-python-*-
+# $Id$
+
+# This file is part of avahi.
+#
+# avahi is free software; you can redistribute it and/or modify it
+# under the terms of the GNU Lesser General Public License as
+# published by the Free Software Foundation; either version 2 of the
+# License, or (at your option) any later version.
+#
+# avahi is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
+# License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with avahi; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+# USA.
+
+import gdbm
+import locale
+
+locale.setlocale(locale.LC_ALL, '')
+
+class ServiceTypeDatabase:
+
+ def __init__(self, filename = "@pkgdatadir@/service-types.db"):
+
+ self.db = gdbm.open(filename, "r")
+
+ l = locale.getlocale(locale.LC_MESSAGES)
+
+ self.suffixes = ()
+
+ if not l[0] is None:
+
+ if not l[1] is None:
+ self.suffixes += (l[0] + "@" + l[1], )
+
+ self.suffixes += (l[0], )
+
+ i = l[0].find("_")
+
+ if i >= 0:
+
+ k = l[0][:i]
+
+ if not l[1] is None:
+ self.suffixes += (k + "@" + l[1], )
+
+ self.suffixes += (k, )
+
+
+ self.suffixes = tuple(map(lambda x: "["+x+"]", self.suffixes)) + ("", )
+
+ def __getitem__(self, key):
+
+ for suffix in self.suffixes:
+ try:
+ return self.db[key + suffix]
+ except KeyError:
+ pass
+
+ raise KeyError()
+
+ def has_key(self, key):
+
+ for suffix in self.suffixes:
+
+ if self.db.has_key(key + suffix):
+ return True
+
+ return False
+
+ def __contains__(self, item):
+
+ for suffix in self.suffixes:
+
+ if item+suffix in self.db:
+ return True
+
+ return False
+
+
+
+if __name__ == "__main__":
+
+ b = ServiceTypeDatabase()
+
+ print b["_http._tcp"]
+ print b["_ftp._tcp"]
+ print b["_webdav._tcp"]
+ print b["_webdavs._tcp"]
+
+ print b["gurki._tcp"]
--- /dev/null
+"""
+ SimpleGladeApp.py
+ Module that provides an object oriented abstraction to pygtk and libglade.
+ Copyright (C) 2004 Sandino Flores Moreno
+"""
+
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 2.1 of the License, or (at your option) any later version.
+#
+# This library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with this library; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+# USA
+
+import os
+import sys
+import re
+
+import tokenize
+import gtk
+import gtk.glade
+import weakref
+import inspect
+
+__version__ = "1.0"
+__author__ = 'Sandino "tigrux" Flores-Moreno'
+
+def bindtextdomain(app_name, locale_dir=None):
+ """
+ Bind the domain represented by app_name to the locale directory locale_dir.
+ It has the effect of loading translations, enabling applications for different
+ languages.
+
+ app_name:
+ a domain to look for translations, tipically the name of an application.
+
+ locale_dir:
+ a directory with locales like locale_dir/lang_isocode/LC_MESSAGES/app_name.mo
+ If omitted or None, then the current binding for app_name is used.
+ """
+ try:
+ import locale
+ import gettext
+ locale.setlocale(locale.LC_ALL, "")
+ gtk.glade.bindtextdomain(app_name, locale_dir)
+ gettext.install(app_name, locale_dir, unicode=1)
+ except (IOError,locale.Error), e:
+ print "Warning", app_name, e
+ __builtins__.__dict__["_"] = lambda x : x
+
+
+class SimpleGladeApp:
+
+ def __init__(self, path, root=None, domain=None, **kwargs):
+ """
+ Load a glade file specified by glade_filename, using root as
+ root widget and domain as the domain for translations.
+
+ If it receives extra named arguments (argname=value), then they are used
+ as attributes of the instance.
+
+ path:
+ path to a glade filename.
+ If glade_filename cannot be found, then it will be searched in the
+ same directory of the program (sys.argv[0])
+
+ root:
+ the name of the widget that is the root of the user interface,
+ usually a window or dialog (a top level widget).
+ If None or ommited, the full user interface is loaded.
+
+ domain:
+ A domain to use for loading translations.
+ If None or ommited, no translation is loaded.
+
+ **kwargs:
+ a dictionary representing the named extra arguments.
+ It is useful to set attributes of new instances, for example:
+ glade_app = SimpleGladeApp("ui.glade", foo="some value", bar="another value")
+ sets two attributes (foo and bar) to glade_app.
+ """
+ if os.path.isfile(path):
+ self.glade_path = path
+ else:
+ glade_dir = os.path.dirname( sys.argv[0] )
+ self.glade_path = os.path.join(glade_dir, path)
+ for key, value in kwargs.items():
+ try:
+ setattr(self, key, weakref.proxy(value) )
+ except TypeError:
+ setattr(self, key, value)
+ self.glade = None
+ self.install_custom_handler(self.custom_handler)
+ self.glade = self.create_glade(self.glade_path, root, domain)
+ if root:
+ self.main_widget = self.get_widget(root)
+ else:
+ self.main_widget = None
+ self.normalize_names()
+ self.add_callbacks(self)
+ self.new()
+
+ def __repr__(self):
+ class_name = self.__class__.__name__
+ if self.main_widget:
+ root = gtk.Widget.get_name(self.main_widget)
+ repr = '%s(path="%s", root="%s")' % (class_name, self.glade_path, root)
+ else:
+ repr = '%s(path="%s")' % (class_name, self.glade_path)
+ return repr
+
+ def new(self):
+ """
+ Method called when the user interface is loaded and ready to be used.
+ At this moment, the widgets are loaded and can be refered as self.widget_name
+ """
+ pass
+
+ def add_callbacks(self, callbacks_proxy):
+ """
+ It uses the methods of callbacks_proxy as callbacks.
+ The callbacks are specified by using:
+ Properties window -> Signals tab
+ in glade-2 (or any other gui designer like gazpacho).
+
+ Methods of classes inheriting from SimpleGladeApp are used as
+ callbacks automatically.
+
+ callbacks_proxy:
+ an instance with methods as code of callbacks.
+ It means it has methods like on_button1_clicked, on_entry1_activate, etc.
+ """
+ self.glade.signal_autoconnect(callbacks_proxy)
+
+ def normalize_names(self):
+ """
+ It is internally used to normalize the name of the widgets.
+ It means a widget named foo:vbox-dialog in glade
+ is refered self.vbox_dialog in the code.
+
+ It also sets a data "prefixes" with the list of
+ prefixes a widget has for each widget.
+ """
+ for widget in self.get_widgets():
+ widget_name = gtk.Widget.get_name(widget)
+ prefixes_name_l = widget_name.split(":")
+ prefixes = prefixes_name_l[ : -1]
+ widget_api_name = prefixes_name_l[-1]
+ widget_api_name = "_".join( re.findall(tokenize.Name, widget_api_name) )
+ gtk.Widget.set_name(widget, widget_api_name)
+ if hasattr(self, widget_api_name):
+ raise AttributeError("instance %s already has an attribute %s" % (self,widget_api_name))
+ else:
+ setattr(self, widget_api_name, widget)
+ if prefixes:
+ gtk.Widget.set_data(widget, "prefixes", prefixes)
+
+ def add_prefix_actions(self, prefix_actions_proxy):
+ """
+ By using a gui designer (glade-2, gazpacho, etc)
+ widgets can have a prefix in theirs names
+ like foo:entry1 or foo:label3
+ It means entry1 and label3 has a prefix action named foo.
+
+ Then, prefix_actions_proxy must have a method named prefix_foo which
+ is called everytime a widget with prefix foo is found, using the found widget
+ as argument.
+
+ prefix_actions_proxy:
+ An instance with methods as prefix actions.
+ It means it has methods like prefix_foo, prefix_bar, etc.
+ """
+ prefix_s = "prefix_"
+ prefix_pos = len(prefix_s)
+
+ is_method = lambda t : callable( t[1] )
+ is_prefix_action = lambda t : t[0].startswith(prefix_s)
+ drop_prefix = lambda (k,w): (k[prefix_pos:],w)
+
+ members_t = inspect.getmembers(prefix_actions_proxy)
+ methods_t = filter(is_method, members_t)
+ prefix_actions_t = filter(is_prefix_action, methods_t)
+ prefix_actions_d = dict( map(drop_prefix, prefix_actions_t) )
+
+ for widget in self.get_widgets():
+ prefixes = gtk.Widget.get_data(widget, "prefixes")
+ if prefixes:
+ for prefix in prefixes:
+ if prefix in prefix_actions_d:
+ prefix_action = prefix_actions_d[prefix]
+ prefix_action(widget)
+
+ def custom_handler(self,
+ glade, function_name, widget_name,
+ str1, str2, int1, int2):
+ """
+ Generic handler for creating custom widgets, internally used to
+ enable custom widgets (custom widgets of glade).
+
+ The custom widgets have a creation function specified in design time.
+ Those creation functions are always called with str1,str2,int1,int2 as
+ arguments, that are values specified in design time.
+
+ Methods of classes inheriting from SimpleGladeApp are used as
+ creation functions automatically.
+
+ If a custom widget has create_foo as creation function, then the
+ method named create_foo is called with str1,str2,int1,int2 as arguments.
+ """
+ try:
+ handler = getattr(self, function_name)
+ return handler(str1, str2, int1, int2)
+ except AttributeError:
+ return None
+
+ def gtk_widget_show(self, widget, *args):
+ """
+ Predefined callback.
+ The widget is showed.
+ Equivalent to widget.show()
+ """
+ widget.show()
+
+ def gtk_widget_hide(self, widget, *args):
+ """
+ Predefined callback.
+ The widget is hidden.
+ Equivalent to widget.hide()
+ """
+ widget.hide()
+
+ def gtk_widget_grab_focus(self, widget, *args):
+ """
+ Predefined callback.
+ The widget grabs the focus.
+ Equivalent to widget.grab_focus()
+ """
+ widget.grab_focus()
+
+ def gtk_widget_destroy(self, widget, *args):
+ """
+ Predefined callback.
+ The widget is destroyed.
+ Equivalent to widget.destroy()
+ """
+ widget.destroy()
+
+ def gtk_window_activate_default(self, window, *args):
+ """
+ Predefined callback.
+ The default widget of the window is activated.
+ Equivalent to window.activate_default()
+ """
+ widget.activate_default()
+
+ def gtk_true(self, *args):
+ """
+ Predefined callback.
+ Equivalent to return True in a callback.
+ Useful for stopping propagation of signals.
+ """
+ return True
+
+ def gtk_false(self, *args):
+ """
+ Predefined callback.
+ Equivalent to return False in a callback.
+ """
+ return False
+
+ def gtk_main_quit(self, *args):
+ """
+ Predefined callback.
+ Equivalent to self.quit()
+ """
+ self.quit()
+
+ def main(self):
+ """
+ Starts the main loop of processing events.
+ The default implementation calls gtk.main()
+
+ Useful for applications that needs a non gtk main loop.
+ For example, applications based on gstreamer needs to override
+ this method with gst.main()
+
+ Do not directly call this method in your programs.
+ Use the method run() instead.
+ """
+ gtk.main()
+
+ def quit(self):
+ """
+ Quit processing events.
+ The default implementation calls gtk.main_quit()
+
+ Useful for applications that needs a non gtk main loop.
+ For example, applications based on gstreamer needs to override
+ this method with gst.main_quit()
+ """
+ gtk.main_quit()
+
+ def run(self):
+ """
+ Starts the main loop of processing events checking for Control-C.
+
+ The default implementation checks wheter a Control-C is pressed,
+ then calls on_keyboard_interrupt().
+
+ Use this method for starting programs.
+ """
+ try:
+ self.main()
+ except KeyboardInterrupt:
+ self.on_keyboard_interrupt()
+
+ def on_keyboard_interrupt(self):
+ """
+ This method is called by the default implementation of run()
+ after a program is finished by pressing Control-C.
+ """
+ pass
+
+ def install_custom_handler(self, custom_handler):
+ gtk.glade.set_custom_handler(custom_handler)
+
+ def create_glade(self, glade_path, root, domain):
+ return gtk.glade.XML(self.glade_path, root, domain)
+
+ def get_widget(self, widget_name):
+ return self.glade.get_widget(widget_name)
+
+ def get_widgets(self):
+ return self.glade.get_widget_prefix("")
--- /dev/null
+# $Id$
+
+# This file is part of avahi.
+#
+# avahi is free software; you can redistribute it and/or modify it
+# under the terms of the GNU Lesser General Public License as
+# published by the Free Software Foundation; either version 2 of the
+# License, or (at your option) any later version.
+#
+# avahi is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
+# License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with avahi; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+# USA.
+
+# Some definitions matching those in core.h
+import socket, dbus
+
+SERVER_INVALID, SERVER_REGISTERING, SERVER_RUNNING, SERVER_COLLISION = range(0, 4)
+
+ENTRY_GROUP_UNCOMMITED, ENTRY_GROUP_REGISTERING, ENTRY_GROUP_ESTABLISHED, ENTRY_GROUP_COLLISION = range(0, 4)
+
+DOMAIN_BROWSER_REGISTER, DOMAIN_BROWSER_REGISTER_DEFAULT, DOMAIN_BROWSER_BROWSE, DOMAIN_BROWSER_BROWSE_DEFAULT, DOMAIN_BROWSER_BROWSE_LEGACY = range(0, 5)
+
+PROTO_UNSPEC, PROTO_INET, PROTO_INET6 = -1, 0, 1
+
+IF_UNSPEC = -1
+
+DBUS_NAME = "org.freedesktop.Avahi"
+DBUS_INTERFACE_SERVER = DBUS_NAME + ".Server"
+DBUS_PATH_SERVER = "/"
+DBUS_INTERFACE_ENTRY_GROUP = DBUS_NAME + ".EntryGroup"
+DBUS_INTERFACE_DOMAIN_BROWSER = DBUS_NAME + ".DomainBrowser"
+DBUS_INTERFACE_SERVICE_TYPE_BROWSER = DBUS_NAME + ".ServiceTypeBrowser"
+DBUS_INTERFACE_SERVICE_BROWSER = DBUS_NAME + ".ServiceBrowser"
+
+def byte_array_to_string(s):
+ r = ""
+
+ for c in s:
+
+ if c >= 32 and c < 127:
+ r += "%c" % c
+ else:
+ r += "."
+
+ return r
+
+def txt_array_to_string_array(t):
+ l = []
+
+ for s in t:
+ l.append(byte_array_to_string(s))
+
+ return l
+
+
+def string_to_byte_array(s):
+ r = []
+
+ for c in s:
+ r.append(dbus.Byte(ord(c)))
+
+ return r
+
+def string_array_to_txt_array(t):
+ l = []
+
+ for s in t:
+ l.append(string_to_byte_array(s))
+
+ return l
+
+def dict_to_txt_array(txt_dict):
+ l = []
+
+ for k,v in txt_dict.items():
+ l.append(string_to_byte_array("%s=%s" % (k,v)))
+
+ return l
# This cool debug trap works on i386/gcc only
AM_CFLAGS+='-DDEBUG_TRAP=__asm__("int $$3")'
-EXTRA_DIST = \
- avahi-publish-address.in \
- avahi-publish-service.in \
- avahi-bookmarks.in \
- avahi-discover.in \
- avahi-discover.desktop.in
-
-SUBDIRS=avahi
-
-if HAVE_PYTHON
-if HAVE_PYTHON_DBUS
-if HAVE_PYGTK
-
-pythonscripts = \
- avahi-publish-address \
- avahi-publish-service \
- avahi-bookmarks \
- avahi-discover
-
-desktopdir = $(datadir)/applications
-desktop_DATA = avahi-discover.desktop
-
-avahi-discover.desktop: avahi-discover.desktop.in
- sed -e 's,@bindir\@,$(bindir),g' $< > $@
- chmod +x $@
-
-avahi-discover: avahi-discover.in
- sed -e 's,@PYTHON\@,$(PYTHON),g' \
- -e 's,@interfacesdir\@,$(interfacesdir),g' $< > $@
- chmod +x $@
-
-avahi-publish-address: avahi-publish-address.in
- sed -e 's,@PYTHON\@,$(PYTHON),g' $< > $@
- chmod +x $@
-
-avahi-publish-service: avahi-publish-service.in
- sed -e 's,@PYTHON\@,$(PYTHON),g' $< > $@
- chmod +x $@
-
-avahi-bookmarks: avahi-bookmarks.in
- sed -e 's,@PYTHON\@,$(PYTHON),g' $< > $@
- chmod +x $@
-
-bin_SCRIPTS = $(pythonscripts)
-CLEANFILES = $(pythonscripts) $(desktop_DATA)
-
-endif
-endif
-endif
-
if HAVE_DBUS
bin_PROGRAMS = avahi-browse avahi-resolve-host-name
+++ /dev/null
-#!@PYTHON@
-# -*-python-*-
-# $Id$
-
-# This file is part of avahi.
-#
-# avahi is free software; you can redistribute it and/or modify it
-# under the terms of the GNU Lesser General Public License as
-# published by the Free Software Foundation; either version 2 of the
-# License, or (at your option) any later version.
-#
-# avahi is distributed in the hope that it will be useful, but WITHOUT
-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
-# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
-# License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public
-# License along with avahi; if not, write to the Free Software
-# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
-# USA.
-
-import sys, getopt
-
-try:
- import avahi, gobject, dbus
-except ImportError:
- print "Sorry, to use this tool you need to install Avahi, pygtk and python-dbus."
- sys.exit(1)
-
-try:
- import dbus.glib
-except ImportError:
- pass
-
-try:
- from twisted.internet import gtk2reactor
- gtk2reactor.install()
- from twisted.internet import reactor
- from twisted.web import server, resource
-except ImportError:
- print "Sorry, to use this tool you need to install twisted and twisted.web."
- sys.exit(1)
-
-urlproto = { "_http._tcp" : "http", "_https._tcp" : "https", "_ftp._tcp" : "ftp" }
-
-port = 8080
-address = "127.0.0.1"
-use_host_names = False
-domain = "local"
-
-class AvahiBookmarks(resource.Resource):
- isLeaf = True
-
- services = {}
-
- def __init__(self):
- resource.Resource.__init__(self)
-
- self.bus = dbus.SystemBus()
- self.server = dbus.Interface(self.bus.get_object(avahi.DBUS_NAME, avahi.DBUS_PATH_SERVER), avahi.DBUS_INTERFACE_SERVER)
-
- self.version_string = self.server.GetVersionString()
-
- self.browse_service_type("_http._tcp")
-
- # Hurrah! if I enable one of the following lines, python segfaults.
- #self.browse_service_type("_https._tcp")
- #self.browse_service_type("_ftp._tcp")
-
- def browse_service_type(self, stype):
-
- global domain
-
- browser = dbus.Interface(self.bus.get_object(avahi.DBUS_NAME, self.server.ServiceBrowserNew(avahi.IF_UNSPEC, avahi.PROTO_UNSPEC, stype, domain, dbus.UInt32(0))), avahi.DBUS_INTERFACE_SERVICE_BROWSER)
- browser.connect_to_signal('ItemNew', self.new_service)
- browser.connect_to_signal('ItemRemove', self.remove_service)
-
- def find_path(self, txt):
-
- l = avahi.txt_array_to_string_array(txt)
-
- for k in l:
- if k[:5] == "path=":
- if k[5:].startswith("/"):
- return k[5:]
- else:
- return "/" + k[5:]
-
- return "/"
-
- def render_GET(self, request):
-
- t = '<html><head><title>Zeroconf Bookmarks</title></head><body><h1>Zeroconf Bookmarks</h1>'
-
- if len(self.services) == 0:
- t += '<p>Sorry, no web services have been registered on the local LAN.</p>'
- else:
- t += '<ul style="padding: 0px; margin: 20px; list-style-type: none">'
-
- for k, v in self.services.iteritems():
-
- if v[3] == 80:
- port = ''
- else:
- port = ':%i' % v[3]
-
- path = self.find_path(v[4])
- t += '<li><a href="%s://%s%s%s">%s</a></li>' % (urlproto[k[3]], v[2], port, path, k[2])
-
- t += '</ul>'
-
- t += '<hr noshade/><p style="font-size: 8; font-family: sans-serif">Served by %s</p></body></html>' % self.version_string
-
- return t
-
-
- def new_service(self, interface, protocol, name, type, domain, flags):
-
- interface, protocol, name, type, domain, host, aprotocol, address, port, txt, flags = self.server.ResolveService(interface, protocol, name, type, domain, avahi.PROTO_UNSPEC, dbus.UInt32(0))
-
- if use_host_names:
- h = host
- else:
- if aprotocol == avahi.PROTO_INET6:
- h = "[" + address + "]"
- else:
- h = address
-
- self.services[(interface, protocol, name, type, domain)] = (host, aprotocol, h, port, txt)
-
- def remove_service(self, interface, protocol, name, type, domain):
- del self.services[(interface, protocol, name, type, domain)]
-
-
-def usage(retval = 0):
- print "%s [options]\n" % sys.argv[0]
- print " -h --help Show this help"
- print " -p --port PORT Specify the port to use (default %u)" % port
- print " -a --address ADDRESS Specify the address to bind to (default %s)" % address
- print " -H --host-names Show all services, regardless of the type"
- print " -d --domain DOMAIN Specify the domain to browse"
- sys.exit(retval)
-
-try:
- opts, args = getopt.getopt(sys.argv[1:], "hp:a:Hd:", ["help", "port=", "address=", "host-names", "domain="])
-except getopt.GetoptError:
- usage(2)
-
-for o, a in opts:
- if o in ("-h", "--help"):
- usage()
-
- if o in ("-p", "--port"):
- port = int(a)
-
- if o in ("-a", "--address"):
- address = a
-
- if o in ("-H", "--host-names"):
- use_host_names = True
-
- if o in ("-d", "--domain"):
- domain = a
-
-site = server.Site(AvahiBookmarks())
-reactor.listenTCP(port, site, interface=address)
-
-print "Now point your web browser to http://%s:%u/!" % (address, port)
-
-try:
- reactor.run()
-except KeyboardInterrupt, k:
- pass
+++ /dev/null
-[Desktop Entry]
-Encoding=UTF-8
-Name=Avahi Zeroconf Browser
-Comment=Browse for Zeroconf services available on your network
-Exec=@bindir@/avahi-discover
-Terminal=false
-Type=Application
-Icon=gnome-nettool.png
-Categories=GNOME;Application;System;Utility
-StartupNotify=false
+++ /dev/null
-#!@PYTHON@
-# -*-python-*-
-# $Id$
-
-# This file is part of avahi.
-#
-# avahi is free software; you can redistribute it and/or modify it
-# under the terms of the GNU Lesser General Public License as
-# published by the Free Software Foundation; either version 2 of the
-# License, or (at your option) any later version.
-#
-# avahi is distributed in the hope that it will be useful, but WITHOUT
-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
-# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
-# License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public
-# License along with avahi; if not, write to the Free Software
-# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
-# USA.
-
-import os, sys
-
-try:
- import avahi, gtk, gobject, dbus, avahi.ServiceTypeDatabase
- from avahi.SimpleGladeApp import SimpleGladeApp
-except ImportError:
- print "Sorry, to use this tool you need to install Avahi, pygtk and python-dbus."
- sys.exit(1)
-
-try:
- import dbus.glib
-except ImportError, e:
- pass
-
-service_type_browsers = {}
-service_browsers = {}
-
-glade_dir = "@interfacesdir@"
-
-service_type_db = avahi.ServiceTypeDatabase.ServiceTypeDatabase()
-
-class Main_window(SimpleGladeApp):
- def __init__(self, path="avahi-discover.glade", root="main_window", domain=None, **kwargs):
- path = os.path.join(glade_dir, path)
- SimpleGladeApp.__init__(self, path, root, domain, **kwargs)
-
- def on_tree_view_cursor_changed(self, widget, *args):
- (model, iter) = widget.get_selection().get_selected()
- (name,interface,protocol,stype,domain) = self.treemodel.get(iter,1,2,3,4,5)
- if stype == None:
- self.info_label.set_markup("<i>No service currently selected.</i>")
- return
- #Asynchronous resolving
- self.server.ResolveService( int(interface), int(protocol), name, stype, domain, avahi.PROTO_UNSPEC, dbus.UInt32(0), reply_handler=self.service_resolved, error_handler=self.print_error)
-
-
- def protoname(self,protocol):
- if protocol == avahi.PROTO_INET:
- return "IPv4"
- if protocol == avahi.PROTO_INET6:
- return "IPv6"
-
-
- def siocgifname(self, interface):
- if interface <= 0:
- return "any"
- else:
- return self.server.GetNetworkInterfaceNameByIndex(interface)
-
- def service_resolved(self, interface, protocol, name, stype, domain, host, aprotocol, address, port, txt, flags):
- print "Service data for service '%s' of type '%s' in domain '%s' on %i.%i:" % (name, stype, domain, interface, protocol)
-
- print "\tHost %s (%s), port %i, TXT data: %s" % (host, address, port, str(avahi.txt_array_to_string_array(txt)))
-
- self.update_label(interface, protocol, name, stype, domain, host, aprotocol, address, port, avahi.txt_array_to_string_array(txt))
-
- def print_error(self, err):
- error_label = "<b>Error:</b> %s" % (err)
- self.info_label.set_markup(error_label)
- print "Error:", str(err)
-
- def lookup_type(self, stype):
- global service_type_db
-
- try:
- return service_type_db[stype]
- except KeyError:
- return stype
-
- def new_service(self, interface, protocol, name, stype, domain, flags):
- print "Found service '%s' of type '%s' in domain '%s' on %i.%i." % (name, stype, domain, interface, protocol)
- if self.zc_ifaces.has_key((interface,protocol)) == False:
- self.zc_ifaces[(interface,protocol)] = self.insert_row(self.treemodel, None, str(self.siocgifname(interface))+" "+str(self.protoname(protocol)),None,interface,protocol,None,domain)
- if self.zc_domains.has_key((interface,protocol,domain)) == False:
- self.zc_domains[(interface,protocol,domain)] = self.insert_row(self.treemodel, self.zc_ifaces[(interface,protocol)], domain,None,interface,protocol,None,domain)
- if self.zc_types.has_key((interface,protocol,stype,domain)) == False:
- thisDomain = self.zc_domains[(interface,protocol,domain)]
- self.zc_types[(interface,protocol,stype,domain)] = self.insert_row(self.treemodel, thisDomain, self.lookup_type(stype), name, interface,None,None,None)
- treeiter = self.insert_row(self.treemodel,self.zc_types[(interface,protocol,stype,domain)], name, name, interface,protocol,stype,domain)
- self.services_browsed[(interface, protocol, name, stype, domain)] = treeiter
- # expand the tree of this path
- self.tree_view.expand_to_path(self.treemodel.get_path(treeiter))
-
-
- def remove_service(self, interface, protocol, name, stype, domain, flags):
- print "Service '%s' of type '%s' in domain '%s' on %i.%i disappeared." % (name, stype, domain, interface, protocol)
- self.info_label.set_markup("")
- treeiter=self.services_browsed[(interface, protocol, name, stype, domain)]
- parent = self.treemodel.iter_parent(treeiter)
- self.treemodel.remove(treeiter)
- del self.services_browsed[(interface, protocol, name, stype, domain)]
- if self.treemodel.iter_has_child(parent) == False:
- treeiter=self.zc_types[(interface,protocol,stype,domain)]
- parent = self.treemodel.iter_parent(treeiter)
- self.treemodel.remove(treeiter)
- del self.zc_types[(interface,protocol,stype,domain)]
- if self.treemodel.iter_has_child(parent) == False:
- treeiter=self.zc_domains[(interface,protocol,domain)]
- parent = self.treemodel.iter_parent(treeiter)
- self.treemodel.remove(treeiter)
- del self.zc_domains[(interface,protocol,domain)]
- if self.treemodel.iter_has_child(parent) == False:
- treeiter=self.zc_ifaces[(interface,protocol)]
- parent = self.treemodel.iter_parent(treeiter)
- self.treemodel.remove(treeiter)
- del self.zc_ifaces[(interface,protocol)]
-
-
- def new_service_type(self, interface, protocol, stype, domain, flags):
- global service_browsers
-
- # Are we already browsing this domain for this type?
- if service_browsers.has_key((interface, protocol, stype, domain)):
- return
-
- print "Browsing for services of type '%s' in domain '%s' on %i.%i ..." % (stype, domain, interface, protocol)
-
- b = dbus.Interface(self.bus.get_object(avahi.DBUS_NAME, self.server.ServiceBrowserNew(interface, protocol, stype, domain, dbus.UInt32(0))), avahi.DBUS_INTERFACE_SERVICE_BROWSER)
- b.connect_to_signal('ItemNew', self.new_service)
- b.connect_to_signal('ItemRemove', self.remove_service)
-
- service_browsers[(interface, protocol, stype, domain)] = b
-
- def browse_domain(self, interface, protocol, domain):
- global service_type_browsers
-
- # Are we already browsing this domain?
- if service_type_browsers.has_key((interface, protocol, domain)):
- return
-
- if self.stype is None:
- print "Browsing domain '%s' on %i.%i ..." % (domain, interface, protocol)
-
- b = dbus.Interface(self.bus.get_object(avahi.DBUS_NAME, self.server.ServiceTypeBrowserNew(interface, protocol, domain, dbus.UInt32(0))), avahi.DBUS_INTERFACE_SERVICE_TYPE_BROWSER)
- b.connect_to_signal('ItemNew', self.new_service_type)
-
- service_type_browsers[(interface, protocol, domain)] = b
- else:
- new_service_type(interface, protocol, stype, domain)
-
- def new_domain(self,interface, protocol, domain, flags):
- if self.zc_ifaces.has_key((interface,protocol)) == False:
- self.zc_ifaces[(interface,protocol)] = self.insert_row(self.treemodel, None, str(self.siocgifname(interface))+" "+str(self.protoname(protocol)),None,interface,protocol,None,domain)
- if self.zc_domains.has_key((interface,protocol,domain)) == False:
- self.zc_domains[(interface,protocol,domain)] = self.insert_row(self.treemodel, self.zc_ifaces[(interface,protocol)], domain,None,interface,protocol,None,domain)
- if domain != "local":
- self.browse_domain(interface, protocol, domain)
-
- def pair_to_dict(self, l):
- res = dict()
- for el in l:
- if "=" not in el:
- res[el]=''
- else:
- tmp = el.split('=',1)
- if len(tmp[0]) > 0:
- res[tmp[0]] = tmp[1]
- return res
-
-
- def update_label(self,interface, protocol, name, stype, domain, host, aprotocol, address, port, txt):
- if len(txt) != 0:
- txts = ""
- txtd = self.pair_to_dict(txt)
- for k,v in txtd.items():
- txts+="<b>TXT <i>%s</i></b> = %s\n" % (k,v)
- else:
- txts = "<b>TXT Data:</b> <i>empty</i>"
-
- infos = "<b>Service Type:</b> %s\n<b>Service Name:</b> %s\n<b>Domain Name:</b> %s\n<b>Interface:</b> %s %s\n<b>Address:</b> %s/%s:%i\n%s" % (stype, name, domain, self.siocgifname(interface), self.protoname(protocol), host, address, port, txts.strip())
- self.info_label.set_markup(infos)
-
- def insert_row(self, model,parent,
- content, name, interface,protocol,stype,domain):
- myiter=model.insert_after(parent,None)
- model.set(myiter,0,content,1,name,2,interface,3,protocol,4,stype,5,domain)
- return myiter
-
- def new(self):
- print "A new main_window has been created"
- self.treemodel=gtk.TreeStore(gobject.TYPE_STRING, gobject.TYPE_STRING, gobject.TYPE_STRING, gobject.TYPE_STRING, gobject.TYPE_STRING, gobject.TYPE_STRING)
- self.tree_view.set_model(self.treemodel)
-
- #creating the columns headers
- self.tree_view.set_headers_visible(False)
- renderer=gtk.CellRendererText()
- column=gtk.TreeViewColumn("",renderer, text=0)
- column.set_resizable(True)
- column.set_sizing("GTK_TREE_VIEW_COLUMN_GROW_ONLY");
- column.set_expand(True);
- self.tree_view.append_column(column)
-
- self.domain = None
- self.stype = None
- self.zc_ifaces = {}
- self.zc_domains = {}
- self.zc_types = {}
- self.services_browsed = {}
-
- self.bus = dbus.SystemBus()
- self.server = dbus.Interface(self.bus.get_object(avahi.DBUS_NAME, avahi.DBUS_PATH_SERVER), avahi.DBUS_INTERFACE_SERVER)
-
- if self.domain is None:
- # Explicitly browse .local
- self.browse_domain(avahi.IF_UNSPEC, avahi.PROTO_UNSPEC, "local")
-
- # Browse for other browsable domains
- db = dbus.Interface(self.bus.get_object(avahi.DBUS_NAME, self.server.DomainBrowserNew(avahi.IF_UNSPEC, avahi.PROTO_UNSPEC, "", avahi.DOMAIN_BROWSER_BROWSE, dbus.UInt32(0))), avahi.DBUS_INTERFACE_DOMAIN_BROWSER)
- db.connect_to_signal('ItemNew', self.new_domain)
- else:
- # Just browse the domain the user wants us to browse
- self.browse_domain(avahi.IF_UNSPEC, avahi.PROTO_UNSPEC, domain)
-
-
-def main():
- main_window = Main_window()
-
- main_window.run()
-
-if __name__ == "__main__":
- main()
-
-
+++ /dev/null
-#!@PYTHON@
-# -*-python-*-
-# $Id$
-
-# This file is part of avahi.
-#
-# avahi is free software; you can redistribute it and/or modify it
-# under the terms of the GNU Lesser General Public License as
-# published by the Free Software Foundation; either version 2 of the
-# License, or (at your option) any later version.
-#
-# avahi is distributed in the hope that it will be useful, but WITHOUT
-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
-# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
-# License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public
-# License along with avahi; if not, write to the Free Software
-# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
-# USA.
-
-import sys, getopt, string
-
-try:
- import avahi, gobject, dbus
-except ImportError:
- print "Sorry, to use this tool you need to install Avahi, pygtk and python-dbus."
- sys.exit(1)
-
-try:
- import dbus.glib
-except ImportError, e:
- pass
-
-def usage(retval = 0):
- print "%s <name> <address>" % sys.argv[0]
- sys.exit(retval)
-
-if len(sys.argv) != 3:
- usage(2)
-
-name = sys.argv[1]
-address = sys.argv[2]
-
-group = None
-n_rename = 0
-
-def remove_address():
- global group
-
- if not (group is None):
- group.Free()
- group = None
-
-def add_address():
- global server, group, name, address
- assert group is None
-
- print "Adding address '%s' for '%s' ..." % (name, address)
- group = dbus.Interface(bus.get_object(avahi.DBUS_NAME, server.EntryGroupNew()), avahi.DBUS_INTERFACE_ENTRY_GROUP)
- group.connect_to_signal('StateChanged', entry_group_state_changed)
- group.AddAddress(avahi.IF_UNSPEC, avahi.PROTO_UNSPEC, dbus.UInt32(0), name, address)
- group.Commit()
-
-def entry_group_state_changed(state):
- global name, server, n_rename, main_loop
-
- if state == avahi.ENTRY_GROUP_ESTABLISHED:
- print "Address established."
- elif state == avahi.ENTRY_GROUP_COLLISION:
-
- n_rename = n_rename + 1
- if n_rename >= 12:
- print "ERROR: No suitable name found after %i retries, exiting." % n_rename
- main_loop.quit()
- else:
- hn = name.split('.')
- hn[0] = server.GetAlternativeHostName(hn[0])
- name = string.join(hn, '.')
- print "WARNING: Address/host name collision, changing name to '%s' ..." % name
- remove_address()
- add_address()
-
-main_loop = gobject.MainLoop()
-
-bus = dbus.SystemBus()
-server = dbus.Interface(bus.get_object(avahi.DBUS_NAME, avahi.DBUS_PATH_SERVER), avahi.DBUS_INTERFACE_SERVER)
-
-add_address()
-
-try:
- main_loop.run()
-except KeyboardInterrupt, k:
- pass
-
-remove_address()
+++ /dev/null
-#!@PYTHON@
-# -*-python-*-
-# $Id$
-
-# This file is part of avahi.
-#
-# avahi is free software; you can redistribute it and/or modify it
-# under the terms of the GNU Lesser General Public License as
-# published by the Free Software Foundation; either version 2 of the
-# License, or (at your option) any later version.
-#
-# avahi is distributed in the hope that it will be useful, but WITHOUT
-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
-# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
-# License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public
-# License along with avahi; if not, write to the Free Software
-# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
-# USA.
-
-import sys, getopt
-
-try:
- import avahi, gobject, dbus
-except ImportError:
- print "Sorry, to use this tool you need to install Avahi, pygtk and python-dbus."
- sys.exit(1)
-
-try:
- import dbus.glib
-except ImportError, e:
- pass
-
-def usage(retval = 0):
- print "%s [options] <name> <type> <port> [<txt> ...]\n" % sys.argv[0]
- print " -h --help Show this help"
- print " -d --domain Domain where to register this service"
- print " -H --host Host where this service resides"
- sys.exit(retval)
-
-try:
- opts, args = getopt.getopt(sys.argv[1:], "hd:H:", ["help", "domain=", "host="])
-except getopt.GetoptError:
- usage(2)
-
-domain = ""
-host = ""
-
-for o, a in opts:
- if o in ("-h", "--help"):
- usage()
-
- if o in ("-d", "--domain"):
- domain = a
-
- if o in ("-H", "--host"):
- host = a
-
-if len(args) < 3:
- usage(2)
-
-name = args[0]
-stype = args[1]
-port = int(args[2])
-txt = args[3:]
-
-# python-dbus doesn't allow transmission of empty arrays, therefore we "fix" it with a bogus entry
-if len(txt) == 0:
- txt.append("python-dbus=brain-damage")
-
-group = None
-n_rename = 0
-
-def remove_service():
- global group
-
- if not group is None:
- group.Reset()
-
-def add_service():
- global server, group, name, stype, domain, host, port, txt
-
- if group is None:
- group = dbus.Interface(bus.get_object(avahi.DBUS_NAME, server.EntryGroupNew()), avahi.DBUS_INTERFACE_ENTRY_GROUP)
- group.connect_to_signal('StateChanged', entry_group_state_changed)
-
- assert group.IsEmpty()
-
- print "Adding service '%s' of type '%s' ..." % (name, stype)
-
- group.AddService(avahi.IF_UNSPEC, avahi.PROTO_UNSPEC, dbus.UInt32(0), name, stype, domain, host, dbus.UInt16(port), avahi.string_array_to_txt_array(txt))
- group.Commit()
-
-def entry_group_state_changed(state):
- global name, server, n_rename
-
-# print "state change: %i" % state
-
- if state == avahi.ENTRY_GROUP_ESTABLISHED:
- print "Service established."
- elif state == avahi.ENTRY_GROUP_COLLISION:
-
- n_rename = n_rename + 1
- if n_rename >= 12:
- print "ERROR: No suitable service name found after %i retries, exiting." % n_rename
- main_loop.quit()
- else:
- name = server.GetAlternativeServiceName(name)
- print "WARNING: Service name collision, changing name to '%s' ..." % name
- remove_service()
- add_service()
-
-def server_state_changed(state):
- if state == avahi.SERVER_COLLISION:
- print "WARNING: Server name collision"
- remove_service()
- elif state == avahi.SERVER_RUNNING:
- add_service()
-
-main_loop = gobject.MainLoop()
-
-bus = dbus.SystemBus()
-server = dbus.Interface(bus.get_object(avahi.DBUS_NAME, avahi.DBUS_PATH_SERVER), avahi.DBUS_INTERFACE_SERVER)
-server.connect_to_signal("StateChanged", server_state_changed)
-server_state_changed(server.GetState())
-
-try:
- main_loop.run()
-except KeyboardInterrupt, k:
- pass
-
-if not group is None:
- group.Free()
+++ /dev/null
-# $Id$
-
-# This file is part of avahi.
-#
-# avahi is free software; you can redistribute it and/or modify it
-# under the terms of the GNU Lesser General Public License as
-# published by the Free Software Foundation; either version 2 of the
-# License, or (at your option) any later version.
-#
-# avahi is distributed in the hope that it will be useful, but WITHOUT
-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
-# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
-# License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public
-# License along with avahi; if not, write to the Free Software
-# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
-# USA.
-
-EXTRA_DIST = __init__.py SimpleGladeApp.py ServiceTypeDatabase.py.in
-
-if HAVE_PYTHON
-
-avahidir = $(pythondir)/avahi
-
-avahi_SCRIPTS = ServiceTypeDatabase.py
-
-ServiceTypeDatabase.py: ServiceTypeDatabase.py.in
- sed -e 's,@PYTHON\@,$(PYTHON),g' \
- -e 's,@pkgdatadir\@,$(pkgdatadir),g' $< > $@
- chmod +x $@
-
-if HAVE_PYGTK
-if HAVE_PYTHON_DBUS
-
-avahi_PYTHON = __init__.py SimpleGladeApp.py
-
-endif
-endif
-endif
-
-CLEANFILES=*.pyc *.pyo ServiceTypeDatabase.py
-
-
+++ /dev/null
-#!@PYTHON@
-# -*-python-*-
-# $Id$
-
-# This file is part of avahi.
-#
-# avahi is free software; you can redistribute it and/or modify it
-# under the terms of the GNU Lesser General Public License as
-# published by the Free Software Foundation; either version 2 of the
-# License, or (at your option) any later version.
-#
-# avahi is distributed in the hope that it will be useful, but WITHOUT
-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
-# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
-# License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public
-# License along with avahi; if not, write to the Free Software
-# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
-# USA.
-
-import gdbm
-import locale
-
-locale.setlocale(locale.LC_ALL, '')
-
-class ServiceTypeDatabase:
-
- def __init__(self, filename = "@pkgdatadir@/service-types.db"):
-
- self.db = gdbm.open(filename, "r")
-
- l = locale.getlocale(locale.LC_MESSAGES)
-
- self.suffixes = ()
-
- if not l[0] is None:
-
- if not l[1] is None:
- self.suffixes += (l[0] + "@" + l[1], )
-
- self.suffixes += (l[0], )
-
- i = l[0].find("_")
-
- if i >= 0:
-
- k = l[0][:i]
-
- if not l[1] is None:
- self.suffixes += (k + "@" + l[1], )
-
- self.suffixes += (k, )
-
-
- self.suffixes = tuple(map(lambda x: "["+x+"]", self.suffixes)) + ("", )
-
- def __getitem__(self, key):
-
- for suffix in self.suffixes:
- try:
- return self.db[key + suffix]
- except KeyError:
- pass
-
- raise KeyError()
-
- def has_key(self, key):
-
- for suffix in self.suffixes:
-
- if self.db.has_key(key + suffix):
- return True
-
- return False
-
- def __contains__(self, item):
-
- for suffix in self.suffixes:
-
- if item+suffix in self.db:
- return True
-
- return False
-
-
-
-if __name__ == "__main__":
-
- b = ServiceTypeDatabase()
-
- print b["_http._tcp"]
- print b["_ftp._tcp"]
- print b["_webdav._tcp"]
- print b["_webdavs._tcp"]
-
- print b["gurki._tcp"]
+++ /dev/null
-"""
- SimpleGladeApp.py
- Module that provides an object oriented abstraction to pygtk and libglade.
- Copyright (C) 2004 Sandino Flores Moreno
-"""
-
-# This library is free software; you can redistribute it and/or
-# modify it under the terms of the GNU Lesser General Public
-# License as published by the Free Software Foundation; either
-# version 2.1 of the License, or (at your option) any later version.
-#
-# This library is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-# Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public
-# License along with this library; if not, write to the Free Software
-# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
-# USA
-
-import os
-import sys
-import re
-
-import tokenize
-import gtk
-import gtk.glade
-import weakref
-import inspect
-
-__version__ = "1.0"
-__author__ = 'Sandino "tigrux" Flores-Moreno'
-
-def bindtextdomain(app_name, locale_dir=None):
- """
- Bind the domain represented by app_name to the locale directory locale_dir.
- It has the effect of loading translations, enabling applications for different
- languages.
-
- app_name:
- a domain to look for translations, tipically the name of an application.
-
- locale_dir:
- a directory with locales like locale_dir/lang_isocode/LC_MESSAGES/app_name.mo
- If omitted or None, then the current binding for app_name is used.
- """
- try:
- import locale
- import gettext
- locale.setlocale(locale.LC_ALL, "")
- gtk.glade.bindtextdomain(app_name, locale_dir)
- gettext.install(app_name, locale_dir, unicode=1)
- except (IOError,locale.Error), e:
- print "Warning", app_name, e
- __builtins__.__dict__["_"] = lambda x : x
-
-
-class SimpleGladeApp:
-
- def __init__(self, path, root=None, domain=None, **kwargs):
- """
- Load a glade file specified by glade_filename, using root as
- root widget and domain as the domain for translations.
-
- If it receives extra named arguments (argname=value), then they are used
- as attributes of the instance.
-
- path:
- path to a glade filename.
- If glade_filename cannot be found, then it will be searched in the
- same directory of the program (sys.argv[0])
-
- root:
- the name of the widget that is the root of the user interface,
- usually a window or dialog (a top level widget).
- If None or ommited, the full user interface is loaded.
-
- domain:
- A domain to use for loading translations.
- If None or ommited, no translation is loaded.
-
- **kwargs:
- a dictionary representing the named extra arguments.
- It is useful to set attributes of new instances, for example:
- glade_app = SimpleGladeApp("ui.glade", foo="some value", bar="another value")
- sets two attributes (foo and bar) to glade_app.
- """
- if os.path.isfile(path):
- self.glade_path = path
- else:
- glade_dir = os.path.dirname( sys.argv[0] )
- self.glade_path = os.path.join(glade_dir, path)
- for key, value in kwargs.items():
- try:
- setattr(self, key, weakref.proxy(value) )
- except TypeError:
- setattr(self, key, value)
- self.glade = None
- self.install_custom_handler(self.custom_handler)
- self.glade = self.create_glade(self.glade_path, root, domain)
- if root:
- self.main_widget = self.get_widget(root)
- else:
- self.main_widget = None
- self.normalize_names()
- self.add_callbacks(self)
- self.new()
-
- def __repr__(self):
- class_name = self.__class__.__name__
- if self.main_widget:
- root = gtk.Widget.get_name(self.main_widget)
- repr = '%s(path="%s", root="%s")' % (class_name, self.glade_path, root)
- else:
- repr = '%s(path="%s")' % (class_name, self.glade_path)
- return repr
-
- def new(self):
- """
- Method called when the user interface is loaded and ready to be used.
- At this moment, the widgets are loaded and can be refered as self.widget_name
- """
- pass
-
- def add_callbacks(self, callbacks_proxy):
- """
- It uses the methods of callbacks_proxy as callbacks.
- The callbacks are specified by using:
- Properties window -> Signals tab
- in glade-2 (or any other gui designer like gazpacho).
-
- Methods of classes inheriting from SimpleGladeApp are used as
- callbacks automatically.
-
- callbacks_proxy:
- an instance with methods as code of callbacks.
- It means it has methods like on_button1_clicked, on_entry1_activate, etc.
- """
- self.glade.signal_autoconnect(callbacks_proxy)
-
- def normalize_names(self):
- """
- It is internally used to normalize the name of the widgets.
- It means a widget named foo:vbox-dialog in glade
- is refered self.vbox_dialog in the code.
-
- It also sets a data "prefixes" with the list of
- prefixes a widget has for each widget.
- """
- for widget in self.get_widgets():
- widget_name = gtk.Widget.get_name(widget)
- prefixes_name_l = widget_name.split(":")
- prefixes = prefixes_name_l[ : -1]
- widget_api_name = prefixes_name_l[-1]
- widget_api_name = "_".join( re.findall(tokenize.Name, widget_api_name) )
- gtk.Widget.set_name(widget, widget_api_name)
- if hasattr(self, widget_api_name):
- raise AttributeError("instance %s already has an attribute %s" % (self,widget_api_name))
- else:
- setattr(self, widget_api_name, widget)
- if prefixes:
- gtk.Widget.set_data(widget, "prefixes", prefixes)
-
- def add_prefix_actions(self, prefix_actions_proxy):
- """
- By using a gui designer (glade-2, gazpacho, etc)
- widgets can have a prefix in theirs names
- like foo:entry1 or foo:label3
- It means entry1 and label3 has a prefix action named foo.
-
- Then, prefix_actions_proxy must have a method named prefix_foo which
- is called everytime a widget with prefix foo is found, using the found widget
- as argument.
-
- prefix_actions_proxy:
- An instance with methods as prefix actions.
- It means it has methods like prefix_foo, prefix_bar, etc.
- """
- prefix_s = "prefix_"
- prefix_pos = len(prefix_s)
-
- is_method = lambda t : callable( t[1] )
- is_prefix_action = lambda t : t[0].startswith(prefix_s)
- drop_prefix = lambda (k,w): (k[prefix_pos:],w)
-
- members_t = inspect.getmembers(prefix_actions_proxy)
- methods_t = filter(is_method, members_t)
- prefix_actions_t = filter(is_prefix_action, methods_t)
- prefix_actions_d = dict( map(drop_prefix, prefix_actions_t) )
-
- for widget in self.get_widgets():
- prefixes = gtk.Widget.get_data(widget, "prefixes")
- if prefixes:
- for prefix in prefixes:
- if prefix in prefix_actions_d:
- prefix_action = prefix_actions_d[prefix]
- prefix_action(widget)
-
- def custom_handler(self,
- glade, function_name, widget_name,
- str1, str2, int1, int2):
- """
- Generic handler for creating custom widgets, internally used to
- enable custom widgets (custom widgets of glade).
-
- The custom widgets have a creation function specified in design time.
- Those creation functions are always called with str1,str2,int1,int2 as
- arguments, that are values specified in design time.
-
- Methods of classes inheriting from SimpleGladeApp are used as
- creation functions automatically.
-
- If a custom widget has create_foo as creation function, then the
- method named create_foo is called with str1,str2,int1,int2 as arguments.
- """
- try:
- handler = getattr(self, function_name)
- return handler(str1, str2, int1, int2)
- except AttributeError:
- return None
-
- def gtk_widget_show(self, widget, *args):
- """
- Predefined callback.
- The widget is showed.
- Equivalent to widget.show()
- """
- widget.show()
-
- def gtk_widget_hide(self, widget, *args):
- """
- Predefined callback.
- The widget is hidden.
- Equivalent to widget.hide()
- """
- widget.hide()
-
- def gtk_widget_grab_focus(self, widget, *args):
- """
- Predefined callback.
- The widget grabs the focus.
- Equivalent to widget.grab_focus()
- """
- widget.grab_focus()
-
- def gtk_widget_destroy(self, widget, *args):
- """
- Predefined callback.
- The widget is destroyed.
- Equivalent to widget.destroy()
- """
- widget.destroy()
-
- def gtk_window_activate_default(self, window, *args):
- """
- Predefined callback.
- The default widget of the window is activated.
- Equivalent to window.activate_default()
- """
- widget.activate_default()
-
- def gtk_true(self, *args):
- """
- Predefined callback.
- Equivalent to return True in a callback.
- Useful for stopping propagation of signals.
- """
- return True
-
- def gtk_false(self, *args):
- """
- Predefined callback.
- Equivalent to return False in a callback.
- """
- return False
-
- def gtk_main_quit(self, *args):
- """
- Predefined callback.
- Equivalent to self.quit()
- """
- self.quit()
-
- def main(self):
- """
- Starts the main loop of processing events.
- The default implementation calls gtk.main()
-
- Useful for applications that needs a non gtk main loop.
- For example, applications based on gstreamer needs to override
- this method with gst.main()
-
- Do not directly call this method in your programs.
- Use the method run() instead.
- """
- gtk.main()
-
- def quit(self):
- """
- Quit processing events.
- The default implementation calls gtk.main_quit()
-
- Useful for applications that needs a non gtk main loop.
- For example, applications based on gstreamer needs to override
- this method with gst.main_quit()
- """
- gtk.main_quit()
-
- def run(self):
- """
- Starts the main loop of processing events checking for Control-C.
-
- The default implementation checks wheter a Control-C is pressed,
- then calls on_keyboard_interrupt().
-
- Use this method for starting programs.
- """
- try:
- self.main()
- except KeyboardInterrupt:
- self.on_keyboard_interrupt()
-
- def on_keyboard_interrupt(self):
- """
- This method is called by the default implementation of run()
- after a program is finished by pressing Control-C.
- """
- pass
-
- def install_custom_handler(self, custom_handler):
- gtk.glade.set_custom_handler(custom_handler)
-
- def create_glade(self, glade_path, root, domain):
- return gtk.glade.XML(self.glade_path, root, domain)
-
- def get_widget(self, widget_name):
- return self.glade.get_widget(widget_name)
-
- def get_widgets(self):
- return self.glade.get_widget_prefix("")
+++ /dev/null
-# $Id$
-
-# This file is part of avahi.
-#
-# avahi is free software; you can redistribute it and/or modify it
-# under the terms of the GNU Lesser General Public License as
-# published by the Free Software Foundation; either version 2 of the
-# License, or (at your option) any later version.
-#
-# avahi is distributed in the hope that it will be useful, but WITHOUT
-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
-# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
-# License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public
-# License along with avahi; if not, write to the Free Software
-# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
-# USA.
-
-# Some definitions matching those in core.h
-import socket, dbus
-
-SERVER_INVALID, SERVER_REGISTERING, SERVER_RUNNING, SERVER_COLLISION = range(0, 4)
-
-ENTRY_GROUP_UNCOMMITED, ENTRY_GROUP_REGISTERING, ENTRY_GROUP_ESTABLISHED, ENTRY_GROUP_COLLISION = range(0, 4)
-
-DOMAIN_BROWSER_REGISTER, DOMAIN_BROWSER_REGISTER_DEFAULT, DOMAIN_BROWSER_BROWSE, DOMAIN_BROWSER_BROWSE_DEFAULT, DOMAIN_BROWSER_BROWSE_LEGACY = range(0, 5)
-
-PROTO_UNSPEC, PROTO_INET, PROTO_INET6 = -1, 0, 1
-
-IF_UNSPEC = -1
-
-DBUS_NAME = "org.freedesktop.Avahi"
-DBUS_INTERFACE_SERVER = DBUS_NAME + ".Server"
-DBUS_PATH_SERVER = "/"
-DBUS_INTERFACE_ENTRY_GROUP = DBUS_NAME + ".EntryGroup"
-DBUS_INTERFACE_DOMAIN_BROWSER = DBUS_NAME + ".DomainBrowser"
-DBUS_INTERFACE_SERVICE_TYPE_BROWSER = DBUS_NAME + ".ServiceTypeBrowser"
-DBUS_INTERFACE_SERVICE_BROWSER = DBUS_NAME + ".ServiceBrowser"
-
-def byte_array_to_string(s):
- r = ""
-
- for c in s:
-
- if c >= 32 and c < 127:
- r += "%c" % c
- else:
- r += "."
-
- return r
-
-def txt_array_to_string_array(t):
- l = []
-
- for s in t:
- l.append(byte_array_to_string(s))
-
- return l
-
-
-def string_to_byte_array(s):
- r = []
-
- for c in s:
- r.append(dbus.Byte(ord(c)))
-
- return r
-
-def string_array_to_txt_array(t):
- l = []
-
- for s in t:
- l.append(string_to_byte_array(s))
-
- return l
-
-def dict_to_txt_array(txt_dict):
- l = []
-
- for k,v in txt_dict.items():
- l.append(string_to_byte_array("%s=%s" % (k,v)))
-
- return l
initscript/darwin/Makefile
avahi-dnsconfd/Makefile
avahi-utils/Makefile
-avahi-utils/avahi/Makefile
+avahi-python/Makefile
+avahi-python/avahi/Makefile
examples/Makefile
common/Makefile
man/Makefile