summaryrefslogtreecommitdiff
path: root/src/gmutil.c
diff options
context:
space:
mode:
authorJaakko Keränen <jaakko.keranen@iki.fi>2020-12-12 07:37:51 +0200
committerJaakko Keränen <jaakko.keranen@iki.fi>2020-12-12 07:37:51 +0200
commit072805e251cbe451d22c04c433b4c63d8a82301d (patch)
treea164d2139b441a8fc19673528fa0bcec09f18932 /src/gmutil.c
parenta3c6810225a1637f1e4d147c7a0d6f967eddf1b2 (diff)
IDN applies to all network schemes
But not "file" or "about".
Diffstat (limited to 'src/gmutil.c')
-rw-r--r--src/gmutil.c41
1 files changed, 33 insertions, 8 deletions
diff --git a/src/gmutil.c b/src/gmutil.c
index 67b0d939..68525be9 100644
--- a/src/gmutil.c
+++ b/src/gmutil.c
@@ -132,6 +132,25 @@ static iBool isAbsolutePath_(iRangecc path) {
132 return isAbsolute_Path(collect_String(urlDecode_String(collect_String(newRange_String(path))))); 132 return isAbsolute_Path(collect_String(urlDecode_String(collect_String(newRange_String(path)))));
133} 133}
134 134
135static iString *punyDecodeHost_(iRangecc host) {
136 iString *result = new_String();
137 iRangecc label = iNullRange;
138 while (nextSplit_Rangecc(host, ".", &label)) {
139 if (!isEmpty_String(result)) {
140 appendChar_String(result, '.');
141 }
142 if (startsWithCase_Rangecc(label, "xn--")) {
143 iString *dec = punyDecode_Rangecc((iRangecc){ label.start + 4, label.end });
144 if (!isEmpty_String(dec)) {
145 append_String(result, dec);
146 continue;
147 }
148 }
149 appendRange_String(result, label);
150 }
151 return result;
152}
153
135const iString *absoluteUrl_String(const iString *d, const iString *urlMaybeRelative) { 154const iString *absoluteUrl_String(const iString *d, const iString *urlMaybeRelative) {
136 iUrl orig; 155 iUrl orig;
137 iUrl rel; 156 iUrl rel;
@@ -152,9 +171,12 @@ const iString *absoluteUrl_String(const iString *d, const iString *urlMaybeRelat
152 } 171 }
153 iString *absolute = collectNew_String(); 172 iString *absolute = collectNew_String();
154 appendRange_String(absolute, scheme); 173 appendRange_String(absolute, scheme);
155 appendCStr_String(absolute, "://"); { 174 appendCStr_String(absolute, "://");
175 /* Authority. */ {
156 const iUrl *selHost = isDef_(rel.host) ? &rel : &orig; 176 const iUrl *selHost = isDef_(rel.host) ? &rel : &orig;
157 appendRange_String(absolute, selHost->host); 177 iString *decHost = punyDecodeHost_(selHost->host);
178 append_String(absolute, decHost);
179 delete_String(decHost);
158 if (!isEmpty_Range(&selHost->port)) { 180 if (!isEmpty_Range(&selHost->port)) {
159 appendCStr_String(absolute, ":"); 181 appendCStr_String(absolute, ":");
160 appendRange_String(absolute, selHost->port); 182 appendRange_String(absolute, selHost->port);
@@ -204,23 +226,26 @@ void punyEncodeUrlHost_String(iString *d) {
204 /* `d` should be an absolute URL. */ 226 /* `d` should be an absolute URL. */
205 iUrl url; 227 iUrl url;
206 init_Url(&url, d); 228 init_Url(&url, d);
229 if (isEmpty_Range(&url.host)) {
230 return;
231 }
207 iString *encoded = new_String(); 232 iString *encoded = new_String();
208 setRange_String(encoded, (iRangecc){ url.scheme.start, url.host.start }); 233 setRange_String(encoded, (iRangecc){ url.scheme.start, url.host.start });
209 /* The domain name needs to be split into segments. */ { 234 /* The domain name needs to be split into labels. */ {
210 iRangecc seg = iNullRange; 235 iRangecc label = iNullRange;
211 iBool isFirst = iTrue; 236 iBool isFirst = iTrue;
212 while (nextSplit_Rangecc(url.host, ".", &seg)) { 237 while (nextSplit_Rangecc(url.host, ".", &label)) {
213 if (!isFirst) { 238 if (!isFirst) {
214 appendChar_String(encoded, '.'); 239 appendChar_String(encoded, '.');
215 } 240 }
216 isFirst = iFalse; 241 isFirst = iFalse;
217 iString *puny = punyEncode_Rangecc(seg); 242 iString *puny = punyEncode_Rangecc(label);
218 if (!isEmpty_String(puny) && !equalPuny_(puny, seg)) { 243 if (!isEmpty_String(puny) && !equalPuny_(puny, label)) {
219 appendCStr_String(encoded, "xn--"); 244 appendCStr_String(encoded, "xn--");
220 append_String(encoded, puny); 245 append_String(encoded, puny);
221 } 246 }
222 else { 247 else {
223 appendRange_String(encoded, seg); 248 appendRange_String(encoded, label);
224 } 249 }
225 delete_String(puny); 250 delete_String(puny);
226 } 251 }