Ejemplo n.º 1
0
Archivo: static.c Proyecto: GNOME/geary
/*
** Register a tokenizer implementation with FTS3 or FTS4.
*/
static int registerTokenizer(
    sqlite3 *db,
    char *zName,
    const sqlite3_tokenizer_module *p
) {
    int rc;
    sqlite3_stmt *pStmt;
    const char *zSql = "SELECT fts3_tokenizer(?, ?)";

#ifdef HAVE_FTS3_TOKENIZER
    /* Enable the 2-argument form of fts3_tokenizer in SQLite >= 3.12 */
    rc = sqlite3_db_config(db,SQLITE_DBCONFIG_ENABLE_FTS3_TOKENIZER,1,0);
    if( rc!=SQLITE_OK ) {
        return rc;
    }
#endif

    rc = sqlite3_prepare_v2(db, zSql, -1, &pStmt, 0);
    if( rc!=SQLITE_OK ) {
        return rc;
    }

    sqlite3_bind_text(pStmt, 1, zName, -1, SQLITE_STATIC);
    sqlite3_bind_blob(pStmt, 2, &p, sizeof(p), SQLITE_STATIC);
    sqlite3_step(pStmt);

    return sqlite3_finalize(pStmt);
}
Ejemplo n.º 2
0
// Load an extension into the sqlite database. Only affects the current connection.
// Parameter details can be found here: http://www.sqlite.org/c3ref/load_extension.html
void Database::loadExtension(const char* apExtensionName, const char *apEntryPointName)
{
#ifdef SQLITE_OMIT_LOAD_EXTENSION
    // Unused
    (void)apExtensionName;
    (void)apEntryPointName;

    throw std::runtime_error("sqlite extensions are disabled");
#else
#ifdef SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION // Since SQLite 3.13 (2016-05-18):
    // Security warning:
    // It is recommended that the SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION method be used to enable only this interface.
    // The use of the sqlite3_enable_load_extension() interface should be avoided to keep the SQL load_extension()
    // disabled and prevent SQL injections from giving attackers access to extension loading capabilities.
    // (NOTE: not using nullptr: cannot pass object of non-POD type 'std::__1::nullptr_t' through variadic function)
    int ret = sqlite3_db_config(mpSQLite, SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION, 1, NULL); // NOTE: not using nullptr
#else
    int ret = sqlite3_enable_load_extension(mpSQLite, 1);
#endif
    check(ret);

    ret = sqlite3_load_extension(mpSQLite, apExtensionName, apEntryPointName, 0);
    check(ret);
#endif
}
Ejemplo n.º 3
0
void Handle::setConfig(Handle::Config config, bool enable)
{
    int dbConfig;
    switch (config) {
        case Config::Fts3Tokenizer:
            dbConfig = SQLITE_DBCONFIG_ENABLE_FTS3_TOKENIZER;
            break;
    }
    sqlite3_db_config((sqlite3 *) m_handle, dbConfig, enable, nullptr);
}
Ejemplo n.º 4
0
bool DB::Connection::connect(const char *
#if HAVE_SQL_TRACE
							 connectionLabel
#endif
							 )
{
	// Create and set file permissions if the DB does not exist.
	int fd = open(_dbpath.c_str(), O_CREAT, S_IRUSR | S_IWUSR);
	if (fd == -1)
	{
		DB::logError("Could not open database: %s (errno %i)",
			     _dbpath.c_str(), errno);
		return false;
	}
	::close(fd);

	int rv = sqlite3_open_v2(_dbpath.c_str(),
							 &_db,
							 SQLITE_OPEN_READWRITE
							 | SQLITE_OPEN_CREATE
							 | SQLITE_OPEN_FULLMUTEX,
							 NULL);

	if (rv != SQLITE_OK) {
		reportErrorDB(_db);
		return false;
	}

	int foreignKeyEnabled = 0;
	rv = sqlite3_db_config(_db,SQLITE_DBCONFIG_ENABLE_FKEY,1,&foreignKeyEnabled);
	if (rv != SQLITE_OK) {
		reportErrorDB(_db);
		return false;
	}

	if (foreignKeyEnabled != 1) {
		DB::logError("Connection::connect: foreign key support not enabled");
		return false;
	}

	rv = sqlite3_busy_timeout(_db, 15000); // 15 seconds
	if (rv != SQLITE_OK) {
		reportErrorDB(_db);
		return false;
	}
#if HAVE_SQL_TRACE
	sqlite3_trace(_db, xTrace, const_cast<char *>(connectionLabel));
#endif
	return true;
}
Ejemplo n.º 5
0
bool DB::Connection::connect(const char *
#if HAVE_SQL_TRACE
							 connectionLabel
#endif
							 )
{
	// Circumvent the sqlite3 reliance on umask to enforce secure permissions
	mode_t saved_umask = umask(S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH);

	int rv = sqlite3_open_v2(_dbpath.c_str(),
							 &_db,
							 SQLITE_OPEN_READWRITE
							 | SQLITE_OPEN_CREATE
							 | SQLITE_OPEN_FULLMUTEX,
							 NULL);
	// Restore umask to avoid side effects
	(void) umask(saved_umask);

	if (rv != SQLITE_OK) {
		reportErrorDB(_db);
		return false;
	}

	int foreignKeyEnabled = 0;
	rv = sqlite3_db_config(_db,SQLITE_DBCONFIG_ENABLE_FKEY,1,&foreignKeyEnabled);
	if (rv != SQLITE_OK) {
		reportErrorDB(_db);
		return false;
	}

	if (foreignKeyEnabled != 1) {
		DB::logError("Connection::connect: foreign key support not enabled");
		return false;
	}

	rv = sqlite3_busy_timeout(_db, 15000); // 15 seconds
	if (rv != SQLITE_OK) {
		reportErrorDB(_db);
		return false;
	}
#if HAVE_SQL_TRACE
	sqlite3_trace(_db, xTrace, const_cast<char *>(connectionLabel));
#endif
	return true;
}
Ejemplo n.º 6
0
 int database::enable_triggers(bool enable)
 {
   return sqlite3_db_config(db_, SQLITE_DBCONFIG_ENABLE_TRIGGER, enable ? 1 : 0, nullptr);
 }
Ejemplo n.º 7
0
 int database::enable_foreign_keys(bool enable)
 {
   return sqlite3_db_config(db_, SQLITE_DBCONFIG_ENABLE_FKEY, enable ? 1 : 0, nullptr);
 }
Ejemplo n.º 8
0
/**
@SYMTestCaseID			SYSLIB-SQLITE3-UT-4004
@SYMTestCaseDesc		Database handle SQLITE3 tests.
						List of called SQLITE3 functions:
						 - sqlite3_config;
						 - sqlite3_initialize;
						 - sqlite3_threadsafe;
						 - sqlite3_vfs_find;
						 - sqlite3_open;
						 - sqlite3_db_config;
						 - sqlite3_libversion;
						 - sqlite3_libversion_number;
						 - sqlite3_set_authorizer;
						 - sqlite3_commit_hook;
						 - sqlite3_rollback_hook;
						 - sqlite3_update_hook;
						 - sqlite3_close;
						 - sqlite3_shutdown;
@SYMTestPriority		High
@SYMTestActions			Database handle SQLITE3 tests.
@SYMTestExpectedResults Test must not fail
@SYMREQ					REQ8782
*/
static void TestSqliteApi()
	{
	void* prev = 0;
	const char* libverstr = 0;
	int libvernum = 0;
	int err;
	int threadSafe = -1;
	sqlite3_vfs* vfs = 0;

	TEST(!TheDb);
	
	TestStart("@SYMTestCaseID:SYSLIB-SQLITE3-UT-4004: Test \"sqlite3_config()\"");
	err = sqlite3_config(SQLITE_CONFIG_MEMSTATUS, 0);
	TEST2(err, SQLITE_OK);
	
	TestNext("Test \"sqlite3_initialize()\"");
	err = sqlite3_initialize();
	TEST2(err, SQLITE_OK);

	TestNext("Test \"sqlite3_threadsafe()\"");
	threadSafe = sqlite3_threadsafe();
	PrintI("SQLITE_THREADSAFE=%d\r\n", threadSafe);
	
	vfs = sqlite3_vfs_find(0);
	TEST(vfs != NULL);
	PrintS("Vfs name=\"%s\"\r\n", vfs->zName);
	
	err = sqlite3_open(TheTestDbName, &TheDb);
	TEST2(err, SQLITE_OK);
	TEST(TheDb != 0);
	
	err = sqlite3_db_config(TheDb, SQLITE_DBCONFIG_LOOKASIDE, 0, 128, 100);
	TEST2(err, SQLITE_OK);
	
	libverstr = sqlite3_libversion();
	libvernum = sqlite3_libversion_number();
	PrintSI("SQLITE version: \"%s\", Number: %d\r\n", libverstr, libvernum);
	
	err = sqlite3_set_authorizer(TheDb, &authorizer_callback, 0);
	TEST2(err, SQLITE_OK);
	
	prev = sqlite3_commit_hook(TheDb, &commit_hook, 0);
	TEST(!prev);
	prev = sqlite3_rollback_hook(TheDb, &rollback_hook, 0);
	TEST(!prev);
	prev = sqlite3_update_hook(TheDb, &update_hook, 0);
	TEST(!prev);
	
	TestNext("@SYMTestCaseID:SYSLIB-SQLITE3-UT-4001: Test \"sqlite3\" handle API");
	TestExec();
	TestNext("@SYMTestCaseID:SYSLIB-SQLITE3-UT-4002: Test \"sqlite3_stmt\" handle API-1");
	TestStatement1();
	TestNext("@SYMTestCaseID:SYSLIB-SQLITE3-UT-4003: Test \"sqlite3_stmt\" handle API-2");
	TestStatement2();
	TestNext("@SYMTestCaseID:PDS-SQLITE3-UT-4038: Test more sqlite3 API");
	TestSqliteApi2();
	TestNext("@SYMTestCaseID:PDS-SQLITE3-UT-4039: Test blob API");
	TestSqliteBlobApi();
	TestNext("@SYMTestCaseID:PDS-SQLITE3-UT-4040: Test mutex API");
	TestSqliteMutexApi();

	err = sqlite3_close(TheDb);
	TEST2(err, SQLITE_OK);
	TheDb = 0;
	
	TestNext("Test \"sqlite3_shutdown()\"");
	err = sqlite3_shutdown();
	TEST2(err, SQLITE_OK);
	
	err = remove(TheTestDbName);
	TEST2(err, 0);
	}
Ejemplo n.º 9
0
QSqlDatabase Database::Connect() {
  QMutexLocker l(&connect_mutex_);

  // Create the directory if it doesn't exist
  if (!QFile::exists(directory_)) {
    QDir dir;
    if (!dir.mkpath(directory_)) {
    }
  }

  const QString connection_id = QString("%1_thread_%2").arg(connection_id_).arg(
      reinterpret_cast<quint64>(QThread::currentThread()));

  // Try to find an existing connection for this thread
  QSqlDatabase db = QSqlDatabase::database(connection_id);
  if (db.isOpen()) {
    return db;
  }

  db = QSqlDatabase::addDatabase("QSQLITE", connection_id);

  if (!injected_database_name_.isNull())
    db.setDatabaseName(injected_database_name_);
  else
    db.setDatabaseName(directory_ + "/" + kDatabaseFilename);

  if (!db.open()) {
    app_->AddError("Database: " + db.lastError().text());
    return db;
  }

  // Find Sqlite3 functions in the Qt plugin.
  StaticInit();

  {

#ifdef SQLITE_DBCONFIG_ENABLE_FTS3_TOKENIZER
    // In case sqlite>=3.12 is compiled without -DSQLITE_ENABLE_FTS3_TOKENIZER (generally a good idea 
    // due to security reasons) the fts3 support should be enabled explicitly.
    // see https://github.com/clementine-player/Clementine/issues/5297
    //
    // See https://www.sqlite.org/fts3.html#custom_application_defined_tokenizers
    QVariant v = db.driver()->handle();
    if (v.isValid() && qstrcmp(v.typeName(), "sqlite3*") == 0) {
      sqlite3* handle = *static_cast<sqlite3**>(v.data());
      if (!handle || sqlite3_db_config(handle, SQLITE_DBCONFIG_ENABLE_FTS3_TOKENIZER, 1, nullptr) != SQLITE_OK) {
        qLog(Fatal) << "Failed to enable FTS3 tokenizer";
      }
    }
#endif

    QSqlQuery set_fts_tokenizer("SELECT fts3_tokenizer(:name, :pointer)", db);
    set_fts_tokenizer.bindValue(":name", "unicode");
    set_fts_tokenizer.bindValue(
        ":pointer", QByteArray(reinterpret_cast<const char*>(&sFTSTokenizer),
                               sizeof(&sFTSTokenizer)));
    if (!set_fts_tokenizer.exec()) {
      qLog(Warning) << "Couldn't register FTS3 tokenizer";
    }
    // Implicit invocation of ~QSqlQuery() when leaving the scope
    // to release any remaining database locks!
  }

  if (db.tables().count() == 0) {
    // Set up initial schema
    qLog(Info) << "Creating initial database schema";
    UpdateDatabaseSchema(0, db);
  }

  // Attach external databases
  for (const QString& key : attached_databases_.keys()) {
    QString filename = attached_databases_[key].filename_;

    if (!injected_database_name_.isNull()) filename = injected_database_name_;

    // Attach the db
    QSqlQuery q("ATTACH DATABASE :filename AS :alias", db);
    q.bindValue(":filename", filename);
    q.bindValue(":alias", key);
    if (!q.exec()) {
      qFatal("Couldn't attach external database '%s'",
             key.toAscii().constData());
    }
  }

  if (startup_schema_version_ == -1) {
    UpdateMainSchema(&db);
  }

  // We might have to initialise the schema in some attached databases now, if
  // they were deleted and don't match up with the main schema version.
  for (const QString& key : attached_databases_.keys()) {
    if (attached_databases_[key].is_temporary_ &&
        attached_databases_[key].schema_.isEmpty())
      continue;
    // Find out if there are any tables in this database
    QSqlQuery q(QString(
                    "SELECT ROWID FROM %1.sqlite_master"
                    " WHERE type='table'").arg(key),
                db);
    if (!q.exec() || !q.next()) {
      q.finish();
      ExecSchemaCommandsFromFile(db, attached_databases_[key].schema_, 0);
    }
  }

  return db;
}