66#include " node.h"
77#include " node_errors.h"
88#include " node_mem-inl.h"
9+ #include " path.h"
910#include " sqlite3.h"
1011#include " util-inl.h"
1112
@@ -78,12 +79,14 @@ inline void THROW_ERR_SQLITE_ERROR(Isolate* isolate, sqlite3* db) {
7879DatabaseSync::DatabaseSync (Environment* env,
7980 Local<Object> object,
8081 Local<String> location,
81- bool open)
82+ bool open,
83+ bool allow_load_extension)
8284 : BaseObject(env, object) {
8385 MakeWeak ();
8486 node::Utf8Value utf8_location (env->isolate (), location);
8587 location_ = utf8_location.ToString ();
8688 connection_ = nullptr ;
89+ allow_load_extension_ = allow_load_extension;
8790
8891 if (open) {
8992 Open ();
@@ -109,6 +112,12 @@ bool DatabaseSync::Open() {
109112 int flags = SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE;
110113 int r = sqlite3_open_v2 (location_.c_str (), &connection_, flags, nullptr );
111114 CHECK_ERROR_OR_THROW (env ()->isolate (), connection_, r, SQLITE_OK, false );
115+ if (allow_load_extension_) {
116+ int load_extension_ret = sqlite3_db_config (
117+ connection_, SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION, 1 , nullptr );
118+ CHECK_ERROR_OR_THROW (
119+ env ()->isolate (), connection_, load_extension_ret, SQLITE_OK, false );
120+ }
112121 return true ;
113122}
114123
@@ -127,6 +136,7 @@ void DatabaseSync::New(const FunctionCallbackInfo<Value>& args) {
127136 }
128137
129138 bool open = true ;
139+ bool allow_load_extension = false ;
130140
131141 if (args.Length () > 1 ) {
132142 if (!args[1 ]->IsObject ()) {
@@ -137,10 +147,17 @@ void DatabaseSync::New(const FunctionCallbackInfo<Value>& args) {
137147
138148 Local<Object> options = args[1 ].As <Object>();
139149 Local<String> open_string = FIXED_ONE_BYTE_STRING (env->isolate (), " open" );
150+ Local<String> allow_load_extension_string =
151+ FIXED_ONE_BYTE_STRING (env->isolate (), " allowLoadExtension" );
140152 Local<Value> open_v;
153+ Local<Value> allow_load_extension_v;
141154 if (!options->Get (env->context (), open_string).ToLocal (&open_v)) {
142155 return ;
143156 }
157+ if (!options->Get (env->context (), allow_load_extension_string)
158+ .ToLocal (&allow_load_extension_v)) {
159+ return ;
160+ }
144161 if (!open_v->IsUndefined ()) {
145162 if (!open_v->IsBoolean ()) {
146163 node::THROW_ERR_INVALID_ARG_TYPE (
@@ -149,9 +166,19 @@ void DatabaseSync::New(const FunctionCallbackInfo<Value>& args) {
149166 }
150167 open = open_v.As <Boolean>()->Value ();
151168 }
169+ if (!allow_load_extension_v->IsUndefined ()) {
170+ if (!allow_load_extension_v->IsBoolean ()) {
171+ node::THROW_ERR_INVALID_ARG_TYPE (
172+ env->isolate (),
173+ " The \" options.allowLoadExtension\" argument must be a boolean." );
174+ return ;
175+ }
176+ allow_load_extension = allow_load_extension_v.As <Boolean>()->Value ();
177+ }
152178 }
153179
154- new DatabaseSync (env, args.This (), args[0 ].As <String>(), open);
180+ new DatabaseSync (
181+ env, args.This (), args[0 ].As <String>(), open, allow_load_extension);
155182}
156183
157184void DatabaseSync::Open (const FunctionCallbackInfo<Value>& args) {
@@ -211,6 +238,35 @@ void DatabaseSync::Exec(const FunctionCallbackInfo<Value>& args) {
211238 CHECK_ERROR_OR_THROW (env->isolate (), db->connection_ , r, SQLITE_OK, void ());
212239}
213240
241+ void DatabaseSync::LoadExtension (const FunctionCallbackInfo<Value>& args) {
242+ DatabaseSync* db;
243+ ASSIGN_OR_RETURN_UNWRAP (&db, args.This ());
244+ Environment* env = Environment::GetCurrent (args);
245+ THROW_AND_RETURN_ON_BAD_STATE (
246+ env, db->connection_ == nullptr , " database is not open" );
247+ THROW_AND_RETURN_ON_BAD_STATE (
248+ env, !db->allow_load_extension_ , " load extension is not allowed" );
249+
250+ if (!args[0 ]->IsString ()) {
251+ node::THROW_ERR_INVALID_ARG_TYPE (env->isolate (),
252+ " The \" path\" argument must be a string." );
253+ return ;
254+ }
255+
256+ auto isolate = env->isolate ();
257+
258+ BufferValue path (isolate, args[0 ]);
259+ CHECK_NOT_NULL (*path);
260+ ToNamespacedPath (env, &path);
261+ THROW_IF_INSUFFICIENT_PERMISSIONS (
262+ env, permission::PermissionScope::kFileSystemRead , path.ToStringView ());
263+ char * errmsg = nullptr ;
264+ int r = sqlite3_load_extension (db->connection_ , *path, nullptr , &errmsg);
265+ if (r != SQLITE_OK) {
266+ isolate->ThrowException (node::ERR_LOAD_SQLITE_EXTENSION (isolate, errmsg));
267+ }
268+ }
269+
214270StatementSync::StatementSync (Environment* env,
215271 Local<Object> object,
216272 sqlite3* db,
@@ -668,6 +724,8 @@ static void Initialize(Local<Object> target,
668724 SetProtoMethod (isolate, db_tmpl, " close" , DatabaseSync::Close);
669725 SetProtoMethod (isolate, db_tmpl, " prepare" , DatabaseSync::Prepare);
670726 SetProtoMethod (isolate, db_tmpl, " exec" , DatabaseSync::Exec);
727+ SetProtoMethod (
728+ isolate, db_tmpl, " loadExtension" , DatabaseSync::LoadExtension);
671729 SetConstructorFunction (context, target, " DatabaseSync" , db_tmpl);
672730 SetConstructorFunction (context,
673731 target,
0 commit comments