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