summaryrefslogtreecommitdiff
path: root/src/gmdocument.c
diff options
context:
space:
mode:
authorJaakko Keränen <jaakko.keranen@iki.fi>2020-08-01 13:17:49 +0300
committerJaakko Keränen <jaakko.keranen@iki.fi>2020-08-01 13:17:49 +0300
commit105b1948a8065659e17407189962ca7a4119e733 (patch)
tree3d5a779ad243537fd7d3b05d6c70008c30bb3435 /src/gmdocument.c
parent3b76ce224e40f670c0988985d9a9405edb7ed24d (diff)
More robust URL processing
Fixed a number of special cases revealed by the client torture test.
Diffstat (limited to 'src/gmdocument.c')
-rw-r--r--src/gmdocument.c32
1 files changed, 19 insertions, 13 deletions
diff --git a/src/gmdocument.c b/src/gmdocument.c
index 0b792d56..116e532a 100644
--- a/src/gmdocument.c
+++ b/src/gmdocument.c
@@ -171,18 +171,17 @@ static iRangecc addLink_GmDocument_(iGmDocument *d, iRangecc line, iGmLinkId *li
171 if (matchRange_RegExp(pattern, line, &m)) { 171 if (matchRange_RegExp(pattern, line, &m)) {
172 iGmLink *link = new_GmLink(); 172 iGmLink *link = new_GmLink();
173 setRange_String(&link->url, capturedRange_RegExpMatch(&m, 1)); 173 setRange_String(&link->url, capturedRange_RegExpMatch(&m, 1));
174 set_String(&link->url, absoluteUrl_String(&d->url, &link->url));
174 /* Check the URL. */ { 175 /* Check the URL. */ {
175 iUrl parts; 176 iUrl parts;
176 init_Url(&parts, &link->url); 177 init_Url(&parts, &link->url);
177 /* Host name. */ 178 if (!equalCase_Rangecc(&parts.host, cstr_String(&d->localHost))) {
178 if (!isEmpty_Range(&parts.host) &&
179 !equalCase_Rangecc(&parts.host, cstr_String(&d->localHost))) {
180 link->flags |= remote_GmLinkFlag; 179 link->flags |= remote_GmLinkFlag;
181 } 180 }
182 if (!isEmpty_Range(&parts.protocol) && !equalCase_Rangecc(&parts.protocol, "gemini")) { 181 if (startsWithCase_Rangecc(&parts.protocol, "gemini")) {
183 link->flags |= remote_GmLinkFlag; 182 link->flags |= gemini_GmLinkFlag;
184 } 183 }
185 if (startsWithCase_Rangecc(&parts.protocol, "http")) { 184 else if (startsWithCase_Rangecc(&parts.protocol, "http")) {
186 link->flags |= http_GmLinkFlag; 185 link->flags |= http_GmLinkFlag;
187 } 186 }
188 else if (equalCase_Rangecc(&parts.protocol, "gopher")) { 187 else if (equalCase_Rangecc(&parts.protocol, "gopher")) {
@@ -191,6 +190,9 @@ static iRangecc addLink_GmDocument_(iGmDocument *d, iRangecc line, iGmLinkId *li
191 else if (equalCase_Rangecc(&parts.protocol, "file")) { 190 else if (equalCase_Rangecc(&parts.protocol, "file")) {
192 link->flags |= file_GmLinkFlag; 191 link->flags |= file_GmLinkFlag;
193 } 192 }
193 else if (equalCase_Rangecc(&parts.protocol, "data")) {
194 link->flags |= data_GmLinkFlag;
195 }
194 /* Check the file name extension, if present. */ 196 /* Check the file name extension, if present. */
195 if (!isEmpty_Range(&parts.path)) { 197 if (!isEmpty_Range(&parts.path)) {
196 iString *path = newRange_String(parts.path); 198 iString *path = newRange_String(parts.path);
@@ -206,11 +208,9 @@ static iRangecc addLink_GmDocument_(iGmDocument *d, iRangecc line, iGmLinkId *li
206 } 208 }
207 delete_String(path); 209 delete_String(path);
208 } 210 }
209 } 211 /* Check if visited. */
210 /* Check if visited. */ { 212 if (cmpString_String(&link->url, &d->url)) {
211 const iString *absUrl = absoluteUrl_String(&d->url, &link->url); 213 link->when = urlVisitTime_History(history_App(), &link->url);
212 if (cmpString_String(absUrl, &d->url)) {
213 link->when = urlVisitTime_History(history_App(), absUrl);
214 if (isValid_Time(&link->when)) { 214 if (isValid_Time(&link->when)) {
215 link->flags |= visited_GmLinkFlag; 215 link->flags |= visited_GmLinkFlag;
216 } 216 }
@@ -401,8 +401,10 @@ static void doLayout_GmDocument_(iGmDocument *d) {
401 if (link->flags & remote_GmLinkFlag) { 401 if (link->flags & remote_GmLinkFlag) {
402 run.visBounds.pos.x -= gap_UI / 2; 402 run.visBounds.pos.x -= gap_UI / 2;
403 } 403 }
404
405 run.color = linkColor_GmDocument(d, run.linkId); 404 run.color = linkColor_GmDocument(d, run.linkId);
405 if (link->flags & visited_GmLinkFlag) {
406 run.color--; /* darker */
407 }
406 pushBack_Array(&d->layout, &run); 408 pushBack_Array(&d->layout, &run);
407 } 409 }
408 run.color = colors[type]; 410 run.color = colors[type];
@@ -554,7 +556,7 @@ static void normalize_GmDocument(iGmDocument *d) {
554 appendCStrN_String(normalized, " ", 1); 556 appendCStrN_String(normalized, " ", 1);
555 } 557 }
556 } 558 }
557 else { 559 else if (*ch != '\r') {
558 appendCStrN_String(normalized, ch, 1); 560 appendCStrN_String(normalized, ch, 1);
559 } 561 }
560 } 562 }
@@ -573,6 +575,7 @@ static void normalize_GmDocument(iGmDocument *d) {
573 iBool isPrevSpace = iFalse; 575 iBool isPrevSpace = iFalse;
574 for (const char *ch = line.start; ch != line.end; ch++) { 576 for (const char *ch = line.start; ch != line.end; ch++) {
575 char c = *ch; 577 char c = *ch;
578 if (c == '\r') continue;
576 if (isNormalizableSpace_(c)) { 579 if (isNormalizableSpace_(c)) {
577 if (isPrevSpace) { 580 if (isPrevSpace) {
578 continue; /* skip repeated spaces */ 581 continue; /* skip repeated spaces */
@@ -738,6 +741,9 @@ uint16_t linkImage_GmDocument(const iGmDocument *d, iGmLinkId linkId) {
738enum iColorId linkColor_GmDocument(const iGmDocument *d, iGmLinkId linkId) { 741enum iColorId linkColor_GmDocument(const iGmDocument *d, iGmLinkId linkId) {
739 const iGmLink *link = link_GmDocument_(d, linkId); 742 const iGmLink *link = link_GmDocument_(d, linkId);
740 if (link) { 743 if (link) {
744 if ((link->flags & supportedProtocol_GmLinkFlag) == 0) {
745 return red_ColorId;
746 }
741 return link->flags & http_GmLinkFlag 747 return link->flags & http_GmLinkFlag
742 ? orange_ColorId 748 ? orange_ColorId
743 : link->flags & gopher_GmLinkFlag ? blue_ColorId : cyan_ColorId; 749 : link->flags & gopher_GmLinkFlag ? blue_ColorId : cyan_ColorId;