diff options
author | Jaakko Keränen <jaakko.keranen@iki.fi> | 2020-12-11 20:40:32 +0200 |
---|---|---|
committer | Jaakko Keränen <jaakko.keranen@iki.fi> | 2020-12-11 20:40:32 +0200 |
commit | 7f8f6f3305161706d44884cccd4961ba4f0490bf (patch) | |
tree | 4b0dc4b492119b7d15c5abb72cc01aa8f3de9a03 /src/gmutil.c | |
parent | 413f8b95e62a33671e166badd8789a1bbf1248ef (diff) |
GmRequest: Punycode for domain names
To support Internationalized Domain Names, we need to encode domain names using Punycode.
IssueID #73
Diffstat (limited to 'src/gmutil.c')
-rw-r--r-- | src/gmutil.c | 41 |
1 files changed, 41 insertions, 0 deletions
diff --git a/src/gmutil.c b/src/gmutil.c index 477d0f17..67b0d939 100644 --- a/src/gmutil.c +++ b/src/gmutil.c | |||
@@ -185,10 +185,51 @@ const iString *absoluteUrl_String(const iString *d, const iString *urlMaybeRelat | |||
185 | appendRange_String(absolute, orig.path); | 185 | appendRange_String(absolute, orig.path); |
186 | } | 186 | } |
187 | appendRange_String(absolute, rel.query); | 187 | appendRange_String(absolute, rel.query); |
188 | normalize_String(absolute); | ||
188 | cleanUrlPath_String(absolute); | 189 | cleanUrlPath_String(absolute); |
189 | return absolute; | 190 | return absolute; |
190 | } | 191 | } |
191 | 192 | ||
193 | static iBool equalPuny_(const iString *d, iRangecc orig) { | ||
194 | if (!endsWith_String(d, "-")) { | ||
195 | return iFalse; /* This is a sufficient condition? */ | ||
196 | } | ||
197 | if (size_String(d) != size_Range(&orig) + 1) { | ||
198 | return iFalse; | ||
199 | } | ||
200 | return iCmpStrN(cstr_String(d), orig.start, size_Range(&orig)) == 0; | ||
201 | } | ||
202 | |||
203 | void punyEncodeUrlHost_String(iString *d) { | ||
204 | /* `d` should be an absolute URL. */ | ||
205 | iUrl url; | ||
206 | init_Url(&url, d); | ||
207 | iString *encoded = new_String(); | ||
208 | setRange_String(encoded, (iRangecc){ url.scheme.start, url.host.start }); | ||
209 | /* The domain name needs to be split into segments. */ { | ||
210 | iRangecc seg = iNullRange; | ||
211 | iBool isFirst = iTrue; | ||
212 | while (nextSplit_Rangecc(url.host, ".", &seg)) { | ||
213 | if (!isFirst) { | ||
214 | appendChar_String(encoded, '.'); | ||
215 | } | ||
216 | isFirst = iFalse; | ||
217 | iString *puny = punyEncode_Rangecc(seg); | ||
218 | if (!isEmpty_String(puny) && !equalPuny_(puny, seg)) { | ||
219 | appendCStr_String(encoded, "xn--"); | ||
220 | append_String(encoded, puny); | ||
221 | } | ||
222 | else { | ||
223 | appendRange_String(encoded, seg); | ||
224 | } | ||
225 | delete_String(puny); | ||
226 | } | ||
227 | } | ||
228 | appendRange_String(encoded, (iRangecc){ url.host.end, constEnd_String(d) }); | ||
229 | set_String(d, encoded); | ||
230 | delete_String(encoded); | ||
231 | } | ||
232 | |||
192 | iString *makeFileUrl_String(const iString *localFilePath) { | 233 | iString *makeFileUrl_String(const iString *localFilePath) { |
193 | iString *url = cleaned_Path(localFilePath); | 234 | iString *url = cleaned_Path(localFilePath); |
194 | replace_Block(&url->chars, '\\', '/'); /* in case it's a Windows path */ | 235 | replace_Block(&url->chars, '\\', '/'); /* in case it's a Windows path */ |