4 * Copyright (C) 2006 Matthew Kehrer
5 * Copyright (C) 2006 Hans Leidekker
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
29 #include "wine/debug.h"
32 WINE_DEFAULT_DEBUG_CHANNEL(dnsapi
);
34 /******************************************************************************
35 * DnsNameCompare_A [DNSAPI.@]
38 BOOL WINAPI
DnsNameCompare_A( PCSTR name1
, PCSTR name2
)
43 TRACE( "(%s,%s)\n", debugstr_a(name1
), debugstr_a(name2
) );
45 name1W
= strdup_aw( name1
);
46 name2W
= strdup_aw( name2
);
48 ret
= DnsNameCompare_W( name1W
, name2W
);
56 /******************************************************************************
57 * DnsNameCompare_W [DNSAPI.@]
60 BOOL WINAPI
DnsNameCompare_W( PCWSTR name1
, PCWSTR name2
)
64 TRACE( "(%s,%s)\n", debugstr_w(name1
), debugstr_w(name2
) );
66 if (!name1
&& !name2
) return TRUE
;
67 if (!name1
|| !name2
) return FALSE
;
69 p
= name1
+ lstrlenW( name1
);
70 q
= name2
+ lstrlenW( name2
);
72 while (p
> name1
&& p
[-1] == '.') p
--;
73 while (q
> name2
&& q
[-1] == '.') q
--;
75 return CompareStringOrdinal( name1
, p
- name1
, name2
, q
- name2
, TRUE
) == CSTR_EQUAL
;
78 /******************************************************************************
79 * DnsValidateName_A [DNSAPI.@]
82 DNS_STATUS WINAPI
DnsValidateName_A( PCSTR name
, DNS_NAME_FORMAT format
)
87 TRACE( "(%s, %d)\n", debugstr_a(name
), format
);
89 nameW
= strdup_aw( name
);
90 ret
= DnsValidateName_W( nameW
, format
);
96 /******************************************************************************
97 * DnsValidateName_UTF8 [DNSAPI.@]
100 DNS_STATUS WINAPI
DnsValidateName_UTF8( PCSTR name
, DNS_NAME_FORMAT format
)
105 TRACE( "(%s, %d)\n", debugstr_a(name
), format
);
107 nameW
= strdup_uw( name
);
108 ret
= DnsValidateName_W( nameW
, format
);
114 #define HAS_EXTENDED 0x0001
115 #define HAS_NUMERIC 0x0002
116 #define HAS_NON_NUMERIC 0x0004
117 #define HAS_DOT 0x0008
118 #define HAS_DOT_DOT 0x0010
119 #define HAS_SPACE 0x0020
120 #define HAS_INVALID 0x0040
121 #define HAS_ASTERISK 0x0080
122 #define HAS_UNDERSCORE 0x0100
123 #define HAS_LONG_LABEL 0x0200
125 /******************************************************************************
126 * DnsValidateName_W [DNSAPI.@]
129 DNS_STATUS WINAPI
DnsValidateName_W( PCWSTR name
, DNS_NAME_FORMAT format
)
132 unsigned int i
, j
, state
= 0;
133 static const WCHAR invalid
[] = L
"{|}~[\\]^':;<=>?@!\"#$%&`()+/,";
135 TRACE( "(%s, %d)\n", debugstr_w(name
), format
);
137 if (!name
) return ERROR_INVALID_NAME
;
139 for (p
= name
, i
= 0, j
= 0; *p
; p
++, i
++, j
++)
145 if (p
[1] == '.') state
|= HAS_DOT_DOT
;
147 else if (*p
< '0' || *p
> '9') state
|= HAS_NON_NUMERIC
;
148 else state
|= HAS_NUMERIC
;
150 if (j
> 62) state
|= HAS_LONG_LABEL
;
152 if (wcschr( invalid
, *p
)) state
|= HAS_INVALID
;
153 else if ((unsigned)*p
> 127) state
|= HAS_EXTENDED
;
154 else if (*p
== ' ') state
|= HAS_SPACE
;
155 else if (*p
== '_') state
|= HAS_UNDERSCORE
;
156 else if (*p
== '*') state
|= HAS_ASTERISK
;
159 if (i
== 0 || i
> 255 ||
160 (state
& HAS_LONG_LABEL
) ||
161 (state
& HAS_DOT_DOT
) ||
162 (name
[0] == '.' && name
[1])) return ERROR_INVALID_NAME
;
168 if ((state
& HAS_EXTENDED
) || (state
& HAS_UNDERSCORE
))
169 return DNS_ERROR_NON_RFC_NAME
;
170 if ((state
& HAS_SPACE
) ||
171 (state
& HAS_INVALID
) ||
172 (state
& HAS_ASTERISK
)) return DNS_ERROR_INVALID_NAME_CHAR
;
175 case DnsNameDomainLabel
:
177 if (state
& HAS_DOT
) return ERROR_INVALID_NAME
;
178 if ((state
& HAS_EXTENDED
) || (state
& HAS_UNDERSCORE
))
179 return DNS_ERROR_NON_RFC_NAME
;
180 if ((state
& HAS_SPACE
) ||
181 (state
& HAS_INVALID
) ||
182 (state
& HAS_ASTERISK
)) return DNS_ERROR_INVALID_NAME_CHAR
;
185 case DnsNameHostnameFull
:
187 if ((state
& HAS_EXTENDED
) || (state
& HAS_UNDERSCORE
))
188 return DNS_ERROR_NON_RFC_NAME
;
189 if ((state
& HAS_SPACE
) ||
190 (state
& HAS_INVALID
) ||
191 (state
& HAS_ASTERISK
)) return DNS_ERROR_INVALID_NAME_CHAR
;
194 case DnsNameHostnameLabel
:
196 if (state
& HAS_DOT
) return ERROR_INVALID_NAME
;
197 if ((state
& HAS_EXTENDED
) || (state
& HAS_UNDERSCORE
))
198 return DNS_ERROR_NON_RFC_NAME
;
199 if ((state
& HAS_SPACE
) ||
200 (state
& HAS_INVALID
) ||
201 (state
& HAS_ASTERISK
)) return DNS_ERROR_INVALID_NAME_CHAR
;
204 case DnsNameWildcard
:
206 if (!(state
& HAS_NON_NUMERIC
) && (state
& HAS_NUMERIC
))
207 return ERROR_INVALID_NAME
;
208 if (name
[0] != '*') return ERROR_INVALID_NAME
;
209 if (name
[1] && name
[1] != '.')
210 return DNS_ERROR_INVALID_NAME_CHAR
;
211 if ((state
& HAS_EXTENDED
) ||
212 (state
& HAS_SPACE
) ||
213 (state
& HAS_INVALID
)) return ERROR_INVALID_NAME
;
216 case DnsNameSrvRecord
:
218 if (!(state
& HAS_NON_NUMERIC
) && (state
& HAS_NUMERIC
))
219 return ERROR_INVALID_NAME
;
220 if (name
[0] != '_') return ERROR_INVALID_NAME
;
221 if ((state
& HAS_UNDERSCORE
) && !name
[1])
222 return DNS_ERROR_NON_RFC_NAME
;
223 if ((state
& HAS_EXTENDED
) ||
224 (state
& HAS_SPACE
) ||
225 (state
& HAS_INVALID
)) return ERROR_INVALID_NAME
;
229 WARN( "unknown format: %d\n", format
);
232 return ERROR_SUCCESS
;