Commit cfc880e2 authored by Matt Tucker's avatar Matt Tucker Committed by matt

Improved database upgrade system (JM-603). Added support for encrypted passwords (JM-291).

git-svn-id: http://svn.igniterealtime.org/svn/repos/wildfire/trunk@3593 b35dd754-fafc-0310-a699-88a17e54d16e
parent 3e0cd231
......@@ -9,9 +9,9 @@
<h1>Wildfire Database Schema Guide</h1>
<h2>Introduction</h2>
<p>
This document outlines the data type conventions and tables in the Jive
Wildfire 2.1 database schema. Some information, like column indexes and foreign keys, is
omitted. For this, please read the individual schema of the database you're interested in.
This document outlines the data type conventions and tables in the Wildfire database schema.
Some information, like column indexes and foreign keys, is omitted. For this, please read
the individual schema of the database you're interested in.
<br>
</p>
<h2>Data Type Conventions</h2>
......@@ -49,6 +49,7 @@ A <span class="primary-key">yellow row</span> denotes a primary key.
<li><a href="#jiveRosterGroups">jiveRosterGroups</a> </li>
<li><a href="#jivePrivacy">jivePrivacyList</a> </li>
<li><a href="#jiveVCard">jiveVCard</a> </li>
<li><a href="#jiveVersion">jiveVersion</a> </li>
<li><a href="#jiveProperty">jiveProperty</a><br>
</li>
<li><a href="#jiveExtComponentConf">jiveExtComponentConf</a> </li>
......@@ -326,7 +327,13 @@ Key)<br>
<td>password</td>
<td>VARCHAR</td>
<td>32</td>
<td>Password Data (plain-text or MD5 hash depending on settings)</td>
<td>Plain-text password data</td>
</tr>
<tr>
<td>encryptedPassword</td>
<td>VARCHAR</td>
<td>255</td>
<td>Encrypted password data (default)</td>
</tr>
<tr>
<td>name</td>
......@@ -592,6 +599,36 @@ roster)</th>
<br>
<br>
<br>
<a name="jiveVersion"></a>
<table class="dbtable">
<tbody>
<tr>
<th colspan="4">jiveVersion (contains product version information)</th>
</tr>
<tr>
<th>Column Name</th>
<th>Type</th>
<th>Length</th>
<th>Description</th>
</tr>
<tr class="primary-key">
<td>name</td>
<td>VARCHAR</td>
<td>50</td>
<td>Name of the item that version information is being tracked for (Primary Key)</td>
</tr>
<tr>
<td>version</td>
<td>INTEGER</td>
<td>n/a</td>
<td>The version number</td>
</tr>
</tbody>
</table>
&nbsp;<a href="#top" class="top">top of page</a>
<br>
<br>
<br>
<a name="jiveProperty"></a>
<table class="dbtable">
<tbody>
......
-- $RCSfile$
-- $Revision: 395 $
-- $Date: 2004-11-13 16:57:13 -0300 (Sat, 13 Nov 2004) $
-- upgrades from Wildfire 1.1.x to 2.0.x
-- jiveUser: Adds new column "username". Removes "nameVisible" & "emailVisible". Changes primary key
ALTER TABLE jiveUser ADD COLUMN username VARCHAR(32) NOT NULL;
ALTER TABLE jiveUser DROP COLUMN nameVisible;
......
// $RCSfile$
// $Revision: 395 $
// $Date: 2004-11-13 16:57:13 -0300 (Sat, 13 Nov 2004) $
// upgrades from Wildfire 1.1.x to 2.0.x
// jiveUser: Adds new column "username". Removes "nameVisible" & "emailVisible". Changes primary key
ALTER TABLE jiveUser ADD COLUMN username VARCHAR(32) NOT NULL;
ALTER TABLE jiveUser DROP COLUMN nameVisible;
......
# $RCSfile$
# $Revision: 395 $
# $Date: 2004-11-13 16:57:13 -0300 (Sat, 13 Nov 2004) $
# upgrades from Wildfire 1.1.x to 2.0.x
# jiveUser: Adds new column "username". Removes "nameVisible" & "emailVisible". Changes primary key
ALTER TABLE jiveUser ADD COLUMN username VARCHAR(32) NOT NULL;
ALTER TABLE jiveUser DROP COLUMN nameVisible;
......
REM // $RCSfile$
REM // $Revision: 784 $
REM // $Date: 2005-01-04 12:47:23 -0300 (Tue, 04 Jan 2005) $
REM // upgrades from Wildfire 1.1.x to 2.0.x
REM // jiveUser: Adds new column "username". Removes "nameVisible" & "emailVisible". Changes primary key
ALTER TABLE jiveUser ADD username VARCHAR2(32) NOT NULL;
ALTER TABLE jiveUser DROP COLUMN nameVisible;
......
-- $RCSfile$
-- $Revision: 395 $
-- $Date: 2004-11-13 16:57:13 -0300 (Sat, 13 Nov 2004) $
-- upgrades from Wildfire 1.1.x to 2.0.x
-- jiveUser: Adds new column "username". Removes "nameVisible" & "emailVisible". Changes primary key
ALTER TABLE jiveUser ADD COLUMN username VARCHAR(32) NOT NULL;
ALTER TABLE jiveUser DROP COLUMN nameVisible;
......
/* $RCSfile$ */
/* $Revision: 840 $ */
/* $Date: 2005-01-10 01:30:06 -0300 (Mon, 10 Jan 2005) $ */
/* upgrades from Wildfire 1.1.x to 2.0.x */
/* jiveUser: Adds new column "username". Removes "nameVisible" & "emailVisible". Changes primary key */
ALTER TABLE jiveUser ADD COLUMN username NVARCHAR(32) NOT NULL;
ALTER TABLE jiveUser DROP COLUMN nameVisible;
......
-- $RCSfile$
-- $Revision: 795 $
-- $Date: 2005-01-06 07:44:42 -0300 (Thu, 06 Jan 2005) $
-- upgrades from Wildfire 2.0.x to 2.1.0
-- jiveGroup: Recreate table from scratch
DROP TABLE jiveGroup;
CREATE TABLE jiveGroup (
......
-- $RCSfile$
-- $Revision: 1650 $
-- $Date: 2005-07-20 00:18:17 -0300 (Wed, 20 Jul 2005) $
-- upgrades from Wildfire 2.1.x to 2.2.0
-- Update jiveVersion to JM 2.2
UPDATE jiveVersion SET majorVersion=2, minorVersion=2;
......
// $RCSfile$
// $Revision: 1650 $
// $Date: 2005-07-20 00:18:17 -0300 (Wed, 20 Jul 2005) $
// upgrades from Wildfire 2.1.x to 2.2.0
// Update jiveVersion to JM 2.2
UPDATE jiveVersion SET majorVersion=2, minorVersion=2;
......
# $RCSfile$
# $Revision: 1650 $
# $Date: 2005-07-20 00:18:17 -0300 (Wed, 20 Jul 2005) $
# upgrades from Wildfire 2.1.x to 2.2.0
# Update jiveVersion to JM 2.2
UPDATE jiveVersion SET majorVersion=2, minorVersion=2;
......
REM // $RCSfile$
REM // $Revision: 1650 $
REM // $Date: 2005-07-20 00:18:17 -0300 (Wed, 20 Jul 2005) $
REM // upgrades from Wildfire 2.1.x to 2.2.0
REM // Update jiveVersion to JM 2.2
UPDATE jiveVersion SET majorVersion=2, minorVersion=2;
......
-- $RCSfile$
-- $Revision: 1650 $
-- $Date: 2005-07-20 00:18:17 -0300 (Wed, 20 Jul 2005) $
-- upgrades from Wildfire 2.1.x to 2.2.0
-- Update jiveVersion to JM 2.2
UPDATE jiveVersion SET majorVersion=2, minorVersion=2;
......
/* $RCSfile$ */
/* $Revision: 1650 $ */
/* $Date: 2005-07-20 00:18:17 -0300 (Wed, 20 Jul 2005) $ */
/* upgrades from Wildfire 2.1.x to 2.2.0 */
/* Update jiveVersion to JM 2.2 */
UPDATE jiveVersion SET majorVersion=2, minorVersion=2;
......
-- $RCSfile$
-- $Revision: 795 $
-- $Date: 2005-01-06 07:44:42 -0300 (Thu, 06 Jan 2005) $
-- upgrades from Wildfire 2.2.x to 2.4.0
-- Update jiveVersion to JM 2.4
UPDATE jiveVersion SET majorVersion=2, minorVersion=4;
......
// $RCSfile$
// $Revision: 795 $
// $Date: 2005-01-06 07:44:42 -0300 (Thu, 06 Jan 2005) $
// upgrades from Wildfire 2.2.x to 2.4.0
// Update jiveVersion to JM 2.4
UPDATE jiveVersion SET majorVersion=2, minorVersion=4;
......
# $RCSfile$
# $Revision: 1650 $
# $Date: 2005-07-20 00:18:17 -0300 (Wed, 20 Jul 2005) $
# upgrades from Wildfire 2.2.x to 2.4.0
# Update jiveVersion to JM 2.4
UPDATE jiveVersion SET majorVersion=2, minorVersion=4;
......
REM // $RCSfile$
REM // $Revision: 795 $
REM // $Date: 2005-01-06 07:44:42 -0300 (Thu, 06 Jan 2005) $
REM // upgrades from Wildfire 2.2.x to 2.4.0
REM // Update jiveVersion to JM 2.4
UPDATE jiveVersion SET majorVersion=2, minorVersion=4;
......
-- $RCSfile$
-- $Revision: 795 $
-- $Date: 2005-01-06 07:44:42 -0300 (Thu, 06 Jan 2005) $
-- upgrades from Wildfire 2.2.x to 2.4.0
-- Update jiveVersion to JM 2.4
UPDATE jiveVersion SET majorVersion=2, minorVersion=4;
......
/* $RCSfile$ */
/* $Revision: 840 $ */
/* $Date: 2005-01-10 01:30:06 -0300 (Mon, 10 Jan 2005) $ */
/* upgrades from Wildfire 2.2.x to 2.4.0 */
/* Update jiveVersion to JM 2.4 */
UPDATE jiveVersion SET majorVersion=2, minorVersion=4;
......
/* $RCSfile$ */
/* $Revision: 840 $ */
/* $Date: 2005-01-10 01:30:06 -0300 (Mon, 10 Jan 2005) $ */
/* upgrades from Wildfire 2.2.x to 2.4.0 */
/* Update jiveVersion to JM 2.4 */
UPDATE jiveVersion SET majorVersion=2, minorVersion=4;
......
-- $RCSfile$
-- $Revision: $
-- $Date: $
-- upgrades from Wildfire 2.4.x to 2.5.0
-- Update jiveVersion to Wildfire 2.5
UPDATE jiveVersion SET majorVersion=2, minorVersion=5;
......
// $RCSfile$
// $Revision: $
// $Date: $
// upgrades from Wildfire 2.4.x to 2.5.0
// Update jiveVersion to Wildfire 2.5
UPDATE jiveVersion SET majorVersion=2, minorVersion=5;
......
# $RCSfile$
# $Revision: $
# $Date: $
# upgrades from Wildfire 2.4.x to 2.5.0
# Update jiveVersion to Wildfire 2.5
UPDATE jiveVersion SET majorVersion=2, minorVersion=5;
......
REM // $RCSfile$
REM // $Revision: $
REM // $Date: $
REM // upgrades from Wildfire 2.4.x to 2.5.0
REM // Update jiveVersion to Wildfire 2.5
UPDATE jiveVersion SET majorVersion=2, minorVersion=5;
......
-- $RCSfile$
-- $Revision: $
-- $Date: $
-- upgrades from Wildfire 2.4.x to 2.5.0
-- Update jiveVersion to Wildfire 2.5
UPDATE jiveVersion SET majorVersion=2, minorVersion=5;
......
/* $RCSfile$ */
/* $Revision: $ */
/* $Date: $ */
/* upgrades from Wildfire 2.4.x to 2.5.0 */
/* Update jiveVersion to Wildfire 2.5 */
UPDATE jiveVersion SET majorVersion=2, minorVersion=5;
......
/* $RCSfile$ */
/* $Revision: $ */
/* $Date: $ */
/* upgrades from Wildfire 2.4.x to 2.5.0 */
/* Update jiveVersion to Wildfire 2.5 */
UPDATE jiveVersion SET majorVersion=2, minorVersion=5;
......
# $Revision: $
# $Date: $
# Update the jiveVersion table to new definition.
DROP TABLE jiveVersion;
CREATE TABLE jiveVersion (
name varchar(50) NOT NULL,
version INTEGER NOT NULL,
CONSTRAINT jiveVersion_pk PRIMARY KEY (name)
);
INSERT INTO jiveVersion (name, version) VALUES ("wildfire", 6);
# Make password column accept null, add encrypted password column.
ALTER TABLE jiveUser ALTER COLUMN password NULL;
ALTER TABLE jiveUser ADD COLUMN encryptedPassword VARCHAR(255) BEFORE name;
\ No newline at end of file
# $Revision: $
# $Date: $
# Update the jiveVersion table to new definition.
DROP TABLE jiveVersion;
CREATE TABLE jiveVersion (
name VARCHAR(50) NOT NULL,
version INTEGER NOT NULL,
PRIMARY KEY (name)
);
INSERT INTO jiveVersion (name, version) VALUES ("wildfire", 6);
# Make password column accept null, add encrypted password column.
ALTER TABLE jiveUser MODIFY password VARCHAR(32) NULL;
ALTER TABLE jiveUser ADD COLUMN encryptedPassword VARCHAR(255) NULL AFTER password;
\ No newline at end of file
-- $RCSfile$
-- $Revision: 1650 $
-- $Date: 2005-07-20 00:18:17 -0300 (Wed, 20 Jul 2005) $
CREATE TABLE jiveUser (
username VARCHAR(32) NOT NULL,
password VARCHAR(32) NOT NULL,
password VARCHAR(32),
encryptedPassword VARCHAR(255),
name VARCHAR(100),
email VARCHAR(100),
creationDate CHAR(15) NOT NULL,
......@@ -108,8 +108,9 @@ CREATE TABLE jiveProperty (
CREATE TABLE jiveVersion (
majorVersion INTEGER NOT NULL,
minorVersion INTEGER NOT NULL
name VARCHAR(50) NOT NULL,
version INTEGER NOT NULL,
CONSTRAINT jiveVersion_pk PRIMARY KEY (name)
);
CREATE TABLE jiveExtComponentConf (
......@@ -207,7 +208,7 @@ INSERT INTO jiveID (idType, id) VALUES (18, 1);
INSERT INTO jiveID (idType, id) VALUES (19, 1);
INSERT INTO jiveID (idType, id) VALUES (23, 1);
INSERT INTO jiveVersion (majorVersion, minorVersion) VALUES (2, 5);
INSERT INTO jiveVersion (name, version) VALUES ("wildfire", 6);
-- Entry for admin user
INSERT INTO jiveUser (username, password, name, email, creationDate, modificationDate)
......
// $RCSfile$
// $Revision: 1650 $
// $Date: 2005-07-20 00:18:17 -0300 (Wed, 20 Jul 2005) $
CREATE TABLE jiveUser (
username VARCHAR(32) NOT NULL,
password VARCHAR(32) NOT NULL,
password VARCHAR(32),
encryptedPassword VARCHAR(255),
name VARCHAR(100),
email VARCHAR(100),
creationDate VARCHAR(15) NOT NULL,
......@@ -108,8 +108,9 @@ CREATE TABLE jiveProperty (
CREATE TABLE jiveVersion (
majorVersion INTEGER NOT NULL,
minorVersion INTEGER NOT NULL
name varchar(50) NOT NULL,
version INTEGER NOT NULL,
CONSTRAINT jiveVersion_pk PRIMARY KEY (name)
);
CREATE TABLE jiveExtComponentConf (
......@@ -207,7 +208,7 @@ INSERT INTO jiveID (idType, id) VALUES (18, 1);
INSERT INTO jiveID (idType, id) VALUES (19, 1);
INSERT INTO jiveID (idType, id) VALUES (23, 1);
INSERT INTO jiveVersion (majorVersion, minorVersion) VALUES (2, 5);
INSERT INTO jiveVersion (name, minorVersion) VALUES ("wildfire", 6);
// Entry for admin user
INSERT INTO jiveUser (username, password, name, email, creationDate, modificationDate)
......
# $RCSfile$
# $Revision: 1650 $
# $Date: 2005-07-20 00:18:17 -0300 (Wed, 20 Jul 2005) $
CREATE TABLE jiveUser (
username VARCHAR(32) NOT NULL,
password VARCHAR(32) NOT NULL,
password VARCHAR(32),
encryptedPassword VARCHAR(255),
name VARCHAR(100),
email VARCHAR(100),
creationDate CHAR(15) NOT NULL,
......@@ -97,8 +97,9 @@ CREATE TABLE jiveProperty (
CREATE TABLE jiveVersion (
majorVersion INTEGER NOT NULL,
minorVersion INTEGER NOT NULL
name VARCHAR(50) NOT NULL,
version INTEGER NOT NULL,
PRIMARY KEY (name)
);
CREATE TABLE jiveExtComponentConf (
......@@ -195,7 +196,7 @@ INSERT INTO jiveID (idType, id) VALUES (18, 1);
INSERT INTO jiveID (idType, id) VALUES (19, 1);
INSERT INTO jiveID (idType, id) VALUES (23, 1);
INSERT INTO jiveVersion (majorVersion, minorVersion) VALUES (2, 5);
INSERT INTO jiveVersion (name, version) VALUES ("wildfire", 6);
# Entry for admin user
INSERT INTO jiveUser (username, password, name, email, creationDate, modificationDate)
......
REM // $RCSfile$
REM // $Revision: 1650 $
REM // $Date: 2005-07-20 00:18:17 -0300 (Wed, 20 Jul 2005) $
CREATE TABLE jiveUser (
username VARCHAR2(32) NOT NULL,
password VARCHAR2(32) NOT NULL,
password VARCHAR2(32),
encryptedPassword VARCHAR2(255),
name VARCHAR2(100),
email VARCHAR2(100),
creationDate CHAR(15) NOT NULL,
......@@ -103,8 +103,9 @@ CREATE TABLE jiveProperty (
);
CREATE TABLE jiveVersion (
majorVersion INTEGER NOT NULL,
minorVersion INTEGER NOT NULL
name VARCHAR2(50) NOT NULL,
version INTEGER NOT NULL,
CONSTRAINT jiveVersion_pk PRIMARY KEY (name)
);
CREATE TABLE jiveExtComponentConf (
......@@ -201,7 +202,7 @@ INSERT INTO jiveID (idType, id) VALUES (18, 1);
INSERT INTO jiveID (idType, id) VALUES (19, 1);
INSERT INTO jiveID (idType, id) VALUES (23, 1);
INSERT INTO jiveVersion (majorVersion, minorVersion) VALUES (2, 5);
INSERT INTO jiveVersion (name, version) VALUES ("wildfire", 6);
REM // Entry for admin user
INSERT INTO jiveUser (username, password, name, email, creationDate, modificationDate)
......
-- $RCSfile$
-- $Revision: 1650 $
-- $Date: 2005-07-20 00:18:17 -0300 (Wed, 20 Jul 2005) $
......@@ -6,7 +5,8 @@
CREATE TABLE jiveUser (
username VARCHAR(32) NOT NULL,
password VARCHAR(32) NOT NULL,
password VARCHAR(32),
encryptedPassword VARCHAR(255),
name VARCHAR(100),
email VARCHAR(100),
creationDate CHAR(15) NOT NULL,
......@@ -111,8 +111,9 @@ CREATE TABLE jiveProperty (
CREATE TABLE jiveVersion (
majorVersion INTEGER NOT NULL,
minorVersion INTEGER NOT NULL
name VARCHAR(50) NOT NULL,
version INTEGER NOT NULL,
CONSTRAINT jiveVersion_pk PRIMARY KEY (name)
);
CREATE TABLE jiveExtComponentConf (
......@@ -210,7 +211,7 @@ INSERT INTO jiveID (idType, id) VALUES (18, 1);
INSERT INTO jiveID (idType, id) VALUES (19, 1);
INSERT INTO jiveID (idType, id) VALUES (23, 1);
INSERT INTO jiveVersion (majorVersion, minorVersion) VALUES (2, 5);
INSERT INTO jiveVersion (name, version) VALUES ("wildfire", 6);
-- Entry for admin user
INSERT INTO jiveUser (username, password, name, email, creationDate, modificationDate)
......
/* $RCSfile$ */
/* $Revision: 1650 $ */
/* $Date: 2005-07-20 00:18:17 -0300 (Wed, 20 Jul 2005) $ */
/* $Revision: 1650 $ */
/* $Date: 2005-07-20 00:18:17 -0300 (Wed, 20 Jul 2005) $ */
CREATE TABLE jiveUser (
username NVARCHAR(32) NOT NULL,
password NVARCHAR(32) NOT NULL,
password NVARCHAR(32),
encryptedPassword NVARCHAR(255),
name NVARCHAR(100),
email VARCHAR(100),
creationDate CHAR(15) NOT NULL,
......@@ -102,15 +102,16 @@ CREATE TABLE jiveID (
CREATE TABLE jiveProperty (
name NVARCHAR(100) NOT NULL,
name NVARCHAR(100) NOT NULL,
propValue NTEXT NOT NULL,
CONSTRAINT jiveProperty_pk PRIMARY KEY (name)
);
CREATE TABLE jiveVersion (
majorVersion INTEGER NOT NULL,
minorVersion INTEGER NOT NULL
name NVARCHAR(50) NOT NULL,
version INTEGER NOT NULL,
CONSTRAINT jiveVersion_pk PRIMARY KEY (name)
);
CREATE TABLE jiveExtComponentConf (
......@@ -208,7 +209,7 @@ INSERT INTO jiveID (idType, id) VALUES (18, 1);
INSERT INTO jiveID (idType, id) VALUES (19, 1);
INSERT INTO jiveID (idType, id) VALUES (23, 1);
INSERT INTO jiveVersion (majorVersion, minorVersion) VALUES (2, 5);
INSERT INTO jiveVersion (name, version) VALUES ("wildfire", 6);
/* Entry for admin user */
INSERT INTO jiveUser (username, password, name, email, creationDate, modificationDate)
......
/* $RCSfile$ */
/* $Revision: 1650 $ */
/* $Date: 2005-07-19 20:18:17 -0700 (Tue, 19 Jul 2005) $ */
/* $Revision: 1650 $ */
/* $Date: 2005-07-19 20:18:17 -0700 (Tue, 19 Jul 2005) $ */
CREATE TABLE jiveUser (
username NVARCHAR(32) NOT NULL,
password NVARCHAR(32) NOT NULL,
password NVARCHAR(32) NULL,
encryptedPassword NVARCHAR(255) NULL,
name NVARCHAR(100) NULL,
email VARCHAR(100) NULL,
creationDate CHAR(15) NOT NULL,
......@@ -109,8 +109,9 @@ CREATE TABLE jiveProperty (
CREATE TABLE jiveVersion (
majorVersion INTEGER NOT NULL,
minorVersion INTEGER NOT NULL
name NVARCHAR(50) NOT NULL,
version INTEGER NOT NULL,
CONSTRAINT jiveVersion_pk PRIMARY KEY (name)
);
CREATE TABLE jiveExtComponentConf (
......@@ -208,7 +209,7 @@ INSERT INTO jiveID (idType, id) VALUES (18, 1);
INSERT INTO jiveID (idType, id) VALUES (19, 1);
INSERT INTO jiveID (idType, id) VALUES (23, 1);
INSERT INTO jiveVersion (majorVersion, minorVersion) VALUES (2, 5);
INSERT INTO jiveVersion (name, version) VALUES ("wildfire", 6);
/* Entry for admin user */
INSERT INTO jiveUser (username, password, name, email, creationDate, modificationDate)
......
......@@ -1502,3 +1502,10 @@ system.cache.desc.effectiveness=* Effectiveness measures how well your cache is
system.cache.total=Total:
system.cache.clear-selected=Clear Selected
# Upgrade process
upgrade.database.old_schema=Found old database version. Upgrading...
upgrade.database.unknown_db=Warning: database type unknown. You must manually upgrade your database.
upgrade.database.interbase_db=Warning: automatic upgrades of Interbase are not supported. You \
must manually upgrade your database.
upgrade.database.success=Database upgraded successfully.
upgrade.database.failure=Database upgrade failed. Please manually upgrade your database.
\ No newline at end of file
......@@ -871,14 +871,14 @@ server2server.settings.never_close=Inaktive Verbindungen nie schliessen.
server2server.settings.close_session=Verbindungen schliessen nachdem sie inaktiv waren f\u00fcr folgende Anzahl an Minuten
server2server.settings.allowed=Verbindung erlauben
server2server.settings.anyone=Jedem
server2server.settings.anyone_info=Jeder entfernte Server darf sich mit diesem Server verbinden. \
Die Tabelle unten benutzen um diese Einstellungen anzupassen.
server2server.settings.anyone_info=Jeder entfernte Server darf sich mit diesem Server verbinden. \
Die Tabelle unten benutzen um diese Einstellungen anzupassen.
server2server.settings.whitelist=Erlauben-Liste
server2server.settings.whitelist_info=Nur bestimmte Server haben die Erlaubnis sich mit diesem Server zu verbinden. \
Die Tabelle unten benutzen um die Server zu definieren.
server2server.settings.whitelist_info=Nur bestimmte Server haben die Erlaubnis sich mit diesem \
Server zu verbinden. Die Tabelle unten benutzen um die Server zu definieren.
server2server.settings.disallowed=Keine Erlaubnis zu verbinden
server2server.settings.disallowed.info=Die Server in der folgenden Liste haben keine Erlaubnis \
sich mit diesem Server zu verbinden. Das Formular unten benutzen um weitere Server zu blocken.
server2server.settings.disallowed.info=Die Server in der folgenden Liste haben keine Erlaubnis \
sich mit diesem Server zu verbinden. Das Formular unten benutzen um weitere Server zu blocken.
server2server.settings.domain=Domain
server2server.settings.remotePort=Port des entfernten Servers
server2server.settings.empty_list=Keine entfernte Server
......@@ -1500,3 +1500,9 @@ system.cache.desc.effectiveness=* Effectiveness measures how well your cache is
system.cache.total=Total:
system.cache.clear-selected=Clear Selected
database.upgrade.old_schema=Found old database version. Upgrading...
database.upgrade.unknown_db=Warning: database type unknown. You must manually upgrade your database.
database.upgrade.interbase_db=Warning: automatic upgrades of Interbase are not supported. You \
must manually upgrade your database.
upgrade.database.success=Database upgraded successfully.
upgrade.database.failure=Database upgrade failed. Please manually upgrade your database.
\ No newline at end of file
......@@ -31,109 +31,6 @@
##
## REVISION HISTORY (by Wildfire version):
##
## 2.2.0 Beta 1
## Added key: 'global.click_edit'
## Added key: 'global.click_delete'
## Added key: 'global.delete'
## Added key: 'global.minutes'
## Added key: 'global.none'
## Added key: 'global.pages'
## Added key: 'global.refresh'
## Added key: 'global.seconds'
## Added key: 'global.showing'
## Added key: 'server.props.component_port'
## Added key: 'server.props.server_port'
## Added key: 'server.props.update.norestart'
## Added key: 'sidebar.client-session'
## Added key: 'sidebar.component-session'
## Added key: 'sidebar.component-session-summary'
## Added key: 'sidebar.component-session-summary.descr'
## Added key: 'sidebar.external-components-settings'
## Added key: 'sidebar.external-components-settings.descr'
## Added key: 'sidebar.server-session'
## Added key: 'sidebar.server-session-summary'
## Added key: 'sidebar.server-session-summary.descr'
## Added key: 'sidebar.server2server-settings'
## Added key: 'sidebar.server2server-settings.descr'
## Added key: 'startup.component'
## Added key: 'startup.server'
## Added sections: 'component.session.summary.*' and 'component.session.details.*'
## Added sections: 'server.session.summary.*' and 'server.session.details.*'
## Added sections: 'server2server.settings.*' and 'component.settings.*'
## Modified key: 'server.props.port'
## Modified key: 'server.props.ssl_port'
## Modified key: 'sidebar.session-summary'
## Modified key: 'plugin.admin.info'
## Removed key: 'group.summary.click_edit'
## Removed key: 'group.summary.click_delete'
## Removed key: 'group.summary.page_delete'
## Removed key: 'group.summary.page'
## Removed key: 'group.summary.showing'
## Removed key: 'logviewer.none'
## Removed key: 'logviewer.refresh'
## Removed key: 'logviewer.seconds'
## Removed key: 'muc.room.affiliations.click_delete'
## Removed key: 'muc.room.affiliations.delete'
## Removed key: 'muc.room.summary.click_edit'
## Removed key: 'muc.room.summary.click_delete'
## Removed key: 'muc.room.summary.page'
## Removed key: 'muc.room.summary.showing'
## Removed key: 'muc.tasks.minutes'
## Removed key: 'plugin.admin.click_edit'
## Removed key: 'plugin.admin.click_delete'
## Removed key: 'plugin.admin.delete'
## Removed key: 'session.summary.page'
## Removed key: 'session.summary.showing'
## Removed key: 'server.properties.delete'
## Removed key: 'user.summary.click_edit'
## Removed key: 'user.summary.click_delete'
## Removed key: 'user.summary.delete'
## Removed key: 'user.summary.pages'
## Removed key: 'user.summary.showing'
##
## 2.2.0 Beta 2
## Added key: 'muc.form.conf.owner_reservednick'
## Added key: 'muc.form.conf.owner_canchangenick'
## Added key: 'muc.form.conf.owner_registration'
## Added key: 'muc.room.edit.form.reservednick'
## Added key: 'muc.room.edit.form.canchangenick'
## Added key: 'muc.room.edit.form.registration'
## Added key: 'audit.policy.log_directory'
## Added key: 'audit.policy.valid_log_directory'
## Added key: 'audit.policy.ignore'
## Added key: 'audit.policy.validignore'
## Added key: 'global.done'
## Added key: 'reg.settings.change_password'
## Added key: 'reg.settings.change_password_info'
## Added key: 'reg.settings.can_change'
## Added key: 'reg.settings.cannot_change'
## Added key: 'reg.settings.allowed_ips'
## Added key: 'reg.settings.allowed_ips_info'
## Added section: 'user.browser.*'
## Added section: 'setup.env.check.*'
## Modified key: 'server2server.settings.title'
## Modified key: 'server2server.settings.info'
## Modified key: 'server2server.settings.label_enable_info'
## Modified key: 'server2server.settings.whitelist'
## Modified key: 'server2server.settings.remotePort'
## Modified key: 'component.settings.info'
## Modified key: 'server.session.summary.info'
## Removed key: 'server2server.settings.port'
##
## 2.2.0 Release Candidate
## Added key: 'sidebar.active-sessions'
## Modified key: 'sidebar.session-summary'
## Modified key: 'sidebar.server-session-summary'
## Modified key: 'sidebar.component-session-summary'
## Modified key: 'server.session.summary.title'
## Modified key: 'component.settings.title'
## Modified key: 'component.session.summary.title'
## Modified key: 'component.session.summary.info'
## Modified key: 'component.session.details.title'
## Removed key: 'sidebar.client-session'
## Removed key: 'sidebar.server-session'
## Removed key: 'sidebar.component-session'
##
## 2.2.1
## Modified key: 'server2server.settings.label_disable_info'
## Modified key: 'server2server.settings.label_enable_info'
......@@ -259,6 +156,7 @@
## Added key: 'sidebar.system-cache.descr'
## Added key: 'startup.starting.pubsub'
## Added section: 'system.cache.*'
## Added section 'upgrade.database.*'
# Wildfire
......@@ -1755,3 +1653,11 @@ system.cache.desc.effectiveness=* Effectiveness measures how well your cache is
may be the case are specially flagged.
system.cache.total=Total:
system.cache.clear-selected=Clear Selected
# Upgrade process
upgrade.database.old_schema=Found old database version. Upgrading...
upgrade.database.unknown_db=Warning: database type unknown. You must manually upgrade your database.
upgrade.database.interbase_db=Warning: automatic upgrades of Interbase are not supported. You \
must manually upgrade your database.
upgrade.database.success=Database upgraded successfully.
upgrade.database.failure=Database upgrade failed. Please manually upgrade your database.
\ No newline at end of file
......@@ -1373,4 +1373,12 @@ system.cache.desc.effectiveness=* La efectividad mide lo bien que esta funcionan
efectividad es baja, usualmente significa que su cache es peque\u00f1o. Caches que se hayan en \
esa situaci\u00f3n ser\u00e1n especialmente marcados.
system.cache.total=Total:
system.cache.clear-selected=Limpiar Seleccionados
\ No newline at end of file
system.cache.clear-selected=Limpiar Seleccionados
# Upgrade process
upgrade.database.old_schema=Found old database version. Upgrading...
upgrade.database.unknown_db=Warning: database type unknown. You must manually upgrade your database.
upgrade.database.interbase_db=Warning: automatic upgrades of Interbase are not supported. You \
must manually upgrade your database.
upgrade.database.success=Database upgraded successfully.
upgrade.database.failure=Database upgrade failed. Please manually upgrade your database.
\ No newline at end of file
......@@ -1615,3 +1615,10 @@ system.cache.desc.effectiveness=* Effectiveness measures how well your cache is
system.cache.total=Total:
system.cache.clear-selected=Clear Selected
# Upgrade process
upgrade.database.old_schema=Found old database version. Upgrading...
upgrade.database.unknown_db=Warning: database type unknown. You must manually upgrade your database.
upgrade.database.interbase_db=Warning: automatic upgrades of Interbase are not supported. You \
must manually upgrade your database.
upgrade.database.success=Database upgraded successfully.
upgrade.database.failure=Database upgrade failed. Please manually upgrade your database.
\ No newline at end of file
......@@ -1501,3 +1501,9 @@ system.cache.desc.effectiveness=* Effectiveness measures how well your cache is
system.cache.total=Total:
system.cache.clear-selected=Clear Selected
database.upgrade.old_schema=Found old database version. Upgrading...
database.upgrade.unknown_db=Warning: database type unknown. You must manually upgrade your database.
database.upgrade.interbase_db=Warning: automatic upgrades of Interbase are not supported. You \
must manually upgrade your database.
upgrade.database.success=Database upgraded successfully.
upgrade.database.failure=Database upgrade failed. Please manually upgrade your database.
\ No newline at end of file
......@@ -1477,3 +1477,9 @@ system.cache.desc.effectiveness=* Effectiveness measures how well your cache is
system.cache.total=Total:
system.cache.clear-selected=Clear Selected
# Upgrade process
upgrade.database.old_schema=Found old database version. Upgrading...
upgrade.database.unknown_db=Warning: database type unknown. You must manually upgrade your database.
upgrade.database.interbase_db=Warning: automatic upgrades of Interbase are not supported. You \
must manually upgrade your database.
upgrade.database.done=Database upgraded successfully.
\ No newline at end of file
......@@ -1131,7 +1131,6 @@ setup.datasource.settings.embedded_info=Utilize um banco de dados interno, manti
# Setup datasource standard Page
setup.datasource.standard.title=Database Settings - Standard Connection
setup.datasource.standard.title=Configura\u00e7\u00f5es do Banco de Dados - Conex\u00e3o Padr\u00e3o
setup.datasource.standard.label=Predefini\u00e7\u00f5es do Driver de Banco de Dados
setup.datasource.standard.info=Especifique um driver JDBC e as propriedades da conex\u00e3o para conectar ao seu \
......@@ -1504,3 +1503,10 @@ system.cache.desc.effectiveness=* Effectiveness measures how well your cache is
system.cache.total=Total:
system.cache.clear-selected=Clear Selected
# Upgrade process
upgrade.database.old_schema=Found old database version. Upgrading...
upgrade.database.unknown_db=Warning: database type unknown. You must manually upgrade your database.
upgrade.database.interbase_db=Warning: automatic upgrades of Interbase are not supported. You \
must manually upgrade your database.
upgrade.database.success=Database upgraded successfully.
upgrade.database.failure=Database upgrade failed. Please manually upgrade your database.
\ No newline at end of file
......@@ -1375,8 +1375,15 @@ system.cache.desc.effectiveness=* Effectiveness measures how well your cache is
system.cache.total=Total:
system.cache.clear-selected=Clear Selected
# Publish-Subscribe
# Upgrade process
upgrade.database.old_schema=Found old database version. Upgrading...
upgrade.database.unknown_db=Warning: database type unknown. You must manually upgrade your database.
upgrade.database.interbase_db=Warning: automatic upgrades of Interbase are not supported. You \
must manually upgrade your database.
upgrade.database.success=Database upgraded successfully.
upgrade.database.failure=Database upgrade failed. Please manually upgrade your database.
# Publish-Subscribe
startup.starting.pubsub=\u53d1\u5e03-\u8ba2\u9605\u57df\uff1a{0}
pubsub.form.default.title=\u9ed8\u8ba4\u8282\u70b9\u914d\u7f6e
pubsub.form.default.instruction=\u7528\u9ed8\u8ba4\u7684\u914d\u7f6e\u8bbe\u5b9a\u65b0\u521b\u5efa\u7684\u8282\u70b9\u3002
......@@ -1423,4 +1430,4 @@ pubsub.form.subscription.include_body=\u9664\u4e86\u6709\u6548\u8f7d\u8377\u5916
pubsub.form.subscription.show-values=\u5728\u7ebf\u7c7b\u578b\u5141\u8bb8\u63a5\u6536\u901a\u77e5
pubsub.form.subscription.subscription_type=\u63a5\u6536\u901a\u77e5\u7684\u9879\u76ee\u6216\u8282\u70b9
pubsub.form.subscription.subscription_depth=\u4ece\u6240\u6709\u7684\u8282\u70b9\u6216\u76f4\u63a5\u5b50\u8282\u70b9\u63a5\u6536\u901a\u77e5
pubsub.form.subscription.keywords=\u5173\u5065\u5b57\u5339\u914d
pubsub.form.subscription.keywords=\u5173\u5065\u5b57\u5339\u914d
\ No newline at end of file
......@@ -15,13 +15,9 @@ package org.jivesoftware.database;
import org.jivesoftware.util.ClassUtils;
import org.jivesoftware.util.JiveGlobals;
import org.jivesoftware.util.Log;
import org.jivesoftware.util.LocaleUtils;
import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;
import java.io.StringReader;
import java.io.StringWriter;
import java.io.*;
import java.sql.Connection;
import java.sql.DatabaseMetaData;
import java.sql.PreparedStatement;
......@@ -32,7 +28,7 @@ import java.sql.Statement;
/**
* Central manager of database connections. All methods are static so that they
* can be easily accessed throughout the classes in the database package.<p>
* <p/>
*
* This class also provides a set of utility methods that abstract out
* operations that may not work on all databases such as setting the max number
* or rows that a query should return.
......@@ -42,20 +38,16 @@ import java.sql.Statement;
*/
public class DbConnectionManager {
private static final String CHECK_VERSION_OLD =
"SELECT minorVersion FROM jiveVersion";
private static final String CHECK_VERSION =
"SELECT majorVersion, minorVersion FROM jiveVersion";
"SELECT version FROM jiveVersion WHERE name=?";
/**
* Database schema major version. The schema version corresponds to the
* product release version, but may not exactly match in the case that
* the product version has advanced without schema changes.
* Database schema version.
*/
private static final int CURRENT_MAJOR_VERSION = 2;
private static final int DATABASE_VERSION = 6;
/**
* Database schema minor version.
*/
private static final int CURRENT_MINOR_VERSION = 5;
private static ConnectionProvider connectionProvider;
private static final Object providerLock = new Object();
......@@ -455,9 +447,8 @@ public class DbConnectionManager {
upgradeDatabase(con);
}
catch (Exception e) {
Log.error("Database upgrade failed. Please manually upgrade your database.", e);
System.out.println("Database upgrade failed. Please manually upgrade your " +
"database.");
Log.error(LocaleUtils.getLocalizedString("upgrade.database.failure"), e);
System.out.println(LocaleUtils.getLocalizedString("upgrade.database.failure"));
}
}
catch (Exception e) {
......@@ -805,26 +796,33 @@ public class DbConnectionManager {
* @throws SQLException if an error occured.
*/
private static boolean upgradeDatabase(Connection con) throws Exception {
int majorVersion;
int minorVersion;
int version = 0;
PreparedStatement pstmt = null;
try {
pstmt = con.prepareStatement(CHECK_VERSION);
pstmt.setString(1, "wildfire");
ResultSet rs = pstmt.executeQuery();
// If no results, assume the version is 2.0.
if (!rs.next()) {
majorVersion = 2;
minorVersion = 0;
}
majorVersion = rs.getInt(1);
minorVersion = rs.getInt(2);
rs.next();
version = rs.getInt(1);
rs.close();
}
catch (SQLException sqle) {
// If the table doesn't exist, an error will be thrown. Therefore
// assume the version is 2.0.
majorVersion = 2;
minorVersion = 0;
// Releases of Wildfire before 2.6.0 stored a major and minor version
// number so the normal check for version can fail. Check for the
// version using the old format in that case.
try {
if (pstmt != null) {
pstmt.close();
}
pstmt = con.prepareStatement(CHECK_VERSION_OLD);
ResultSet rs = pstmt.executeQuery();
rs.next();
version = rs.getInt(1);
rs.close();
}
catch (SQLException sqle2) {
// Must be database version 0.
}
}
finally {
try {
......@@ -836,44 +834,34 @@ public class DbConnectionManager {
Log.error(e);
}
}
if (majorVersion == CURRENT_MAJOR_VERSION && minorVersion == CURRENT_MINOR_VERSION) {
if (version == DATABASE_VERSION) {
return false;
}
// The database is an old version that needs to be upgraded.
Log.info("Found old database schema (" + majorVersion + "." + minorVersion + "). " +
"Upgrading to latest schema.");
System.out.println("Found old database schema (" + majorVersion + "." +
minorVersion + "). " + "Upgrading to latest schema.");
Log.info(LocaleUtils.getLocalizedString("upgrade.database.old_schema"));
System.out.println(LocaleUtils.getLocalizedString("upgrade.database.old_schema"));
if (databaseType == DatabaseType.unknown) {
Log.info("Warning: database type unknown. You must manually upgrade your database.");
System.out.println("Warning: database type unknown. You must manually upgrade your " +
"database.");
Log.info(LocaleUtils.getLocalizedString("upgrade.database.unknown_db"));
System.out.println(LocaleUtils.getLocalizedString("upgrade.database.unknown_db"));
return false;
}
else if (databaseType == DatabaseType.interbase) {
Log.info("Warning: automatic upgrades of Interbase are not supported. You " +
"must manually upgrade your database.");
System.out.println("Warning: automatic upgrades of Interbase are not supported. You " +
"must manually upgrade your database.");
Log.info(LocaleUtils.getLocalizedString("upgrade.database.interbase_db"));
System.out.println(LocaleUtils.getLocalizedString("upgrade.database.interbase_db"));
return false;
}
// Run all upgrade scripts until we're up to the latest schema.
for (int i = minorVersion; i < CURRENT_MINOR_VERSION; i++) {
for (int i = version+1; i <= DATABASE_VERSION; i++) {
BufferedReader in = null;
Statement stmt;
try {
// Resource will be like "/database/upgrade/2.0_to_2.1/wildfire_hsqldb.sql"
String resourceName = "/database/upgrade/" + CURRENT_MAJOR_VERSION + "." + i +
"_to_" + CURRENT_MAJOR_VERSION + "." + (i + 1) + "/wildfire_" +
// Resource will be like "/database/upgrade/6/wildfire_hsqldb.sql"
String resourceName = "/database/upgrade/" + i + "/wildfire_" +
databaseType + ".sql";
InputStream resource = DbConnectionManager.class.getResourceAsStream(resourceName);
if (resource == null) {
Log.info("Warning: Make sure that database was not modified for release: " +
CURRENT_MAJOR_VERSION + "." + (i + 1) + ". Upgrade script not found: " +
resourceName);
System.out.println("Warning: Make sure that database was not modified for " +
"release: " + CURRENT_MAJOR_VERSION + "." + (i + 1) +
". Upgrade script not found: " + resourceName);
// If the resource is null, the specific upgrade number is not available.
continue;
}
in = new BufferedReader(new InputStreamReader(resource));
......@@ -901,16 +889,15 @@ public class DbConnectionManager {
stmt.close();
}
}
// If the version is greater than 6, automatically update the version information.
// Previous to version 6, the upgrade scripts set the version themselves.
if (version > 6) {
stmt = con.createStatement();
stmt.execute("UPDATE jiveVersion SET version=" + i + " WHERE name='wildfire'");
stmt.close();
}
}
finally {
try {
if (pstmt != null) {
pstmt.close();
}
}
catch (Exception e) {
Log.error(e);
}
if (in != null) {
try {
in.close();
......@@ -921,8 +908,8 @@ public class DbConnectionManager {
}
}
}
Log.info("Database upgraded successfully.");
System.out.println("Database upgraded successfully.");
Log.info(LocaleUtils.getLocalizedString("upgrade.database.success"));
System.out.println(LocaleUtils.getLocalizedString("upgrade.database.success"));
return true;
}
......
/**
* $RCSfile$
* $Revision: 3657 $
* $Date: 2002-09-09 08:31:31 -0700 (Mon, 09 Sep 2002) $
*
* Adapted from Markus Hahn's Blowfish package so that all functionality is
* in a single source file. Please visit the following URL for his excellent
* package: http://www.hotpixel.net/software.html
*
* Copyright (c) 1997-2002 Markus Hahn <markus_hahn@gmx.net>
*
* Released under the Apache 2.0 license.
*/
package org.jivesoftware.util;
import java.util.*;
import java.security.*;
/**
* A class that provides easy Blowfish encryption.<p>
*
* @author Markus Hahn <markus_hahn@gmx.net>
*/
public class Blowfish {
private BlowfishCBC m_bfish;
private static Random m_rndGen = new Random();
/**
* Creates a new Blowfish object using the specified key (oversized
* password will be cut).
*
* @param password the password (treated as a real unicode array)
*/
public Blowfish(String password) {
// hash down the password to a 160bit key
MessageDigest digest = null;
try {
digest = MessageDigest.getInstance("SHA1");
digest.update(password.getBytes());
}
catch (Exception e) {
Log.error(e);
}
// setup the encryptor (use a dummy IV)
m_bfish = new BlowfishCBC(digest.digest(), 0);
digest.reset();
}
/**
* Encrypts a string (treated in UNICODE) using the
* standard Java random generator, which isn't that
* great for creating IVs
*
* @param sPlainText string to encrypt
* @return encrypted string in binhex format
*/
public String encryptString(String sPlainText) {
// get the IV
long lCBCIV;
synchronized (m_rndGen)
{
lCBCIV = m_rndGen.nextLong();
}
// map the call;
return encStr(sPlainText, lCBCIV);
}
// Internal routine for string encryption
private String encStr(String sPlainText,
long lNewCBCIV)
{
// allocate the buffer (align to the next 8 byte border plus padding)
int nStrLen = sPlainText.length();
byte[] buf = new byte [((nStrLen << 1) & 0xfffffff8) + 8];
// copy all bytes of the string into the buffer (use network byte order)
int nI;
int nPos = 0;
for (nI = 0; nI < nStrLen; nI++)
{
char cActChar = sPlainText.charAt(nI);
buf[nPos++] = (byte) ((cActChar >> 8) & 0x0ff);
buf[nPos++] = (byte) (cActChar & 0x0ff) ;
}
// pad the rest with the PKCS5 scheme
byte bPadVal = (byte)(buf.length - (nStrLen << 1));
while (nPos < buf.length)
{
buf[nPos++] = bPadVal;
}
// create the encryptor
m_bfish.setCBCIV(lNewCBCIV);
// encrypt the buffer
m_bfish.encrypt(buf);
// return the binhex string
byte[] newCBCIV = new byte[BlowfishCBC.BLOCKSIZE];
longToByteArray(lNewCBCIV,
newCBCIV,
0);
return bytesToBinHex(newCBCIV, 0, BlowfishCBC.BLOCKSIZE) +
bytesToBinHex(buf, 0, buf.length);
}
/**
* decrypts a hexbin string (handling is case sensitive)
* @param sCipherText hexbin string to decrypt
* @return decrypted string (null equals an error)
*/
public String decryptString(String sCipherText)
{
// get the number of estimated bytes in the string (cut off broken blocks)
int nLen = (sCipherText.length() >> 1) & ~7;
// does the given stuff make sense (at least the CBC IV)?
if (nLen < BlowfishECB.BLOCKSIZE)
return null;
// get the CBC IV
byte[] cbciv = new byte[BlowfishCBC.BLOCKSIZE];
int nNumOfBytes = binHexToBytes(sCipherText,
cbciv,
0,
0,
BlowfishCBC.BLOCKSIZE);
if (nNumOfBytes < BlowfishCBC.BLOCKSIZE)
return null;
// (got it)
m_bfish.setCBCIV(cbciv);
// something left to decrypt?
nLen -= BlowfishCBC.BLOCKSIZE;
if (nLen == 0)
{
return "";
}
// get all data bytes now
byte[] buf = new byte[nLen];
nNumOfBytes = binHexToBytes(sCipherText,
buf,
BlowfishCBC.BLOCKSIZE * 2,
0,
nLen);
// we cannot accept broken binhex sequences due to padding
// and decryption
if (nNumOfBytes < nLen)
{
return null;
}
// decrypt the buffer
m_bfish.decrypt(buf);
// get the last padding byte
int nPadByte = (int)buf[buf.length - 1] & 0x0ff;
// ( try to get all information if the padding doesn't seem to be correct)
if ((nPadByte > 8) || (nPadByte < 0))
{
nPadByte = 0;
}
// calculate the real size of this message
nNumOfBytes -= nPadByte;
if (nNumOfBytes < 0)
{
return "";
}
// success
return byteArrayToUNCString(buf, 0, nNumOfBytes);
}
/**
* destroys (clears) the encryption engine,
* after that the instance is not valid anymore
*/
public void destroy()
{
m_bfish.cleanUp();
}
/**
* implementation of the Blowfish encryption algorithm in ECB mode
* @author Markus Hahn <markus_hahn@gmx.net>
* @version Feburary 14, 2001
*/
private static class BlowfishECB
{
/** maximum possible key length */
public final static int MAXKEYLENGTH = 56;
/** block size of this cipher (in bytes) */
public final static int BLOCKSIZE = 8;
// size of the single boxes
final static int PBOX_ENTRIES = 18;
final static int SBOX_ENTRIES = 256;
// the boxes
int[] m_pbox;
int[] m_sbox1;
int[] m_sbox2;
int[] m_sbox3;
int[] m_sbox4;
/**
* default constructor
* @param bfkey key material, up to MAXKEYLENGTH bytes
*/
public BlowfishECB(byte[] bfkey)
{
// create the boxes
int nI;
m_pbox = new int[PBOX_ENTRIES];
for (nI = 0; nI < PBOX_ENTRIES; nI++)
{
m_pbox[nI] = pbox_init[nI];
}
m_sbox1 = new int[SBOX_ENTRIES];
m_sbox2 = new int[SBOX_ENTRIES];
m_sbox3 = new int[SBOX_ENTRIES];
m_sbox4 = new int[SBOX_ENTRIES];
for (nI = 0; nI < SBOX_ENTRIES; nI++)
{
m_sbox1[nI] = sbox_init_1[nI];
m_sbox2[nI] = sbox_init_2[nI];
m_sbox3[nI] = sbox_init_3[nI];
m_sbox4[nI] = sbox_init_4[nI];
}
// xor the key over the p-boxes
int nLen = bfkey.length;
if (nLen == 0) return; // such a setup is also valid (zero key "encryption" is possible)
int nKeyPos = 0;
int nBuild = 0;
int nJ;
for (nI = 0; nI < PBOX_ENTRIES; nI++)
{
for (nJ = 0; nJ < 4; nJ++)
{
nBuild = (nBuild << 8) | (((int) bfkey[nKeyPos]) & 0x0ff);
if (++nKeyPos == nLen)
{
nKeyPos = 0;
}
}
m_pbox[nI] ^= nBuild;
}
// encrypt all boxes with the all zero string
long lZero = 0;
// (same as above)
for (nI = 0; nI < PBOX_ENTRIES; nI += 2)
{
lZero = encryptBlock(lZero);
m_pbox[nI] = (int) (lZero >>> 32);
m_pbox[nI+1] = (int) (lZero & 0x0ffffffffL);
}
for (nI = 0; nI < SBOX_ENTRIES; nI += 2)
{
lZero = encryptBlock(lZero);
m_sbox1[nI] = (int) (lZero >>> 32);
m_sbox1[nI+1] = (int) (lZero & 0x0ffffffffL);
}
for (nI = 0; nI < SBOX_ENTRIES; nI += 2)
{
lZero = encryptBlock(lZero);
m_sbox2[nI] = (int) (lZero >>> 32);
m_sbox2[nI+1] = (int) (lZero & 0x0ffffffffL);
}
for (nI = 0; nI < SBOX_ENTRIES; nI += 2)
{
lZero = encryptBlock(lZero);
m_sbox3[nI] = (int) (lZero >>> 32);
m_sbox3[nI+1] = (int) (lZero & 0x0ffffffffL);
}
for (nI = 0; nI < SBOX_ENTRIES; nI += 2)
{
lZero = encryptBlock(lZero);
m_sbox4[nI] = (int) (lZero >>> 32);
m_sbox4[nI+1] = (int) (lZero & 0x0ffffffffL);
}
}
/**
* to clear data in the boxes before an instance is freed
*/
public void cleanUp()
{
int nI;
for (nI = 0; nI < PBOX_ENTRIES; nI++)
{
m_pbox[nI] = 0;
}
for (nI = 0; nI < SBOX_ENTRIES; nI++)
{
m_sbox1[nI] = m_sbox2[nI] = m_sbox3[nI] = m_sbox4[nI] = 0;
}
}
/**
* selftest routine, to check e.g. for a valid class file transmission
* @return true: selftest passed / false: selftest failed
*/
public static boolean selfTest()
{
// test vector #1 (checking for the "signed bug")
byte[] testKey1 = { (byte) 0x1c, (byte) 0x58, (byte) 0x7f, (byte) 0x1c,
(byte) 0x13, (byte) 0x92, (byte) 0x4f, (byte) 0xef };
int[] tv_p1 = { 0x30553228, 0x6d6f295a };
int[] tv_c1 = { 0x55cb3774, 0xd13ef201 };
int[] tv_t1 = new int[2];
// test vector #2 (offical vector by Bruce Schneier)
String sTestKey2 = "Who is John Galt?";
byte[] testKey2 = sTestKey2.getBytes();
int[] tv_p2 = { 0xfedcba98, 0x76543210 };
int[] tv_c2 = { 0xcc91732b, 0x8022f684 };
int[] tv_t2 = new int[2];
// start the tests, check for a proper decryption, too
BlowfishECB testbf1 = new BlowfishECB(testKey1);
testbf1.encrypt(tv_p1, tv_t1);
if ((tv_t1[0] != tv_c1[0]) ||
(tv_t1[1] != tv_c1[1]))
{
return false;
}
testbf1.decrypt(tv_t1);
if ((tv_t1[0] != tv_p1[0]) ||
(tv_t1[1] != tv_p1[1]))
{
return false;
}
BlowfishECB testbf2 = new BlowfishECB(testKey2);
testbf2.encrypt(tv_p2, tv_t2);
if ((tv_t2[0] != tv_c2[0]) ||
(tv_t2[1] != tv_c2[1]))
{
return false;
}
testbf2.decrypt(tv_t2);
if ((tv_t2[0] != tv_p2[0]) ||
(tv_t2[1] != tv_p2[1]))
{
return false;
}
// all tests passed
return true;
}
// internal routine to encrypt a 64bit block
protected long encryptBlock(long lPlainBlock)
{
// split the block in two 32 bit halves
int nHi = longHi32(lPlainBlock);
int nLo = longLo32(lPlainBlock);
// encrypt the block, gain more speed by unrooling the loop
// (we avoid swapping by using nHi and nLo alternating at
// odd an even loop nubers) and using local references
int[] sbox1 = m_sbox1;
int[] sbox2 = m_sbox2;
int[] sbox3 = m_sbox3;
int[] sbox4 = m_sbox4;
int[] pbox = m_pbox;
nHi ^= pbox[0];
nLo ^= (((sbox1[nHi >>> 24] + sbox2[(nHi >>> 16) & 0x0ff]) ^ sbox3[(nHi >>> 8) & 0x0ff]) + sbox4[nHi & 0x0ff]) ^ pbox[1];
nHi ^= (((sbox1[nLo >>> 24] + sbox2[(nLo >>> 16) & 0x0ff]) ^ sbox3[(nLo >>> 8) & 0x0ff]) + sbox4[nLo & 0x0ff]) ^ pbox[2];
nLo ^= (((sbox1[nHi >>> 24] + sbox2[(nHi >>> 16) & 0x0ff]) ^ sbox3[(nHi >>> 8) & 0x0ff]) + sbox4[nHi & 0x0ff]) ^ pbox[3];
nHi ^= (((sbox1[nLo >>> 24] + sbox2[(nLo >>> 16) & 0x0ff]) ^ sbox3[(nLo >>> 8) & 0x0ff]) + sbox4[nLo & 0x0ff]) ^ pbox[4];
nLo ^= (((sbox1[nHi >>> 24] + sbox2[(nHi >>> 16) & 0x0ff]) ^ sbox3[(nHi >>> 8) & 0x0ff]) + sbox4[nHi & 0x0ff]) ^ pbox[5];
nHi ^= (((sbox1[nLo >>> 24] + sbox2[(nLo >>> 16) & 0x0ff]) ^ sbox3[(nLo >>> 8) & 0x0ff]) + sbox4[nLo & 0x0ff]) ^ pbox[6];
nLo ^= (((sbox1[nHi >>> 24] + sbox2[(nHi >>> 16) & 0x0ff]) ^ sbox3[(nHi >>> 8) & 0x0ff]) + sbox4[nHi & 0x0ff]) ^ pbox[7];
nHi ^= (((sbox1[nLo >>> 24] + sbox2[(nLo >>> 16) & 0x0ff]) ^ sbox3[(nLo >>> 8) & 0x0ff]) + sbox4[nLo & 0x0ff]) ^ pbox[8];
nLo ^= (((sbox1[nHi >>> 24] + sbox2[(nHi >>> 16) & 0x0ff]) ^ sbox3[(nHi >>> 8) & 0x0ff]) + sbox4[nHi & 0x0ff]) ^ pbox[9];
nHi ^= (((sbox1[nLo >>> 24] + sbox2[(nLo >>> 16) & 0x0ff]) ^ sbox3[(nLo >>> 8) & 0x0ff]) + sbox4[nLo & 0x0ff]) ^ pbox[10];
nLo ^= (((sbox1[nHi >>> 24] + sbox2[(nHi >>> 16) & 0x0ff]) ^ sbox3[(nHi >>> 8) & 0x0ff]) + sbox4[nHi & 0x0ff]) ^ pbox[11];
nHi ^= (((sbox1[nLo >>> 24] + sbox2[(nLo >>> 16) & 0x0ff]) ^ sbox3[(nLo >>> 8) & 0x0ff]) + sbox4[nLo & 0x0ff]) ^ pbox[12];
nLo ^= (((sbox1[nHi >>> 24] + sbox2[(nHi >>> 16) & 0x0ff]) ^ sbox3[(nHi >>> 8) & 0x0ff]) + sbox4[nHi & 0x0ff]) ^ pbox[13];
nHi ^= (((sbox1[nLo >>> 24] + sbox2[(nLo >>> 16) & 0x0ff]) ^ sbox3[(nLo >>> 8) & 0x0ff]) + sbox4[nLo & 0x0ff]) ^ pbox[14];
nLo ^= (((sbox1[nHi >>> 24] + sbox2[(nHi >>> 16) & 0x0ff]) ^ sbox3[(nHi >>> 8) & 0x0ff]) + sbox4[nHi & 0x0ff]) ^ pbox[15];
nHi ^= (((sbox1[nLo >>> 24] + sbox2[(nLo >>> 16) & 0x0ff]) ^ sbox3[(nLo >>> 8) & 0x0ff]) + sbox4[nLo & 0x0ff]) ^ pbox[16];
// finalize, cross and return the reassembled block
return makeLong(nHi, nLo ^ pbox[17]);
}
// internal routine to decrypt a 64bit block
protected long decryptBlock(long lCipherBlock) {
// (same as above)
int nHi = longHi32(lCipherBlock);
int nLo = longLo32(lCipherBlock);
nHi ^= m_pbox[17];
nLo ^= (((m_sbox1[nHi >>> 24] + m_sbox2[(nHi >>> 16) & 0x0ff]) ^ m_sbox3[(nHi >>> 8) & 0x0ff]) + m_sbox4[nHi & 0x0ff]) ^ m_pbox[16];
nHi ^= (((m_sbox1[nLo >>> 24] + m_sbox2[(nLo >>> 16) & 0x0ff]) ^ m_sbox3[(nLo >>> 8) & 0x0ff]) + m_sbox4[nLo & 0x0ff]) ^ m_pbox[15];
nLo ^= (((m_sbox1[nHi >>> 24] + m_sbox2[(nHi >>> 16) & 0x0ff]) ^ m_sbox3[(nHi >>> 8) & 0x0ff]) + m_sbox4[nHi & 0x0ff]) ^ m_pbox[14];
nHi ^= (((m_sbox1[nLo >>> 24] + m_sbox2[(nLo >>> 16) & 0x0ff]) ^ m_sbox3[(nLo >>> 8) & 0x0ff]) + m_sbox4[nLo & 0x0ff]) ^ m_pbox[13];
nLo ^= (((m_sbox1[nHi >>> 24] + m_sbox2[(nHi >>> 16) & 0x0ff]) ^ m_sbox3[(nHi >>> 8) & 0x0ff]) + m_sbox4[nHi & 0x0ff]) ^ m_pbox[12];
nHi ^= (((m_sbox1[nLo >>> 24] + m_sbox2[(nLo >>> 16) & 0x0ff]) ^ m_sbox3[(nLo >>> 8) & 0x0ff]) + m_sbox4[nLo & 0x0ff]) ^ m_pbox[11];
nLo ^= (((m_sbox1[nHi >>> 24] + m_sbox2[(nHi >>> 16) & 0x0ff]) ^ m_sbox3[(nHi >>> 8) & 0x0ff]) + m_sbox4[nHi & 0x0ff]) ^ m_pbox[10];
nHi ^= (((m_sbox1[nLo >>> 24] + m_sbox2[(nLo >>> 16) & 0x0ff]) ^ m_sbox3[(nLo >>> 8) & 0x0ff]) + m_sbox4[nLo & 0x0ff]) ^ m_pbox[9];
nLo ^= (((m_sbox1[nHi >>> 24] + m_sbox2[(nHi >>> 16) & 0x0ff]) ^ m_sbox3[(nHi >>> 8) & 0x0ff]) + m_sbox4[nHi & 0x0ff]) ^ m_pbox[8];
nHi ^= (((m_sbox1[nLo >>> 24] + m_sbox2[(nLo >>> 16) & 0x0ff]) ^ m_sbox3[(nLo >>> 8) & 0x0ff]) + m_sbox4[nLo & 0x0ff]) ^ m_pbox[7];
nLo ^= (((m_sbox1[nHi >>> 24] + m_sbox2[(nHi >>> 16) & 0x0ff]) ^ m_sbox3[(nHi >>> 8) & 0x0ff]) + m_sbox4[nHi & 0x0ff]) ^ m_pbox[6];
nHi ^= (((m_sbox1[nLo >>> 24] + m_sbox2[(nLo >>> 16) & 0x0ff]) ^ m_sbox3[(nLo >>> 8) & 0x0ff]) + m_sbox4[nLo & 0x0ff]) ^ m_pbox[5];
nLo ^= (((m_sbox1[nHi >>> 24] + m_sbox2[(nHi >>> 16) & 0x0ff]) ^ m_sbox3[(nHi >>> 8) & 0x0ff]) + m_sbox4[nHi & 0x0ff]) ^ m_pbox[4];
nHi ^= (((m_sbox1[nLo >>> 24] + m_sbox2[(nLo >>> 16) & 0x0ff]) ^ m_sbox3[(nLo >>> 8) & 0x0ff]) + m_sbox4[nLo & 0x0ff]) ^ m_pbox[3];
nLo ^= (((m_sbox1[nHi >>> 24] + m_sbox2[(nHi >>> 16) & 0x0ff]) ^ m_sbox3[(nHi >>> 8) & 0x0ff]) + m_sbox4[nHi & 0x0ff]) ^ m_pbox[2];
nHi ^= (((m_sbox1[nLo >>> 24] + m_sbox2[(nLo >>> 16) & 0x0ff]) ^ m_sbox3[(nLo >>> 8) & 0x0ff]) + m_sbox4[nLo & 0x0ff]) ^ m_pbox[1];
return makeLong(nHi, nLo ^ m_pbox[0]);
}
/**
* Encrypts a byte buffer (should be aligned to an 8 byte border) to another
* buffer (of the same size or bigger)
*
* @param inbuffer buffer with plaintext data
* @param outbuffer buffer to get the ciphertext data
*/
public void encrypt(byte[] inbuffer, byte[] outbuffer) {
int nLen = inbuffer.length;
long lTemp;
for (int nI = 0; nI < nLen; nI +=8)
{
// encrypt a temporary 64bit block
lTemp = byteArrayToLong(inbuffer, nI);
lTemp = encryptBlock(lTemp);
longToByteArray(lTemp, outbuffer, nI);
}
}
/**
* encrypts a byte buffer (should be aligned to an 8 byte border) to itself
* @param buffer buffer to encrypt
*/
public void encrypt(byte[] buffer)
{
int nLen = buffer.length;
long lTemp;
for (int nI = 0; nI < nLen; nI +=8)
{
// encrypt a temporary 64bit block
lTemp = byteArrayToLong(buffer, nI);
lTemp = encryptBlock(lTemp);
longToByteArray(lTemp, buffer, nI);
}
}
/**
* encrypts an integer buffer (should be aligned to an
* two integer border) to another int buffer (of the
* same size or bigger)
* @param inbuffer buffer with plaintext data
* @param outbuffer buffer to get the ciphertext data
*/
public void encrypt(int[] inbuffer, int[] outbuffer) {
int nLen = inbuffer.length;
long lTemp;
for (int nI = 0; nI < nLen; nI +=2)
{
// encrypt a temporary 64bit block
lTemp = intArrayToLong(inbuffer, nI);
lTemp = encryptBlock(lTemp);
longToIntArray(lTemp, outbuffer, nI);
}
}
/**
* encrypts an int buffer (should be aligned to a
* two integer border)
* @param buffer buffer to encrypt
*/
public void encrypt(int[] buffer) {
int nLen = buffer.length;
long lTemp;
for (int nI = 0; nI < nLen; nI +=2)
{
// encrypt a temporary 64bit block
lTemp = intArrayToLong(buffer, nI);
lTemp = encryptBlock(lTemp);
longToIntArray(lTemp, buffer, nI);
}
}
/**
* encrypts a long buffer to another long buffer (of the same size or bigger)
* @param inbuffer buffer with plaintext data
* @param outbuffer buffer to get the ciphertext data
*/
public void encrypt(long[] inbuffer, long[] outbuffer) {
int nLen = inbuffer.length;
for (int nI = 0; nI < nLen; nI++)
{
outbuffer[nI] = encryptBlock(inbuffer[nI]);
}
}
/**
* encrypts a long buffer to itself
* @param buffer buffer to encrypt
*/
public void encrypt(long[] buffer) {
int nLen = buffer.length;
for (int nI = 0; nI < nLen; nI++)
{
buffer[nI] = encryptBlock(buffer[nI]);
}
}
/**
* decrypts a byte buffer (should be aligned to an 8 byte border)
* to another byte buffer (of the same size or bigger)
* @param inbuffer buffer with ciphertext data
* @param outbuffer buffer to get the plaintext data
*/
public void decrypt(byte[] inbuffer,
byte[] outbuffer)
{
int nLen = inbuffer.length;
long lTemp;
for (int nI = 0; nI < nLen; nI +=8)
{
// decrypt a temporary 64bit block
lTemp = byteArrayToLong(inbuffer, nI);
lTemp = decryptBlock(lTemp);
longToByteArray(lTemp, outbuffer, nI);
}
}
/**
* decrypts a byte buffer (should be aligned to an 8 byte border) to itself
* @param buffer buffer to decrypt
*/
public void decrypt(byte[] buffer)
{
int nLen = buffer.length;
long lTemp;
for (int nI = 0; nI < nLen; nI +=8)
{
// decrypt over a temporary 64bit block
lTemp = byteArrayToLong(buffer, nI);
lTemp = decryptBlock(lTemp);
longToByteArray(lTemp, buffer, nI);
}
}
/**
* decrypts an integer buffer (should be aligned to an
* two integer border) to another int buffer (of the same size or bigger)
* @param inbuffer buffer with ciphertext data
* @param outbuffer buffer to get the plaintext data
*/
public void decrypt(int[] inbuffer,
int[] outbuffer)
{
int nLen = inbuffer.length;
long lTemp;
for (int nI = 0; nI < nLen; nI +=2)
{
// decrypt a temporary 64bit block
lTemp = intArrayToLong(inbuffer, nI);
lTemp = decryptBlock(lTemp);
longToIntArray(lTemp, outbuffer, nI);
}
}
/**
* decrypts an int buffer (should be aligned to an
* two integer border)
* @param buffer buffer to decrypt
*/
public void decrypt(int[] buffer)
{
int nLen = buffer.length;
long lTemp;
for (int nI = 0; nI < nLen; nI +=2)
{
// decrypt a temporary 64bit block
lTemp = intArrayToLong(buffer, nI);
lTemp = decryptBlock(lTemp);
longToIntArray(lTemp, buffer, nI);
}
}
/**
* decrypts a long buffer to another long buffer (of the same size or bigger)
* @param inbuffer buffer with ciphertext data
* @param outbuffer buffer to get the plaintext data
*/
public void decrypt(long[] inbuffer,
long[] outbuffer)
{
int nLen = inbuffer.length;
for (int nI = 0; nI < nLen; nI++)
{
outbuffer[nI] = decryptBlock(inbuffer[nI]);
}
}
/**
* decrypts a long buffer to itself
* @param buffer buffer to decrypt
*/
public void decrypt(long[] buffer) {
int nLen = buffer.length;
for (int nI = 0; nI < nLen; nI++)
{
buffer[nI] = decryptBlock(buffer[nI]);
}
}
// the boxes init. data,
// FIXME: it might be better to create them at runtime to make the class
// file smaller, e.g. by calculating the hexdigits of pi (default)
// or just a fixed random sequence (out of the standard)
final static int pbox_init[] = {
0x243f6a88, 0x85a308d3, 0x13198a2e, 0x03707344, 0xa4093822, 0x299f31d0,
0x082efa98, 0xec4e6c89, 0x452821e6, 0x38d01377, 0xbe5466cf, 0x34e90c6c,
0xc0ac29b7, 0xc97c50dd, 0x3f84d5b5, 0xb5470917, 0x9216d5d9, 0x8979fb1b };
final static int sbox_init_1[] = {
0xd1310ba6, 0x98dfb5ac, 0x2ffd72db, 0xd01adfb7, 0xb8e1afed, 0x6a267e96,
0xba7c9045, 0xf12c7f99, 0x24a19947, 0xb3916cf7, 0x0801f2e2, 0x858efc16,
0x636920d8, 0x71574e69, 0xa458fea3, 0xf4933d7e, 0x0d95748f, 0x728eb658,
0x718bcd58, 0x82154aee, 0x7b54a41d, 0xc25a59b5, 0x9c30d539, 0x2af26013,
0xc5d1b023, 0x286085f0, 0xca417918, 0xb8db38ef, 0x8e79dcb0, 0x603a180e,
0x6c9e0e8b, 0xb01e8a3e, 0xd71577c1, 0xbd314b27, 0x78af2fda, 0x55605c60,
0xe65525f3, 0xaa55ab94, 0x57489862, 0x63e81440, 0x55ca396a, 0x2aab10b6,
0xb4cc5c34, 0x1141e8ce, 0xa15486af, 0x7c72e993, 0xb3ee1411, 0x636fbc2a,
0x2ba9c55d, 0x741831f6, 0xce5c3e16, 0x9b87931e, 0xafd6ba33, 0x6c24cf5c,
0x7a325381, 0x28958677, 0x3b8f4898, 0x6b4bb9af, 0xc4bfe81b, 0x66282193,
0x61d809cc, 0xfb21a991, 0x487cac60, 0x5dec8032, 0xef845d5d, 0xe98575b1,
0xdc262302, 0xeb651b88, 0x23893e81, 0xd396acc5, 0x0f6d6ff3, 0x83f44239,
0x2e0b4482, 0xa4842004, 0x69c8f04a, 0x9e1f9b5e, 0x21c66842, 0xf6e96c9a,
0x670c9c61, 0xabd388f0, 0x6a51a0d2, 0xd8542f68, 0x960fa728, 0xab5133a3,
0x6eef0b6c, 0x137a3be4, 0xba3bf050, 0x7efb2a98, 0xa1f1651d, 0x39af0176,
0x66ca593e, 0x82430e88, 0x8cee8619, 0x456f9fb4, 0x7d84a5c3, 0x3b8b5ebe,
0xe06f75d8, 0x85c12073, 0x401a449f, 0x56c16aa6, 0x4ed3aa62, 0x363f7706,
0x1bfedf72, 0x429b023d, 0x37d0d724, 0xd00a1248, 0xdb0fead3, 0x49f1c09b,
0x075372c9, 0x80991b7b, 0x25d479d8, 0xf6e8def7, 0xe3fe501a, 0xb6794c3b,
0x976ce0bd, 0x04c006ba, 0xc1a94fb6, 0x409f60c4, 0x5e5c9ec2, 0x196a2463,
0x68fb6faf, 0x3e6c53b5, 0x1339b2eb, 0x3b52ec6f, 0x6dfc511f, 0x9b30952c,
0xcc814544, 0xaf5ebd09, 0xbee3d004, 0xde334afd, 0x660f2807, 0x192e4bb3,
0xc0cba857, 0x45c8740f, 0xd20b5f39, 0xb9d3fbdb, 0x5579c0bd, 0x1a60320a,
0xd6a100c6, 0x402c7279, 0x679f25fe, 0xfb1fa3cc, 0x8ea5e9f8, 0xdb3222f8,
0x3c7516df, 0xfd616b15, 0x2f501ec8, 0xad0552ab, 0x323db5fa, 0xfd238760,
0x53317b48, 0x3e00df82, 0x9e5c57bb, 0xca6f8ca0, 0x1a87562e, 0xdf1769db,
0xd542a8f6, 0x287effc3, 0xac6732c6, 0x8c4f5573, 0x695b27b0, 0xbbca58c8,
0xe1ffa35d, 0xb8f011a0, 0x10fa3d98, 0xfd2183b8, 0x4afcb56c, 0x2dd1d35b,
0x9a53e479, 0xb6f84565, 0xd28e49bc, 0x4bfb9790, 0xe1ddf2da, 0xa4cb7e33,
0x62fb1341, 0xcee4c6e8, 0xef20cada, 0x36774c01, 0xd07e9efe, 0x2bf11fb4,
0x95dbda4d, 0xae909198, 0xeaad8e71, 0x6b93d5a0, 0xd08ed1d0, 0xafc725e0,
0x8e3c5b2f, 0x8e7594b7, 0x8ff6e2fb, 0xf2122b64, 0x8888b812, 0x900df01c,
0x4fad5ea0, 0x688fc31c, 0xd1cff191, 0xb3a8c1ad, 0x2f2f2218, 0xbe0e1777,
0xea752dfe, 0x8b021fa1, 0xe5a0cc0f, 0xb56f74e8, 0x18acf3d6, 0xce89e299,
0xb4a84fe0, 0xfd13e0b7, 0x7cc43b81, 0xd2ada8d9, 0x165fa266, 0x80957705,
0x93cc7314, 0x211a1477, 0xe6ad2065, 0x77b5fa86, 0xc75442f5, 0xfb9d35cf,
0xebcdaf0c, 0x7b3e89a0, 0xd6411bd3, 0xae1e7e49, 0x00250e2d, 0x2071b35e,
0x226800bb, 0x57b8e0af, 0x2464369b, 0xf009b91e, 0x5563911d, 0x59dfa6aa,
0x78c14389, 0xd95a537f, 0x207d5ba2, 0x02e5b9c5, 0x83260376, 0x6295cfa9,
0x11c81968, 0x4e734a41, 0xb3472dca, 0x7b14a94a, 0x1b510052, 0x9a532915,
0xd60f573f, 0xbc9bc6e4, 0x2b60a476, 0x81e67400, 0x08ba6fb5, 0x571be91f,
0xf296ec6b, 0x2a0dd915, 0xb6636521, 0xe7b9f9b6, 0xff34052e, 0xc5855664,
0x53b02d5d, 0xa99f8fa1, 0x08ba4799, 0x6e85076a };
final static int sbox_init_2[] = {
0x4b7a70e9, 0xb5b32944,
0xdb75092e, 0xc4192623, 0xad6ea6b0, 0x49a7df7d, 0x9cee60b8, 0x8fedb266,
0xecaa8c71, 0x699a17ff, 0x5664526c, 0xc2b19ee1, 0x193602a5, 0x75094c29,
0xa0591340, 0xe4183a3e, 0x3f54989a, 0x5b429d65, 0x6b8fe4d6, 0x99f73fd6,
0xa1d29c07, 0xefe830f5, 0x4d2d38e6, 0xf0255dc1, 0x4cdd2086, 0x8470eb26,
0x6382e9c6, 0x021ecc5e, 0x09686b3f, 0x3ebaefc9, 0x3c971814, 0x6b6a70a1,
0x687f3584, 0x52a0e286, 0xb79c5305, 0xaa500737, 0x3e07841c, 0x7fdeae5c,
0x8e7d44ec, 0x5716f2b8, 0xb03ada37, 0xf0500c0d, 0xf01c1f04, 0x0200b3ff,
0xae0cf51a, 0x3cb574b2, 0x25837a58, 0xdc0921bd, 0xd19113f9, 0x7ca92ff6,
0x94324773, 0x22f54701, 0x3ae5e581, 0x37c2dadc, 0xc8b57634, 0x9af3dda7,
0xa9446146, 0x0fd0030e, 0xecc8c73e, 0xa4751e41, 0xe238cd99, 0x3bea0e2f,
0x3280bba1, 0x183eb331, 0x4e548b38, 0x4f6db908, 0x6f420d03, 0xf60a04bf,
0x2cb81290, 0x24977c79, 0x5679b072, 0xbcaf89af, 0xde9a771f, 0xd9930810,
0xb38bae12, 0xdccf3f2e, 0x5512721f, 0x2e6b7124, 0x501adde6, 0x9f84cd87,
0x7a584718, 0x7408da17, 0xbc9f9abc, 0xe94b7d8c, 0xec7aec3a, 0xdb851dfa,
0x63094366, 0xc464c3d2, 0xef1c1847, 0x3215d908, 0xdd433b37, 0x24c2ba16,
0x12a14d43, 0x2a65c451, 0x50940002, 0x133ae4dd, 0x71dff89e, 0x10314e55,
0x81ac77d6, 0x5f11199b, 0x043556f1, 0xd7a3c76b, 0x3c11183b, 0x5924a509,
0xf28fe6ed, 0x97f1fbfa, 0x9ebabf2c, 0x1e153c6e, 0x86e34570, 0xeae96fb1,
0x860e5e0a, 0x5a3e2ab3, 0x771fe71c, 0x4e3d06fa, 0x2965dcb9, 0x99e71d0f,
0x803e89d6, 0x5266c825, 0x2e4cc978, 0x9c10b36a, 0xc6150eba, 0x94e2ea78,
0xa5fc3c53, 0x1e0a2df4, 0xf2f74ea7, 0x361d2b3d, 0x1939260f, 0x19c27960,
0x5223a708, 0xf71312b6, 0xebadfe6e, 0xeac31f66, 0xe3bc4595, 0xa67bc883,
0xb17f37d1, 0x018cff28, 0xc332ddef, 0xbe6c5aa5, 0x65582185, 0x68ab9802,
0xeecea50f, 0xdb2f953b, 0x2aef7dad, 0x5b6e2f84, 0x1521b628, 0x29076170,
0xecdd4775, 0x619f1510, 0x13cca830, 0xeb61bd96, 0x0334fe1e, 0xaa0363cf,
0xb5735c90, 0x4c70a239, 0xd59e9e0b, 0xcbaade14, 0xeecc86bc, 0x60622ca7,
0x9cab5cab, 0xb2f3846e, 0x648b1eaf, 0x19bdf0ca, 0xa02369b9, 0x655abb50,
0x40685a32, 0x3c2ab4b3, 0x319ee9d5, 0xc021b8f7, 0x9b540b19, 0x875fa099,
0x95f7997e, 0x623d7da8, 0xf837889a, 0x97e32d77, 0x11ed935f, 0x16681281,
0x0e358829, 0xc7e61fd6, 0x96dedfa1, 0x7858ba99, 0x57f584a5, 0x1b227263,
0x9b83c3ff, 0x1ac24696, 0xcdb30aeb, 0x532e3054, 0x8fd948e4, 0x6dbc3128,
0x58ebf2ef, 0x34c6ffea, 0xfe28ed61, 0xee7c3c73, 0x5d4a14d9, 0xe864b7e3,
0x42105d14, 0x203e13e0, 0x45eee2b6, 0xa3aaabea, 0xdb6c4f15, 0xfacb4fd0,
0xc742f442, 0xef6abbb5, 0x654f3b1d, 0x41cd2105, 0xd81e799e, 0x86854dc7,
0xe44b476a, 0x3d816250, 0xcf62a1f2, 0x5b8d2646, 0xfc8883a0, 0xc1c7b6a3,
0x7f1524c3, 0x69cb7492, 0x47848a0b, 0x5692b285, 0x095bbf00, 0xad19489d,
0x1462b174, 0x23820e00, 0x58428d2a, 0x0c55f5ea, 0x1dadf43e, 0x233f7061,
0x3372f092, 0x8d937e41, 0xd65fecf1, 0x6c223bdb, 0x7cde3759, 0xcbee7460,
0x4085f2a7, 0xce77326e, 0xa6078084, 0x19f8509e, 0xe8efd855, 0x61d99735,
0xa969a7aa, 0xc50c06c2, 0x5a04abfc, 0x800bcadc, 0x9e447a2e, 0xc3453484,
0xfdd56705, 0x0e1e9ec9, 0xdb73dbd3, 0x105588cd, 0x675fda79, 0xe3674340,
0xc5c43465, 0x713e38d8, 0x3d28f89e, 0xf16dff20, 0x153e21e7, 0x8fb03d4a,
0xe6e39f2b, 0xdb83adf7 };
final static int sbox_init_3[] = {
0xe93d5a68, 0x948140f7, 0xf64c261c, 0x94692934,
0x411520f7, 0x7602d4f7, 0xbcf46b2e, 0xd4a20068, 0xd4082471, 0x3320f46a,
0x43b7d4b7, 0x500061af, 0x1e39f62e, 0x97244546, 0x14214f74, 0xbf8b8840,
0x4d95fc1d, 0x96b591af, 0x70f4ddd3, 0x66a02f45, 0xbfbc09ec, 0x03bd9785,
0x7fac6dd0, 0x31cb8504, 0x96eb27b3, 0x55fd3941, 0xda2547e6, 0xabca0a9a,
0x28507825, 0x530429f4, 0x0a2c86da, 0xe9b66dfb, 0x68dc1462, 0xd7486900,
0x680ec0a4, 0x27a18dee, 0x4f3ffea2, 0xe887ad8c, 0xb58ce006, 0x7af4d6b6,
0xaace1e7c, 0xd3375fec, 0xce78a399, 0x406b2a42, 0x20fe9e35, 0xd9f385b9,
0xee39d7ab, 0x3b124e8b, 0x1dc9faf7, 0x4b6d1856, 0x26a36631, 0xeae397b2,
0x3a6efa74, 0xdd5b4332, 0x6841e7f7, 0xca7820fb, 0xfb0af54e, 0xd8feb397,
0x454056ac, 0xba489527, 0x55533a3a, 0x20838d87, 0xfe6ba9b7, 0xd096954b,
0x55a867bc, 0xa1159a58, 0xcca92963, 0x99e1db33, 0xa62a4a56, 0x3f3125f9,
0x5ef47e1c, 0x9029317c, 0xfdf8e802, 0x04272f70, 0x80bb155c, 0x05282ce3,
0x95c11548, 0xe4c66d22, 0x48c1133f, 0xc70f86dc, 0x07f9c9ee, 0x41041f0f,
0x404779a4, 0x5d886e17, 0x325f51eb, 0xd59bc0d1, 0xf2bcc18f, 0x41113564,
0x257b7834, 0x602a9c60, 0xdff8e8a3, 0x1f636c1b, 0x0e12b4c2, 0x02e1329e,
0xaf664fd1, 0xcad18115, 0x6b2395e0, 0x333e92e1, 0x3b240b62, 0xeebeb922,
0x85b2a20e, 0xe6ba0d99, 0xde720c8c, 0x2da2f728, 0xd0127845, 0x95b794fd,
0x647d0862, 0xe7ccf5f0, 0x5449a36f, 0x877d48fa, 0xc39dfd27, 0xf33e8d1e,
0x0a476341, 0x992eff74, 0x3a6f6eab, 0xf4f8fd37, 0xa812dc60, 0xa1ebddf8,
0x991be14c, 0xdb6e6b0d, 0xc67b5510, 0x6d672c37, 0x2765d43b, 0xdcd0e804,
0xf1290dc7, 0xcc00ffa3, 0xb5390f92, 0x690fed0b, 0x667b9ffb, 0xcedb7d9c,
0xa091cf0b, 0xd9155ea3, 0xbb132f88, 0x515bad24, 0x7b9479bf, 0x763bd6eb,
0x37392eb3, 0xcc115979, 0x8026e297, 0xf42e312d, 0x6842ada7, 0xc66a2b3b,
0x12754ccc, 0x782ef11c, 0x6a124237, 0xb79251e7, 0x06a1bbe6, 0x4bfb6350,
0x1a6b1018, 0x11caedfa, 0x3d25bdd8, 0xe2e1c3c9, 0x44421659, 0x0a121386,
0xd90cec6e, 0xd5abea2a, 0x64af674e, 0xda86a85f, 0xbebfe988, 0x64e4c3fe,
0x9dbc8057, 0xf0f7c086, 0x60787bf8, 0x6003604d, 0xd1fd8346, 0xf6381fb0,
0x7745ae04, 0xd736fccc, 0x83426b33, 0xf01eab71, 0xb0804187, 0x3c005e5f,
0x77a057be, 0xbde8ae24, 0x55464299, 0xbf582e61, 0x4e58f48f, 0xf2ddfda2,
0xf474ef38, 0x8789bdc2, 0x5366f9c3, 0xc8b38e74, 0xb475f255, 0x46fcd9b9,
0x7aeb2661, 0x8b1ddf84, 0x846a0e79, 0x915f95e2, 0x466e598e, 0x20b45770,
0x8cd55591, 0xc902de4c, 0xb90bace1, 0xbb8205d0, 0x11a86248, 0x7574a99e,
0xb77f19b6, 0xe0a9dc09, 0x662d09a1, 0xc4324633, 0xe85a1f02, 0x09f0be8c,
0x4a99a025, 0x1d6efe10, 0x1ab93d1d, 0x0ba5a4df, 0xa186f20f, 0x2868f169,
0xdcb7da83, 0x573906fe, 0xa1e2ce9b, 0x4fcd7f52, 0x50115e01, 0xa70683fa,
0xa002b5c4, 0x0de6d027, 0x9af88c27, 0x773f8641, 0xc3604c06, 0x61a806b5,
0xf0177a28, 0xc0f586e0, 0x006058aa, 0x30dc7d62, 0x11e69ed7, 0x2338ea63,
0x53c2dd94, 0xc2c21634, 0xbbcbee56, 0x90bcb6de, 0xebfc7da1, 0xce591d76,
0x6f05e409, 0x4b7c0188, 0x39720a3d, 0x7c927c24, 0x86e3725f, 0x724d9db9,
0x1ac15bb4, 0xd39eb8fc, 0xed545578, 0x08fca5b5, 0xd83d7cd3, 0x4dad0fc4,
0x1e50ef5e, 0xb161e6f8, 0xa28514d9, 0x6c51133c, 0x6fd5c7e7, 0x56e14ec4,
0x362abfce, 0xddc6c837, 0xd79a3234, 0x92638212, 0x670efa8e, 0x406000e0 };
final static int sbox_init_4[] = {
0x3a39ce37, 0xd3faf5cf, 0xabc27737, 0x5ac52d1b, 0x5cb0679e, 0x4fa33742,
0xd3822740, 0x99bc9bbe, 0xd5118e9d, 0xbf0f7315, 0xd62d1c7e, 0xc700c47b,
0xb78c1b6b, 0x21a19045, 0xb26eb1be, 0x6a366eb4, 0x5748ab2f, 0xbc946e79,
0xc6a376d2, 0x6549c2c8, 0x530ff8ee, 0x468dde7d, 0xd5730a1d, 0x4cd04dc6,
0x2939bbdb, 0xa9ba4650, 0xac9526e8, 0xbe5ee304, 0xa1fad5f0, 0x6a2d519a,
0x63ef8ce2, 0x9a86ee22, 0xc089c2b8, 0x43242ef6, 0xa51e03aa, 0x9cf2d0a4,
0x83c061ba, 0x9be96a4d, 0x8fe51550, 0xba645bd6, 0x2826a2f9, 0xa73a3ae1,
0x4ba99586, 0xef5562e9, 0xc72fefd3, 0xf752f7da, 0x3f046f69, 0x77fa0a59,
0x80e4a915, 0x87b08601, 0x9b09e6ad, 0x3b3ee593, 0xe990fd5a, 0x9e34d797,
0x2cf0b7d9, 0x022b8b51, 0x96d5ac3a, 0x017da67d, 0xd1cf3ed6, 0x7c7d2d28,
0x1f9f25cf, 0xadf2b89b, 0x5ad6b472, 0x5a88f54c, 0xe029ac71, 0xe019a5e6,
0x47b0acfd, 0xed93fa9b, 0xe8d3c48d, 0x283b57cc, 0xf8d56629, 0x79132e28,
0x785f0191, 0xed756055, 0xf7960e44, 0xe3d35e8c, 0x15056dd4, 0x88f46dba,
0x03a16125, 0x0564f0bd, 0xc3eb9e15, 0x3c9057a2, 0x97271aec, 0xa93a072a,
0x1b3f6d9b, 0x1e6321f5, 0xf59c66fb, 0x26dcf319, 0x7533d928, 0xb155fdf5,
0x03563482, 0x8aba3cbb, 0x28517711, 0xc20ad9f8, 0xabcc5167, 0xccad925f,
0x4de81751, 0x3830dc8e, 0x379d5862, 0x9320f991, 0xea7a90c2, 0xfb3e7bce,
0x5121ce64, 0x774fbe32, 0xa8b6e37e, 0xc3293d46, 0x48de5369, 0x6413e680,
0xa2ae0810, 0xdd6db224, 0x69852dfd, 0x09072166, 0xb39a460a, 0x6445c0dd,
0x586cdecf, 0x1c20c8ae, 0x5bbef7dd, 0x1b588d40, 0xccd2017f, 0x6bb4e3bb,
0xdda26a7e, 0x3a59ff45, 0x3e350a44, 0xbcb4cdd5, 0x72eacea8, 0xfa6484bb,
0x8d6612ae, 0xbf3c6f47, 0xd29be463, 0x542f5d9e, 0xaec2771b, 0xf64e6370,
0x740e0d8d, 0xe75b1357, 0xf8721671, 0xaf537d5d, 0x4040cb08, 0x4eb4e2cc,
0x34d2466a, 0x0115af84, 0xe1b00428, 0x95983a1d, 0x06b89fb4, 0xce6ea048,
0x6f3f3b82, 0x3520ab82, 0x011a1d4b, 0x277227f8, 0x611560b1, 0xe7933fdc,
0xbb3a792b, 0x344525bd, 0xa08839e1, 0x51ce794b, 0x2f32c9b7, 0xa01fbac9,
0xe01cc87e, 0xbcc7d1f6, 0xcf0111c3, 0xa1e8aac7, 0x1a908749, 0xd44fbd9a,
0xd0dadecb, 0xd50ada38, 0x0339c32a, 0xc6913667, 0x8df9317c, 0xe0b12b4f,
0xf79e59b7, 0x43f5bb3a, 0xf2d519ff, 0x27d9459c, 0xbf97222c, 0x15e6fc2a,
0x0f91fc71, 0x9b941525, 0xfae59361, 0xceb69ceb, 0xc2a86459, 0x12baa8d1,
0xb6c1075e, 0xe3056a0c, 0x10d25065, 0xcb03a442, 0xe0ec6e0e, 0x1698db3b,
0x4c98a0be, 0x3278e964, 0x9f1f9532, 0xe0d392df, 0xd3a0342b, 0x8971f21e,
0x1b0a7441, 0x4ba3348c, 0xc5be7120, 0xc37632d8, 0xdf359f8d, 0x9b992f2e,
0xe60b6f47, 0x0fe3f11d, 0xe54cda54, 0x1edad891, 0xce6279cf, 0xcd3e7e6f,
0x1618b166, 0xfd2c1d05, 0x848fd2c5, 0xf6fb2299, 0xf523f357, 0xa6327623,
0x93a83531, 0x56cccd02, 0xacf08162, 0x5a75ebb5, 0x6e163697, 0x88d273cc,
0xde966292, 0x81b949d0, 0x4c50901b, 0x71c65614, 0xe6c6c7bd, 0x327a140a,
0x45e1d006, 0xc3f27b9a, 0xc9aa53fd, 0x62a80f00, 0xbb25bfe2, 0x35bdd2f6,
0x71126905, 0xb2040222, 0xb6cbcf7c, 0xcd769c2b, 0x53113ec0, 0x1640e3d3,
0x38abbd60, 0x2547adf0, 0xba38209c, 0xf746ce76, 0x77afa1c5, 0x20756060,
0x85cbfe4e, 0x8ae88dd8, 0x7aaaf9b0, 0x4cf9aa7e, 0x1948c25c, 0x02fb8a8c,
0x01c36ae4, 0xd6ebe1f9, 0x90d4f869, 0xa65cdea0, 0x3f09252d, 0xc208e69f,
0xb74e6132, 0xce77e25b, 0x578fdfe3, 0x3ac372e6 };
}
private static class BlowfishCBC extends BlowfishECB {
// here we hold the CBC IV
long m_lCBCIV;
/**
* get the current CBC IV (for cipher resets)
* @return current CBC IV
*/
public long getCBCIV()
{
return m_lCBCIV;
}
/**
* get the current CBC IV (for cipher resets)
* @param dest wher eto put current CBC IV in network byte ordered array
*/
public void getCBCIV(byte[] dest)
{
longToByteArray(m_lCBCIV, dest, 0);
}
/**
* set the current CBC IV (for cipher resets)
* @param lNewCBCIV the new CBC IV
*/
public void setCBCIV(long lNewCBCIV)
{
m_lCBCIV = lNewCBCIV;
}
/**
* set the current CBC IV (for cipher resets)
* @param newCBCIV the new CBC IV in network byte ordered array
*/
public void setCBCIV(byte[] newCBCIV)
{
m_lCBCIV = byteArrayToLong(newCBCIV, 0);
}
/**
* constructor, stores a zero CBC IV
* @param bfkey key material, up to MAXKEYLENGTH bytes
*/
public BlowfishCBC(byte[] bfkey)
{
super(bfkey);
// store zero CBCB IV
setCBCIV(0);
}
/**
* constructor
* @param bfkey key material, up to MAXKEYLENGTH bytes
* @param lInitCBCIV the CBC IV
*/
public BlowfishCBC(byte[] bfkey,
long lInitCBCIV)
{
super(bfkey);
// store the CBCB IV
setCBCIV(lInitCBCIV);
}
/**
* constructor
* @param bfkey key material, up to MAXKEYLENGTH bytes
* @param initCBCIV the CBC IV (array with min. BLOCKSIZE bytes)
*/
public BlowfishCBC(byte[] bfkey,
byte[] initCBCIV)
{
super(bfkey);
// store the CBCB IV
setCBCIV(initCBCIV);
}
/**
* cleans up all critical internals,
* call this if you don't need an instance anymore
*/
public void cleanUp()
{
m_lCBCIV = 0;
super.cleanUp();
}
// internal routine to encrypt a block in CBC mode
private long encryptBlockCBC(long lPlainblock)
{
// chain with the CBC IV
lPlainblock ^= m_lCBCIV;
// encrypt the block
lPlainblock = super.encryptBlock(lPlainblock);
// the encrypted block is the new CBC IV
return (m_lCBCIV = lPlainblock);
}
// internal routine to decrypt a block in CBC mode
private long decryptBlockCBC(long lCipherblock)
{
// save the current block
long lTemp = lCipherblock;
// decrypt the block
lCipherblock = super.decryptBlock(lCipherblock);
// dechain the block
lCipherblock ^= m_lCBCIV;
// set the new CBC IV
m_lCBCIV = lTemp;
// return the decrypted block
return lCipherblock;
}
/**
* encrypts a byte buffer (should be aligned to an 8 byte border)
* to another buffer (of the same size or bigger)
* @param inbuffer buffer with plaintext data
* @param outbuffer buffer to get the ciphertext data
*/
public void encrypt(byte[] inbuffer,
byte[] outbuffer)
{
int nLen = inbuffer.length;
long lTemp;
for (int nI = 0; nI < nLen; nI +=8)
{
// encrypt a temporary 64bit block
lTemp = byteArrayToLong(inbuffer, nI);
lTemp = encryptBlockCBC(lTemp);
longToByteArray(lTemp, outbuffer, nI);
}
}
/**
* encrypts a byte buffer (should be aligned to an 8 byte border) to itself
* @param buffer buffer to encrypt
*/
public void encrypt(byte[] buffer)
{
int nLen = buffer.length;
long lTemp;
for (int nI = 0; nI < nLen; nI +=8)
{
// encrypt a temporary 64bit block
lTemp = byteArrayToLong(buffer, nI);
lTemp = encryptBlockCBC(lTemp);
longToByteArray(lTemp, buffer, nI);
}
}
/**
* encrypts an int buffer (should be aligned to an
* two integer border) to another int buffer (of the same
* size or bigger)
* @param inbuffer buffer with plaintext data
* @param outbuffer buffer to get the ciphertext data
*/
public void encrypt(int[] inbuffer,
int[] outbuffer)
{
int nLen = inbuffer.length;
long lTemp;
for (int nI = 0; nI < nLen; nI +=2)
{
// encrypt a temporary 64bit block
lTemp = intArrayToLong(inbuffer, nI);
lTemp = encryptBlockCBC(lTemp);
longToIntArray(lTemp, outbuffer, nI);
}
}
/**
* encrypts an integer buffer (should be aligned to an
* @param buffer buffer to encrypt
*/
public void encrypt(int[] buffer)
{
int nLen = buffer.length;
long lTemp;
for (int nI = 0; nI < nLen; nI +=2)
{
// encrypt a temporary 64bit block
lTemp = intArrayToLong(buffer, nI);
lTemp = encryptBlockCBC(lTemp);
longToIntArray(lTemp, buffer, nI);
}
}
/**
* encrypts a long buffer to another long buffer (of the same size or bigger)
* @param inbuffer buffer with plaintext data
* @param outbuffer buffer to get the ciphertext data
*/
public void encrypt(long[] inbuffer,
long[] outbuffer)
{
int nLen = inbuffer.length;
for (int nI = 0; nI < nLen; nI++)
{
outbuffer[nI] = encryptBlockCBC(inbuffer[nI]);
}
}
/**
* encrypts a long buffer to itself
* @param buffer buffer to encrypt
*/
public void encrypt(long[] buffer)
{
int nLen = buffer.length;
for (int nI = 0; nI < nLen; nI++)
{
buffer[nI] = encryptBlockCBC(buffer[nI]);
}
}
/**
* decrypts a byte buffer (should be aligned to an 8 byte border)
* to another buffer (of the same size or bigger)
* @param inbuffer buffer with ciphertext data
* @param outbuffer buffer to get the plaintext data
*/
public void decrypt(byte[] inbuffer,
byte[] outbuffer)
{
int nLen = inbuffer.length;
long lTemp;
for (int nI = 0; nI < nLen; nI +=8)
{
// decrypt a temporary 64bit block
lTemp = byteArrayToLong(inbuffer, nI);
lTemp = decryptBlockCBC(lTemp);
longToByteArray(lTemp, outbuffer, nI);
}
}
/**
* decrypts a byte buffer (should be aligned to an 8 byte border) to itself
* @param buffer buffer to decrypt
*/
public void decrypt(byte[] buffer)
{
int nLen = buffer.length;
long lTemp;
for (int nI = 0; nI < nLen; nI +=8)
{
// decrypt over a temporary 64bit block
lTemp = byteArrayToLong(buffer, nI);
lTemp = decryptBlockCBC(lTemp);
longToByteArray(lTemp, buffer, nI);
}
}
/**
* decrypts an integer buffer (should be aligned to an
* two integer border) to another int buffer (of the same size or bigger)
* @param inbuffer buffer with ciphertext data
* @param outbuffer buffer to get the plaintext data
*/
public void decrypt(int[] inbuffer,
int[] outbuffer)
{
int nLen = inbuffer.length;
long lTemp;
for (int nI = 0; nI < nLen; nI +=2)
{
// decrypt a temporary 64bit block
lTemp = intArrayToLong(inbuffer, nI);
lTemp = decryptBlockCBC(lTemp);
longToIntArray(lTemp, outbuffer, nI);
}
}
/**
* decrypts an int buffer (should be aligned to a
* two integer border)
* @param buffer buffer to decrypt
*/
public void decrypt(int[] buffer)
{
int nLen = buffer.length;
long lTemp;
for (int nI = 0; nI < nLen; nI +=2)
{
// decrypt a temporary 64bit block
lTemp = intArrayToLong(buffer, nI);
lTemp = decryptBlockCBC(lTemp);
longToIntArray(lTemp, buffer, nI);
}
}
/**
* decrypts a long buffer to another long buffer (of the same size or bigger)
* @param inbuffer buffer with ciphertext data
* @param outbuffer buffer to get the plaintext data
*/
public void decrypt(long[] inbuffer,
long[] outbuffer)
{
int nLen = inbuffer.length;
for (int nI = 0; nI < nLen; nI++)
{
outbuffer[nI] = decryptBlockCBC(inbuffer[nI]);
}
}
/**
* decrypts a long buffer to itself
* @param buffer buffer to decrypt
*/
public void decrypt(long[] buffer)
{
int nLen = buffer.length;
for (int nI = 0; nI < nLen; nI++)
{
buffer[nI] = decryptBlockCBC(buffer[nI]);
}
}
}
/**
* gets bytes from an array into a long
* @param buffer where to get the bytes
* @param nStartIndex index from where to read the data
* @return the 64bit integer
*/
private static long byteArrayToLong(byte[] buffer,
int nStartIndex)
{
return (((long)buffer[nStartIndex]) << 56) |
(((long)buffer[nStartIndex + 1] & 0x0ffL) << 48) |
(((long)buffer[nStartIndex + 2] & 0x0ffL) << 40) |
(((long)buffer[nStartIndex + 3] & 0x0ffL) << 32) |
(((long)buffer[nStartIndex + 4] & 0x0ffL) << 24) |
(((long)buffer[nStartIndex + 5] & 0x0ffL) << 16) |
(((long)buffer[nStartIndex + 6] & 0x0ffL) << 8) |
((long)buffer[nStartIndex + 7] & 0x0ff);
}
/**
* converts a long o bytes which are put into a given array
* @param lValue the 64bit integer to convert
* @param buffer the target buffer
* @param nStartIndex where to place the bytes in the buffer
*/
private static void longToByteArray(long lValue,
byte[] buffer,
int nStartIndex)
{
buffer[nStartIndex] = (byte) (lValue >>> 56);
buffer[nStartIndex + 1] = (byte) ((lValue >>> 48) & 0x0ff);
buffer[nStartIndex + 2] = (byte) ((lValue >>> 40) & 0x0ff);
buffer[nStartIndex + 3] = (byte) ((lValue >>> 32) & 0x0ff);
buffer[nStartIndex + 4] = (byte) ((lValue >>> 24) & 0x0ff);
buffer[nStartIndex + 5] = (byte) ((lValue >>> 16) & 0x0ff);
buffer[nStartIndex + 6] = (byte) ((lValue >>> 8) & 0x0ff);
buffer[nStartIndex + 7] = (byte) lValue;
}
/**
* converts values from an integer array to a long
* @param buffer where to get the bytes
* @param nStartIndex index from where to read the data
* @return the 64bit integer
*/
private static long intArrayToLong(int[] buffer,
int nStartIndex)
{
return (((long) buffer[nStartIndex]) << 32) |
(((long) buffer[nStartIndex + 1]) & 0x0ffffffffL);
}
/**
* converts a long to integers which are put into a given array
* @param lValue the 64bit integer to convert
* @param buffer the target buffer
* @param nStartIndex where to place the bytes in the buffer
*/
private static void longToIntArray(long lValue,
int[] buffer,
int nStartIndex)
{
buffer[nStartIndex] = (int) (lValue >>> 32);
buffer[nStartIndex + 1] = (int) lValue;
}
/**
* makes a long from two integers (treated unsigned)
* @param nLo lower 32bits
* @param nHi higher 32bits
* @return the built long
*/
private static long makeLong(int nLo,
int nHi)
{
return (((long)nHi << 32) |
((long)nLo & 0x00000000ffffffffL));
}
/**
* gets the lower 32 bits of a long
* @param lVal the long integer
* @return lower 32 bits
*/
private static int longLo32(long lVal)
{
return (int)lVal;
}
/**
* gets the higher 32 bits of a long
* @param lVal the long integer
* @return higher 32 bits
*/
private static int longHi32(long lVal)
{
return (int)((lVal >>> 32));
}
// our table for binhex conversion
final static char[] HEXTAB = { '0', '1', '2', '3', '4', '5', '6', '7',
'8', '9', 'a', 'b', 'c', 'd', 'e', 'f' };
/**
* converts a byte array to a binhex string
* @param data the byte array
* @param nStartPos start index where to get the bytes
* @param nNumOfBytes number of bytes to convert
* @return the binhex string
*/
private static String bytesToBinHex(byte[] data,
int nStartPos,
int nNumOfBytes)
{
StringBuffer sbuf = new StringBuffer();
sbuf.setLength(nNumOfBytes << 1);
int nPos = 0;
for (int nI = 0; nI < nNumOfBytes; nI++)
{
sbuf.setCharAt(nPos++, HEXTAB[(data[nI + nStartPos] >> 4) & 0x0f]);
sbuf.setCharAt(nPos++, HEXTAB[data[nI + nStartPos] & 0x0f]);
}
return sbuf.toString();
}
/**
* converts a binhex string back into a byte array (invalid codes will be skipped)
* @param sBinHex binhex string
* @param data the target array
* @param nSrcPos from which character in the string the conversion should begin,
* remember that (nSrcPos modulo 2) should equals 0 normally
* @param nDstPos to store the bytes from which position in the array
* @param nNumOfBytes number of bytes to extract
* @return number of extracted bytes
*/
private static int binHexToBytes(String sBinHex,
byte[] data,
int nSrcPos,
int nDstPos,
int nNumOfBytes)
{
// check for correct ranges
int nStrLen = sBinHex.length();
int nAvailBytes = (nStrLen - nSrcPos) >> 1;
if (nAvailBytes < nNumOfBytes)
{
nNumOfBytes = nAvailBytes;
}
int nOutputCapacity = data.length - nDstPos;
if (nNumOfBytes > nOutputCapacity)
{
nNumOfBytes = nOutputCapacity;
}
// convert now
int nResult = 0;
for (int nI = 0; nI < nNumOfBytes; nI++)
{
byte bActByte = 0;
boolean blConvertOK = true;
for (int nJ = 0; nJ < 2; nJ++)
{
bActByte <<= 4;
char cActChar = sBinHex.charAt(nSrcPos++);
if ((cActChar >= 'a') && (cActChar <= 'f'))
{
bActByte |= (byte)(cActChar - 'a') + 10;
}
else
{
if ((cActChar >= '0') && (cActChar <= '9'))
{
bActByte |= (byte)(cActChar - '0');
}
else
{
blConvertOK = false;
}
}
}
if (blConvertOK)
{
data[nDstPos++] = bActByte;
nResult++;
}
}
return nResult;
}
/**
* converts a byte array into an UNICODE string
* @param data the byte array
* @param nStartPos where to begin the conversion
* @param nNumOfBytes number of bytes to handle
* @return the string
*/
private static String byteArrayToUNCString(byte[] data,
int nStartPos,
int nNumOfBytes)
{
// we need two bytes for every character
nNumOfBytes &= ~1;
// enough bytes in the buffer?
int nAvailCapacity = data.length - nStartPos;
if (nAvailCapacity < nNumOfBytes)
{
nNumOfBytes = nAvailCapacity;
}
StringBuffer sbuf = new StringBuffer();
sbuf.setLength(nNumOfBytes >> 1);
int nSBufPos = 0;
while (nNumOfBytes > 0)
{
sbuf.setCharAt(nSBufPos++,
(char)(((int)data[nStartPos] << 8) | ((int)data[nStartPos + 1] & 0x0ff)));
nStartPos += 2;
nNumOfBytes -= 2;
}
return sbuf.toString();
}
}
......@@ -254,7 +254,7 @@ public class XMPPServer {
name = JiveGlobals.getProperty("xmpp.domain", "127.0.0.1").toLowerCase();
version = new Version(2, 5, 1, Version.ReleaseStatus.Release, -1);
version = new Version(2, 6, 0, Version.ReleaseStatus.Beta, -1);
if ("true".equals(JiveGlobals.getXMLProperty("setup"))) {
setupMode = false;
}
......@@ -502,8 +502,8 @@ public class XMPPServer {
if (isRestartable()) {
try {
Class wrapperClass = Class.forName(WRAPPER_CLASSNAME);
Method stopMethod = wrapperClass.getMethod("stop", new Class[]{Integer.TYPE});
stopMethod.invoke(null, new Object[]{0});
Method stopMethod = wrapperClass.getMethod("stop", Integer.TYPE);
stopMethod.invoke(null, 0);
}
catch (Exception e) {
Log.error("Could not stop container", e);
......@@ -530,7 +530,7 @@ public class XMPPServer {
}
public boolean isRestartable() {
boolean restartable = false;
boolean restartable;
try {
restartable = Class.forName(WRAPPER_CLASSNAME) != null;
}
......@@ -548,7 +548,7 @@ public class XMPPServer {
* @return true if the server is running in standalone mode.
*/
public boolean isStandAlone() {
boolean standalone = false;
boolean standalone;
try {
standalone = Class.forName(STARTER_CLASSNAME) != null;
}
......@@ -595,7 +595,7 @@ public class XMPPServer {
* We do the verification by checking for the Wildfire config file in
* the config dir of jiveHome.
*
* @param homeGuess a guess at the path to the home directory.
* @param homeGuess a guess at the path to the home directory.
* @param jiveConfigName the name of the config file to check.
* @return a file pointing to the home directory or null if the
* home directory guess was wrong.
......@@ -603,22 +603,18 @@ public class XMPPServer {
* directory provided
*/
private File verifyHome(String homeGuess, String jiveConfigName) throws FileNotFoundException {
File realHome = null;
File guess = new File(homeGuess);
File configFileGuess = new File(guess, jiveConfigName);
if (configFileGuess.exists()) {
realHome = guess;
}
File wildfireHome = new File(guess, jiveConfigName);
if (!wildfireHome.exists()) {
File wildfireHome = new File(homeGuess);
File configFile = new File(wildfireHome, jiveConfigName);
if (!configFile.exists()) {
throw new FileNotFoundException();
}
try {
return new File(realHome.getCanonicalPath());
}
catch (Exception ex) {
throw new FileNotFoundException();
else {
try {
return new File(wildfireHome.getCanonicalPath());
}
catch (Exception ex) {
throw new FileNotFoundException();
}
}
}
......
......@@ -11,13 +11,8 @@
package org.jivesoftware.wildfire.auth;
import org.jivesoftware.database.DbConnectionManager;
import org.jivesoftware.util.Log;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import org.jivesoftware.wildfire.user.UserNotFoundException;
import org.jivesoftware.wildfire.user.DefaultUserProvider;
/**
* Default AuthProvider implementation. It authenticates against the <tt>jiveUser</tt>
......@@ -30,41 +25,33 @@ import java.sql.SQLException;
*/
public class DefaultAuthProvider implements AuthProvider {
private static final String AUTHORIZE =
"SELECT username FROM jiveUser WHERE username=? AND password=?";
private static final String SELECT_PASSWORD =
"SELECT password FROM jiveUser WHERE username=?";
private DefaultUserProvider userProvider;
/**
* Constructs a new DefaultAuthProvider.
*/
public DefaultAuthProvider() {
// Create a new default user provider since we need it to get the
// user's password. We always create our own user provider because
// we don't know what user provider is configured for the system and
// the contract of this class is to authenticate against the jiveUser
// database table.
userProvider = new DefaultUserProvider();
}
public void authenticate(String username, String password) throws UnauthorizedException {
if (username == null || password == null) {
throw new UnauthorizedException();
}
username = username.trim().toLowerCase();
Connection con = null;
PreparedStatement pstmt = null;
try {
con = DbConnectionManager.getConnection();
pstmt = con.prepareStatement(AUTHORIZE);
pstmt.setString(1, username);
pstmt.setString(2, password);
ResultSet rs = pstmt.executeQuery();
// If the query has no results, the username and password
// did not match a user record. Therefore, throw an exception.
if (!rs.next()) {
if (!password.equals(userProvider.getPassword(username))) {
throw new UnauthorizedException();
}
rs.close();
}
catch (SQLException e) {
Log.error("Exception in DbAuthProvider", e);
catch (UserNotFoundException unfe) {
throw new UnauthorizedException();
}
finally {
try { if (pstmt != null) pstmt.close(); }
catch (Exception e) { Log.error(e); }
try { if (con != null) con.close(); }
catch (Exception e) { Log.error(e); }
}
// Got this far, so the user must be authorized.
}
......@@ -73,37 +60,16 @@ public class DefaultAuthProvider implements AuthProvider {
throw new UnauthorizedException();
}
username = username.trim().toLowerCase();
Connection con = null;
PreparedStatement pstmt = null;
try {
con = DbConnectionManager.getConnection();
pstmt = con.prepareStatement(SELECT_PASSWORD);
pstmt.setString(1, username);
ResultSet rs = pstmt.executeQuery();
// If the query had no results, the username and password
// did not match a user record. Therefore, throw an exception.
if (!rs.next()) {
throw new UnauthorizedException();
}
String pass = rs.getString(1);
String anticipatedDigest = AuthFactory.createDigest(token, pass);
String password = userProvider.getPassword(username);
String anticipatedDigest = AuthFactory.createDigest(token, password);
if (!digest.equalsIgnoreCase(anticipatedDigest)) {
throw new UnauthorizedException();
}
rs.close();
}
catch (SQLException e) {
Log.error("Exception in DbAuthProvider", e);
catch (UserNotFoundException unfe) {
throw new UnauthorizedException();
}
finally {
try { if (pstmt != null) pstmt.close(); }
catch (Exception e) { Log.error(e); }
try { if (con != null) con.close(); }
catch (Exception e) { Log.error(e); }
}
// Got this far, so the user must be authorized.
}
......
......@@ -12,19 +12,23 @@
package org.jivesoftware.wildfire.user;
import org.jivesoftware.database.DbConnectionManager;
import org.jivesoftware.util.LocaleUtils;
import org.jivesoftware.util.Log;
import org.jivesoftware.util.StringUtils;
import org.jivesoftware.util.*;
import org.jivesoftware.wildfire.vcard.VCardManager;
import java.sql.*;
import java.util.*;
import java.util.Date;
/**
* Default implementation of the UserProvider interface, which reads and writes data
* from the <tt>jiveUser</tt> database table.
* from the <tt>jiveUser</tt> database table.<p>
*
* Passwords can be stored as plain text, or encrypted using Blowfish. The
* encryption/decryption key is stored as the Wildfire property <tt>passwordKey</tt>,
* which is automatically created on first-time use. It's critical that the password key
* not be changed once created, or existing passwords will be lost. By default
* passwords will be stored encrypted. Plain-text password storage can be enabled
* by setting the Wildfire property <tt>user.usePlainPassword</tt> to <tt>true</tt>.
*
* @author Matt Tucker
*/
......@@ -37,8 +41,8 @@ public class DefaultUserProvider implements UserProvider {
private static final String ALL_USERS =
"SELECT username FROM jiveUser";
private static final String INSERT_USER =
"INSERT INTO jiveUser (username,password,name,email,creationDate,modificationDate) " +
"VALUES (?,?,?,?,?,?)";
"INSERT INTO jiveUser (username,password,encryptedPassword,name,email,creationDate,modificationDate) " +
"VALUES (?,?,?,?,?,?,?)";
private static final String DELETE_USER_PROPS =
"DELETE FROM jiveUserProp WHERE username=?";
private static final String DELETE_USER =
......@@ -52,9 +56,33 @@ public class DefaultUserProvider implements UserProvider {
private static final String UPDATE_MODIFICATION_DATE =
"UPDATE jiveUser SET modificationDate=? WHERE username=?";
private static final String LOAD_PASSWORD =
"SELECT password FROM jiveUser WHERE username=?";
"SELECT password,encryptedPassword FROM jiveUser WHERE username=?";
private static final String UPDATE_PASSWORD =
"UPDATE jiveUser SET password=? WHERE username=?";
"UPDATE jiveUser SET password=?, encryptedPassword=? WHERE username=?";
private static Blowfish cipher = null;
private static synchronized Blowfish getCipher() {
if (cipher != null) {
return cipher;
}
// Get the password key, stored as a database property. Obviously,
// protecting your database is critical for making the
// encryption fully secure.
String keyString;
try {
keyString = JiveGlobals.getProperty("passwordKey");
if (keyString == null) {
keyString = StringUtils.randomString(15);
JiveGlobals.setProperty("passwordKey", keyString);
}
cipher = new Blowfish(keyString);
}
catch (Exception e) {
Log.error(e);
}
return cipher;
}
public User loadUser(String username) throws UserNotFoundException {
Connection con = null;
......@@ -100,6 +128,16 @@ public class DefaultUserProvider implements UserProvider {
}
catch (UserNotFoundException unfe) {
// The user doesn't already exist so we can create a new user
// Determine if the password should be stored as plain text or encrypted.
boolean usePlainPassword = JiveGlobals.getBooleanProperty("user.usePlainPassword");
String encryptedPassword = null;
if (!usePlainPassword) {
encryptedPassword = getCipher().encryptString(password);
// Set password to null so that it's inserted that way.
password = null;
}
Date now = new Date();
Connection con = null;
PreparedStatement pstmt = null;
......@@ -107,21 +145,32 @@ public class DefaultUserProvider implements UserProvider {
con = DbConnectionManager.getConnection();
pstmt = con.prepareStatement(INSERT_USER);
pstmt.setString(1, username);
pstmt.setString(2, password);
if (name == null) {
if (password == null) {
pstmt.setNull(2, Types.VARCHAR);
}
else {
pstmt.setString(2, password);
}
if (encryptedPassword == null) {
pstmt.setNull(3, Types.VARCHAR);
}
else {
pstmt.setString(3, name);
pstmt.setString(3, encryptedPassword);
}
if (email == null) {
if (name == null) {
pstmt.setNull(4, Types.VARCHAR);
}
else {
pstmt.setString(4, email);
pstmt.setString(4, name);
}
if (email == null) {
pstmt.setNull(5, Types.VARCHAR);
}
else {
pstmt.setString(5, email);
}
pstmt.setString(5, StringUtils.dateToMillis(now));
pstmt.setString(6, StringUtils.dateToMillis(now));
pstmt.setString(7, StringUtils.dateToMillis(now));
pstmt.execute();
}
catch (Exception e) {
......@@ -150,7 +199,9 @@ public class DefaultUserProvider implements UserProvider {
try {
VCardManager.getInstance().deleteVCard(username);
}
catch (UnsupportedOperationException e) {}
catch (UnsupportedOperationException e) {
// Ignore.
}
// Delete all of the users's extended properties
con = DbConnectionManager.getTransactionConnection();
pstmt = con.prepareStatement(DELETE_USER_PROPS);
......@@ -223,7 +274,7 @@ public class DefaultUserProvider implements UserProvider {
try { if (con != null) { con.close(); } }
catch (Exception e) { Log.error(e); }
}
return new UserCollection((String[])usernames.toArray(new String[usernames.size()]));
return new UserCollection(usernames.toArray(new String[usernames.size()]));
}
public Collection<User> getUsers(int startIndex, int numResults) {
......@@ -252,7 +303,7 @@ public class DefaultUserProvider implements UserProvider {
try { if (con != null) { con.close(); } }
catch (Exception e) { Log.error(e); }
}
return new UserCollection((String[])usernames.toArray(new String[usernames.size()]));
return new UserCollection(usernames.toArray(new String[usernames.size()]));
}
public void setName(String username, String name) throws UserNotFoundException {
......@@ -370,7 +421,14 @@ public class DefaultUserProvider implements UserProvider {
if (!rs.next()) {
throw new UserNotFoundException(username);
}
return rs.getString(1);
String plainText = rs.getString(1);
String encrypted = rs.getString(2);
if (encrypted != null) {
return getCipher().decryptString(encrypted);
}
else {
return plainText;
}
}
catch (SQLException sqle) {
throw new UserNotFoundException(sqle);
......@@ -388,12 +446,30 @@ public class DefaultUserProvider implements UserProvider {
// Reject the operation since the provider is read-only
throw new UnsupportedOperationException();
}
// Determine if the password should be stored as plain text or encrypted.
boolean usePlainPassword = JiveGlobals.getBooleanProperty("user.usePlainPassword");
String encryptedPassword = null;
if (!usePlainPassword) {
encryptedPassword = getCipher().encryptString(password);
// Set password to null so that it's inserted that way.
password = null;
}
Connection con = null;
PreparedStatement pstmt = null;
try {
con = DbConnectionManager.getConnection();
pstmt = con.prepareStatement(UPDATE_PASSWORD);
pstmt.setString(1, password);
if (password == null) {
pstmt.setNull(1, Types.VARCHAR);
}
else {
pstmt.setString(1, password);
}
if (encryptedPassword == null) {
pstmt.setNull(2, Types.VARCHAR);
}
pstmt.setString(2, username);
pstmt.executeUpdate();
}
......@@ -474,7 +550,7 @@ public class DefaultUserProvider implements UserProvider {
try { if (con != null) { con.close(); } }
catch (Exception e) { Log.error(e); }
}
return new UserCollection((String[])usernames.toArray(new String[usernames.size()]));
return new UserCollection(usernames.toArray(new String[usernames.size()]));
}
public Collection<User> findUsers(Set<String> fields, String query, int startIndex,
......@@ -543,7 +619,7 @@ public class DefaultUserProvider implements UserProvider {
try { if (con != null) { con.close(); } }
catch (Exception e) { Log.error(e); }
}
return new UserCollection((String[])usernames.toArray(new String[usernames.size()]));
return new UserCollection(usernames.toArray(new String[usernames.size()]));
}
public boolean isReadOnly() {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment