summaryrefslogtreecommitdiff
path: root/src/gmutil.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/gmutil.c')
-rw-r--r--src/gmutil.c26
1 files changed, 23 insertions, 3 deletions
diff --git a/src/gmutil.c b/src/gmutil.c
index 4b144097..52fe6b28 100644
--- a/src/gmutil.c
+++ b/src/gmutil.c
@@ -27,6 +27,14 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */
27#include <the_Foundation/path.h> 27#include <the_Foundation/path.h>
28 28
29void init_Url(iUrl *d, const iString *text) { 29void init_Url(iUrl *d, const iString *text) {
30 /* Handle "file:" as a special case since it only has the path part. */
31 if (startsWithCase_String(text, "file://")) {
32 iZap(*d);
33 const char *cstr = constBegin_String(text);
34 d->scheme = (iRangecc){ cstr, cstr + 4 };
35 d->path = (iRangecc){ cstr + 7, constEnd_String(text) };
36 return;
37 }
30 static iRegExp *absoluteUrlPattern_; 38 static iRegExp *absoluteUrlPattern_;
31 static iRegExp *relativeUrlPattern_; 39 static iRegExp *relativeUrlPattern_;
32 if (!absoluteUrlPattern_) { 40 if (!absoluteUrlPattern_) {
@@ -98,8 +106,11 @@ void cleanUrlPath_String(iString *d) {
98 else if (equal_Rangecc(seg, ".")) { 106 else if (equal_Rangecc(seg, ".")) {
99 /* Skip it. */ 107 /* Skip it. */
100 } 108 }
101 else { 109 else if (!isEmpty_Range(&seg)) {
102 appendCStr_String(&clean, "/"); 110 /* Ensure the cleaned path starts with a slash if the original does. */
111 if (!isEmpty_String(&clean) || startsWith_Rangecc(parts.path, "/")) {
112 appendCStr_String(&clean, "/");
113 }
103 appendRange_String(&clean, seg); 114 appendRange_String(&clean, seg);
104 } 115 }
105 } 116 }
@@ -127,6 +138,10 @@ iRangecc urlHost_String(const iString *d) {
127 return url.host; 138 return url.host;
128} 139}
129 140
141static iBool isAbsolutePath_(iRangecc path) {
142 return isAbsolute_Path(collect_String(urlDecode_String(collect_String(newRange_String(path)))));
143}
144
130const iString *absoluteUrl_String(const iString *d, const iString *urlMaybeRelative) { 145const iString *absoluteUrl_String(const iString *d, const iString *urlMaybeRelative) {
131 iUrl orig; 146 iUrl orig;
132 iUrl rel; 147 iUrl rel;
@@ -155,7 +170,7 @@ const iString *absoluteUrl_String(const iString *d, const iString *urlMaybeRelat
155 appendRange_String(absolute, selHost->port); 170 appendRange_String(absolute, selHost->port);
156 } 171 }
157 } 172 }
158 if (isDef_(rel.scheme) || isDef_(rel.host) || startsWith_Rangecc(rel.path, "/")) { 173 if (isDef_(rel.scheme) || isDef_(rel.host) || isAbsolutePath_(rel.path)) {
159 appendRange_String(absolute, isDef_(rel.path) ? rel.path : range_CStr("/")); /* absolute path */ 174 appendRange_String(absolute, isDef_(rel.path) ? rel.path : range_CStr("/")); /* absolute path */
160 } 175 }
161 else { 176 else {
@@ -180,10 +195,15 @@ const iString *absoluteUrl_String(const iString *d, const iString *urlMaybeRelat
180iString *makeFileUrl_String(const iString *localFilePath) { 195iString *makeFileUrl_String(const iString *localFilePath) {
181 iString *url = cleaned_Path(localFilePath); 196 iString *url = cleaned_Path(localFilePath);
182 replace_Block(&url->chars, '\\', '/'); /* in case it's a Windows path */ 197 replace_Block(&url->chars, '\\', '/'); /* in case it's a Windows path */
198 set_String(url, collect_String(urlEncodeExclude_String(url, "/")));
183 prependCStr_String(url, "file://"); 199 prependCStr_String(url, "file://");
184 return url; 200 return url;
185} 201}
186 202
203const char *makeFileUrl_CStr(const char *localFilePath) {
204 return cstrCollect_String(makeFileUrl_String(collectNewCStr_String(localFilePath)));
205}
206
187void urlEncodeSpaces_String(iString *d) { 207void urlEncodeSpaces_String(iString *d) {
188 for (;;) { 208 for (;;) {
189 const size_t pos = indexOfCStr_String(d, " "); 209 const size_t pos = indexOfCStr_String(d, " ");