@@ -158,6 +158,7 @@ def emit(self, record):
158
158
159
159
_HAS_A_TO_Z = re .compile (r'[A-Za-z]' )
160
160
_HAS_ONLY_A_TO_Z_NUM_HYPHEN = re .compile (r'^[A-Za-z0-9\-]+$' )
161
+ _HAS_ASCII_CONTROL_CHARS = re .compile (r'[\x00-\x1f\x7f]' )
161
162
162
163
163
164
@enum .unique
@@ -212,6 +213,14 @@ def service_type_name(type_):
212
213
213
214
The instance name <Instance> and sub type <sub> may be up to 63 bytes.
214
215
216
+ The portion of the Service Instance Name is a user-
217
+ friendly name consisting of arbitrary Net-Unicode text [RFC5198]. It
218
+ MUST NOT contain ASCII control characters (byte values 0x00-0x1F and
219
+ 0x7F) [RFC20] but otherwise is allowed to contain any characters,
220
+ without restriction, including spaces, uppercase, lowercase,
221
+ punctuation -- including dots -- accented characters, non-Roman text,
222
+ and anything else that may be represented using Net-Unicode.
223
+
215
224
:param type_: Type, SubType or service name to validate
216
225
:return: fully qualified service name (eg: _http._tcp.local.)
217
226
"""
@@ -220,15 +229,15 @@ def service_type_name(type_):
220
229
"Type '%s' must end with '._tcp.local.' or '._udp.local.'" %
221
230
type_ )
222
231
223
- if type_ .startswith ('.' ):
224
- raise BadTypeInNameException (
225
- "Type '%s' must not start with '.'" % type_ )
226
-
227
232
remaining = type_ [:- len ('._tcp.local.' )].split ('.' )
228
233
name = remaining .pop ()
229
234
if not name :
230
235
raise BadTypeInNameException ("No Service name found" )
231
236
237
+ if len (remaining ) == 1 and len (remaining [0 ]) == 0 :
238
+ raise BadTypeInNameException (
239
+ "Type '%s' must not start with '.'" % type_ )
240
+
232
241
if name [0 ] != '_' :
233
242
raise BadTypeInNameException (
234
243
"Service name (%s) must start with '_'" % name )
@@ -260,20 +269,23 @@ def service_type_name(type_):
260
269
261
270
if remaining and remaining [- 1 ] == '_sub' :
262
271
remaining .pop ()
263
- if len (remaining ) == 0 :
272
+ if len (remaining ) == 0 or len ( remaining [ 0 ]) == 0 :
264
273
raise BadTypeInNameException (
265
274
"_sub requires a subtype name" )
266
275
267
276
if len (remaining ) > 1 :
268
- raise BadTypeInNameException (
269
- "Unexpected characters '%s.' in '%s'" % (
270
- '.' .join (remaining [1 :]), type_ ))
277
+ remaining = ['.' .join (remaining )]
271
278
272
279
if remaining :
273
280
length = len (remaining [0 ].encode ('utf-8' ))
274
281
if length > 63 :
275
282
raise BadTypeInNameException ("Too long: '%s'" % remaining [0 ])
276
283
284
+ if _HAS_ASCII_CONTROL_CHARS .search (remaining [0 ]):
285
+ raise BadTypeInNameException (
286
+ "Ascii control character 0x00-0x1F and 0x7F illegal in '%s'" %
287
+ remaining [0 ])
288
+
277
289
return '_' + name + type_ [- len ('._tcp.local.' ):]
278
290
279
291
@@ -1846,13 +1858,13 @@ def unregister_all_services(self):
1846
1858
def check_service (self , info , allow_name_change ):
1847
1859
"""Checks the network for a unique service name, modifying the
1848
1860
ServiceInfo passed in if it is not unique."""
1849
- service_name = service_type_name (info .name )
1850
1861
1851
- # This asserts breaks on the current subtype based tests
1862
+ # This is kind of funky because of the subtype based tests
1852
1863
# need to make subtypes a first class citizen
1853
- # assert service_name == info.type
1854
- # instead try:
1855
- assert service_name == '.' .join (info .type .split ('.' )[- 4 :])
1864
+ service_name = service_type_name (info .name )
1865
+ if not info .type .endswith (service_name ):
1866
+ raise BadTypeInNameException
1867
+
1856
1868
instance_name = info .name [:- len (service_name ) - 1 ]
1857
1869
next_instance_number = 2
1858
1870
0 commit comments