diff options
author | Jaakko Keränen <jaakko.keranen@iki.fi> | 2020-07-29 20:08:27 +0300 |
---|---|---|
committer | Jaakko Keränen <jaakko.keranen@iki.fi> | 2020-07-29 20:08:27 +0300 |
commit | b49f40e2e2a54db326d28a4cf4c9257f831cf782 (patch) | |
tree | 3cad6698b69773171d338c6dc6c6163ae5a97077 /src | |
parent | d9c45cc1d143ce806a28502c31e8ec0eace09d97 (diff) |
Utility for making absolute URLs
Diffstat (limited to 'src')
-rw-r--r-- | src/gmutil.c | 53 | ||||
-rw-r--r-- | src/gmutil.h | 5 | ||||
-rw-r--r-- | src/ui/documentwidget.c | 61 |
3 files changed, 60 insertions, 59 deletions
diff --git a/src/gmutil.c b/src/gmutil.c index 1a8d469f..af090574 100644 --- a/src/gmutil.c +++ b/src/gmutil.c | |||
@@ -32,6 +32,59 @@ void init_Url(iUrl *d, const iString *text) { | |||
32 | iRelease(absPat); | 32 | iRelease(absPat); |
33 | } | 33 | } |
34 | 34 | ||
35 | static iRangecc dirPath_(iRangecc path) { | ||
36 | const size_t pos = lastIndexOfCStr_Rangecc(&path, "/"); | ||
37 | if (pos == iInvalidPos) return path; | ||
38 | return (iRangecc){ path.start, path.start + pos }; | ||
39 | } | ||
40 | |||
41 | const iString *absoluteUrl_String(const iString *d, const iString *urlMaybeRelative) { | ||
42 | if (indexOfCStr_String(urlMaybeRelative, "://") != iInvalidPos) { | ||
43 | /* Already absolute. */ | ||
44 | return urlMaybeRelative; | ||
45 | } | ||
46 | iUrl parts; | ||
47 | init_Url(&parts, d); | ||
48 | iString *absolute = new_String(); | ||
49 | appendRange_String(absolute, parts.protocol); | ||
50 | appendCStr_String(absolute, "://"); | ||
51 | appendRange_String(absolute, parts.host); | ||
52 | if (!isEmpty_Range(&parts.port)) { | ||
53 | appendCStr_String(absolute, ":"); | ||
54 | appendRange_String(absolute, parts.port); | ||
55 | } | ||
56 | if (startsWith_String(urlMaybeRelative, "/")) { | ||
57 | append_String(absolute, urlMaybeRelative); | ||
58 | } | ||
59 | else { | ||
60 | iRangecc relPath = range_String(urlMaybeRelative); | ||
61 | iRangecc dir = dirPath_(parts.path); | ||
62 | for (;;) { | ||
63 | if (equal_Rangecc(&relPath, ".")) { | ||
64 | relPath.start++; | ||
65 | } | ||
66 | else if (startsWith_Rangecc(&relPath, "./")) { | ||
67 | relPath.start += 2; | ||
68 | } | ||
69 | else if (equal_Rangecc(&relPath, "..")) { | ||
70 | relPath.start += 2; | ||
71 | dir = dirPath_(dir); | ||
72 | } | ||
73 | else if (startsWith_Rangecc(&relPath, "../")) { | ||
74 | relPath.start += 3; | ||
75 | dir = dirPath_(dir); | ||
76 | } | ||
77 | else break; | ||
78 | } | ||
79 | appendRange_String(absolute, dir); | ||
80 | if (!endsWith_String(absolute, "/")) { | ||
81 | appendCStr_String(absolute, "/"); | ||
82 | } | ||
83 | appendRange_String(absolute, relPath); | ||
84 | } | ||
85 | return collect_String(absolute); | ||
86 | } | ||
87 | |||
35 | void urlEncodeSpaces_String(iString *d) { | 88 | void urlEncodeSpaces_String(iString *d) { |
36 | for (;;) { | 89 | for (;;) { |
37 | const size_t pos = indexOfCStr_String(d, " "); | 90 | const size_t pos = indexOfCStr_String(d, " "); |
diff --git a/src/gmutil.h b/src/gmutil.h index 41711af7..4a1fdee9 100644 --- a/src/gmutil.h +++ b/src/gmutil.h | |||
@@ -13,6 +13,7 @@ struct Impl_Url { | |||
13 | iRangecc query; | 13 | iRangecc query; |
14 | }; | 14 | }; |
15 | 15 | ||
16 | void init_Url (iUrl *, const iString *text); | 16 | void init_Url (iUrl *, const iString *text); |
17 | 17 | ||
18 | void urlEncodeSpaces_String (iString *); | 18 | const iString * absoluteUrl_String (const iString *, const iString *urlMaybeRelative); |
19 | void urlEncodeSpaces_String (iString *); | ||
diff --git a/src/ui/documentwidget.c b/src/ui/documentwidget.c index 52628143..07761aa7 100644 --- a/src/ui/documentwidget.c +++ b/src/ui/documentwidget.c | |||
@@ -409,59 +409,6 @@ static void scrollTo_DocumentWidget_(iDocumentWidget *d, int documentY) { | |||
409 | scroll_DocumentWidget_(d, 0); /* clamp it */ | 409 | scroll_DocumentWidget_(d, 0); /* clamp it */ |
410 | } | 410 | } |
411 | 411 | ||
412 | static iRangecc dirPath_(iRangecc path) { | ||
413 | const size_t pos = lastIndexOfCStr_Rangecc(&path, "/"); | ||
414 | if (pos == iInvalidPos) return path; | ||
415 | return (iRangecc){ path.start, path.start + pos }; | ||
416 | } | ||
417 | |||
418 | static const iString *absoluteUrl_DocumentWidget_(const iDocumentWidget *d, const iString *url) { | ||
419 | if (indexOfCStr_String(url, "://") != iInvalidPos) { | ||
420 | /* Already absolute. */ | ||
421 | return url; | ||
422 | } | ||
423 | iUrl parts; | ||
424 | init_Url(&parts, d->url); | ||
425 | iString *absolute = new_String(); | ||
426 | appendRange_String(absolute, parts.protocol); | ||
427 | appendCStr_String(absolute, "://"); | ||
428 | appendRange_String(absolute, parts.host); | ||
429 | if (!isEmpty_Range(&parts.port)) { | ||
430 | appendCStr_String(absolute, ":"); | ||
431 | appendRange_String(absolute, parts.port); | ||
432 | } | ||
433 | if (startsWith_String(url, "/")) { | ||
434 | append_String(absolute, url); | ||
435 | } | ||
436 | else { | ||
437 | iRangecc relPath = range_String(url); | ||
438 | iRangecc dir = dirPath_(parts.path); | ||
439 | for (;;) { | ||
440 | if (equal_Rangecc(&relPath, ".")) { | ||
441 | relPath.start++; | ||
442 | } | ||
443 | else if (startsWith_Rangecc(&relPath, "./")) { | ||
444 | relPath.start += 2; | ||
445 | } | ||
446 | else if (equal_Rangecc(&relPath, "..")) { | ||
447 | relPath.start += 2; | ||
448 | dir = dirPath_(dir); | ||
449 | } | ||
450 | else if (startsWith_Rangecc(&relPath, "../")) { | ||
451 | relPath.start += 3; | ||
452 | dir = dirPath_(dir); | ||
453 | } | ||
454 | else break; | ||
455 | } | ||
456 | appendRange_String(absolute, dir); | ||
457 | if (!endsWith_String(absolute, "/")) { | ||
458 | appendCStr_String(absolute, "/"); | ||
459 | } | ||
460 | appendRange_String(absolute, relPath); | ||
461 | } | ||
462 | return collect_String(absolute); | ||
463 | } | ||
464 | |||
465 | static void checkResponseCode_DocumentWidget_(iDocumentWidget *d) { | 412 | static void checkResponseCode_DocumentWidget_(iDocumentWidget *d) { |
466 | if (!d->request) { | 413 | if (!d->request) { |
467 | return; | 414 | return; |
@@ -542,7 +489,7 @@ static iBool requestMedia_DocumentWidget_(iDocumentWidget *d, iGmLinkId linkId) | |||
542 | pushBack_ObjectList( | 489 | pushBack_ObjectList( |
543 | d->media, | 490 | d->media, |
544 | iClob(new_MediaRequest( | 491 | iClob(new_MediaRequest( |
545 | d, linkId, absoluteUrl_DocumentWidget_(d, linkUrl_GmDocument(d->doc, linkId))))); | 492 | d, linkId, absoluteUrl_String(d->url, linkUrl_GmDocument(d->doc, linkId))))); |
546 | return iTrue; | 493 | return iTrue; |
547 | } | 494 | } |
548 | return iFalse; | 495 | return iFalse; |
@@ -605,7 +552,7 @@ static iBool processEvent_DocumentWidget_(iDocumentWidget *d, const SDL_Event *e | |||
605 | else if (isCommand_Widget(w, ev, "document.copylink")) { | 552 | else if (isCommand_Widget(w, ev, "document.copylink")) { |
606 | if (d->hoverLink) { | 553 | if (d->hoverLink) { |
607 | SDL_SetClipboardText(cstr_String( | 554 | SDL_SetClipboardText(cstr_String( |
608 | absoluteUrl_DocumentWidget_(d, linkUrl_GmDocument(d->doc, d->hoverLink->linkId)))); | 555 | absoluteUrl_String(d->url, linkUrl_GmDocument(d->doc, d->hoverLink->linkId)))); |
609 | } | 556 | } |
610 | else { | 557 | else { |
611 | SDL_SetClipboardText(cstr_String(d->url)); | 558 | SDL_SetClipboardText(cstr_String(d->url)); |
@@ -820,8 +767,8 @@ static iBool processEvent_DocumentWidget_(iDocumentWidget *d, const SDL_Event *e | |||
820 | } | 767 | } |
821 | else { | 768 | else { |
822 | postCommandf_App("open url:%s", | 769 | postCommandf_App("open url:%s", |
823 | cstr_String(absoluteUrl_DocumentWidget_( | 770 | cstr_String(absoluteUrl_String( |
824 | d, linkUrl_GmDocument(d->doc, linkId)))); | 771 | d->url, linkUrl_GmDocument(d->doc, linkId)))); |
825 | } | 772 | } |
826 | } | 773 | } |
827 | if (d->selectMark.start) { | 774 | if (d->selectMark.start) { |