%PDF- %PDF-
Direktori : /home2/vacivi36/vittasync.vacivitta.com.br/vittasync/node/src/ |
Current File : //home2/vacivi36/vittasync.vacivitta.com.br/vittasync/node/src/node_dotenv.cc |
#include "node_dotenv.h" #include <regex> // NOLINT(build/c++11) #include <unordered_set> #include "env-inl.h" #include "node_file.h" #include "uv.h" namespace node { using v8::Local; using v8::NewStringType; using v8::Object; using v8::String; /** * The inspiration for this implementation comes from the original dotenv code, * available at https://github.com/motdotla/dotenv */ const std::regex LINE( "\\s*(?:export\\s+)?([\\w.-]+)(?:\\s*=\\s*?|:\\s+?)(\\s*'(?:\\\\'|[^']" ")*'|\\s*\"(?:\\\\\"|[^\"])*\"|\\s*`(?:\\\\`|[^`])*`|[^#\r\n]+)?\\s*(?" ":#.*)?"); // NOLINT(whitespace/line_length) std::vector<std::string> Dotenv::GetPathFromArgs( const std::vector<std::string>& args) { const auto find_match = [](const std::string& arg) { const std::string_view flag = "--env-file"; return strncmp(arg.c_str(), flag.data(), flag.size()) == 0; }; std::vector<std::string> paths; auto path = std::find_if(args.begin(), args.end(), find_match); while (path != args.end()) { auto equal_char = path->find('='); if (equal_char != std::string::npos) { paths.push_back(path->substr(equal_char + 1)); } else { auto next_path = std::next(path); if (next_path == args.end()) { return paths; } paths.push_back(*next_path); } path = std::find_if(++path, args.end(), find_match); } return paths; } void Dotenv::SetEnvironment(node::Environment* env) { if (store_.empty()) { return; } auto isolate = env->isolate(); for (const auto& entry : store_) { auto key = entry.first; auto value = entry.second; auto existing = env->env_vars()->Get(key.data()); if (existing.IsNothing()) { env->env_vars()->Set( isolate, v8::String::NewFromUtf8( isolate, key.data(), NewStringType::kNormal, key.size()) .ToLocalChecked(), v8::String::NewFromUtf8( isolate, value.data(), NewStringType::kNormal, value.size()) .ToLocalChecked()); } } } Local<Object> Dotenv::ToObject(Environment* env) { Local<Object> result = Object::New(env->isolate()); for (const auto& entry : store_) { auto key = entry.first; auto value = entry.second; result ->Set( env->context(), v8::String::NewFromUtf8( env->isolate(), key.data(), NewStringType::kNormal, key.size()) .ToLocalChecked(), v8::String::NewFromUtf8(env->isolate(), value.data(), NewStringType::kNormal, value.size()) .ToLocalChecked()) .Check(); } return result; } void Dotenv::ParseContent(const std::string_view content) { std::string lines = std::string(content); lines = std::regex_replace(lines, std::regex("\r\n?"), "\n"); std::smatch match; while (std::regex_search(lines, match, LINE)) { const std::string key = match[1].str(); // Default undefined or null to an empty string std::string value = match[2].str(); // Remove leading whitespaces value.erase(0, value.find_first_not_of(" \t")); // Remove trailing whitespaces if (!value.empty()) { value.erase(value.find_last_not_of(" \t") + 1); } if (!value.empty() && value.front() == '"') { value = std::regex_replace(value, std::regex("\\\\n"), "\n"); value = std::regex_replace(value, std::regex("\\\\r"), "\r"); } // Remove surrounding quotes value = trim_quotes(value); store_.insert_or_assign(std::string(key), value); lines = match.suffix(); } } Dotenv::ParseResult Dotenv::ParsePath(const std::string_view path) { uv_fs_t req; auto defer_req_cleanup = OnScopeLeave([&req]() { uv_fs_req_cleanup(&req); }); uv_file file = uv_fs_open(nullptr, &req, path.data(), 0, 438, nullptr); if (req.result < 0) { // req will be cleaned up by scope leave. return ParseResult::FileError; } uv_fs_req_cleanup(&req); auto defer_close = OnScopeLeave([file]() { uv_fs_t close_req; CHECK_EQ(0, uv_fs_close(nullptr, &close_req, file, nullptr)); uv_fs_req_cleanup(&close_req); }); std::string result{}; char buffer[8192]; uv_buf_t buf = uv_buf_init(buffer, sizeof(buffer)); while (true) { auto r = uv_fs_read(nullptr, &req, file, &buf, 1, -1, nullptr); if (req.result < 0) { // req will be cleaned up by scope leave. return ParseResult::InvalidContent; } uv_fs_req_cleanup(&req); if (r <= 0) { break; } result.append(buf.base, r); } ParseContent(result); return ParseResult::Valid; } void Dotenv::AssignNodeOptionsIfAvailable(std::string* node_options) { auto match = store_.find("NODE_OPTIONS"); if (match != store_.end()) { *node_options = match->second; } } std::string_view Dotenv::trim_quotes(std::string_view str) { static const std::unordered_set<char> quotes = {'"', '\'', '`'}; if (str.size() >= 2 && quotes.count(str.front()) && quotes.count(str.back())) { str = str.substr(1, str.size() - 2); } return str; } } // namespace node