1 /***
2 This file is part of avahi.
3
4 avahi is free software; you can redistribute it and/or modify it
5 under the terms of the GNU Lesser General Public License as
6 published by the Free Software Foundation; either version 2.1 of the
7 License, or (at your option) any later version.
8
9 avahi is distributed in the hope that it will be useful, but WITHOUT
10 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
11 or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General
12 Public License for more details.
13
14 You should have received a copy of the GNU Lesser General Public
15 License along with avahi; if not, write to the Free Software
16 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
17 USA.
18 ***/
19
20 #ifdef HAVE_CONFIG_H
21 #include <config.h>
22 #endif
23
24 #include <string.h>
25 #include <stdlib.h>
26 #include <ctype.h>
27 #include <assert.h>
28
29 #include "alternative.h"
30 #include "malloc.h"
31 #include "domain.h"
32 #include "utf8.h"
33
drop_incomplete_utf8(char * c)34 static void drop_incomplete_utf8(char *c) {
35 char *e;
36
37 e = strchr(c, 0) - 1;
38
39 while (e >= c) {
40
41 if (avahi_utf8_valid(c))
42 break;
43
44 assert(*e & 128);
45 *e = 0;
46
47 e--;
48 }
49 }
50
avahi_alternative_host_name(const char * s)51 char *avahi_alternative_host_name(const char *s) {
52 const char *e;
53 char *r;
54
55 assert(s);
56
57 if (!avahi_is_valid_host_name(s))
58 return NULL;
59
60 if ((e = strrchr(s, '-'))) {
61 const char *p;
62
63 e++;
64
65 for (p = e; *p; p++)
66 if (!isdigit(*p)) {
67 e = NULL;
68 break;
69 }
70
71 if (e && (*e == '0' || *e == 0))
72 e = NULL;
73 }
74
75 if (e) {
76 char *c, *m;
77 size_t l;
78 int n;
79
80 n = atoi(e)+1;
81 if (!(m = avahi_strdup_printf("%i", n)))
82 return NULL;
83
84 l = e-s-1;
85
86 if (l >= AVAHI_LABEL_MAX-1-strlen(m)-1)
87 l = AVAHI_LABEL_MAX-1-strlen(m)-1;
88
89 if (!(c = avahi_strndup(s, l))) {
90 avahi_free(m);
91 return NULL;
92 }
93
94 drop_incomplete_utf8(c);
95
96 r = avahi_strdup_printf("%s-%s", c, m);
97 avahi_free(c);
98 avahi_free(m);
99
100 } else {
101 char *c;
102
103 if (!(c = avahi_strndup(s, AVAHI_LABEL_MAX-1-2)))
104 return NULL;
105
106 drop_incomplete_utf8(c);
107
108 r = avahi_strdup_printf("%s-2", c);
109 avahi_free(c);
110 }
111
112 assert(avahi_is_valid_host_name(r));
113
114 return r;
115 }
116
avahi_alternative_service_name(const char * s)117 char *avahi_alternative_service_name(const char *s) {
118 const char *e;
119 char *r;
120
121 assert(s);
122
123 if (!avahi_is_valid_service_name(s))
124 return NULL;
125
126 if ((e = strstr(s, " #"))) {
127 const char *n, *p;
128 e += 2;
129
130 while ((n = strstr(e, " #")))
131 e = n + 2;
132
133 for (p = e; *p; p++)
134 if (!isdigit(*p)) {
135 e = NULL;
136 break;
137 }
138
139 if (e && (*e == '0' || *e == 0))
140 e = NULL;
141 }
142
143 if (e) {
144 char *c, *m;
145 size_t l;
146 int n;
147
148 n = atoi(e)+1;
149 if (!(m = avahi_strdup_printf("%i", n)))
150 return NULL;
151
152 l = e-s-2;
153
154 if (l >= AVAHI_LABEL_MAX-1-strlen(m)-2)
155 l = AVAHI_LABEL_MAX-1-strlen(m)-2;
156
157 if (!(c = avahi_strndup(s, l))) {
158 avahi_free(m);
159 return NULL;
160 }
161
162 drop_incomplete_utf8(c);
163
164 r = avahi_strdup_printf("%s #%s", c, m);
165 avahi_free(c);
166 avahi_free(m);
167 } else {
168 char *c;
169
170 if (!(c = avahi_strndup(s, AVAHI_LABEL_MAX-1-3)))
171 return NULL;
172
173 drop_incomplete_utf8(c);
174
175 r = avahi_strdup_printf("%s #2", c);
176 avahi_free(c);
177 }
178
179 assert(avahi_is_valid_service_name(r));
180
181 return r;
182 }
183