xref: /aosp_15_r20/external/cronet/url/url_canon_mailtourl.cc (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
1*6777b538SAndroid Build Coastguard Worker // Copyright 2013 The Chromium Authors
2*6777b538SAndroid Build Coastguard Worker // Use of this source code is governed by a BSD-style license that can be
3*6777b538SAndroid Build Coastguard Worker // found in the LICENSE file.
4*6777b538SAndroid Build Coastguard Worker 
5*6777b538SAndroid Build Coastguard Worker // Functions for canonicalizing "mailto:" URLs.
6*6777b538SAndroid Build Coastguard Worker 
7*6777b538SAndroid Build Coastguard Worker #include "url/url_canon.h"
8*6777b538SAndroid Build Coastguard Worker #include "url/url_canon_internal.h"
9*6777b538SAndroid Build Coastguard Worker #include "url/url_file.h"
10*6777b538SAndroid Build Coastguard Worker #include "url/url_parse_internal.h"
11*6777b538SAndroid Build Coastguard Worker 
12*6777b538SAndroid Build Coastguard Worker namespace url {
13*6777b538SAndroid Build Coastguard Worker 
14*6777b538SAndroid Build Coastguard Worker namespace {
15*6777b538SAndroid Build Coastguard Worker 
16*6777b538SAndroid Build Coastguard Worker // Certain characters should be percent-encoded when they appear in the path
17*6777b538SAndroid Build Coastguard Worker // component of a mailto URL, to improve compatibility and mitigate against
18*6777b538SAndroid Build Coastguard Worker // command-injection attacks on mailto handlers. See https://crbug.com/711020.
19*6777b538SAndroid Build Coastguard Worker template <typename UCHAR>
ShouldEncodeMailboxCharacter(UCHAR uch)20*6777b538SAndroid Build Coastguard Worker bool ShouldEncodeMailboxCharacter(UCHAR uch) {
21*6777b538SAndroid Build Coastguard Worker   if (uch < 0x21 ||                              // space & control characters.
22*6777b538SAndroid Build Coastguard Worker       uch > 0x7e ||                              // high-ascii characters.
23*6777b538SAndroid Build Coastguard Worker       uch == 0x22 ||                             // quote.
24*6777b538SAndroid Build Coastguard Worker       uch == 0x3c || uch == 0x3e ||              // angle brackets.
25*6777b538SAndroid Build Coastguard Worker       uch == 0x60 ||                             // backtick.
26*6777b538SAndroid Build Coastguard Worker       uch == 0x7b || uch == 0x7c || uch == 0x7d  // braces and pipe.
27*6777b538SAndroid Build Coastguard Worker       ) {
28*6777b538SAndroid Build Coastguard Worker     return true;
29*6777b538SAndroid Build Coastguard Worker   }
30*6777b538SAndroid Build Coastguard Worker   return false;
31*6777b538SAndroid Build Coastguard Worker }
32*6777b538SAndroid Build Coastguard Worker 
33*6777b538SAndroid Build Coastguard Worker template <typename CHAR, typename UCHAR>
DoCanonicalizeMailtoURL(const URLComponentSource<CHAR> & source,const Parsed & parsed,CanonOutput * output,Parsed * new_parsed)34*6777b538SAndroid Build Coastguard Worker bool DoCanonicalizeMailtoURL(const URLComponentSource<CHAR>& source,
35*6777b538SAndroid Build Coastguard Worker                              const Parsed& parsed,
36*6777b538SAndroid Build Coastguard Worker                              CanonOutput* output,
37*6777b538SAndroid Build Coastguard Worker                              Parsed* new_parsed) {
38*6777b538SAndroid Build Coastguard Worker   // mailto: only uses {scheme, path, query} -- clear the rest.
39*6777b538SAndroid Build Coastguard Worker   new_parsed->username = Component();
40*6777b538SAndroid Build Coastguard Worker   new_parsed->password = Component();
41*6777b538SAndroid Build Coastguard Worker   new_parsed->host = Component();
42*6777b538SAndroid Build Coastguard Worker   new_parsed->port = Component();
43*6777b538SAndroid Build Coastguard Worker   new_parsed->ref = Component();
44*6777b538SAndroid Build Coastguard Worker 
45*6777b538SAndroid Build Coastguard Worker   // Scheme (known, so we don't bother running it through the more
46*6777b538SAndroid Build Coastguard Worker   // complicated scheme canonicalizer).
47*6777b538SAndroid Build Coastguard Worker   new_parsed->scheme.begin = output->length();
48*6777b538SAndroid Build Coastguard Worker   output->Append("mailto:");
49*6777b538SAndroid Build Coastguard Worker   new_parsed->scheme.len = 6;
50*6777b538SAndroid Build Coastguard Worker 
51*6777b538SAndroid Build Coastguard Worker   bool success = true;
52*6777b538SAndroid Build Coastguard Worker 
53*6777b538SAndroid Build Coastguard Worker   // Path
54*6777b538SAndroid Build Coastguard Worker   if (parsed.path.is_valid()) {
55*6777b538SAndroid Build Coastguard Worker     new_parsed->path.begin = output->length();
56*6777b538SAndroid Build Coastguard Worker 
57*6777b538SAndroid Build Coastguard Worker     // Copy the path using path URL's more lax escaping rules.
58*6777b538SAndroid Build Coastguard Worker     // We convert to UTF-8 and escape non-ASCII, but leave most
59*6777b538SAndroid Build Coastguard Worker     // ASCII characters alone.
60*6777b538SAndroid Build Coastguard Worker     size_t end = static_cast<size_t>(parsed.path.end());
61*6777b538SAndroid Build Coastguard Worker     for (size_t i = static_cast<size_t>(parsed.path.begin); i < end; ++i) {
62*6777b538SAndroid Build Coastguard Worker       UCHAR uch = static_cast<UCHAR>(source.path[i]);
63*6777b538SAndroid Build Coastguard Worker       if (ShouldEncodeMailboxCharacter<UCHAR>(uch))
64*6777b538SAndroid Build Coastguard Worker         success &= AppendUTF8EscapedChar(source.path, &i, end, output);
65*6777b538SAndroid Build Coastguard Worker       else
66*6777b538SAndroid Build Coastguard Worker         output->push_back(static_cast<char>(uch));
67*6777b538SAndroid Build Coastguard Worker     }
68*6777b538SAndroid Build Coastguard Worker 
69*6777b538SAndroid Build Coastguard Worker     new_parsed->path.len = output->length() - new_parsed->path.begin;
70*6777b538SAndroid Build Coastguard Worker   } else {
71*6777b538SAndroid Build Coastguard Worker     // No path at all
72*6777b538SAndroid Build Coastguard Worker     new_parsed->path.reset();
73*6777b538SAndroid Build Coastguard Worker   }
74*6777b538SAndroid Build Coastguard Worker 
75*6777b538SAndroid Build Coastguard Worker   // Query -- always use the default UTF8 charset converter.
76*6777b538SAndroid Build Coastguard Worker   CanonicalizeQuery(source.query, parsed.query, NULL,
77*6777b538SAndroid Build Coastguard Worker                     output, &new_parsed->query);
78*6777b538SAndroid Build Coastguard Worker 
79*6777b538SAndroid Build Coastguard Worker   return success;
80*6777b538SAndroid Build Coastguard Worker }
81*6777b538SAndroid Build Coastguard Worker 
82*6777b538SAndroid Build Coastguard Worker } // namespace
83*6777b538SAndroid Build Coastguard Worker 
CanonicalizeMailtoURL(const char * spec,int spec_len,const Parsed & parsed,CanonOutput * output,Parsed * new_parsed)84*6777b538SAndroid Build Coastguard Worker bool CanonicalizeMailtoURL(const char* spec,
85*6777b538SAndroid Build Coastguard Worker                            int spec_len,
86*6777b538SAndroid Build Coastguard Worker                            const Parsed& parsed,
87*6777b538SAndroid Build Coastguard Worker                            CanonOutput* output,
88*6777b538SAndroid Build Coastguard Worker                            Parsed* new_parsed) {
89*6777b538SAndroid Build Coastguard Worker   return DoCanonicalizeMailtoURL<char, unsigned char>(
90*6777b538SAndroid Build Coastguard Worker       URLComponentSource<char>(spec), parsed, output, new_parsed);
91*6777b538SAndroid Build Coastguard Worker }
92*6777b538SAndroid Build Coastguard Worker 
CanonicalizeMailtoURL(const char16_t * spec,int spec_len,const Parsed & parsed,CanonOutput * output,Parsed * new_parsed)93*6777b538SAndroid Build Coastguard Worker bool CanonicalizeMailtoURL(const char16_t* spec,
94*6777b538SAndroid Build Coastguard Worker                            int spec_len,
95*6777b538SAndroid Build Coastguard Worker                            const Parsed& parsed,
96*6777b538SAndroid Build Coastguard Worker                            CanonOutput* output,
97*6777b538SAndroid Build Coastguard Worker                            Parsed* new_parsed) {
98*6777b538SAndroid Build Coastguard Worker   return DoCanonicalizeMailtoURL<char16_t, char16_t>(
99*6777b538SAndroid Build Coastguard Worker       URLComponentSource<char16_t>(spec), parsed, output, new_parsed);
100*6777b538SAndroid Build Coastguard Worker }
101*6777b538SAndroid Build Coastguard Worker 
ReplaceMailtoURL(const char * base,const Parsed & base_parsed,const Replacements<char> & replacements,CanonOutput * output,Parsed * new_parsed)102*6777b538SAndroid Build Coastguard Worker bool ReplaceMailtoURL(const char* base,
103*6777b538SAndroid Build Coastguard Worker                       const Parsed& base_parsed,
104*6777b538SAndroid Build Coastguard Worker                       const Replacements<char>& replacements,
105*6777b538SAndroid Build Coastguard Worker                       CanonOutput* output,
106*6777b538SAndroid Build Coastguard Worker                       Parsed* new_parsed) {
107*6777b538SAndroid Build Coastguard Worker   URLComponentSource<char> source(base);
108*6777b538SAndroid Build Coastguard Worker   Parsed parsed(base_parsed);
109*6777b538SAndroid Build Coastguard Worker   SetupOverrideComponents(base, replacements, &source, &parsed);
110*6777b538SAndroid Build Coastguard Worker   return DoCanonicalizeMailtoURL<char, unsigned char>(
111*6777b538SAndroid Build Coastguard Worker       source, parsed, output, new_parsed);
112*6777b538SAndroid Build Coastguard Worker }
113*6777b538SAndroid Build Coastguard Worker 
ReplaceMailtoURL(const char * base,const Parsed & base_parsed,const Replacements<char16_t> & replacements,CanonOutput * output,Parsed * new_parsed)114*6777b538SAndroid Build Coastguard Worker bool ReplaceMailtoURL(const char* base,
115*6777b538SAndroid Build Coastguard Worker                       const Parsed& base_parsed,
116*6777b538SAndroid Build Coastguard Worker                       const Replacements<char16_t>& replacements,
117*6777b538SAndroid Build Coastguard Worker                       CanonOutput* output,
118*6777b538SAndroid Build Coastguard Worker                       Parsed* new_parsed) {
119*6777b538SAndroid Build Coastguard Worker   RawCanonOutput<1024> utf8;
120*6777b538SAndroid Build Coastguard Worker   URLComponentSource<char> source(base);
121*6777b538SAndroid Build Coastguard Worker   Parsed parsed(base_parsed);
122*6777b538SAndroid Build Coastguard Worker   SetupUTF16OverrideComponents(base, replacements, &utf8, &source, &parsed);
123*6777b538SAndroid Build Coastguard Worker   return DoCanonicalizeMailtoURL<char, unsigned char>(
124*6777b538SAndroid Build Coastguard Worker       source, parsed, output, new_parsed);
125*6777b538SAndroid Build Coastguard Worker }
126*6777b538SAndroid Build Coastguard Worker 
127*6777b538SAndroid Build Coastguard Worker }  // namespace url
128