1 // Copyright 2013 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 // Functions for canonicalizing "filesystem:file:" URLs. 6 7 #include "url/url_canon.h" 8 #include "url/url_canon_internal.h" 9 #include "url/url_file.h" 10 #include "url/url_parse_internal.h" 11 #include "url/url_util.h" 12 #include "url/url_util_internal.h" 13 14 namespace url_canon { 15 16 namespace { 17 18 // We use the URLComponentSource for the outer URL, as it can have replacements, 19 // whereas the inner_url can't, so it uses spec. 20 template<typename CHAR, typename UCHAR> 21 bool DoCanonicalizeFileSystemURL(const CHAR* spec, 22 const URLComponentSource<CHAR>& source, 23 const url_parse::Parsed& parsed, 24 CharsetConverter* charset_converter, 25 CanonOutput* output, 26 url_parse::Parsed* new_parsed) { 27 // filesystem only uses {scheme, path, query, ref} -- clear the rest. 28 new_parsed->username = url_parse::Component(); 29 new_parsed->password = url_parse::Component(); 30 new_parsed->host = url_parse::Component(); 31 new_parsed->port = url_parse::Component(); 32 33 const url_parse::Parsed* inner_parsed = parsed.inner_parsed(); 34 url_parse::Parsed new_inner_parsed; 35 36 // Scheme (known, so we don't bother running it through the more 37 // complicated scheme canonicalizer). 38 new_parsed->scheme.begin = output->length(); 39 output->Append("filesystem:", 11); 40 new_parsed->scheme.len = 10; 41 42 if (!parsed.inner_parsed() || !parsed.inner_parsed()->scheme.is_valid()) 43 return false; 44 45 bool success = true; 46 if (url_util::CompareSchemeComponent(spec, inner_parsed->scheme, 47 url_util::kFileScheme)) { 48 new_inner_parsed.scheme.begin = output->length(); 49 output->Append("file://", 7); 50 new_inner_parsed.scheme.len = 4; 51 success &= CanonicalizePath(spec, inner_parsed->path, output, 52 &new_inner_parsed.path); 53 } else if (url_util::IsStandard(spec, inner_parsed->scheme)) { 54 success = 55 url_canon::CanonicalizeStandardURL(spec, 56 parsed.inner_parsed()->Length(), 57 *parsed.inner_parsed(), 58 charset_converter, output, 59 &new_inner_parsed); 60 } else { 61 // TODO(ericu): The URL is wrong, but should we try to output more of what 62 // we were given? Echoing back filesystem:mailto etc. doesn't seem all that 63 // useful. 64 return false; 65 } 66 // The filesystem type must be more than just a leading slash for validity. 67 success &= parsed.inner_parsed()->path.len > 1; 68 69 success &= CanonicalizePath(source.path, parsed.path, output, 70 &new_parsed->path); 71 72 // Ignore failures for query/ref since the URL can probably still be loaded. 73 CanonicalizeQuery(source.query, parsed.query, charset_converter, 74 output, &new_parsed->query); 75 CanonicalizeRef(source.ref, parsed.ref, output, &new_parsed->ref); 76 if (success) 77 new_parsed->set_inner_parsed(new_inner_parsed); 78 79 return success; 80 } 81 82 } // namespace 83 84 bool CanonicalizeFileSystemURL(const char* spec, 85 int spec_len, 86 const url_parse::Parsed& parsed, 87 CharsetConverter* charset_converter, 88 CanonOutput* output, 89 url_parse::Parsed* new_parsed) { 90 return DoCanonicalizeFileSystemURL<char, unsigned char>( 91 spec, URLComponentSource<char>(spec), parsed, charset_converter, output, 92 new_parsed); 93 } 94 95 bool CanonicalizeFileSystemURL(const base::char16* spec, 96 int spec_len, 97 const url_parse::Parsed& parsed, 98 CharsetConverter* charset_converter, 99 CanonOutput* output, 100 url_parse::Parsed* new_parsed) { 101 return DoCanonicalizeFileSystemURL<base::char16, base::char16>( 102 spec, URLComponentSource<base::char16>(spec), parsed, charset_converter, 103 output, new_parsed); 104 } 105 106 bool ReplaceFileSystemURL(const char* base, 107 const url_parse::Parsed& base_parsed, 108 const Replacements<char>& replacements, 109 CharsetConverter* charset_converter, 110 CanonOutput* output, 111 url_parse::Parsed* new_parsed) { 112 URLComponentSource<char> source(base); 113 url_parse::Parsed parsed(base_parsed); 114 SetupOverrideComponents(base, replacements, &source, &parsed); 115 return DoCanonicalizeFileSystemURL<char, unsigned char>( 116 base, source, parsed, charset_converter, output, new_parsed); 117 } 118 119 bool ReplaceFileSystemURL(const char* base, 120 const url_parse::Parsed& base_parsed, 121 const Replacements<base::char16>& replacements, 122 CharsetConverter* charset_converter, 123 CanonOutput* output, 124 url_parse::Parsed* new_parsed) { 125 RawCanonOutput<1024> utf8; 126 URLComponentSource<char> source(base); 127 url_parse::Parsed parsed(base_parsed); 128 SetupUTF16OverrideComponents(base, replacements, &utf8, &source, &parsed); 129 return DoCanonicalizeFileSystemURL<char, unsigned char>( 130 base, source, parsed, charset_converter, output, new_parsed); 131 } 132 133 } // namespace url_canon 134