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.
5 #include "storage/common/database/database_identifier.h"
7 #include "base/strings/string_number_conversions.h"
8 #include "base/strings/string_util.h"
9 #include "url/url_canon.h"
14 std::string
GetIdentifierFromOrigin(const GURL
& origin
) {
15 return DatabaseIdentifier::CreateFromOrigin(origin
).ToString();
19 GURL
GetOriginFromIdentifier(const std::string
& identifier
) {
20 return DatabaseIdentifier::Parse(identifier
).ToOrigin();
23 static bool SchemeIsUnique(const std::string
& scheme
) {
24 return scheme
== "about" || scheme
== "data" || scheme
== "javascript";
28 const DatabaseIdentifier
DatabaseIdentifier::UniqueFileIdentifier() {
29 return DatabaseIdentifier("", "", 0, true, true);
33 DatabaseIdentifier
DatabaseIdentifier::CreateFromOrigin(const GURL
& origin
) {
34 if (!origin
.is_valid() || origin
.is_empty() ||
35 !origin
.IsStandard() || SchemeIsUnique(origin
.scheme()))
36 return DatabaseIdentifier();
38 if (origin
.SchemeIsFile())
39 return UniqueFileIdentifier();
41 int port
= origin
.IntPort();
42 if (port
== url::PORT_INVALID
)
43 return DatabaseIdentifier();
45 // We encode the default port for the specified scheme as 0. GURL
46 // canonicalizes this as an unspecified port.
47 if (port
== url::PORT_UNSPECIFIED
)
50 return DatabaseIdentifier(origin
.scheme(),
58 DatabaseIdentifier
DatabaseIdentifier::Parse(const std::string
& identifier
) {
59 if (!base::IsStringASCII(identifier
))
60 return DatabaseIdentifier();
61 if (identifier
.find("..") != std::string::npos
)
62 return DatabaseIdentifier();
63 char forbidden
[] = {'\\', '/', ':' ,'\0'};
64 if (identifier
.find_first_of(forbidden
, 0, arraysize(forbidden
)) !=
66 return DatabaseIdentifier();
69 size_t first_underscore
= identifier
.find_first_of('_');
70 if (first_underscore
== std::string::npos
|| first_underscore
== 0)
71 return DatabaseIdentifier();
73 size_t last_underscore
= identifier
.find_last_of('_');
74 if (last_underscore
== std::string::npos
||
75 last_underscore
== first_underscore
||
76 last_underscore
== identifier
.length() - 1)
77 return DatabaseIdentifier();
79 std::string
scheme(identifier
.data(), first_underscore
);
81 return UniqueFileIdentifier();
83 // This magical set of schemes is always treated as unique.
84 if (SchemeIsUnique(scheme
))
85 return DatabaseIdentifier();
87 base::StringPiece
port_str(identifier
.begin() + last_underscore
+ 1,
90 if (!base::StringToInt(port_str
, &port
) || port
< 0 || port
>= 1 << 16)
91 return DatabaseIdentifier();
93 std::string
hostname(identifier
.data() + first_underscore
+ 1,
94 last_underscore
- first_underscore
- 1);
95 GURL
url(scheme
+ "://" + hostname
+ "/");
97 if (!url
.IsStandard())
100 // If a url doesn't parse cleanly or doesn't round trip, reject it.
101 if (!url
.is_valid() || url
.scheme() != scheme
|| url
.host() != hostname
)
102 return DatabaseIdentifier();
104 return DatabaseIdentifier(scheme
, hostname
, port
, false /* unique */, false);
107 DatabaseIdentifier::DatabaseIdentifier()
113 DatabaseIdentifier::DatabaseIdentifier(const std::string
& scheme
,
114 const std::string
& hostname
,
119 hostname_(base::StringToLowerASCII(hostname
)),
121 is_unique_(is_unique
),
125 DatabaseIdentifier::~DatabaseIdentifier() {}
127 std::string
DatabaseIdentifier::ToString() const {
132 return scheme_
+ "_" + hostname_
+ "_" + base::IntToString(port_
);
135 GURL
DatabaseIdentifier::ToOrigin() const {
137 return GURL("file:///");
141 return GURL(scheme_
+ "://" + hostname_
);
142 return GURL(scheme_
+ "://" + hostname_
+ ":" + base::IntToString(port_
));
145 } // namespace storage