Skip to content

Commit

Permalink
url: warn when operation requires ICU
Browse files Browse the repository at this point in the history
Continuation of: nodejs#35099

Signed-off-by: Darshan Sen <[email protected]>
  • Loading branch information
RaisinTen committed May 23, 2021
1 parent 7afa7b9 commit e31fd7a
Show file tree
Hide file tree
Showing 2 changed files with 36 additions and 18 deletions.
51 changes: 34 additions & 17 deletions src/node_url.cc
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
#include "node_errors.h"
#include "node_external_reference.h"
#include "node_i18n.h"
#include "node_process.h" // TODO: Replace with node_process-inl.h
#include "util-inl.h"

#include <cmath>
Expand Down Expand Up @@ -56,7 +57,8 @@ class URLHost {
void ParseIPv4Host(const char* input, size_t length, bool* is_ipv4);
void ParseIPv6Host(const char* input, size_t length);
void ParseOpaqueHost(const char* input, size_t length);
void ParseHost(const char* input,
void ParseHost(Environment* env,
const char* input,
size_t length,
bool is_special,
bool unicode = false);
Expand Down Expand Up @@ -767,15 +769,19 @@ bool StartsWithWindowsDriveLetter(const char* p, const char* end) {
}

#if defined(NODE_HAVE_I18N_SUPPORT)
bool ToUnicode(const std::string& input, std::string* output) {
bool ToUnicode(Environment* env,
const std::string& input,
std::string* output) {
MaybeStackBuffer<char> buf;
if (i18n::ToUnicode(&buf, input.c_str(), input.length()) < 0)
return false;
output->assign(*buf, buf.length());
return true;
}

bool ToASCII(const std::string& input, std::string* output) {
bool ToASCII(Environment* env,
const std::string& input,
std::string* output) {
MaybeStackBuffer<char> buf;
if (i18n::ToASCII(&buf, input.c_str(), input.length()) < 0)
return false;
Expand All @@ -786,12 +792,20 @@ bool ToASCII(const std::string& input, std::string* output) {
}
#else
// Intentional non-ops if ICU is not present.
bool ToUnicode(const std::string& input, std::string* output) {
bool ToUnicode(Environment* env,
const std::string& input,
std::string* output) {
ProcessEmitWarning(env,
"Cannot convert to unicode when intl is disabled");
*output = input;
return true;
}

bool ToASCII(const std::string& input, std::string* output) {
bool ToASCII(Environment* env,
const std::string& input,
std::string* output) {
ProcessEmitWarning(env,
"Cannot convert to ASCII when intl is disabled");
*output = input;
return true;
}
Expand Down Expand Up @@ -1022,7 +1036,8 @@ void URLHost::ParseOpaqueHost(const char* input, size_t length) {
SetOpaque(std::move(output));
}

void URLHost::ParseHost(const char* input,
void URLHost::ParseHost(Environment* env,
const char* input,
size_t length,
bool is_special,
bool unicode) {
Expand All @@ -1045,7 +1060,7 @@ void URLHost::ParseHost(const char* input,
std::string decoded = PercentDecode(input, length);

// Then we have to punycode toASCII
if (!ToASCII(decoded, &decoded))
if (!ToASCII(env, decoded, &decoded))
return;

// If any of the following characters are still present, we have to fail
Expand All @@ -1063,7 +1078,7 @@ void URLHost::ParseHost(const char* input,
return;

// If the unicode flag is set, run the result through punycode ToUnicode
if (unicode && !ToUnicode(decoded, &decoded))
if (unicode && !ToUnicode(env, decoded, &decoded))
return;

// It's not an IPv4 or IPv6 address, it must be a domain
Expand Down Expand Up @@ -1169,7 +1184,8 @@ std::string URLHost::ToString() const {
return dest;
}

bool ParseHost(const std::string& input,
bool ParseHost(Environment* env,
const std::string& input,
std::string* output,
bool is_special,
bool unicode = false) {
Expand All @@ -1178,7 +1194,7 @@ bool ParseHost(const std::string& input,
return true;
}
URLHost host;
host.ParseHost(input.c_str(), input.length(), is_special, unicode);
host.ParseHost(env, input.c_str(), input.length(), is_special, unicode);
if (host.ParsingFailed())
return false;
*output = host.ToStringMove();
Expand Down Expand Up @@ -1767,7 +1783,7 @@ void URL::Parse(const char* input,
return;
}
url->flags |= URL_FLAGS_HAS_HOST;
if (!ParseHost(buffer, &url->host, special)) {
if (!ParseHost(env_, buffer, &url->host, special)) {
url->flags |= URL_FLAGS_FAILED;
return;
}
Expand All @@ -1794,7 +1810,7 @@ void URL::Parse(const char* input,
return;
}
url->flags |= URL_FLAGS_HAS_HOST;
if (!ParseHost(buffer, &url->host, special)) {
if (!ParseHost(env_, buffer, &url->host, special)) {
url->flags |= URL_FLAGS_FAILED;
return;
}
Expand Down Expand Up @@ -1962,7 +1978,7 @@ void URL::Parse(const char* input,
state = kPathStart;
} else {
std::string host;
if (!ParseHost(buffer, &host, special)) {
if (!ParseHost(env_, buffer, &host, special)) {
url->flags |= URL_FLAGS_FAILED;
return;
}
Expand Down Expand Up @@ -2298,7 +2314,7 @@ void DomainToASCII(const FunctionCallbackInfo<Value>& args) {

URLHost host;
// Assuming the host is used for a special scheme.
host.ParseHost(*value, value.length(), true);
host.ParseHost(env, *value, value.length(), true);
if (host.ParsingFailed()) {
args.GetReturnValue().Set(FIXED_ONE_BYTE_STRING(env->isolate(), ""));
return;
Expand All @@ -2316,7 +2332,7 @@ void DomainToUnicode(const FunctionCallbackInfo<Value>& args) {

URLHost host;
// Assuming the host is used for a special scheme.
host.ParseHost(*value, value.length(), true, true);
host.ParseHost(env, *value, value.length(), true, true);
if (host.ParsingFailed()) {
args.GetReturnValue().Set(FIXED_ONE_BYTE_STRING(env->isolate(), ""));
return;
Expand Down Expand Up @@ -2406,7 +2422,7 @@ std::string URL::ToFilePath() const {
if ((context_.flags & URL_FLAGS_HAS_HOST) &&
context_.host.length() > 0) {
std::string unicode_host;
if (!ToUnicode(context_.host, &unicode_host)) {
if (!ToUnicode(env_, context_.host, &unicode_host)) {
return "";
}
return "\\\\" + unicode_host + decoded_path;
Expand Down Expand Up @@ -2442,7 +2458,8 @@ URL URL::FromFilePath(const std::string& file_path) {
// This function works by calling out to a JS function that creates and
// returns the JS URL object. Be mindful of the JS<->Native boundary
// crossing that is required.
MaybeLocal<Value> URL::ToObject(Environment* env) const {
MaybeLocal<Value> URL::ToObject(Environment* env) {
env_ = env;
Isolate* isolate = env->isolate();
Local<Context> context = env->context();
Context::Scope context_scope(context);
Expand Down
3 changes: 2 additions & 1 deletion src/node_url.h
Original file line number Diff line number Diff line change
Expand Up @@ -173,7 +173,7 @@ class URL {
// Get the file URL from native file system path.
static URL FromFilePath(const std::string& file_path);

v8::MaybeLocal<v8::Value> ToObject(Environment* env) const;
v8::MaybeLocal<v8::Value> ToObject(Environment* env);

URL(const URL&) = default;
URL& operator=(const URL&) = default;
Expand All @@ -183,6 +183,7 @@ class URL {
URL() : URL("") {}

private:
Environment* env_ = nullptr;
struct url_data context_;
};

Expand Down

0 comments on commit e31fd7a

Please sign in to comment.