5 # This file is part of avahi.
7 # avahi is free software; you can redistribute it and/or modify it
8 # under the terms of the GNU Lesser General Public License as
9 # published by the Free Software Foundation; either version 2 of the
10 # License, or (at your option) any later version.
12 # avahi is distributed in the hope that it will be useful, but WITHOUT
13 # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
14 # or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
15 # License for more details.
17 # You should have received a copy of the GNU Lesser General Public
18 # License along with avahi; if not, write to the Free Software
19 # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
25 import avahi, gobject, dbus
27 print "Sorry, to use this tool you need to install Avahi, pygtk and python-dbus."
36 from twisted.internet import glib2reactor
37 glib2reactor.install()
38 from twisted.internet import reactor
39 from twisted.web import server, resource
41 print "Sorry, to use this tool you need to install twisted and twisted.web."
44 urlproto = { "_http._tcp" : "http", "_https._tcp" : "https", "_ftp._tcp" : "ftp" }
51 class AvahiBookmarks(resource.Resource):
56 def __init__(self, use_host_names):
57 resource.Resource.__init__(self)
59 self.bus = dbus.SystemBus()
60 self.server = dbus.Interface(self.bus.get_object(avahi.DBUS_NAME, avahi.DBUS_PATH_SERVER), avahi.DBUS_INTERFACE_SERVER)
62 self.version_string = self.server.GetVersionString()
64 self.browse_service_type("_http._tcp")
65 self.browse_service_type("_https._tcp")
66 self.browse_service_type("_ftp._tcp")
68 if use_host_names is None:
70 self.use_host_names = self.server.IsNSSSupportAvailable()
72 self.use_host_names = False
74 self.use_host_names = use_host_names
76 def browse_service_type(self, stype):
80 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)
81 browser.connect_to_signal('ItemNew', self.new_service)
82 browser.connect_to_signal('ItemRemove', self.remove_service)
84 def find_path(self, txt):
86 l = avahi.txt_array_to_string_array(txt)
90 if k[5:].startswith("/"):
97 def render_GET(self, request):
99 t = '<html><head><title>Zeroconf Bookmarks</title></head><body><h1>Zeroconf Bookmarks</h1>'
101 if len(self.services) == 0:
102 t += '<p>Sorry, no web services have been registered on the local LAN.</p>'
104 t += '<ul style="padding: 0px; margin: 20px; list-style-type: none">'
106 for k, v in self.services.iteritems():
113 path = self.find_path(v[4])
114 t += '<li><a href="%s://%s%s%s">%s</a></li>' % (urlproto[k[3]], v[2], port, path, k[2])
118 t += '<hr noshade/><p style="font-size: 8; font-family: sans-serif">Served by %s</p></body></html>' % self.version_string
123 def new_service(self, interface, protocol, name, type, domain, flags):
125 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))
127 if self.use_host_names:
130 if aprotocol == avahi.PROTO_INET6:
131 h = "[" + address + "]"
135 self.services[(interface, protocol, name, type, domain)] = (host, aprotocol, h, port, txt)
137 def remove_service(self, interface, protocol, name, type, domain):
138 del self.services[(interface, protocol, name, type, domain)]
141 def usage(retval = 0):
142 print "%s [options]\n" % sys.argv[0]
143 print " -h --help Show this help"
144 print " -p --port PORT Specify the port to use (default %u)" % port
145 print " -a --address ADDRESS Specify the address to bind to (default %s)" % address
146 print " -H --host-names Show links with real hostnames"
147 print " -A --addresses Show links with numeric IP addresses"
148 print " -d --domain DOMAIN Specify the domain to browse"
152 opts, args = getopt.getopt(sys.argv[1:], "hp:a:HAd:", ["help", "port=", "address=", "host-names", "addresses", "domain="])
153 except getopt.GetoptError:
157 if o in ("-h", "--help"):
160 if o in ("-p", "--port"):
163 if o in ("-a", "--address"):
166 if o in ("-H", "--host-names"):
167 use_host_names = True
169 if o in ("-A", "--addresses"):
170 use_host_names = False
172 if o in ("-d", "--domain"):
175 site = server.Site(AvahiBookmarks(use_host_names))
176 reactor.listenTCP(port, site, interface=address)
178 print "Now point your web browser to http://%s:%u/!" % (address, port)
182 except KeyboardInterrupt, k: