11cb0ef41Sopenharmony_ci#ifndef SRC_PERMISSION_FS_PERMISSION_H_
21cb0ef41Sopenharmony_ci#define SRC_PERMISSION_FS_PERMISSION_H_
31cb0ef41Sopenharmony_ci
41cb0ef41Sopenharmony_ci#if defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS
51cb0ef41Sopenharmony_ci
61cb0ef41Sopenharmony_ci#include "v8.h"
71cb0ef41Sopenharmony_ci
81cb0ef41Sopenharmony_ci#include <unordered_map>
91cb0ef41Sopenharmony_ci#include "permission/permission_base.h"
101cb0ef41Sopenharmony_ci#include "util.h"
111cb0ef41Sopenharmony_ci
121cb0ef41Sopenharmony_cinamespace node {
131cb0ef41Sopenharmony_ci
141cb0ef41Sopenharmony_cinamespace permission {
151cb0ef41Sopenharmony_ci
161cb0ef41Sopenharmony_ciclass FSPermission final : public PermissionBase {
171cb0ef41Sopenharmony_ci public:
181cb0ef41Sopenharmony_ci  void Apply(const std::string& allow, PermissionScope scope) override;
191cb0ef41Sopenharmony_ci  bool is_granted(PermissionScope perm, const std::string_view& param) override;
201cb0ef41Sopenharmony_ci
211cb0ef41Sopenharmony_ci  struct RadixTree {
221cb0ef41Sopenharmony_ci    struct Node {
231cb0ef41Sopenharmony_ci      std::string prefix;
241cb0ef41Sopenharmony_ci      std::unordered_map<char, Node*> children;
251cb0ef41Sopenharmony_ci      Node* wildcard_child;
261cb0ef41Sopenharmony_ci
271cb0ef41Sopenharmony_ci      explicit Node(const std::string& pre)
281cb0ef41Sopenharmony_ci          : prefix(pre), wildcard_child(nullptr) {}
291cb0ef41Sopenharmony_ci
301cb0ef41Sopenharmony_ci      Node() : wildcard_child(nullptr) {}
311cb0ef41Sopenharmony_ci
321cb0ef41Sopenharmony_ci      Node* CreateChild(std::string prefix) {
331cb0ef41Sopenharmony_ci        char label = prefix[0];
341cb0ef41Sopenharmony_ci
351cb0ef41Sopenharmony_ci        Node* child = children[label];
361cb0ef41Sopenharmony_ci        if (child == nullptr) {
371cb0ef41Sopenharmony_ci          children[label] = new Node(prefix);
381cb0ef41Sopenharmony_ci          return children[label];
391cb0ef41Sopenharmony_ci        }
401cb0ef41Sopenharmony_ci
411cb0ef41Sopenharmony_ci        // swap prefix
421cb0ef41Sopenharmony_ci        unsigned int i = 0;
431cb0ef41Sopenharmony_ci        unsigned int prefix_len = prefix.length();
441cb0ef41Sopenharmony_ci        for (; i < child->prefix.length(); ++i) {
451cb0ef41Sopenharmony_ci          if (i > prefix_len || prefix[i] != child->prefix[i]) {
461cb0ef41Sopenharmony_ci            std::string parent_prefix = child->prefix.substr(0, i);
471cb0ef41Sopenharmony_ci            std::string child_prefix = child->prefix.substr(i);
481cb0ef41Sopenharmony_ci
491cb0ef41Sopenharmony_ci            child->prefix = child_prefix;
501cb0ef41Sopenharmony_ci            Node* split_child = new Node(parent_prefix);
511cb0ef41Sopenharmony_ci            split_child->children[child_prefix[0]] = child;
521cb0ef41Sopenharmony_ci            children[parent_prefix[0]] = split_child;
531cb0ef41Sopenharmony_ci
541cb0ef41Sopenharmony_ci            return split_child->CreateChild(prefix.substr(i));
551cb0ef41Sopenharmony_ci          }
561cb0ef41Sopenharmony_ci        }
571cb0ef41Sopenharmony_ci        return child->CreateChild(prefix.substr(i));
581cb0ef41Sopenharmony_ci      }
591cb0ef41Sopenharmony_ci
601cb0ef41Sopenharmony_ci      Node* CreateWildcardChild() {
611cb0ef41Sopenharmony_ci        if (wildcard_child != nullptr) {
621cb0ef41Sopenharmony_ci          return wildcard_child;
631cb0ef41Sopenharmony_ci        }
641cb0ef41Sopenharmony_ci        wildcard_child = new Node();
651cb0ef41Sopenharmony_ci        return wildcard_child;
661cb0ef41Sopenharmony_ci      }
671cb0ef41Sopenharmony_ci
681cb0ef41Sopenharmony_ci      Node* NextNode(const std::string& path, unsigned int idx) {
691cb0ef41Sopenharmony_ci        if (idx >= path.length()) {
701cb0ef41Sopenharmony_ci          return nullptr;
711cb0ef41Sopenharmony_ci        }
721cb0ef41Sopenharmony_ci
731cb0ef41Sopenharmony_ci        auto it = children.find(path[idx]);
741cb0ef41Sopenharmony_ci        if (it == children.end()) {
751cb0ef41Sopenharmony_ci          return nullptr;
761cb0ef41Sopenharmony_ci        }
771cb0ef41Sopenharmony_ci        auto child = it->second;
781cb0ef41Sopenharmony_ci        // match prefix
791cb0ef41Sopenharmony_ci        unsigned int prefix_len = child->prefix.length();
801cb0ef41Sopenharmony_ci        for (unsigned int i = 0; i < path.length(); ++i) {
811cb0ef41Sopenharmony_ci          if (i >= prefix_len || child->prefix[i] == '*') {
821cb0ef41Sopenharmony_ci            return child;
831cb0ef41Sopenharmony_ci          }
841cb0ef41Sopenharmony_ci
851cb0ef41Sopenharmony_ci          // Handle optional trailing
861cb0ef41Sopenharmony_ci          // path = /home/subdirectory
871cb0ef41Sopenharmony_ci          // child = subdirectory/*
881cb0ef41Sopenharmony_ci          if (idx >= path.length() &&
891cb0ef41Sopenharmony_ci              child->prefix[i] == node::kPathSeparator) {
901cb0ef41Sopenharmony_ci            continue;
911cb0ef41Sopenharmony_ci          }
921cb0ef41Sopenharmony_ci
931cb0ef41Sopenharmony_ci          if (path[idx++] != child->prefix[i]) {
941cb0ef41Sopenharmony_ci            return nullptr;
951cb0ef41Sopenharmony_ci          }
961cb0ef41Sopenharmony_ci        }
971cb0ef41Sopenharmony_ci        return child;
981cb0ef41Sopenharmony_ci      }
991cb0ef41Sopenharmony_ci
1001cb0ef41Sopenharmony_ci      // A node can be a *end* node and have children
1011cb0ef41Sopenharmony_ci      // E.g: */slower*, */slown* are inserted:
1021cb0ef41Sopenharmony_ci      // /slow
1031cb0ef41Sopenharmony_ci      // ---> er
1041cb0ef41Sopenharmony_ci      // ---> n
1051cb0ef41Sopenharmony_ci      // If */slow* is inserted right after, it will create an
1061cb0ef41Sopenharmony_ci      // empty node
1071cb0ef41Sopenharmony_ci      // /slow
1081cb0ef41Sopenharmony_ci      // ---> '\000' ASCII (0) || \0
1091cb0ef41Sopenharmony_ci      // ---> er
1101cb0ef41Sopenharmony_ci      // ---> n
1111cb0ef41Sopenharmony_ci      bool IsEndNode() {
1121cb0ef41Sopenharmony_ci        if (children.size() == 0) {
1131cb0ef41Sopenharmony_ci          return true;
1141cb0ef41Sopenharmony_ci        }
1151cb0ef41Sopenharmony_ci        return children['\0'] != nullptr;
1161cb0ef41Sopenharmony_ci      }
1171cb0ef41Sopenharmony_ci    };
1181cb0ef41Sopenharmony_ci
1191cb0ef41Sopenharmony_ci    RadixTree();
1201cb0ef41Sopenharmony_ci    ~RadixTree();
1211cb0ef41Sopenharmony_ci    void Insert(const std::string& s);
1221cb0ef41Sopenharmony_ci    bool Lookup(const std::string_view& s) { return Lookup(s, false); }
1231cb0ef41Sopenharmony_ci    bool Lookup(const std::string_view& s, bool when_empty_return);
1241cb0ef41Sopenharmony_ci
1251cb0ef41Sopenharmony_ci   private:
1261cb0ef41Sopenharmony_ci    Node* root_node_;
1271cb0ef41Sopenharmony_ci  };
1281cb0ef41Sopenharmony_ci
1291cb0ef41Sopenharmony_ci private:
1301cb0ef41Sopenharmony_ci  void GrantAccess(PermissionScope scope, const std::string& param);
1311cb0ef41Sopenharmony_ci  // fs granted on startup
1321cb0ef41Sopenharmony_ci  RadixTree granted_in_fs_;
1331cb0ef41Sopenharmony_ci  RadixTree granted_out_fs_;
1341cb0ef41Sopenharmony_ci
1351cb0ef41Sopenharmony_ci  bool deny_all_in_ = true;
1361cb0ef41Sopenharmony_ci  bool deny_all_out_ = true;
1371cb0ef41Sopenharmony_ci
1381cb0ef41Sopenharmony_ci  bool allow_all_in_ = false;
1391cb0ef41Sopenharmony_ci  bool allow_all_out_ = false;
1401cb0ef41Sopenharmony_ci};
1411cb0ef41Sopenharmony_ci
1421cb0ef41Sopenharmony_ci}  // namespace permission
1431cb0ef41Sopenharmony_ci
1441cb0ef41Sopenharmony_ci}  // namespace node
1451cb0ef41Sopenharmony_ci
1461cb0ef41Sopenharmony_ci#endif  // defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS
1471cb0ef41Sopenharmony_ci#endif  // SRC_PERMISSION_FS_PERMISSION_H_
148