net.sourceforge.jtds
jtds
diff --git a/build/ci/updater/src/main/java/com/igniterealtime/openfire/updaterunner/Main.java b/build/ci/updater/src/main/java/com/igniterealtime/openfire/updaterunner/Main.java
index e5706163f8..97ae75712e 100644
--- a/build/ci/updater/src/main/java/com/igniterealtime/openfire/updaterunner/Main.java
+++ b/build/ci/updater/src/main/java/com/igniterealtime/openfire/updaterunner/Main.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2021-2025 Ignite Realtime Foundation. All rights reserved.
+ * Copyright (C) 2021-2026 Ignite Realtime Foundation. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -49,6 +49,7 @@ public static void main(String[] args) throws Exception
"Oracle","oracle.jdbc.driver.OracleDriver","jdbc:oracle:thin:@HOSTNAME:1521:SID"
"Microsoft SQL Server (legacy)","net.sourceforge.jtds.jdbc.Driver","jdbc:jtds:sqlserver://HOSTNAME/DATABASENAME;appName=Openfire"
"PostgreSQL","org.postgresql.Driver","jdbc:postgresql://HOSTNAME:5432/DATABASENAME"
+ "Firebird","org.firebirdsql.jdbc.FBDriver","jdbc:firebirdsql://HOSTNAME:3050//ABSOLUTE_PATH_TO_DATABASE_FILE"
"IBM DB2","com.ibm.db2.jcc.DB2Driver","jdbc:db2://HOSTNAME:50000/DATABASENAME"
"Microsoft SQL Server","com.microsoft.sqlserver.jdbc.SQLServerDriver","jdbc:sqlserver://HOSTNAME:1433;databaseName=DATABASENAME;applicationName=Openfire"
*/
diff --git a/distribution/src/database/openfire_firebird.sql b/distribution/src/database/openfire_firebird.sql
new file mode 100644
index 0000000000..8479488d75
--- /dev/null
+++ b/distribution/src/database/openfire_firebird.sql
@@ -0,0 +1,441 @@
+-- In Firebird, TEXT is represented as BLOB SUB_TYPE TEXT CHARACTER SET UTF8.
+
+CREATE TABLE ofUser
+(
+ username VARCHAR(64) NOT NULL,
+ storedKey VARCHAR(32),
+ serverKey VARCHAR(32),
+ salt VARCHAR(32),
+ iterations INTEGER,
+ plainPassword VARCHAR(32),
+ encryptedPassword VARCHAR(255),
+ name VARCHAR(100),
+ email VARCHAR(100),
+ creationDate CHAR(15) NOT NULL,
+ modificationDate CHAR(15) NOT NULL,
+ CONSTRAINT ofUser_pk PRIMARY KEY (username)
+);
+CREATE INDEX ofUser_cDate_idx ON ofUser (creationDate);
+
+
+CREATE TABLE ofUserProp
+(
+ username VARCHAR(64) NOT NULL,
+ name VARCHAR(100) NOT NULL,
+ propValue BLOB SUB_TYPE TEXT CHARACTER SET UTF8 NOT NULL,
+ CONSTRAINT ofUserProp_pk PRIMARY KEY (username, name)
+);
+
+
+CREATE TABLE ofUserFlag
+(
+ username VARCHAR(64) NOT NULL,
+ name VARCHAR(100) NOT NULL,
+ startTime CHAR(15),
+ endTime CHAR(15),
+ CONSTRAINT ofUserFlag_pk PRIMARY KEY (username, name)
+);
+CREATE INDEX ofUserFlag_sTime_idx ON ofUserFlag (startTime);
+CREATE INDEX ofUserFlag_eTime_idx ON ofUserFlag (endTime);
+
+
+CREATE TABLE ofOffline
+(
+ username VARCHAR(64) NOT NULL,
+ messageID INTEGER NOT NULL,
+ creationDate CHAR(15) NOT NULL,
+ messageSize INTEGER NOT NULL,
+ stanza BLOB SUB_TYPE TEXT CHARACTER SET UTF8 NOT NULL,
+ CONSTRAINT ofOffline_pk PRIMARY KEY (username, messageID)
+);
+
+
+CREATE TABLE ofPresence
+(
+ username VARCHAR(64) NOT NULL,
+ offlinePresence BLOB SUB_TYPE TEXT CHARACTER SET UTF8,
+ offlineDate VARCHAR(15) NOT NULL,
+ CONSTRAINT ofPresence_pk PRIMARY KEY (username)
+);
+
+
+CREATE TABLE ofRoster
+(
+ rosterID INTEGER NOT NULL,
+ username VARCHAR(64) NOT NULL,
+ jid VARCHAR(1024) NOT NULL,
+ sub INTEGER NOT NULL,
+ ask INTEGER NOT NULL,
+ recv INTEGER NOT NULL,
+ nick VARCHAR(255),
+ stanza BLOB SUB_TYPE TEXT CHARACTER SET UTF8,
+ CONSTRAINT ofRoster_pk PRIMARY KEY (rosterID)
+);
+CREATE INDEX ofRoster_username_idx ON ofRoster (username);
+CREATE INDEX ofRoster_jid_idx ON ofRoster (jid);
+
+
+CREATE TABLE ofRosterGroups
+(
+ rosterID INTEGER NOT NULL,
+ rank INTEGER NOT NULL,
+ groupName VARCHAR(255) NOT NULL,
+ CONSTRAINT ofRosterGroups_pk PRIMARY KEY (rosterID, rank)
+);
+CREATE INDEX ofRosterGroups_rosterID_idx ON ofRosterGroups (rosterID);
+ALTER TABLE ofRosterGroups
+ ADD CONSTRAINT ofRosterGroups_rosterID_fk FOREIGN KEY (rosterID) REFERENCES ofRoster;
+
+
+CREATE TABLE ofVCard
+(
+ username VARCHAR(64) NOT NULL,
+ vcard BLOB SUB_TYPE TEXT CHARACTER SET UTF8 NOT NULL,
+ CONSTRAINT ofVCard_pk PRIMARY KEY (username)
+);
+
+
+CREATE TABLE ofGroup
+(
+ groupName VARCHAR(50) NOT NULL,
+ description VARCHAR(255),
+ CONSTRAINT ofGroup_pk PRIMARY KEY (groupName)
+);
+
+
+CREATE TABLE ofGroupProp
+(
+ groupName VARCHAR(50) NOT NULL,
+ name VARCHAR(100) NOT NULL,
+ propValue BLOB SUB_TYPE TEXT CHARACTER SET UTF8 NOT NULL,
+ CONSTRAINT ofGroupProp_pk PRIMARY KEY (groupName, name)
+);
+
+
+CREATE TABLE ofGroupUser
+(
+ groupName VARCHAR(50) NOT NULL,
+ username VARCHAR(100) NOT NULL,
+ administrator INTEGER NOT NULL,
+ CONSTRAINT ofGroupUser_pk PRIMARY KEY (groupName, username, administrator)
+);
+
+
+CREATE TABLE ofID
+(
+ idType INTEGER NOT NULL,
+ id INTEGER NOT NULL,
+ CONSTRAINT ofID_pk PRIMARY KEY (idType)
+);
+
+
+CREATE TABLE ofProperty
+(
+ name VARCHAR(100) NOT NULL,
+ propValue VARCHAR(4000) NOT NULL,
+ encrypted INTEGER,
+ iv CHAR(24),
+ CONSTRAINT ofProperty_pk PRIMARY KEY (name)
+);
+
+
+CREATE TABLE ofVersion
+(
+ name VARCHAR(50) NOT NULL,
+ version INTEGER NOT NULL,
+ CONSTRAINT ofVersion_pk PRIMARY KEY (name)
+);
+
+CREATE TABLE ofExtComponentConf
+(
+ subdomain VARCHAR(255) NOT NULL,
+ wildcard INTEGER NOT NULL,
+ secret VARCHAR(255),
+ permission VARCHAR(10) NOT NULL,
+ CONSTRAINT ofExtComponentConf_pk PRIMARY KEY (subdomain)
+);
+
+CREATE TABLE ofRemoteServerConf
+(
+ xmppDomain VARCHAR(255) NOT NULL,
+ remotePort INTEGER,
+ permission VARCHAR(10) NOT NULL,
+ CONSTRAINT ofRemoteServerConf_pk PRIMARY KEY (xmppDomain)
+);
+
+CREATE TABLE ofPrivacyList
+(
+ username VARCHAR(64) NOT NULL,
+ name VARCHAR(100) NOT NULL,
+ isDefault INTEGER NOT NULL,
+ list BLOB SUB_TYPE TEXT CHARACTER SET UTF8 NOT NULL,
+ CONSTRAINT ofPrivacyList_pk PRIMARY KEY (username, name)
+);
+CREATE INDEX ofPrivacyList_default_idx ON ofPrivacyList (username, isDefault);
+
+CREATE TABLE ofSecurityAuditLog
+(
+ msgID INTEGER NOT NULL,
+ username VARCHAR(64) NOT NULL,
+ entryStamp BIGINT NOT NULL,
+ summary VARCHAR(255) NOT NULL,
+ node VARCHAR(255) NOT NULL,
+ details BLOB SUB_TYPE TEXT CHARACTER SET UTF8,
+ CONSTRAINT ofSecurityAuditLog_pk PRIMARY KEY (msgID)
+);
+CREATE INDEX ofSecurityAuditLog_tstamp_idx ON ofSecurityAuditLog (entryStamp);
+CREATE INDEX ofSecurityAuditLog_uname_idx ON ofSecurityAuditLog (username);
+
+-- MUC Tables
+
+CREATE TABLE ofMucService
+(
+ serviceID INTEGER NOT NULL,
+ subdomain VARCHAR(255) NOT NULL,
+ description VARCHAR(255),
+ isHidden INTEGER NOT NULL,
+ CONSTRAINT ofMucService_pk PRIMARY KEY (subdomain)
+);
+CREATE INDEX ofMucService_serviceid_idx ON ofMucService (serviceID);
+
+CREATE TABLE ofMucServiceProp
+(
+ serviceID INTEGER NOT NULL,
+ name VARCHAR(100) NOT NULL,
+ propValue BLOB SUB_TYPE TEXT CHARACTER SET UTF8 NOT NULL,
+ CONSTRAINT ofMucServiceProp_pk PRIMARY KEY (serviceID, name)
+);
+
+CREATE TABLE ofMucRoom
+(
+ serviceID INTEGER NOT NULL,
+ roomID INTEGER NOT NULL,
+ creationDate CHAR(15) NOT NULL,
+ modificationDate CHAR(15) NOT NULL,
+ name VARCHAR(50) NOT NULL,
+ naturalName VARCHAR(255) NOT NULL,
+ description VARCHAR(255),
+ lockedDate CHAR(15) NOT NULL,
+ emptyDate CHAR(15),
+ canChangeSubject INTEGER NOT NULL,
+ maxUsers INTEGER NOT NULL,
+ publicRoom INTEGER NOT NULL,
+ moderated INTEGER NOT NULL,
+ membersOnly INTEGER NOT NULL,
+ canInvite INTEGER NOT NULL,
+ roomPassword VARCHAR(50),
+ canDiscoverJID INTEGER NOT NULL,
+ logEnabled INTEGER NOT NULL,
+ retireOnDeletion INTEGER NOT NULL,
+ preserveHistOnDel INTEGER NOT NULL,
+ subject BLOB SUB_TYPE TEXT CHARACTER SET UTF8,
+ rolesToBroadcast INTEGER NOT NULL,
+ useReservedNick INTEGER NOT NULL,
+ canChangeNick INTEGER NOT NULL,
+ canRegister INTEGER NOT NULL,
+ allowpm INTEGER,
+ fmucEnabled INTEGER,
+ fmucOutboundNode BLOB SUB_TYPE TEXT CHARACTER SET UTF8,
+ fmucOutboundMode INTEGER,
+ fmucInboundNodes BLOB SUB_TYPE TEXT CHARACTER SET UTF8,
+ CONSTRAINT ofMucRoom_pk PRIMARY KEY (serviceID, name)
+);
+CREATE INDEX ofMucRoom_roomid_idx ON ofMucRoom (roomID);
+CREATE INDEX ofMucRoom_serviceid_idx ON ofMucRoom (serviceID);
+
+CREATE TABLE ofMucRoomProp
+(
+ roomID INTEGER NOT NULL,
+ name VARCHAR(100) NOT NULL,
+ propValue BLOB SUB_TYPE TEXT CHARACTER SET UTF8 NOT NULL,
+ CONSTRAINT ofMucRoomProp_pk PRIMARY KEY (roomID, name)
+);
+
+CREATE TABLE ofMucRoomRetiree
+(
+ serviceID INTEGER NOT NULL,
+ name VARCHAR(50) NOT NULL,
+ alternateJID VARCHAR(2000),
+ reason VARCHAR(1024),
+ retiredAt TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
+ CONSTRAINT ofMucRoomRetiree_pk PRIMARY KEY (serviceID, name)
+);
+
+CREATE TABLE ofMucAffiliation
+(
+ roomID INTEGER NOT NULL,
+ jid VARCHAR(1024) NOT NULL,
+ affiliation INTEGER NOT NULL,
+ CONSTRAINT ofMucAffiliation_pk PRIMARY KEY (roomID, jid)
+);
+
+CREATE TABLE ofMucMember
+(
+ roomID INTEGER NOT NULL,
+ jid VARCHAR(1024) NOT NULL,
+ nickname VARCHAR(255),
+ firstName VARCHAR(100),
+ lastName VARCHAR(100),
+ url VARCHAR(100),
+ email VARCHAR(100),
+ faqentry VARCHAR(100),
+ CONSTRAINT ofMucMember_pk PRIMARY KEY (roomID, jid)
+);
+
+CREATE TABLE ofMucConversationLog
+(
+ roomID INTEGER NOT NULL,
+ messageID INTEGER NOT NULL,
+ sender VARCHAR(1024) NOT NULL,
+ nickname VARCHAR(255),
+ logTime CHAR(15) NOT NULL,
+ subject VARCHAR(255),
+ body BLOB SUB_TYPE TEXT CHARACTER SET UTF8,
+ stanza BLOB SUB_TYPE TEXT CHARACTER SET UTF8
+);
+CREATE INDEX ofMucConversationLog_roomtime_idx ON ofMucConversationLog (roomID, logTime);
+CREATE INDEX ofMucConversationLog_time_idx ON ofMucConversationLog (logTime);
+CREATE INDEX ofMucConversationLog_msg_id ON ofMucConversationLog (messageID);
+
+
+-- PubSub Tables
+
+CREATE TABLE ofPubsubNode
+(
+ serviceID VARCHAR(100) NOT NULL,
+ nodeID VARCHAR(100) NOT NULL,
+ leaf INTEGER NOT NULL,
+ creationDate CHAR(15) NOT NULL,
+ modificationDate CHAR(15) NOT NULL,
+ parent VARCHAR(100),
+ deliverPayloads INTEGER NOT NULL,
+ maxPayloadSize INTEGER,
+ persistItems INTEGER,
+ maxItems INTEGER,
+ notifyConfigChanges INTEGER NOT NULL,
+ notifyDelete INTEGER NOT NULL,
+ notifyRetract INTEGER NOT NULL,
+ presenceBased INTEGER NOT NULL,
+ sendItemSubscribe INTEGER NOT NULL,
+ publisherModel VARCHAR(15) NOT NULL,
+ subscriptionEnabled INTEGER NOT NULL,
+ configSubscription INTEGER NOT NULL,
+ accessModel VARCHAR(10) NOT NULL,
+ payloadType VARCHAR(100),
+ bodyXSLT VARCHAR(100),
+ dataformXSLT VARCHAR(100),
+ creator VARCHAR(1024) NOT NULL,
+ description VARCHAR(255),
+ language VARCHAR(255),
+ name VARCHAR(50),
+ replyPolicy VARCHAR(15),
+ associationPolicy VARCHAR(15),
+ maxLeafNodes INTEGER,
+ CONSTRAINT ofPubsubNode_pk PRIMARY KEY (serviceID, nodeID)
+);
+
+CREATE TABLE ofPubsubNodeJIDs
+(
+ serviceID VARCHAR(100) NOT NULL,
+ nodeID VARCHAR(100) NOT NULL,
+ jid VARCHAR(1024) NOT NULL,
+ associationType VARCHAR(20) NOT NULL,
+ CONSTRAINT ofPubsubNodeJIDs_pk PRIMARY KEY (serviceID, nodeID, jid)
+);
+
+CREATE TABLE ofPubsubNodeGroups
+(
+ serviceID VARCHAR(100) NOT NULL,
+ nodeID VARCHAR(100) NOT NULL,
+ rosterGroup VARCHAR(100) NOT NULL
+);
+CREATE INDEX ofPubsubNodeGroups_idx ON ofPubsubNodeGroups (serviceID, nodeID);
+
+CREATE TABLE ofPubsubAffiliation
+(
+ serviceID VARCHAR(100) NOT NULL,
+ nodeID VARCHAR(100) NOT NULL,
+ jid VARCHAR(1024) NOT NULL,
+ affiliation VARCHAR(10) NOT NULL,
+ CONSTRAINT ofPubsubAffiliation_pk PRIMARY KEY (serviceID, nodeID, jid)
+);
+
+CREATE TABLE ofPubsubItem
+(
+ serviceID VARCHAR(100) NOT NULL,
+ nodeID VARCHAR(100) NOT NULL,
+ id VARCHAR(100) NOT NULL,
+ jid VARCHAR(1024) NOT NULL,
+ creationDate CHAR(15) NOT NULL,
+ payload BLOB SUB_TYPE TEXT CHARACTER SET UTF8,
+ CONSTRAINT ofPubsubItem_pk PRIMARY KEY (serviceID, nodeID, id)
+);
+
+CREATE TABLE ofPubsubSubscription
+(
+ serviceID VARCHAR(100) NOT NULL,
+ nodeID VARCHAR(100) NOT NULL,
+ id VARCHAR(100) NOT NULL,
+ jid VARCHAR(1024) NOT NULL,
+ owner VARCHAR(1024) NOT NULL,
+ state VARCHAR(15) NOT NULL,
+ deliver INTEGER NOT NULL,
+ digest INTEGER NOT NULL,
+ digest_frequency INTEGER NOT NULL,
+ expire CHAR(15),
+ includeBody INTEGER NOT NULL,
+ showValues VARCHAR(30) NOT NULL,
+ subscriptionType VARCHAR(10) NOT NULL,
+ subscriptionDepth INTEGER NOT NULL,
+ keyword VARCHAR(200),
+ CONSTRAINT ofPubsubSubscription_pk PRIMARY KEY (serviceID, nodeID, id)
+);
+
+CREATE TABLE ofPubsubDefaultConf
+(
+ serviceID VARCHAR(100) NOT NULL,
+ leaf INTEGER NOT NULL,
+ deliverPayloads INTEGER NOT NULL,
+ maxPayloadSize INTEGER NOT NULL,
+ persistItems INTEGER NOT NULL,
+ maxItems INTEGER NOT NULL,
+ notifyConfigChanges INTEGER NOT NULL,
+ notifyDelete INTEGER NOT NULL,
+ notifyRetract INTEGER NOT NULL,
+ presenceBased INTEGER NOT NULL,
+ sendItemSubscribe INTEGER NOT NULL,
+ publisherModel VARCHAR(15) NOT NULL,
+ subscriptionEnabled INTEGER NOT NULL,
+ accessModel VARCHAR(10) NOT NULL,
+ language VARCHAR(255),
+ replyPolicy VARCHAR(15),
+ associationPolicy VARCHAR(15) NOT NULL,
+ maxLeafNodes INTEGER NOT NULL,
+ CONSTRAINT ofPubsubDefaultConf_pk PRIMARY KEY (serviceID, leaf)
+);
+
+-- Finally, insert default table values.
+
+INSERT INTO ofID (idType, id)
+VALUES (18, 1);
+INSERT INTO ofID (idType, id)
+VALUES (19, 1);
+INSERT INTO ofID (idType, id)
+VALUES (23, 1);
+INSERT INTO ofID (idType, id)
+VALUES (26, 2);
+INSERT INTO ofID (idType, id)
+VALUES (27, 1);
+
+-- Entry for admin user
+INSERT INTO ofUser (username, plainPassword, name, email, creationDate, modificationDate)
+VALUES ('admin', 'admin', 'Administrator', 'admin@example.com', '0', '0');
+
+-- Entry for default conference service
+INSERT INTO ofMucService (serviceID, subdomain, isHidden)
+VALUES (1, 'conference', 0);
+
+-- Do this last, as it is used by a continuous integration check to verify that the entire script was executed successfully.
+INSERT INTO ofVersion (name, version)
+VALUES ('openfire', 38);
+
diff --git a/documentation/database.html b/documentation/database.html
index 40901bfac0..59902ac1d9 100644
--- a/documentation/database.html
+++ b/documentation/database.html
@@ -28,7 +28,7 @@ Introduction
JDBC drivers are required for Openfire to communicate with your database. Suggested drivers for particular
databases are noted below where applicable. Openfire bundles JDBC drivers for MySQL, Oracle, PostgreSQL,
- Microsoft SQL Server, and HSQLDB.
+ Microsoft SQL Server, Firebird, and HSQLDB.
All supported database schemas can be found in the resources/database directory of the
@@ -48,6 +48,7 @@
Introduction
Oracle
Microsoft SQL Server
PostgreSQL
+ Firebird
IBM DB2
HSQLDB
@@ -333,6 +334,65 @@ Further Help
+
+
+ Firebird
+
+
+
+ JDBC Drivers
+
+
+ The JDBC driver for Firebird is bundled with Openfire, so you do not need to download and install a
+ separate driver.
+
+
+ In the Openfire web-based setup tool, use the following values:
+
+
+ - driver:
org.firebirdsql.jdbc.FBDriver
+ - server:
jdbc:firebirdsql://HOSTNAME:PORT//ABSOLUTE_PATH_TO_DATABASE_FILE
+
+
+ where HOSTNAME, PORT and ABSOLUTE_PATH_TO_DATABASE_FILE are the values for your setup. The default
+ Firebird port is 3050.
+
+
+
+
+
+
+ Setup Instructions
+
+
+ -
+ Create an empty Firebird database file that will be used by Openfire.
+
+ -
+ Ensure the configured user has read/write permissions on that database file.
+
+ -
+ Start the Openfire setup tool and configure the Firebird JDBC connection values.
+
+ -
+ Openfire will automatically install the schema from
resources/database/openfire_firebird.sql.
+
+
+
+
+
+
+
+
+
IBM DB2 7
diff --git a/xmppserver/pom.xml b/xmppserver/pom.xml
index 3984592fee..f3269275c2 100644
--- a/xmppserver/pom.xml
+++ b/xmppserver/pom.xml
@@ -472,6 +472,11 @@
postgresql
42.7.8
+