| 113 | } |
| 114 | |
| 115 | static char *url_normalize_1(const char *url, struct url_info *out_info, char allow_globs) |
| 116 | { |
| 117 | /* |
| 118 | * Normalize NUL-terminated url using the following rules: |
| 119 | * |
| 120 | * 1. Case-insensitive parts of url will be converted to lower case |
| 121 | * 2. %-encoded characters that do not need to be will be unencoded |
| 122 | * 3. Characters that are not %-encoded and must be will be encoded |
| 123 | * 4. All %-encodings will be converted to upper case hexadecimal |
| 124 | * 5. Leading 0s are removed from port numbers |
| 125 | * 6. If the default port for the scheme is given it will be removed |
| 126 | * 7. A path part (including empty) not starting with '/' has one added |
| 127 | * 8. Any dot segments (. or ..) in the path are resolved and removed |
| 128 | * 9. IPv6 host literals are allowed (but not normalized or validated) |
| 129 | * |
| 130 | * The rules are based on information in RFC 3986. |
| 131 | * |
| 132 | * Please note this function requires a full URL including a scheme |
| 133 | * and host part (except for file: URLs which may have an empty host). |
| 134 | * |
| 135 | * The return value is a newly allocated string that must be freed |
| 136 | * or NULL if the url is not valid. |
| 137 | * |
| 138 | * If out_info is non-NULL, the url and err fields therein will always |
| 139 | * be set. If a non-NULL value is returned, it will be stored in |
| 140 | * out_info->url as well, out_info->err will be set to NULL and the |
| 141 | * other fields of *out_info will also be filled in. If a NULL value |
| 142 | * is returned, NULL will be stored in out_info->url and out_info->err |
| 143 | * will be set to a brief, translated, error message, but no other |
| 144 | * fields will be filled in. |
| 145 | * |
| 146 | * This is NOT a URL validation function. Full URL validation is NOT |
| 147 | * performed. Some invalid host names are passed through this function |
| 148 | * undetected. However, most all other problems that make a URL invalid |
| 149 | * will be detected (including a missing host for non file: URLs). |
| 150 | */ |
| 151 | |
| 152 | size_t url_len = strlen(url); |
| 153 | struct strbuf norm; |
| 154 | size_t spanned; |
| 155 | size_t scheme_len, user_off=0, user_len=0, passwd_off=0, passwd_len=0; |
| 156 | size_t host_off=0, host_len=0, port_off=0, port_len=0, path_off, path_len, result_len; |
| 157 | const char *slash_ptr, *at_ptr, *colon_ptr, *path_start; |
| 158 | char *result; |
| 159 | |
| 160 | /* |
| 161 | * Copy lowercased scheme and :// suffix, %-escapes are not allowed |
| 162 | * First character of scheme must be URL_ALPHA |
| 163 | */ |
| 164 | spanned = strspn(url, URL_SCHEME_CHARS); |
| 165 | if (!spanned || !isalpha(url[0]) || spanned + 3 > url_len || |
| 166 | url[spanned] != ':' || url[spanned+1] != '/' || url[spanned+2] != '/') { |
| 167 | if (out_info) { |
| 168 | out_info->url = NULL; |
| 169 | out_info->err = _("invalid URL scheme name or missing '://' suffix"); |
| 170 | } |
| 171 | return NULL; /* Bad scheme and/or missing "://" part */ |
| 172 | } |
no test coverage detected