diff --git a/.github/workflows/continuous-integration-workflow.yml b/.github/workflows/continuous-integration-workflow.yml index b6bd796554..8f5d8edde9 100644 --- a/.github/workflows/continuous-integration-workflow.yml +++ b/.github/workflows/continuous-integration-workflow.yml @@ -603,6 +603,117 @@ jobs: ./mvnw -B clean package exec:java -Dexec.args="$GITHUB_WORKSPACE" + firebird-install: + name: Test Firebird install script + needs: [build, should-do-database-tests, check_branch] + runs-on: ubuntu-latest + if: ${{ needs.should-do-database-tests.outputs.check == 'true' || needs.check_branch.outputs.is_publishable_branch == 'true'}} + steps: + - name: Checkout Openfire + uses: actions/checkout@v6 + - name: Set up JDK 17 Zulu + uses: actions/setup-java@v5 + with: + java-version: 17 + distribution: zulu + cache: maven + - name: Restore mvn repo artifacts from build job + uses: actions/download-artifact@v8 + with: + name: Maven Repository + path: ~/.m2/repository/org/igniterealtime/openfire/ + - name: Set environment variables + run: | + echo "CONNECTION_STRING=jdbc:firebirdsql://localhost:3050//var/lib/firebird/data/openfire.fdb" >> $GITHUB_ENV + echo "CONNECTION_DRIVER=org.firebirdsql.jdbc.FBDriver" >> $GITHUB_ENV + echo "CONNECTION_USERNAME=sysdba" >> $GITHUB_ENV + echo "CONNECTION_PASSWORD=SecurePa55w0rd" >> $GITHUB_ENV + OPENFIREVSN=$(./mvnw help:evaluate -Dexpression=project.version -q -DforceStdout) + echo "OPENFIREVSN=$OPENFIREVSN" >> $GITHUB_ENV + echo "JAVA_HOME=$(echo $JAVA_HOME_17_X64)" >> $GITHUB_ENV + - name: Start database server with an empty database + run: | + mkdir olddb + docker compose -f ./build/ci/compose/firebird.yml up --wait + - name: Execute Openfire's database install script + run: | + pushd ./build/ci/updater + ./mvnw -B clean package exec:java -Dexec.args="$GITHUB_WORKSPACE" + + # Firebird support was added recently and upgrade scripts are not available yet by virtue of support being new. + # Skip Firebird upgrade execution until the target upgrade directory exists. This step can be removed completely + # after things have matured. + firebird-upgrade-precheck: + name: Check Firebird upgrade prerequisites + needs: [should-do-database-tests, check_branch] + runs-on: ubuntu-latest + if: ${{ needs.should-do-database-tests.outputs.check == 'true' || needs.check_branch.outputs.is_publishable_branch == 'true'}} + outputs: + upgrade-dir-exists: ${{ steps.check-firebird-upgrade-dir.outputs.exists }} + steps: + - name: Checkout Openfire + uses: actions/checkout@v6 + - name: Check if Firebird upgrade directory exists + id: check-firebird-upgrade-dir + run: | + if [ -d distribution/src/database/upgrade/39 ]; then + echo "exists=true" >> "$GITHUB_OUTPUT" + else + echo "exists=false" >> "$GITHUB_OUTPUT" + echo "Skipping firebird-upgrade: Firebird support is new and upgrade scripts are not available yet." + fi + + + firebird-upgrade: + name: Test Firebird upgrade scripts + needs: [build, should-do-database-tests, check_branch, firebird-upgrade-precheck] + runs-on: ubuntu-latest + if: ${{ needs.should-do-database-tests.outputs.check == 'true' || needs.check_branch.outputs.is_publishable_branch == 'true' }} + steps: + - name: Skip Firebird upgrade test when scripts are not available yet + if: ${{ needs.firebird-upgrade-precheck.outputs.upgrade-dir-exists != 'true' }} + run: 'echo "Skipping firebird-upgrade: Firebird support is new and upgrade scripts are not available yet."' + - name: Checkout Openfire + if: ${{ needs.firebird-upgrade-precheck.outputs.upgrade-dir-exists == 'true' }} + uses: actions/checkout@v6 + - name: Set up JDK 17 Zulu + if: ${{ needs.firebird-upgrade-precheck.outputs.upgrade-dir-exists == 'true' }} + uses: actions/setup-java@v5 + with: + java-version: 17 + distribution: zulu + cache: maven + - name: Restore mvn repo artifacts from build job + if: ${{ needs.firebird-upgrade-precheck.outputs.upgrade-dir-exists == 'true' }} + uses: actions/download-artifact@v8 + with: + name: Maven Repository + path: ~/.m2/repository/org/igniterealtime/openfire/ + - name: Set environment variables + if: ${{ needs.firebird-upgrade-precheck.outputs.upgrade-dir-exists == 'true' }} + run: | + echo "CONNECTION_STRING=jdbc:firebirdsql://localhost:3050//var/lib/firebird/data/openfire.fdb" >> $GITHUB_ENV + echo "CONNECTION_DRIVER=org.firebirdsql.jdbc.FBDriver" >> $GITHUB_ENV + echo "CONNECTION_USERNAME=sysdba" >> $GITHUB_ENV + echo "CONNECTION_PASSWORD=SecurePa55w0rd" >> $GITHUB_ENV + OPENFIREVSN=$(./mvnw help:evaluate -Dexpression=project.version -q -DforceStdout) + echo "OPENFIREVSN=$OPENFIREVSN" >> $GITHUB_ENV + echo "JAVA_HOME=$(echo $JAVA_HOME_17_X64)" >> $GITHUB_ENV + - name: Download an old Openfire database installation script + if: ${{ needs.firebird-upgrade-precheck.outputs.upgrade-dir-exists == 'true' }} + run: | + mkdir olddb + curl https://raw.githubusercontent.com/igniterealtime/Openfire/v5.1.0/distribution/src/database/openfire_firebird.sql > $GITHUB_WORKSPACE/olddb/openfire_firebird.sql + - name: Start database server, install old version of the Openfire database + if: ${{ needs.firebird-upgrade-precheck.outputs.upgrade-dir-exists == 'true' }} + run: docker compose -f ./build/ci/compose/firebird.yml up --wait + - name: Execute Openfire's database upgrade scripts + if: ${{ needs.firebird-upgrade-precheck.outputs.upgrade-dir-exists == 'true' }} + run: | + pushd ./build/ci/updater + ./mvnw -B clean package exec:java -Dexec.args="$GITHUB_WORKSPACE" + + mysql-install: name: Test MySQL install script needs: [build, should-do-database-tests, check_branch] @@ -768,7 +879,7 @@ jobs: publish-maven: name: Publish to Maven runs-on: ubuntu-latest - needs: [aioxmpp, connectivity, integration, xitf, check_branch, hsqldb-install, hsqldb-upgrade, sqlserver-install, sqlserver-upgrade, postgres-install, postgres-upgrade, mysql-install, mysql-upgrade, oracle-install, oracle-upgrade] + needs: [aioxmpp, connectivity, integration, xitf, check_branch, hsqldb-install, hsqldb-upgrade, sqlserver-install, sqlserver-upgrade, postgres-install, postgres-upgrade, firebird-install, firebird-upgrade, mysql-install, mysql-upgrade, oracle-install, oracle-upgrade] if: ${{github.repository == 'igniterealtime/Openfire' && github.event_name == 'push' && needs.check_branch.outputs.is_publishable_branch == 'true'}} steps: @@ -795,7 +906,7 @@ jobs: publish-docker: name: Publish to GitHub's Docker registry runs-on: ubuntu-latest - needs: [build-docker, aioxmpp, connectivity, integration, xitf, check_branch, hsqldb-install, hsqldb-upgrade, sqlserver-install, sqlserver-upgrade, postgres-install, postgres-upgrade, mysql-install, mysql-upgrade, oracle-install, oracle-upgrade] + needs: [build-docker, aioxmpp, connectivity, integration, xitf, check_branch, hsqldb-install, hsqldb-upgrade, sqlserver-install, sqlserver-upgrade, postgres-install, postgres-upgrade, firebird-install, firebird-upgrade, mysql-install, mysql-upgrade, oracle-install, oracle-upgrade] if: | github.event_name == 'push' && (contains(github.ref, 'refs/tags/') || github.ref == 'refs/heads/main') @@ -854,7 +965,7 @@ jobs: build-deb-artifact: name: Generate DEB artifact runs-on: ubuntu-latest - needs: [aioxmpp, connectivity, integration, xitf, check_branch, hsqldb-install, hsqldb-upgrade, sqlserver-install, sqlserver-upgrade, postgres-install, postgres-upgrade, mysql-install, mysql-upgrade, oracle-install, oracle-upgrade] + needs: [aioxmpp, connectivity, integration, xitf, check_branch, hsqldb-install, hsqldb-upgrade, sqlserver-install, sqlserver-upgrade, postgres-install, postgres-upgrade, firebird-install, firebird-upgrade, mysql-install, mysql-upgrade, oracle-install, oracle-upgrade] steps: - uses: actions/checkout@v6 with: diff --git a/build/ci/compose/firebird.yml b/build/ci/compose/firebird.yml new file mode 100644 index 0000000000..f284efd117 --- /dev/null +++ b/build/ci/compose/firebird.yml @@ -0,0 +1,16 @@ +services: + db: + image: firebirdsql/firebird:5.0.3 + ports: + - "3050:3050" + environment: + - FIREBIRD_DATABASE=openfire.fdb + - FIREBIRD_ROOT_PASSWORD=${CONNECTION_PASSWORD} + healthcheck: + test: [ "CMD-SHELL", "echo 'select 1 from rdb$$database;' | /opt/firebird/bin/isql -user SYSDBA -password $$FIREBIRD_ROOT_PASSWORD localhost/3050:/var/lib/firebird/data/$$FIREBIRD_DATABASE >/dev/null 2>&1" ] + interval: 5s + timeout: 10s + retries: 30 + volumes: + - ${GITHUB_WORKSPACE}/olddb:/var/lib/firebird/data + diff --git a/build/ci/updater/pom.xml b/build/ci/updater/pom.xml index 2213313305..f5b142eb54 100644 --- a/build/ci/updater/pom.xml +++ b/build/ci/updater/pom.xml @@ -64,6 +64,11 @@ postgresql 42.7.8 + + org.firebirdsql.jdbc + jaybird + 6.0.5 + 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

    + +
      +
    1. + Create an empty Firebird database file that will be used by Openfire. +
    2. +
    3. + Ensure the configured user has read/write permissions on that database file. +
    4. +
    5. + Start the Openfire setup tool and configure the Firebird JDBC connection values. +
    6. +
    7. + Openfire will automatically install the schema from resources/database/openfire_firebird.sql. +
    8. +
    + +
    + +
    + +

    Further Help

    + + + +
    + +
    +

    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 + + org.firebirdsql.jdbc + jaybird + 6.0.5 + net.sourceforge.jtds jtds diff --git a/xmppserver/src/main/java/org/jivesoftware/database/DbConnectionManager.java b/xmppserver/src/main/java/org/jivesoftware/database/DbConnectionManager.java index a8dfe3bbb8..2928a7a8f1 100644 --- a/xmppserver/src/main/java/org/jivesoftware/database/DbConnectionManager.java +++ b/xmppserver/src/main/java/org/jivesoftware/database/DbConnectionManager.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004-2008 Jive Software, 2017-2024 Ignite Realtime Foundation. All rights reserved. + * Copyright (C) 2004-2008 Jive Software, 2017-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. @@ -901,6 +901,10 @@ else if (dbName.contains("hsql")) { else if (dbName.contains("db2")) { databaseType = DatabaseType.db2; } + // Firebird properties. + else if (dbName.contains("firebird")) { + databaseType = DatabaseType.firebird; + } } /** @@ -994,6 +998,9 @@ else if (driver.contains("db2")) { else if (driver.contains("oracle")) { return "select 1 from dual"; } + else if (driver.contains("firebird")) { + return "select 1 from rdb$database"; + } else { return "select 1"; } @@ -1018,6 +1025,8 @@ public enum DatabaseType { db2, + firebird, + sqlserver, interbase, diff --git a/xmppserver/src/main/webapp/setup/setup-datasource-standard.jsp b/xmppserver/src/main/webapp/setup/setup-datasource-standard.jsp index af45464d39..5e5fe8a6c3 100644 --- a/xmppserver/src/main/webapp/setup/setup-datasource-standard.jsp +++ b/xmppserver/src/main/webapp/setup/setup-datasource-standard.jsp @@ -1,6 +1,6 @@ <%-- - - - Copyright (C) 2004-2008 Jive Software, 2017-2025 Ignite Realtime Foundation. All rights reserved. + - Copyright (C) 2004-2008 Jive Software, 2017-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. @@ -222,6 +222,7 @@ presets.add(new String[]{"Oracle","oracle.jdbc.driver.OracleDriver","jdbc:oracle:thin:@HOSTNAME:1521:SID"}); presets.add(new String[]{"Microsoft SQL Server (legacy)","net.sourceforge.jtds.jdbc.Driver","jdbc:jtds:sqlserver://HOSTNAME/DATABASENAME;appName=Openfire"}); presets.add(new String[]{"PostgreSQL","org.postgresql.Driver","jdbc:postgresql://HOSTNAME:5432/DATABASENAME"}); + presets.add(new String[]{"Firebird","org.firebirdsql.jdbc.FBDriver","jdbc:firebirdsql://HOSTNAME:3050//ABSOLUTE_PATH_TO_DATABASE_FILE"}); presets.add(new String[]{"IBM DB2","com.ibm.db2.jcc.DB2Driver","jdbc:db2://HOSTNAME:50000/DATABASENAME"}); presets.add(new String[]{"Microsoft SQL Server","com.microsoft.sqlserver.jdbc.SQLServerDriver","jdbc:sqlserver://HOSTNAME:1433;databaseName=DATABASENAME;applicationName=Openfire"}); pageContext.setAttribute("presets", presets );