1 /* $Id: uri.cc,v 1.6 2004/09/08 16:47:25 atterer Exp $ -*- C++ -*-
3 |_) /| Copyright (C) 2004 | richard@
4 | \/¯| Richard Atterer | atterer.org
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License, version 2. See
8 the file COPYING for details.
18 //______________________________________________________________________
23 <scheme>://<user>:<password>@<host>:<port>/<url-path>
24 Some or all of the parts "<user>:<password>@", ":<password>",
25 ":<port>", and "/<url-path>" may be excluded. */
27 /** Create a new URI from an absolute base URI and a relative URI. (rel can
28 also be absolute, in this case, the result in dest equals rel.) */
29 void uriJoin(string* dest, const string& base, const string& rel) {
30 if (isRealUrl(rel) || base.empty()) {
35 /* Parse base URL. We can assume that that URL is in a valid format, so the
36 url-path starts after the 3rd '/', if that is present */
37 string::size_type hostSlash = base.find('/');
38 if (hostSlash != string::npos) {
39 hostSlash = base.find('/', hostSlash + 1);
40 if (hostSlash != string::npos)
41 hostSlash = base.find('/', hostSlash + 1);
44 if (hostSlash == string::npos) {
45 hostSlash = dest->length();
48 // hostSlash points to the '/' after the hostname
50 // Remove leafname from dest
51 string::size_type n = dest->find_last_of('/');
54 string::size_type r = 0; // Offset from which onward to append rel to dest
55 if (rel.length() > 0 && rel[0] == '/') {
56 // rel is server-absolute
57 dest->erase(hostSlash + 1);
61 // Scan through rel, applying path components to dest
62 while (r < rel.length()) {
63 //debug("url='%1', rel='%2'", *dest, rel.c_str() + r);
64 if (compat_compare(rel, r, 2, "./", 2) == 0) {
66 } else if (compat_compare(rel, r, 3, "../", 3) == 0) {
69 string::size_type n = dest->length() - 1;
70 Assert((*dest)[n] == '/');
71 n = dest->rfind('/', n - 1);
72 if (n != string::npos && n >= hostSlash)
75 string::size_type n = rel.find('/', r);
76 if (n != string::npos) ++n; else n = rel.length();
77 //debug("%1 %2 %3", rel, r, n);
78 dest->append(rel, r, n - r);
83 //______________________________________________________________________
85 unsigned findLabelColon(const string& s) {
86 string::const_iterator i = s.begin(), e = s.end();
88 if (*i == '/' || static_cast<unsigned char>(*i) <= ' ') return 0;
89 if (*i == ':') return i - s.begin();
94 //______________________________________________________________________
96 bool isRealUrl(const string& s) {
97 unsigned l = findLabelColon(s);
98 return l > 0 && s.length() >= l + 3 && s[l + 1] == '/' && s[l + 2] == '/';
100 //______________________________________________________________________
102 bool isLabelUrl(const string& s) {
103 unsigned l = findLabelColon(s);
104 return l > 0 && s.length() >= l + 3 && s[l + 1] != '/' && s[l + 2] != '/';