assert(size > 0);
r = ret_s;
+ *ret_s = 0;
+
while (*s) {
char label[AVAHI_LABEL_MAX];
if (!(avahi_unescape_label(&s, label, sizeof(label))))
return NULL;
- if (strlen(label) > 0) {
-
- if (!empty) {
- if (size < 1)
- return NULL;
+ if (label[0] == 0) {
- *(r++) = '.';
- size--;
+ if (*s == 0 && empty)
+ return ret_s;
- } else
- empty = 0;
-
- avahi_escape_label(label, strlen(label), &r, &size);
+ return NULL;
}
+
+ if (!empty) {
+ if (size < 1)
+ return NULL;
+
+ *(r++) = '.';
+ size--;
+
+ } else
+ empty = 0;
+
+ avahi_escape_label(label, strlen(label), &r, &size);
}
- if (empty)
- return NULL;
-
return ret_s;
}
}
}
-int avahi_is_valid_service_type(const char *t) {
+int avahi_is_valid_service_type_generic(const char *t) {
assert(t);
if (strlen(t) >= AVAHI_DOMAIN_NAME_MAX || !*t)
return 1;
}
-int avahi_is_valid_domain_name(const char *t) {
+int avahi_is_valid_service_type_strict(const char *t) {
+ char label[AVAHI_LABEL_MAX];
assert(t);
if (strlen(t) >= AVAHI_DOMAIN_NAME_MAX || !*t)
return 0;
+ /* Application name */
+
+ if (!(avahi_unescape_label(&t, label, sizeof(label))))
+ return 0;
+
+ if (strlen(label) <= 2 || label[0] != '_')
+ return 0;
+
+ if (!*t)
+ return 0;
+
+ /* _tcp or _udp boilerplate */
+
+ if (!(avahi_unescape_label(&t, label, sizeof(label))))
+ return 0;
+
+ if (strcasecmp(label, "_tcp") && strcasecmp(label, "_udp"))
+ return 0;
+
+ if (*t)
+ return 0;
+
+ return 1;
+}
+
+const char *avahi_get_type_from_subtype(const char *t) {
+ char label[AVAHI_LABEL_MAX];
+ const char *ret;
+ assert(t);
+
+ if (strlen(t) >= AVAHI_DOMAIN_NAME_MAX || !*t)
+ return NULL;
+
+ /* Subtype name */
+
+ if (!(avahi_unescape_label(&t, label, sizeof(label))))
+ return NULL;
+
+ if (strlen(label) <= 2 || label[0] != '_')
+ return NULL;
+
+ if (!*t)
+ return NULL;
+
+ /* String "_sub" */
+
+ if (!(avahi_unescape_label(&t, label, sizeof(label))))
+ return NULL;
+
+ if (strcasecmp(label, "_sub"))
+ return NULL;
+
+ if (!*t)
+ return NULL;
+
+ ret = t;
+
+ /* Application name */
+
+ if (!(avahi_unescape_label(&t, label, sizeof(label))))
+ return NULL;
+
+ if (strlen(label) <= 2 || label[0] != '_')
+ return NULL;
+
+ if (!*t)
+ return NULL;
+
+ /* _tcp or _udp boilerplate */
+
+ if (!(avahi_unescape_label(&t, label, sizeof(label))))
+ return NULL;
+
+ if (strcasecmp(label, "_tcp") && strcasecmp(label, "_udp"))
+ return NULL;
+
+ if (*t)
+ return NULL;
+
+ return ret;
+}
+
+int avahi_is_valid_service_subtype(const char *t) {
+ assert(t);
+
+ return !!avahi_get_type_from_subtype(t);
+}
+
+int avahi_is_valid_domain_name(const char *t) {
+ int is_first = 1;
+ assert(t);
+
+ if (strlen(t) >= AVAHI_DOMAIN_NAME_MAX)
+ return 0;
+
do {
char label[AVAHI_LABEL_MAX];
if (!(avahi_unescape_label(&t, label, sizeof(label))))
return 0;
- if (strlen(label) < 1)
+ /* Explicitly allow the root domain name */
+ if (is_first && label[0] == 0 && *t == 0)
+ return 1;
+
+ is_first = 0;
+
+ if (label[0] == 0)
return 0;
} while (*t);
}
int avahi_service_name_join(char *p, size_t size, const char *name, const char *type, const char *domain) {
- char escaped_name[AVAHI_LABEL_MAX];
+ char escaped_name[AVAHI_LABEL_MAX*4];
char normalized_type[AVAHI_DOMAIN_NAME_MAX];
char normalized_domain[AVAHI_DOMAIN_NAME_MAX];
if ((name && !avahi_is_valid_service_name(name)))
return AVAHI_ERR_INVALID_SERVICE_NAME;
- if (!avahi_is_valid_service_type(type))
+ if (!avahi_is_valid_service_type_generic(type))
return AVAHI_ERR_INVALID_SERVICE_TYPE;
if (!avahi_is_valid_domain_name(domain))
return AVAHI_OK;
}
+#ifndef HAVE_STRLCPY
-char *avahi_strlcpy(char *dest, const char *src, size_t n) {
+static size_t strlcpy(char *dest, const char *src, size_t n) {
assert(dest);
assert(src);
-
- if (n == 0)
- return dest;
-
- strncpy(dest, src, n-1);
- dest[n-1] = 0;
- return dest;
+
+ if (n > 0) {
+ strncpy(dest, src, n-1);
+ dest[n-1] = 0;
+ }
+
+ return strlen(src);
}
+#endif
+
int avahi_service_name_split(const char *p, char *name, size_t name_size, char *type, size_t type_size, char *domain, size_t domain_size) {
enum {
NAME,
switch (state) {
case NAME:
- avahi_strlcpy(name, buf, name_size);
+ strlcpy(name, buf, name_size);
state = TYPE;
break;