summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJaakko Keränen <jaakko.keranen@iki.fi>2020-12-11 20:40:32 +0200
committerJaakko Keränen <jaakko.keranen@iki.fi>2020-12-11 20:40:32 +0200
commit7f8f6f3305161706d44884cccd4961ba4f0490bf (patch)
tree4b0dc4b492119b7d15c5abb72cc01aa8f3de9a03
parent413f8b95e62a33671e166badd8789a1bbf1248ef (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.c5
-rw-r--r--src/gmutil.c41
-rw-r--r--src/gmutil.h1
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
492void setUrl_GmRequest(iGmRequest *d, const iString *url) { 492void 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
193static 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
203void 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
192iString *makeFileUrl_String(const iString *localFilePath) { 233iString *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);
103iRangecc urlScheme_String (const iString *); 103iRangecc urlScheme_String (const iString *);
104iRangecc urlHost_String (const iString *); 104iRangecc urlHost_String (const iString *);
105const iString * absoluteUrl_String (const iString *, const iString *urlMaybeRelative); 105const iString * absoluteUrl_String (const iString *, const iString *urlMaybeRelative);
106void punyEncodeUrlHost_String(iString *);
106iString * makeFileUrl_String (const iString *localFilePath); 107iString * makeFileUrl_String (const iString *localFilePath);
107const char * makeFileUrl_CStr (const char *localFilePath); 108const char * makeFileUrl_CStr (const char *localFilePath);
108void urlEncodeSpaces_String (iString *); 109void urlEncodeSpaces_String (iString *);