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 | |
parent | 413f8b95e62a33671e166badd8789a1bbf1248ef (diff) |
GmRequest: Punycode for domain names
To support Internationalized Domain Names, we need to encode domain names using Punycode.
IssueID #73
-rw-r--r-- | src/gmrequest.c | 5 | ||||
-rw-r--r-- | src/gmutil.c | 41 | ||||
-rw-r--r-- | src/gmutil.h | 1 |
3 files changed, 46 insertions, 1 deletions
diff --git a/src/gmrequest.c b/src/gmrequest.c index 884486b3..41b97620 100644 --- a/src/gmrequest.c +++ b/src/gmrequest.c | |||
@@ -491,6 +491,9 @@ void deinit_GmRequest(iGmRequest *d) { | |||
491 | 491 | ||
492 | void setUrl_GmRequest(iGmRequest *d, const iString *url) { | 492 | void setUrl_GmRequest(iGmRequest *d, const iString *url) { |
493 | set_String(&d->url, url); | 493 | set_String(&d->url, url); |
494 | /* Encode hostname to Punycode here because we want to submit the Punycode domain name | ||
495 | in the request. (TODO: Pending possible Gemini spec change.) */ | ||
496 | punyEncodeUrlHost_String(&d->url); | ||
494 | urlEncodeSpaces_String(&d->url); | 497 | urlEncodeSpaces_String(&d->url); |
495 | } | 498 | } |
496 | 499 | ||
@@ -646,7 +649,7 @@ void submit_GmRequest(iGmRequest *d) { | |||
646 | if (port == 0) { | 649 | if (port == 0) { |
647 | port = 1965; /* default Gemini port */ | 650 | port = 1965; /* default Gemini port */ |
648 | } | 651 | } |
649 | setUrl_TlsRequest(d->req, host, port); | 652 | setHost_TlsRequest(d->req, host, port); |
650 | setContent_TlsRequest(d->req, | 653 | setContent_TlsRequest(d->req, |
651 | utf8_String(collectNewFormat_String("%s\r\n", cstr_String(&d->url)))); | 654 | utf8_String(collectNewFormat_String("%s\r\n", cstr_String(&d->url)))); |
652 | submit_TlsRequest(d->req); | 655 | submit_TlsRequest(d->req); |
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 */ |
diff --git a/src/gmutil.h b/src/gmutil.h index 926f5a10..bbadbafd 100644 --- a/src/gmutil.h +++ b/src/gmutil.h | |||
@@ -103,6 +103,7 @@ void init_Url (iUrl *, const iString *text); | |||
103 | iRangecc urlScheme_String (const iString *); | 103 | iRangecc urlScheme_String (const iString *); |
104 | iRangecc urlHost_String (const iString *); | 104 | iRangecc urlHost_String (const iString *); |
105 | const iString * absoluteUrl_String (const iString *, const iString *urlMaybeRelative); | 105 | const iString * absoluteUrl_String (const iString *, const iString *urlMaybeRelative); |
106 | void punyEncodeUrlHost_String(iString *); | ||
106 | iString * makeFileUrl_String (const iString *localFilePath); | 107 | iString * makeFileUrl_String (const iString *localFilePath); |
107 | const char * makeFileUrl_CStr (const char *localFilePath); | 108 | const char * makeFileUrl_CStr (const char *localFilePath); |
108 | void urlEncodeSpaces_String (iString *); | 109 | void urlEncodeSpaces_String (iString *); |