From 21360bfc25798135e05be6308b210d0fc167c739 Mon Sep 17 00:00:00 2001 From: Jan Steemann Date: Tue, 5 Nov 2013 12:42:50 +0100 Subject: [PATCH 1/8] free json in case of error --- arangod/RestHandler/RestEdgeHandler.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arangod/RestHandler/RestEdgeHandler.cpp b/arangod/RestHandler/RestEdgeHandler.cpp index a3a0305523..41b0af9498 100644 --- a/arangod/RestHandler/RestEdgeHandler.cpp +++ b/arangod/RestHandler/RestEdgeHandler.cpp @@ -249,6 +249,8 @@ bool RestEdgeHandler::createDocument () { if (res != TRI_ERROR_NO_ERROR) { FREE_STRING(TRI_CORE_MEM_ZONE, edge._fromKey); FREE_STRING(TRI_CORE_MEM_ZONE, edge._toKey); + + TRI_FreeJson(TRI_UNKNOWN_MEM_ZONE, json); if (res == TRI_ERROR_ARANGO_COLLECTION_NOT_FOUND) { generateError(HttpResponse::NOT_FOUND, res, wrongPart + " does not point to a valid collection"); From 8382e5dbb63dadbd5d421ee7a588c3f6cbdf0cd0 Mon Sep 17 00:00:00 2001 From: Jan Steemann Date: Mon, 4 Nov 2013 17:43:57 +0100 Subject: [PATCH 2/8] flush authentication cache --- arangod/V8Server/v8-vocbase.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/arangod/V8Server/v8-vocbase.cpp b/arangod/V8Server/v8-vocbase.cpp index 21af738d65..a351cfcd29 100644 --- a/arangod/V8Server/v8-vocbase.cpp +++ b/arangod/V8Server/v8-vocbase.cpp @@ -8005,6 +8005,9 @@ static v8::Handle JS_CreateDatabase (v8::Arguments const& argv) { // version check failed // TODO: report an error } + + // populate the authentication cache. otherwise no one can access the new database + TRI_ReloadAuthInfo(database); // finally decrease the reference-counter TRI_ReleaseVocBase(database); From d30ca7b658af1a8ddbf42742a97b2ae1008724c1 Mon Sep 17 00:00:00 2001 From: Jan Steemann Date: Mon, 4 Nov 2013 14:22:00 +0100 Subject: [PATCH 3/8] added `/_api/database/user` method --- .../ImplementorManual/HttpDatabase.md | 4 + .../ImplementorManual/HttpDatabaseTOC.md | 1 + UnitTests/Makefile.unittests | 1 + arangod/V8Server/v8-vocbase.cpp | 20 ++- arangod/VocBase/auth.c | 2 +- arangod/VocBase/server.c | 93 ++++++++++++- arangod/VocBase/server.h | 9 ++ arangod/VocBase/vocbase.c | 2 + js/actions/api-database.js | 74 +++++++++-- .../frontend/js/bootstrap/module-internal.js | 19 +++ js/common/bootstrap/module-internal.js | 19 +++ js/common/tests/shell-base64.js | 123 ++++++++++++++++++ lib/V8/v8-utils.cpp | 60 ++++++++- 13 files changed, 406 insertions(+), 21 deletions(-) create mode 100644 js/common/tests/shell-base64.js diff --git a/Documentation/ImplementorManual/HttpDatabase.md b/Documentation/ImplementorManual/HttpDatabase.md index dd77deb1a7..99919bd8dc 100644 --- a/Documentation/ImplementorManual/HttpDatabase.md +++ b/Documentation/ImplementorManual/HttpDatabase.md @@ -82,6 +82,10 @@ Managing Databases using HTTP {#HttpDatabaseHttp} @anchor HttpDatabaseCurrent @copydetails JSF_get_api_database_current +@CLEARPAGE +@anchor HttpDatabaseUser +@copydetails JSF_get_api_database_user + @CLEARPAGE @anchor HttpDatabaseList @copydetails JSF_get_api_database_list diff --git a/Documentation/ImplementorManual/HttpDatabaseTOC.md b/Documentation/ImplementorManual/HttpDatabaseTOC.md index 0b04dfa08e..6d856bc344 100644 --- a/Documentation/ImplementorManual/HttpDatabaseTOC.md +++ b/Documentation/ImplementorManual/HttpDatabaseTOC.md @@ -7,6 +7,7 @@ TOC {#HttpDatabaseTOC} - @ref HttpDatabaseManagement - @ref HttpDatabaseHttp - @ref HttpDatabaseCurrent "GET /_api/database/current" + - @ref HttpDatabaseUser "GET /_api/database/user" - @ref HttpDatabaseList "GET /_api/database" - @ref HttpDatabaseCreate "POST /_api/database" - @ref HttpDatabaseDelete "DELETE /_api/database/database-name" diff --git a/UnitTests/Makefile.unittests b/UnitTests/Makefile.unittests index 9c2f3c771c..6232cc3b6d 100755 --- a/UnitTests/Makefile.unittests +++ b/UnitTests/Makefile.unittests @@ -284,6 +284,7 @@ SHELL_COMMON = \ @top_srcdir@/js/common/tests/shell-require.js \ @top_srcdir@/js/common/tests/shell-aqlfunctions.js \ @top_srcdir@/js/common/tests/shell-attributes.js \ + @top_srcdir@/js/common/tests/shell-base64.js \ @top_srcdir@/js/common/tests/shell-collection.js \ @top_srcdir@/js/common/tests/shell-collection-volatile.js \ @top_srcdir@/js/common/tests/shell-crypto.js \ diff --git a/arangod/V8Server/v8-vocbase.cpp b/arangod/V8Server/v8-vocbase.cpp index a351cfcd29..99efab1352 100644 --- a/arangod/V8Server/v8-vocbase.cpp +++ b/arangod/V8Server/v8-vocbase.cpp @@ -7866,7 +7866,8 @@ static v8::Handle JS_UseDatabase (v8::Arguments const& argv) { static v8::Handle JS_ListDatabases (v8::Arguments const& argv) { v8::HandleScope scope; - if (argv.Length() != 0) { + const uint32_t argc = argv.Length(); + if (argc != 0 && argc != 2) { TRI_V8_EXCEPTION_USAGE(scope, "db._listDatabases()"); } @@ -7876,7 +7877,8 @@ static v8::Handle JS_ListDatabases (v8::Arguments const& argv) { TRI_V8_EXCEPTION(scope, TRI_ERROR_ARANGO_DATABASE_NOT_FOUND); } - if (! TRI_IsSystemVocBase(vocbase)) { + if (argc == 0 && + ! TRI_IsSystemVocBase(vocbase)) { TRI_V8_EXCEPTION(scope, TRI_ERROR_ARANGO_USE_SYSTEM_DATABASE); } @@ -7884,7 +7886,19 @@ static v8::Handle JS_ListDatabases (v8::Arguments const& argv) { TRI_vector_string_t names; TRI_InitVectorString(&names, TRI_UNKNOWN_MEM_ZONE); - int res = TRI_GetDatabaseNamesServer((TRI_server_t*) v8g->_server, &names); + + int res; + + if (argc == 0) { + // return all databases + res = TRI_GetDatabaseNamesServer((TRI_server_t*) v8g->_server, &names); + } + else { + // return all databases for a specific user + string username = TRI_ObjectToString(argv[0]); + string password = TRI_ObjectToString(argv[1]); + res = TRI_GetUserDatabasesServer((TRI_server_t*) v8g->_server, username.c_str(), password.c_str(), &names); + } if (res != TRI_ERROR_NO_ERROR) { TRI_DestroyVectorString(&names); diff --git a/arangod/VocBase/auth.c b/arangod/VocBase/auth.c index c4e152644a..3670fd090c 100644 --- a/arangod/VocBase/auth.c +++ b/arangod/VocBase/auth.c @@ -567,7 +567,7 @@ bool TRI_CheckAuthenticationAuthInfo (TRI_vocbase_t* vocbase, TRI_ReadUnlockReadWriteLock(&vocbase->_authInfoLock); - if (res) { + if (res && hash != NULL) { // insert item into the cache TRI_vocbase_auth_cache_t* cached; diff --git a/arangod/VocBase/server.c b/arangod/VocBase/server.c index 6f03479969..9c008e7617 100644 --- a/arangod/VocBase/server.c +++ b/arangod/VocBase/server.c @@ -43,6 +43,7 @@ #include "BasicsC/random.h" #include "BasicsC/tri-strings.h" #include "Ahuacatl/ahuacatl-statementlist.h" +#include "VocBase/auth.h" #include "VocBase/vocbase.h" // ----------------------------------------------------------------------------- @@ -474,9 +475,39 @@ static int WriteShutdownInfo (TRI_server_t* server) { //////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////// -/// @brief returns the current tick value, without using a lock +/// @brief check if a user can see a database //////////////////////////////////////////////////////////////////////////////// +static bool CanUseDatabase (TRI_vocbase_t* vocbase, + char const* username, + char const* password) { + if (! vocbase->_settings.requireAuthentication) { + // authentication is turned off + return true; + } + + return TRI_CheckAuthenticationAuthInfo(vocbase, NULL, username, password); +} + +//////////////////////////////////////////////////////////////////////////////// +/// @brief comparator for database names +//////////////////////////////////////////////////////////////////////////////// + +static int DatabaseNameComparator (const void* lhs, const void* rhs) { + const char* l = *((char**) lhs); + const char* r = *((char**) rhs); + + return strcmp(l, r); +} + +//////////////////////////////////////////////////////////////////////////////// +/// @brief sort a list of database names +//////////////////////////////////////////////////////////////////////////////// + +static void SortDatabaseNames (TRI_vector_string_t* names) { + qsort(names->_buffer, names->_length, sizeof(char*), &DatabaseNameComparator); +} + //////////////////////////////////////////////////////////////////////////////// /// @brief extract the numeric part from a filename //////////////////////////////////////////////////////////////////////////////// @@ -498,7 +529,7 @@ static uint64_t GetNumericFilenamePart (const char* filename) { /// the filename. this is used to sort database filenames on startup //////////////////////////////////////////////////////////////////////////////// -static int NameComparator (const void* lhs, const void* rhs) { +static int DatabaseIdComparator (const void* lhs, const void* rhs) { const char* l = *((char**) lhs); const char* r = *((char**) rhs); @@ -600,7 +631,7 @@ static int OpenDatabases (TRI_server_t* server) { // open databases in defined order if (n > 1) { - qsort(files._buffer, n, sizeof(char**), &NameComparator); + qsort(files._buffer, n, sizeof(char**), &DatabaseIdComparator); } for (i = 0; i < n; ++i) { @@ -914,7 +945,7 @@ static int GetDatabases (TRI_server_t* server, regfree(&re); // sort by id - qsort(databases->_buffer, databases->_length, sizeof(char*), &NameComparator); + qsort(databases->_buffer, databases->_length, sizeof(char*), &DatabaseIdComparator); return res; } @@ -2178,6 +2209,58 @@ void TRI_ReleaseDatabaseServer (TRI_server_t* server, TRI_ReleaseVocBase(vocbase); } +//////////////////////////////////////////////////////////////////////////////// +/// @brief return the list of all databases a user can see +//////////////////////////////////////////////////////////////////////////////// + +int TRI_GetUserDatabasesServer (TRI_server_t* server, + char const* username, + char const* password, + TRI_vector_string_t* names) { + + size_t i, n; + int res; + + res = TRI_ERROR_NO_ERROR; + + TRI_ReadLockReadWriteLock(&server->_databasesLock); + n = server->_databases._nrAlloc; + + for (i = 0; i < n; ++i) { + TRI_vocbase_t* vocbase = server->_databases._table[i]; + + if (vocbase != NULL) { + char* copy; + + assert(vocbase->_name != NULL); + + if (! CanUseDatabase(vocbase, username, password)) { + // user cannot see database + continue; + } + + copy = TRI_DuplicateStringZ(names->_memoryZone, vocbase->_name); + + if (copy == NULL) { + res = TRI_ERROR_OUT_OF_MEMORY; + break; + } + + if (TRI_PushBackVectorString(names, copy) != TRI_ERROR_NO_ERROR) { + // insertion failed. + TRI_Free(names->_memoryZone, copy); + res = TRI_ERROR_OUT_OF_MEMORY; + break; + } + } + } + TRI_ReadUnlockReadWriteLock(&server->_databasesLock); + + SortDatabaseNames(names); + + return res; +} + //////////////////////////////////////////////////////////////////////////////// /// @brief return the list of all database names //////////////////////////////////////////////////////////////////////////////// @@ -2217,6 +2300,8 @@ int TRI_GetDatabaseNamesServer (TRI_server_t* server, } } TRI_ReadUnlockReadWriteLock(&server->_databasesLock); + + SortDatabaseNames(names); return res; } diff --git a/arangod/VocBase/server.h b/arangod/VocBase/server.h index b22061a8e1..bcd73cbc11 100644 --- a/arangod/VocBase/server.h +++ b/arangod/VocBase/server.h @@ -207,6 +207,15 @@ struct TRI_vocbase_s* TRI_UseDatabaseServer (TRI_server_t*, void TRI_ReleaseDatabaseServer (TRI_server_t*, struct TRI_vocbase_s*); +//////////////////////////////////////////////////////////////////////////////// +/// @brief return the list of all databases a user can see +//////////////////////////////////////////////////////////////////////////////// + +int TRI_GetUserDatabasesServer (TRI_server_t*, + char const*, + char const*, + TRI_vector_string_t*); + //////////////////////////////////////////////////////////////////////////////// /// @brief return the list of all database names //////////////////////////////////////////////////////////////////////////////// diff --git a/arangod/VocBase/vocbase.c b/arangod/VocBase/vocbase.c index b21e45fc91..a439748830 100644 --- a/arangod/VocBase/vocbase.c +++ b/arangod/VocBase/vocbase.c @@ -1374,6 +1374,8 @@ TRI_vocbase_t* TRI_OpenVocBase (TRI_server_t* server, } + TRI_ReloadAuthInfo(vocbase); + // ............................................................................. // vocbase is now active // ............................................................................. diff --git a/js/actions/api-database.js b/js/actions/api-database.js index dfef8aadc0..031b01ed48 100644 --- a/js/actions/api-database.js +++ b/js/actions/api-database.js @@ -49,7 +49,7 @@ var API = "_api/database"; /// @RESTHEADER{GET /_api/database,retrieves a list of all existing databases} /// /// @RESTDESCRIPTION -/// Retrieves a list of all existing databases +/// Retrieves the list of all existing databases /// /// Note: retrieving the list of databases is only possible from within the `_system` database. /// @@ -64,9 +64,6 @@ var API = "_api/database"; /// @RESTRETURNCODE{403} /// is returned if the request was not executed in the `_system` database. /// -/// @RESTRETURNCODE{404} -/// is returned if the database could not be found. -/// /// @EXAMPLES /// /// @EXAMPLE_ARANGOSH_RUN{RestDatabaseGet} @@ -79,6 +76,36 @@ var API = "_api/database"; /// @END_EXAMPLE_ARANGOSH_RUN //////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// +/// @fn JSF_get_api_database_user +/// @brief retrieves a list of all databases the current user can access +/// +/// @RESTHEADER{GET /_api/database/user,retrieves a list of all databases the current user can access} +/// +/// @RESTDESCRIPTION +/// Retrieves the list of all databases the current user can access without +/// specifying a different username or password. +/// +/// @RESTRETURNCODES +/// +/// @RESTRETURNCODE{200} +/// is returned if the list of database was compiled successfully. +/// +/// @RESTRETURNCODE{400} +/// is returned if the request is invalid. +/// +/// @EXAMPLES +/// +/// @EXAMPLE_ARANGOSH_RUN{RestDatabaseGetUser} +/// var url = "/_api/database/user"; +/// var response = logCurlRequest('GET', url); +/// +/// assert(response.code === 200); +/// +/// logJsonResponse(response); +/// @END_EXAMPLE_ARANGOSH_RUN +//////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// /// @fn JSF_get_api_database_current /// @brief retrieves information about the current database @@ -127,7 +154,7 @@ function get_api_database (req, res) { return; } - if (req.suffix.length === 1 && req.suffix[0] !== 'current') { + if (req.suffix.length > 1) { actions.resultBad(req, res, arangodb.ERROR_HTTP_BAD_PARAMETER); return; } @@ -138,13 +165,36 @@ function get_api_database (req, res) { result = arangodb.db._listDatabases(); } else { - // information about the current database - result = { - name: arangodb.db._name(), - id: arangodb.db._id(), - path: arangodb.db._path(), - isSystem: arangodb.db._isSystem() - }; + if (req.suffix[0] === 'user') { + // return all databases for current user + var username = '', password = ''; + + if (req.headers.hasOwnProperty('authorization')) { + var header = req.headers.authorization.replace(/^Basic\s+/i, ''); + var decoded = require("internal").base64Decode(header); + var pos = decoded.indexOf(':'); + + if (pos >= 0) { + username = decoded.substr(0, pos); + password = decoded.substr(pos + 1, decoded.length - pos - 1); + } + } + + result = arangodb.db._listDatabases(username, password); + } + else if (req.suffix[0] === 'current') { + // information about the current database + result = { + name: arangodb.db._name(), + id: arangodb.db._id(), + path: arangodb.db._path(), + isSystem: arangodb.db._isSystem() + }; + } + else { + actions.resultBad(req, res, arangodb.ERROR_HTTP_BAD_PARAMETER); + return; + } } actions.resultOk(req, res, actions.HTTP_OK, { result : result }); diff --git a/js/apps/system/aardvark/frontend/js/bootstrap/module-internal.js b/js/apps/system/aardvark/frontend/js/bootstrap/module-internal.js index a860fbb7fb..18f8cd021b 100644 --- a/js/apps/system/aardvark/frontend/js/bootstrap/module-internal.js +++ b/js/apps/system/aardvark/frontend/js/bootstrap/module-internal.js @@ -5,6 +5,7 @@ REPLICATION_LOGGER_CONFIGURE, REPLICATION_APPLIER_CONFIGURE, REPLICATION_APPLIER_START, REPLICATION_APPLIER_STOP, REPLICATION_APPLIER_FORGET, REPLICATION_APPLIER_STATE, REPLICATION_SYNCHRONISE, REPLICATION_SERVER_ID, CONFIGURE_ENDPOINT, REMOVE_ENDPOINT, LIST_ENDPOINTS, + SYS_BASE64DECODE, SYS_BASE64ENCODE, SYS_DEBUG_CAN_USE_FAILAT, SYS_DEBUG_SET_FAILAT, SYS_DEBUG_REMOVE_FAILAT, SYS_DEBUG_CLEAR_FAILAT, SYS_DOWNLOAD, SYS_EXECUTE, SYS_LOAD, SYS_LOG_LEVEL, SYS_MD5, SYS_OUTPUT, SYS_PROCESS_STATISTICS, SYS_RAND, SYS_SERVER_STATISTICS, SYS_SPRINTF, SYS_TIME, SYS_START_PAGER, SYS_STOP_PAGER, @@ -356,6 +357,24 @@ delete LIST_ENDPOINTS; } +//////////////////////////////////////////////////////////////////////////////// +/// @brief base64Decode +//////////////////////////////////////////////////////////////////////////////// + + if (typeof SYS_BASE64DECODE !== "undefined") { + exports.base64Decode = SYS_BASE64DECODE; + delete SYS_BASE64DECODE; + } + +//////////////////////////////////////////////////////////////////////////////// +/// @brief base64Encode +//////////////////////////////////////////////////////////////////////////////// + + if (typeof SYS_BASE64ENCODE !== "undefined") { + exports.base64Encode = SYS_BASE64ENCODE; + delete SYS_BASE64ENCODE; + } + //////////////////////////////////////////////////////////////////////////////// /// @brief debugSetFailAt //////////////////////////////////////////////////////////////////////////////// diff --git a/js/common/bootstrap/module-internal.js b/js/common/bootstrap/module-internal.js index a860fbb7fb..18f8cd021b 100644 --- a/js/common/bootstrap/module-internal.js +++ b/js/common/bootstrap/module-internal.js @@ -5,6 +5,7 @@ REPLICATION_LOGGER_CONFIGURE, REPLICATION_APPLIER_CONFIGURE, REPLICATION_APPLIER_START, REPLICATION_APPLIER_STOP, REPLICATION_APPLIER_FORGET, REPLICATION_APPLIER_STATE, REPLICATION_SYNCHRONISE, REPLICATION_SERVER_ID, CONFIGURE_ENDPOINT, REMOVE_ENDPOINT, LIST_ENDPOINTS, + SYS_BASE64DECODE, SYS_BASE64ENCODE, SYS_DEBUG_CAN_USE_FAILAT, SYS_DEBUG_SET_FAILAT, SYS_DEBUG_REMOVE_FAILAT, SYS_DEBUG_CLEAR_FAILAT, SYS_DOWNLOAD, SYS_EXECUTE, SYS_LOAD, SYS_LOG_LEVEL, SYS_MD5, SYS_OUTPUT, SYS_PROCESS_STATISTICS, SYS_RAND, SYS_SERVER_STATISTICS, SYS_SPRINTF, SYS_TIME, SYS_START_PAGER, SYS_STOP_PAGER, @@ -356,6 +357,24 @@ delete LIST_ENDPOINTS; } +//////////////////////////////////////////////////////////////////////////////// +/// @brief base64Decode +//////////////////////////////////////////////////////////////////////////////// + + if (typeof SYS_BASE64DECODE !== "undefined") { + exports.base64Decode = SYS_BASE64DECODE; + delete SYS_BASE64DECODE; + } + +//////////////////////////////////////////////////////////////////////////////// +/// @brief base64Encode +//////////////////////////////////////////////////////////////////////////////// + + if (typeof SYS_BASE64ENCODE !== "undefined") { + exports.base64Encode = SYS_BASE64ENCODE; + delete SYS_BASE64ENCODE; + } + //////////////////////////////////////////////////////////////////////////////// /// @brief debugSetFailAt //////////////////////////////////////////////////////////////////////////////// diff --git a/js/common/tests/shell-base64.js b/js/common/tests/shell-base64.js new file mode 100644 index 0000000000..cfacaa7832 --- /dev/null +++ b/js/common/tests/shell-base64.js @@ -0,0 +1,123 @@ +//////////////////////////////////////////////////////////////////////////////// +/// @brief test the base64 functions +/// +/// @file +/// +/// DISCLAIMER +/// +/// Copyright 2010-2012 triagens GmbH, Cologne, Germany +/// +/// Licensed under the Apache License, Version 2.0 (the "License"); +/// you may not use this file except in compliance with the License. +/// You may obtain a copy of the License at +/// +/// http://www.apache.org/licenses/LICENSE-2.0 +/// +/// Unless required by applicable law or agreed to in writing, software +/// distributed under the License is distributed on an "AS IS" BASIS, +/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +/// See the License for the specific language governing permissions and +/// limitations under the License. +/// +/// Copyright holder is triAGENS GmbH, Cologne, Germany +/// +/// @author Jan Steemann +/// @author Copyright 2013, triAGENS GmbH, Cologne, Germany +//////////////////////////////////////////////////////////////////////////////// + +var jsunity = require("jsunity"); +var internal = require("internal"); + +// ----------------------------------------------------------------------------- +// --SECTION-- base64 functions +// ----------------------------------------------------------------------------- + +//////////////////////////////////////////////////////////////////////////////// +/// @brief test suite +//////////////////////////////////////////////////////////////////////////////// + +function Base64Suite () { + return { + +//////////////////////////////////////////////////////////////////////////////// +/// @brief test encode +//////////////////////////////////////////////////////////////////////////////// + + testBase64Encode : function () { + var data = [ + ["",""], + [" ","IA=="], + [" ","ICA="], + ["\nnew line\n","Cm5ldyBsaW5lCg=="], + ["abc","YWJj"], + ["ABC","QUJD"], + ["abC","YWJD"], + [" aBC","IGFCQw=="], + ["123","MTIz"], + ["abcdef123456","YWJjZGVmMTIzNDU2"], + ["the Quick brown fox jumped over the lazy dog","dGhlIFF1aWNrIGJyb3duIGZveCBqdW1wZWQgb3ZlciB0aGUgbGF6eSBkb2c="], + ["This is a long string that contains a lot of characters. It should work without any particular problems, too.","VGhpcyBpcyBhIGxvbmcgc3RyaW5nIHRoYXQgY29udGFpbnMgYSBsb3Qgb2YgY2hhcmFjdGVycy4gSXQgc2hvdWxkIHdvcmsgd2l0aG91dCBhbnkgcGFydGljdWxhciBwcm9ibGVtcywgdG9vLg=="], + [1,"MQ=="], + [2,"Mg=="], + [-1,"LTE="], + [100,"MTAw"], + [1000,"MTAwMA=="], + [99,"OTk="] + ]; + + data.forEach(function (value) { + assertEqual(value[1], internal.base64Encode(value[0])); + }); + }, + +//////////////////////////////////////////////////////////////////////////////// +/// @brief test decode +//////////////////////////////////////////////////////////////////////////////// + + testBase64Decode : function () { + var data = [ + ["",""], + [" ","IA=="], + [" ","ICA="], + ["\nnew line\n","Cm5ldyBsaW5lCg=="], + ["abc","YWJj"], + ["ABC","QUJD"], + ["abC","YWJD"], + [" aBC","IGFCQw=="], + ["123","MTIz"], + ["abcdef123456","YWJjZGVmMTIzNDU2"], + ["the Quick brown fox jumped over the lazy dog","dGhlIFF1aWNrIGJyb3duIGZveCBqdW1wZWQgb3ZlciB0aGUgbGF6eSBkb2c="], + ["This is a long string that contains a lot of characters. It should work without any particular problems, too.","VGhpcyBpcyBhIGxvbmcgc3RyaW5nIHRoYXQgY29udGFpbnMgYSBsb3Qgb2YgY2hhcmFjdGVycy4gSXQgc2hvdWxkIHdvcmsgd2l0aG91dCBhbnkgcGFydGljdWxhciBwcm9ibGVtcywgdG9vLg=="], + ["1","MQ=="], + ["2","Mg=="], + ["-1","LTE="], + ["100","MTAw"], + ["1000","MTAwMA=="], + ["99","OTk="] + ]; + + data.forEach(function (value) { + assertEqual(value[0], internal.base64Decode(value[1])); + }); + } + + }; +} + +// ----------------------------------------------------------------------------- +// --SECTION-- main +// ----------------------------------------------------------------------------- + +//////////////////////////////////////////////////////////////////////////////// +/// @brief executes the test suite +//////////////////////////////////////////////////////////////////////////////// + +jsunity.run(Base64Suite); + +return jsunity.done(); + +// Local Variables: +// mode: outline-minor +// outline-regexp: "^\\(/// @brief\\|/// @addtogroup\\|// --SECTION--\\|/// @page\\|/// @}\\)" +// End: + diff --git a/lib/V8/v8-utils.cpp b/lib/V8/v8-utils.cpp index 75014adf6c..3b8dae8e24 100644 --- a/lib/V8/v8-utils.cpp +++ b/lib/V8/v8-utils.cpp @@ -283,6 +283,62 @@ static void FillDistribution (v8::Handle list, // --SECTION-- JS functions // ----------------------------------------------------------------------------- +//////////////////////////////////////////////////////////////////////////////// +/// @brief decode a base64-encoded string +/// +/// @FUN{internal.base64Decode(@FA{value})} +/// +/// Base64-decodes the string @FA{value}. +//////////////////////////////////////////////////////////////////////////////// + +static v8::Handle JS_Base64Decode (v8::Arguments const& argv) { + v8::HandleScope scope; + + if (argv.Length() != 1) { + TRI_V8_EXCEPTION_USAGE(scope, "base64Decode()"); + } + + string base64; + + try { + string value = TRI_ObjectToString(argv[0]); + base64 = StringUtils::decodeBase64(value); + } + catch (...) { + TRI_V8_EXCEPTION_MESSAGE(scope, TRI_errno(), TRI_last_error()); + } + + return scope.Close(v8::String::New(base64.c_str(), base64.size())); +} + +//////////////////////////////////////////////////////////////////////////////// +/// @brief base64-encode a string +/// +/// @FUN{internal.base64Encode(@FA{value})} +/// +/// Base64-encodes the string @FA{value}. +//////////////////////////////////////////////////////////////////////////////// + +static v8::Handle JS_Base64Encode (v8::Arguments const& argv) { + v8::HandleScope scope; + + if (argv.Length() != 1) { + TRI_V8_EXCEPTION_USAGE(scope, "base64Encode()"); + } + + string base64; + + try { + string value = TRI_ObjectToString(argv[0]); + base64 = StringUtils::encodeBase64(value); + } + catch (...) { + TRI_V8_EXCEPTION_MESSAGE(scope, TRI_errno(), TRI_last_error()); + } + + return scope.Close(v8::String::New(base64.c_str(), base64.size())); +} + //////////////////////////////////////////////////////////////////////////////// /// @brief parse a Javascript snippet, but do not execute it /// @@ -1709,7 +1765,7 @@ static v8::Handle JS_Read64 (v8::Arguments const& argv) { TRI_V8_EXCEPTION_MESSAGE(scope, TRI_errno(), TRI_last_error()); } - return scope.Close(v8::String::New(base64.c_str())); + return scope.Close(v8::String::New(base64.c_str(), base64.size())); } //////////////////////////////////////////////////////////////////////////////// @@ -2700,6 +2756,8 @@ void TRI_InitV8Utils (v8::Handle context, TRI_AddGlobalFunctionVocbase(context, "FS_UNZIP_FILE", JS_UnzipFile); TRI_AddGlobalFunctionVocbase(context, "FS_ZIP_FILE", JS_ZipFile); + TRI_AddGlobalFunctionVocbase(context, "SYS_BASE64DECODE", JS_Base64Decode); + TRI_AddGlobalFunctionVocbase(context, "SYS_BASE64ENCODE", JS_Base64Encode); TRI_AddGlobalFunctionVocbase(context, "SYS_DOWNLOAD", JS_Download); TRI_AddGlobalFunctionVocbase(context, "SYS_EXECUTE", JS_Execute); TRI_AddGlobalFunctionVocbase(context, "SYS_GETLINE", JS_Getline); From 1d8d26b7abd1d9423e6f511c5b000ba2fb532c42 Mon Sep 17 00:00:00 2001 From: Jan Steemann Date: Mon, 4 Nov 2013 14:23:30 +0100 Subject: [PATCH 4/8] added test --- UnitTests/HttpInterface/api-database-spec.rb | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/UnitTests/HttpInterface/api-database-spec.rb b/UnitTests/HttpInterface/api-database-spec.rb index cb6d85ba51..bd3119ec43 100644 --- a/UnitTests/HttpInterface/api-database-spec.rb +++ b/UnitTests/HttpInterface/api-database-spec.rb @@ -22,6 +22,19 @@ describe ArangoDB do result.should include("_system") end +################################################################################ +## retrieving the list of databases for the current user +################################################################################ + + it "retrieves the list of user-specific databases" do + doc = ArangoDB.log_get("#{prefix}-list-user", api + "/user") + + doc.code.should eq(200) + result = doc.parsed_response["result"] + + result.should include("_system") + end + ################################################################################ ## checking information about current database ################################################################################ From 0d844c3f06b447b459ea8dcd91cd90c760dbdd85 Mon Sep 17 00:00:00 2001 From: Frank Celler Date: Wed, 6 Nov 2013 16:44:46 +0100 Subject: [PATCH 5/8] generated arm conf files --- .gitignore | 2 ++ CMakeLists.txt | 5 ++++- Makefile.am | 38 +++++++++++++++++++++++++++--------- Makefile.in | 44 +++++++++++++++++++++++++++++------------- arangod/CMakeLists.txt | 22 +++++++++++++++------ 5 files changed, 82 insertions(+), 29 deletions(-) diff --git a/.gitignore b/.gitignore index 37714a1119..58f4864c8c 100644 --- a/.gitignore +++ b/.gitignore @@ -74,6 +74,8 @@ arangod/Ahuacatl/ahuacatl-tokens.c bin/ etc/arangodb/arangob.conf etc/arangodb/arangod-uid.conf +etc/arangodb/arangod-arm.conf +etc/arangodb/arangod-uid-arm.conf etc/arangodb/arangod.conf etc/arangodb/arangodump.conf etc/arangodb/arangoimp.conf diff --git a/CMakeLists.txt b/CMakeLists.txt index 4cc72c6023..3b5a637f74 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -82,6 +82,7 @@ set(ARANGODB_VERSION "1.x.y-rc1" CACHE path "ArangoDB version") ### Posible options are: ### - dmg-cli: Mac OS X shell client application ### - debian: debian package +### - raspbian: raspberry debian package ################################################################################ set(BUILD_PACKAGE "unknown" CACHE path "Package type to build") @@ -350,6 +351,8 @@ set(CPACK_SET_DESTDIR ON) if (BUILD_PACKAGE STREQUAL "dmg-cli") set(CPACK_PACKAGE_NAME "ArangoDB-CLI") +elseif (BUILD_PACKAGE STREQUAL "raspbian") + set(CPACK_PACKAGE_NAME "arangodb") elseif (BUILD_PACKAGE STREQUAL "debian") set(CPACK_PACKAGE_NAME "arangodb") endif () @@ -374,7 +377,7 @@ endif () ### @brief debian package ################################################################################ -if (BUILD_PACKAGE STREQUAL "debian") +if (BUILD_PACKAGE STREQUAL "debian" or BUILD_PACKAGE STREQUAL "raspbian") set(CPACK_DEBIAN_PACKAGE_SECTION "database") set(CPACK_DEBIAN_PACKAGE_CONTROL_EXTRA "${PROJECT_SOURCE_DIR}/Installation/Debian/postinst;${PROJECT_SOURCE_DIR}/Installation/Debian/preinst;${PROJECT_SOURCE_DIR}/Installation/Debian/postrm;${PROJECT_SOURCE_DIR}/Installation/Debian/prerm;") diff --git a/Makefile.am b/Makefile.am index 49154386b9..1669f98f14 100644 --- a/Makefile.am +++ b/Makefile.am @@ -64,6 +64,26 @@ BISON_FILES = BISONXX_FILES = +################################################################################ +### @brief configuration files +################################################################################ + +BUILT_SOURCES += etc/arangodb/arangod-uid.conf + +etc/arangodb/arangod-uid.conf: @srcdir@/etc/arangodb/arangod.conf + sed -e 's:^# \([ug]id\):\1:' $< > $@ + +BUILT_SOURCES += etc/arangodb/arangod-arm.conf + +etc/arangodb/arangod-arm.conf: @srcdir@/etc/arangodb/arangod.conf + sed -e '/^\[server\]/,/^\[/s:^threads.*:threads = 1:' $< > $@ + +BUILT_SOURCES += etc/arangodb/arangod-uid-arm.conf + +etc/arangodb/arangod-uid-arm.conf: @srcdir@/etc/arangodb/arangod.conf + sed -e 's:^# \([ug]id\):\1:' $< \ + | sed -e '/^\[server\]/,/^\[/s:^threads.*:threads = 1:' > $@ + ## ----------------------------------------------------------------------------- ## --SECTION-- PATHS ## ----------------------------------------------------------------------------- @@ -86,11 +106,6 @@ TRI_BINDIR = ${bindir} endif -BUILT_SOURCES += etc/arangodb/arangod-uid.conf - -etc/arangodb/arangod-uid.conf: @srcdir@/etc/arangodb/arangod.conf - sed -e 's:# \([ug]id\):\1:' $< > $@ - ## ----------------------------------------------------------------------------- ## --SECTION-- FLAGS ## ----------------------------------------------------------------------------- @@ -517,7 +532,9 @@ pack-dmg: cd Build && cmake \ -D "BUILD_PACKAGE=dmg-cli" \ - -D "CMAKE_INSTALL_PREFIX=/opt/arangodb" \ + -D "CMAKE_INSTALL_PREFIX=${prefix}" \ + -D "ETCDIR=${sysconfdir}" \ + -D "VARDIR=${localstatedir}" \ -D "USE_MRUBY=ON" \ -D "USE_RAW_CONFIG=ON" \ -D "ARANGODB_VERSION=@VERSION@" \ @@ -540,6 +557,9 @@ pack-arm: rm -rf Build && mkdir Build ./configure \ + --prefix=/usr \ + --sysconfdir=/etc \ + --localstatedir=/var \ --enable-all-in-one-icu \ --enable-all-in-one-v8 \ --enable-all-in-one-libev \ @@ -547,9 +567,9 @@ pack-arm: cd Build && cmake \ -D "BUILD_PACKAGE=debian" \ - -D "CMAKE_INSTALL_PREFIX=/usr" \ - -D "ETCDIR=/etc" \ - -D "VARDIR=/var" \ + -D "CMAKE_INSTALL_PREFIX=${prefix}" \ + -D "ETCDIR=${sysconfdir}" \ + -D "VARDIR=${localstatedir}" \ -D "USE_MRUBY=OFF" \ -D "USE_RAW_CONFIG=OFF" \ -D "ARANGODB_VERSION=@VERSION@" \ diff --git a/Makefile.in b/Makefile.in index 3c673bc4ce..934fac7cca 100644 --- a/Makefile.in +++ b/Makefile.in @@ -1128,18 +1128,24 @@ VERSION_PATCH := $(wordlist 3,3,$(subst ., ,$(VERSION))) ### @brief source to build before compile ################################################################################ +################################################################################ +### @brief configuration files +################################################################################ + ################################################################################ ### @brief sets up the directories ################################################################################ BUILT_SOURCES = build.h etc/arangodb/arangod-uid.conf \ - etc/arangodb/arangob.conf etc/arangodb/arangod.conf \ - etc/arangodb/arangodump.conf etc/arangodb/arangoimp.conf \ - etc/arangodb/arangoirb.conf etc/arangodb/arangorestore.conf \ - etc/arangodb/arangosh.conf $(am__append_12) \ - Doxygen/.setup-directories $(JAVASCRIPT_BROWSER) \ - @builddir@/.setup-js-directories $(am__append_13) \ - $(am__append_15) $(am__append_16) @ZLIB_LIBS@ $(am__append_17) \ - $(am__append_19) $(am__append_21) $(am__append_23) + etc/arangodb/arangod-arm.conf \ + etc/arangodb/arangod-uid-arm.conf etc/arangodb/arangob.conf \ + etc/arangodb/arangod.conf etc/arangodb/arangodump.conf \ + etc/arangodb/arangoimp.conf etc/arangodb/arangoirb.conf \ + etc/arangodb/arangorestore.conf etc/arangodb/arangosh.conf \ + $(am__append_12) Doxygen/.setup-directories \ + $(JAVASCRIPT_BROWSER) @builddir@/.setup-js-directories \ + $(am__append_13) $(am__append_15) $(am__append_16) @ZLIB_LIBS@ \ + $(am__append_17) $(am__append_19) $(am__append_21) \ + $(am__append_23) ################################################################################ ### @brief man pages to install @@ -7440,7 +7446,14 @@ uninstall-man: uninstall-man1 uninstall-man8 etc/arangodb/arangod-uid.conf: @srcdir@/etc/arangodb/arangod.conf - sed -e 's:# \([ug]id\):\1:' $< > $@ + sed -e 's:^# \([ug]id\):\1:' $< > $@ + +etc/arangodb/arangod-arm.conf: @srcdir@/etc/arangodb/arangod.conf + sed -e '/^\[server\]/,/^\[/s:^threads.*:threads = 1:' $< > $@ + +etc/arangodb/arangod-uid-arm.conf: @srcdir@/etc/arangodb/arangod.conf + sed -e 's:^# \([ug]id\):\1:' $< \ + | sed -e '/^\[server\]/,/^\[/s:^threads.*:threads = 1:' > $@ ################################################################################ ### @brief /var data @@ -8676,7 +8689,9 @@ pack-dmg: cd Build && cmake \ -D "BUILD_PACKAGE=dmg-cli" \ - -D "CMAKE_INSTALL_PREFIX=/opt/arangodb" \ + -D "CMAKE_INSTALL_PREFIX=${prefix}" \ + -D "ETCDIR=${sysconfdir}" \ + -D "VARDIR=${localstatedir}" \ -D "USE_MRUBY=ON" \ -D "USE_RAW_CONFIG=ON" \ -D "ARANGODB_VERSION=@VERSION@" \ @@ -8699,6 +8714,9 @@ pack-arm: rm -rf Build && mkdir Build ./configure \ + --prefix=/usr \ + --sysconfdir=/etc \ + --localstatedir=/var \ --enable-all-in-one-icu \ --enable-all-in-one-v8 \ --enable-all-in-one-libev \ @@ -8706,9 +8724,9 @@ pack-arm: cd Build && cmake \ -D "BUILD_PACKAGE=debian" \ - -D "CMAKE_INSTALL_PREFIX=/usr" \ - -D "ETCDIR=/etc" \ - -D "VARDIR=/var" \ + -D "CMAKE_INSTALL_PREFIX=${prefix}" \ + -D "ETCDIR=${sysconfdir}" \ + -D "VARDIR=${localstatedir}" \ -D "USE_MRUBY=OFF" \ -D "USE_RAW_CONFIG=OFF" \ -D "ARANGODB_VERSION=@VERSION@" \ diff --git a/arangod/CMakeLists.txt b/arangod/CMakeLists.txt index cad83d8065..a33488e1bf 100644 --- a/arangod/CMakeLists.txt +++ b/arangod/CMakeLists.txt @@ -156,13 +156,23 @@ if (USE_RAW_CONFIG) RENAME arangod-relative.conf) endif () -install( - FILES ${PROJECT_SOURCE_DIR}/etc/arangodb/arangod.conf - DESTINATION ${ETCDIR_NATIVE}) +if (BUILD_PACKAGE STREQUAL "raspbian") + install( + FILES ${PROJECT_SOURCE_DIR}/etc/arangodb/arangod-arm.conf + DESTINATION ${ETCDIR_NATIVE}) -install( - FILES ${PROJECT_SOURCE_DIR}/etc/arangodb/arangod-uid.conf - DESTINATION ${ETCDIR_NATIVE}) + install( + FILES ${PROJECT_SOURCE_DIR}/etc/arangodb/arangod-uid-arm.conf + DESTINATION ${ETCDIR_NATIVE}) +else () + install( + FILES ${PROJECT_SOURCE_DIR}/etc/arangodb/arangod.conf + DESTINATION ${ETCDIR_NATIVE}) + + install( + FILES ${PROJECT_SOURCE_DIR}/etc/arangodb/arangod-uid.conf + DESTINATION ${ETCDIR_NATIVE}) +endif () install( DIRECTORY ${PROJECT_SOURCE_DIR}/js/common ${PROJECT_SOURCE_DIR}/js/server ${PROJECT_SOURCE_DIR}/js/actions From a18beb974182d223beba97e1846870dad3e3048e Mon Sep 17 00:00:00 2001 From: Frank Celler Date: Wed, 6 Nov 2013 16:49:16 +0100 Subject: [PATCH 6/8] generated arm conf files --- CMakeLists.txt | 2 +- Makefile.in | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 3b5a637f74..ba4cfa02fb 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -377,7 +377,7 @@ endif () ### @brief debian package ################################################################################ -if (BUILD_PACKAGE STREQUAL "debian" or BUILD_PACKAGE STREQUAL "raspbian") +if ((BUILD_PACKAGE STREQUAL "debian") OR (BUILD_PACKAGE STREQUAL "raspbian")) set(CPACK_DEBIAN_PACKAGE_SECTION "database") set(CPACK_DEBIAN_PACKAGE_CONTROL_EXTRA "${PROJECT_SOURCE_DIR}/Installation/Debian/postinst;${PROJECT_SOURCE_DIR}/Installation/Debian/preinst;${PROJECT_SOURCE_DIR}/Installation/Debian/postrm;${PROJECT_SOURCE_DIR}/Installation/Debian/prerm;") diff --git a/Makefile.in b/Makefile.in index 934fac7cca..117c147492 100644 --- a/Makefile.in +++ b/Makefile.in @@ -1767,6 +1767,7 @@ SHELL_COMMON = \ @top_srcdir@/js/common/tests/shell-require.js \ @top_srcdir@/js/common/tests/shell-aqlfunctions.js \ @top_srcdir@/js/common/tests/shell-attributes.js \ + @top_srcdir@/js/common/tests/shell-base64.js \ @top_srcdir@/js/common/tests/shell-collection.js \ @top_srcdir@/js/common/tests/shell-collection-volatile.js \ @top_srcdir@/js/common/tests/shell-crypto.js \ From 8856a93455e8437f94716815bb99389477355b98 Mon Sep 17 00:00:00 2001 From: Frank Celler Date: Wed, 6 Nov 2013 16:03:47 +0000 Subject: [PATCH 7/8] fixed permissions --- CMakeLists.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index ba4cfa02fb..2b983ed6f2 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -384,6 +384,7 @@ if ((BUILD_PACKAGE STREQUAL "debian") OR (BUILD_PACKAGE STREQUAL "raspbian")) install( FILES ${PROJECT_SOURCE_DIR}/Installation/Debian/rc.arangodb + PERMISSIONS OWNER_READ OWNER_EXECUTE GROUP_READ GROUP_EXECUTE WORLD_READ WORLD_EXECUTE DESTINATION /etc/init.d RENAME arangodb) From bae8bb1d97dda33a2278e54629e01c3bcf377862 Mon Sep 17 00:00:00 2001 From: Frank Celler Date: Wed, 6 Nov 2013 17:08:54 +0100 Subject: [PATCH 8/8] use recursive make to reload changes --- Makefile.am | 10 ++++++++-- Makefile.in | 10 ++++++++-- 2 files changed, 16 insertions(+), 4 deletions(-) diff --git a/Makefile.am b/Makefile.am index 1669f98f14..f9d19e58e5 100644 --- a/Makefile.am +++ b/Makefile.am @@ -516,7 +516,7 @@ endif ### @brief MacOSX bundle ################################################################################ -.PHONY: pack-dmg +.PHONY: pack-dmg pack-dmg-cmake DMG_NAME := ArangoDB-CLI.app @@ -530,6 +530,9 @@ pack-dmg: --enable-all-in-one-libev \ --enable-mruby + ${MAKE} pack-dmg-cmake + +pack-dmg-cmake: cd Build && cmake \ -D "BUILD_PACKAGE=dmg-cli" \ -D "CMAKE_INSTALL_PREFIX=${prefix}" \ @@ -551,7 +554,7 @@ pack-dmg: ### @brief debian arm package ################################################################################ -.PHONY: pack-arm +.PHONY: pack-arm pack-arm-cmake pack-arm: rm -rf Build && mkdir Build @@ -565,6 +568,9 @@ pack-arm: --enable-all-in-one-libev \ --disable-mruby + ${MAKE} pack-arm-cmake + +pack-arm-cmake: cd Build && cmake \ -D "BUILD_PACKAGE=debian" \ -D "CMAKE_INSTALL_PREFIX=${prefix}" \ diff --git a/Makefile.in b/Makefile.in index 117c147492..ea6cdfb657 100644 --- a/Makefile.in +++ b/Makefile.in @@ -8676,7 +8676,7 @@ clean-zlib: ### @brief MacOSX bundle ################################################################################ -.PHONY: pack-dmg +.PHONY: pack-dmg pack-dmg-cmake pack-dmg: rm -rf Build && mkdir Build @@ -8688,6 +8688,9 @@ pack-dmg: --enable-all-in-one-libev \ --enable-mruby + ${MAKE} pack-dmg-cmake + +pack-dmg-cmake: cd Build && cmake \ -D "BUILD_PACKAGE=dmg-cli" \ -D "CMAKE_INSTALL_PREFIX=${prefix}" \ @@ -8709,7 +8712,7 @@ pack-dmg: ### @brief debian arm package ################################################################################ -.PHONY: pack-arm +.PHONY: pack-arm pack-arm-cmake pack-arm: rm -rf Build && mkdir Build @@ -8723,6 +8726,9 @@ pack-arm: --enable-all-in-one-libev \ --disable-mruby + ${MAKE} pack-arm-cmake + +pack-arm-cmake: cd Build && cmake \ -D "BUILD_PACKAGE=debian" \ -D "CMAKE_INSTALL_PREFIX=${prefix}" \