* remove "avahi start/stop/restart" stuff as avahi detects changes itself (so there...
[enigma2-plugins.git] / bonjour / src / Bonjour.py
1 # -*- coding: utf-8 -*-
2 from enigma import eConsoleAppContainer, eTimer
3 from xml.etree.cElementTree import parse as cet_parse
4 from os import path, listdir
5 from os import remove as os_remove
6
7 class Bonjour:
8         AVAHI_SERVICES_DIR = '/etc/avahi/services/'
9         AVAHI_START_SCRIPT = '/etc/init.d/avahi-daemon'
10          
11         def __init__(self):     
12                 self.services = []              
13                 self.files = {}         
14                 self.reloadConfig()
15                 
16         def __createServiceConfig(self, service):
17                 lines = [
18                                 '<?xml version="1.0" standalone="no"?><!--*-nxml-*-->\n',
19                                 '<!DOCTYPE service-group SYSTEM "avahi-service.dtd">\n',
20                                 '<!-- This file has been created by enigma2-plugin-extensions-bonjour -->\n',                           
21                                 '<service-group>\n',
22                                 '\t<name replace-wildcards="yes">%s</name>\n' %(service['name']),
23                                 '\t<service>\n',
24                                 '\t\t<type>%s</type>\n' %(service['type']),
25                                 '\t\t<port>%s</port>\n' %(service['port']) 
26                                 ]
27                 
28                 if service['text'] is not None and service['text'] != "":
29                         lines.add('\t\t<text-record>%s</text-record>\n' %(service['text']) )
30                 
31                 lines.extend([
32                                         '\t</service>\n', 
33                                         '</service-group>\n'
34                                         ])
35                 
36                 return lines
37         
38         def __writeService(self, service):
39                 print "[Bonjour.__writeService] Creating service file '%s'" %(service['file'])  
40                 if 'type' in service and 'port' in service and 'file' in service:
41                         filepath = "%s%s" %(self.AVAHI_SERVICES_DIR, service['file'])
42                         file = open(filepath, 'w');
43                         file.writelines(self.__createServiceConfig(service))
44                         file.close()
45                         return True
46                 
47                 print "[Bonjour.__writeService] Cannot create service file '%s'" %(service['file'])             
48                 return False
49         
50         def __deleteService(self, protocol):            
51                 filepath = "%s%s.service" %(self.AVAHI_SERVICES_DIR, protocol)
52                 if path.exists(filepath):
53                         
54                         os_remove(filepath)
55                         return True
56                 
57                 return False
58                                 
59         def __parse(self, file):
60                 print "[Bonjour.__parse] parsing %s%s" %(self.AVAHI_SERVICES_DIR, file) 
61                 config = cet_parse(self.AVAHI_SERVICES_DIR + file).getroot()
62                 
63                 name = config.find('name').text
64                 
65                 service = config.find('service')                
66                 type = service.find('type').text
67                 port = service.find('port').text
68                 text = service.get('text-record')
69                 if text is None:
70                         text = ""
71                 else: 
72                         text = text.text
73                 
74                 service = self.buildServiceFull(file, name, type, port, text)           
75                 self.registerService(service)
76         
77         def __removeServiceFromList(self, service):     
78                 oldservices = self.services
79                 self.services = []
80                 
81                 for s in oldservices:
82                         if s['file'] != service['file']:
83                                 self.services.append(s)
84                                 self.files[s['file']] = len(self.services) - 1
85                 
86                 self.files[service['file']] = None
87         
88         
89         def reloadConfig(self):
90                 self.services = []
91                 self.files = {}
92                 if path.exists(self.AVAHI_SERVICES_DIR):
93                         print "[Bonjour.reloadConfig] reloading config"
94                         service_files = filter( lambda x: x.endswith('.service'), listdir(self.AVAHI_SERVICES_DIR) )
95                         for file in service_files:
96                                 self.__parse(file)
97                 
98                 self.registerDefaultServices()
99
100         
101         def registerService(self, service, replace = False):
102                 print "[Bonjour.registerService] %s" %service
103                 
104                 if 'type' in service and 'port' in service and 'file' in service:                                       
105                         if (service['file'] not in self.files) or replace:
106                                 filepath = "%s%s" %(self.AVAHI_SERVICES_DIR, service['file'])
107                                 if not self.__writeService(service):
108                                         return False
109                                         
110                                 if replace and service['file'] in self.files:                           
111                                         self.__removeServiceFromList(service)
112                                 
113                                 
114                                 self.services.append(service)
115                                 self.files[service['file']] = len(self.services) - 1
116                                 
117                                 return True
118                                 
119                 else:
120                         print "[Bonjour.registerService] Missing port or type definition in %s%s" %(self.AVAHI_SERVICES_DIR, service['file'])
121                         return False    
122         
123         
124         def updateService(self, service):
125                 if 'type' in service and 'port' in service and 'file' in service:
126                         
127                         filepath = "%s%s" %(self.AVAHI_SERVICES_DIR, service['file'])
128                         if not path.exists(filepath):
129                                 print "[Bonjour.updateService] Cannot update non-existent service file '%s'" %(service['file'])
130                                 return False
131                         
132                         else:
133                                 if not self.__writeService(service):
134                                         print "[Bonjour.updateService] Cannot write service file '%s'" %(service['file'])
135                                         return False
136
137                 return True
138         
139         def unregisterService(self, protocol):
140                 if self.__deleteService(protocol):
141                         self.reloadConfig()
142                 
143         
144         def buildService(self, protocol, port, text="", udp = False):
145                 file = "%s.service" %protocol
146                 
147                 type = "_%s._tcp" %protocol
148                 if udp:
149                         type = "_%s._udp" %protocol     
150                 
151                 name = "%h "
152                 name += protocol.upper()
153                 
154                 return {
155                                 'file' : file,
156                                 'name' : name,
157                                 'type' : type,
158                                 'port' : port,
159                                 'text' : text
160                                 }
161         
162         def buildServiceFull(self, file, name, type, port, text="", udp = False):               
163                 return {
164                                 'file' : file,
165                                 'name' : name,
166                                 'type' : type,
167                                 'port' : port,
168                                 'text' : text
169                                 }
170         
171         def registerDefaultServices(self):
172                 print "[Bonjour.registerDefaultServices] called"
173                 service = self.buildService('ftp', '21')
174                 filepath = "%s%s" %(self.AVAHI_SERVICES_DIR, service['file'])
175                 if not path.exists(filepath):
176                         self.registerService(service)
177                         
178                 service = self.buildService('ssh', '22')
179                 filepath = "%s%s" %(self.AVAHI_SERVICES_DIR, service['file'])
180                 if not path.exists(filepath):
181                         self.registerService(service)
182
183                 service = self.buildService('sftp-ssh', '22')
184                 filepath = "%s%s" %(self.AVAHI_SERVICES_DIR, service['file'])
185                 if not path.exists(filepath):
186                         self.registerService(service)
187
188                 service = self.buildService('smb', '139')
189                 filepath = "%s%s" %(self.AVAHI_SERVICES_DIR, service['file'])
190                 if not path.exists(filepath):
191                         self.registerService(service)
192                         
193 bonjour = Bonjour()