This commit is contained in:
Mickaël Rémond 2015-02-11 13:02:18 +01:00
parent b9357194a3
commit ce8f97b55f
19 changed files with 0 additions and 1871 deletions

View File

@ -1,192 +0,0 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<html>
<head>
<title>User Import/Export Plugin Changelog</title>
<style type="text/css">
/* global font and body settings */
body {
font-size: 100%;
background-color: #d3d6d9;
padding: 0px;
margin: 0px 0px 30px 0px;
}
body,td,th {
font-family: arial, helvetica, sans-serif;
font-size: 10pt;
}
pre,tt,code {
font-family: courier new, monospaced;
font-size: 9pt;
}
#pageContainer {
display: block;
position: relative;
clear: both;
background-color: #fff;
border: 1px solid #999;
padding: 40px;
margin: 30px;
-moz-border-radius: 6px;
}
#pageHeader {
display: block;
position: relative;
height: 80px;
background-color: #e7eaee;
border: 1px solid #cccccc;
border-bottom: none;
-moz-border-radius: 5px 5px 0px 0px;
margin: 10px 0px 0px 0px;
}
#pageBody {
margin: 0px 18px 0px 20px;
}
/* anchors */
a:link {
color: #11568c;
}
a:visited {
color: #571c8d;
}
a:hover {
color: #7a1d42;
text-decoration: underline;
}
a:active {
color: #7a1d42;
}
/* page header elements (logo and navigation) */
.navigation {
display: block;
position: relative;
height: 20px;
background-color: #335588;
border: 1px solid #cccccc;
border-top: none;
color: #ffffff;
font-size: 11px;
line-height: 18px;
padding: 0px 0px 0px 0px;
margin: 0px 0px 25px 0px;
overflow: hidden;
}
.navigation a {
margin: 0px 20px 0px 20px;
}
.navigation a:link {
color: #ffffff;
}
.navigation a:visited {
color: #ffffff;
}
.navigation a:hover {
color: #ffffff;
}
.navigation a:active {
color: #ffffff;
}
/* headings */
h1 {
display: block;
position: relative;
font-size: 1.7em;
font-weight: bold;
color: #670e15;
padding: 0px;
margin: 30px 0px 0px 20px;
}
h2 {
font-size: 1.3em;
font-weight: bold;
margin: 40px 0px 6px 0px;
padding: 0px;
color: #335588;
}
h3 {
font-size: 1.0em;
font-weight: bold;
margin: 25px 0px 3px 0px;
padding: 0px;
color: #334466;
}
/* general elements */
p {
margin: 0px 0px 15px 0px;
}
ul {
margin: 5px 0px 15px 35px;
}
li {
padding-bottom: 4px;
}
tt {
font-family: courier new;
font-weight: bold;
color: #060;
}
hr {
display: block;
height: 1px;
background-color: #999999;
border: none;
margin: 40px 0px 20px 0px;
}
.footer {
font-size: 8pt;
color: #666;
text-align: center;
margin-top: 2em;
padding-top: 0.5em;
border-top: 1px #CCC solid;
}
</style>
</head>
<body>
<div id="pageContainer">
<div id="pageHeader">
<h1>User Import/Export XEP-0227 compliant Plugin Changelog</h1>
</div>
<div id="pageBody">
<br/>
<p><b>Note:</b> Openfire plugin improved to export to XEP-227
format. There is also old code to import users, but using a custom Openfire
format. If you are interested you can improve it to also support XEP-227
import.</p>
<h2>0.0.1 -- <span style="font-weight: normal;">August 3,
2009</span></h2>
<ul>
<li>Initial release.</li>
</ul>
</div>
</div>
</body>
</html>

View File

@ -1,79 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified">
<xs:element name="Openfire">
<xs:complexType>
<xs:sequence>
<xs:element ref="User" maxOccurs="unbounded" />
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="User">
<xs:complexType>
<xs:all>
<xs:element ref="Username"/>
<xs:element ref="Password"/>
<xs:element ref="Email" />
<xs:element ref="Name" />
<xs:element ref="CreationDate" />
<xs:element ref="ModifiedDate" />
<xs:element ref="Roster" />
</xs:all>
</xs:complexType>
</xs:element>
<xs:element name="Username" type="xs:string" />
<xs:element name="Password" type="xs:string" />
<xs:element name="Email" type="xs:string" />
<xs:element name="Name" type="xs:string" />
<xs:element name="CreationDate" type="jive-date" />
<xs:element name="ModifiedDate" type="jive-date" />
<xs:element name="Roster">
<xs:complexType>
<xs:sequence>
<xs:element ref="Item" minOccurs="0" maxOccurs="unbounded" />
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="Item">
<xs:complexType>
<xs:sequence>
<xs:element ref="Group" maxOccurs="unbounded" />
</xs:sequence>
<xs:attribute ref="jid" use="required" />
<xs:attribute name="askstatus" use="required" />
<xs:attribute name="recvstatus" use="required" />
<xs:attribute name="substatus" use="required" />
<xs:attribute name="name" />
</xs:complexType>
</xs:element>
<xs:element name="Group" type="xs:string" />
<xs:attribute name="jid" type="xs:string" />
<xs:attribute name="name" type="xs:string" />
<xs:attribute name="askstatus">
<xs:simpleType>
<xs:restriction base="xs:integer">
<xs:minInclusive value="-1" />
<xs:maxInclusive value="3" />
</xs:restriction>
</xs:simpleType>
</xs:attribute>
<xs:attribute name="recvstatus">
<xs:simpleType>
<xs:restriction base="xs:integer">
<xs:minInclusive value="-1" />
<xs:maxInclusive value="3" />
</xs:restriction>
</xs:simpleType>
</xs:attribute>
<xs:attribute name="substatus">
<xs:simpleType>
<xs:restriction base="xs:integer">
<xs:minInclusive value="-1" />
<xs:maxInclusive value="3" />
</xs:restriction>
</xs:simpleType>
</xs:attribute>
<xs:simpleType name="jive-date">
<xs:restriction base="xs:string"></xs:restriction>
</xs:simpleType>
</xs:schema>

View File

@ -1,47 +0,0 @@
<?xml version='1.0' encoding='UTF-8'?>
<xs:schema
xmlns:xs='http://www.w3.org/2001/XMLSchema'
targetNamespace='http://www.xmpp.org/extensions/xep-0227.html#ns'
xmlns='http://www.xmpp.org/extensions/xep-0227.html#ns'
elementFormDefault='qualified'>
<xs:element name='server-data'>
<xs:complexType>
<xs:sequence>
<xs:element ref='host' maxOccurs='unbounded'/>
<xs:any namespace='##other' minOccurs='0' maxOccurs='unbounded'/>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name='host'>
<xs:complexType>
<xs:sequence>
<xs:element ref='user' maxOccurs='unbounded'/>
<xs:any namespace='##other' minOccurs='0' maxOccurs='unbounded'/>
</xs:sequence>
<xs:attribute name='jid' type='xs:string' use='required'/>
</xs:complexType>
</xs:element>
<xs:element name='user'>
<xs:complexType>
<xs:sequence>
<xs:element ref='offline-messages' minOccurs='0' maxOccurs='1'/>
<xs:any namespace='##other' minOccurs='0' maxOccurs='unbounded'/>
</xs:sequence>
<xs:attribute name='name' type='xs:string' use='required'/>
<xs:attribute name='password' type='xs:string' use='optional'/>
</xs:complexType>
</xs:element>
<xs:element name='offline-messages'>
<xs:complexType>
<xs:sequence>
<xs:any namespace='##other' minOccurs='0' maxOccurs='unbounded'/>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:schema>

View File

@ -1,18 +0,0 @@
Copy in this directory the following files:
commons-fileupload-1.0.jar
dom4j-1.6.1.jar
isorelax.jar
msv.jar
relaxngDatatype.jar
xsdlib.jar
You can get those files from the original Openfire plugin: userImportExport.jar
Note: openfire.jar file in this folder must be used if you want to export the
private stored info also you will need to comment out lines 332 up to 335 in
ExporterXEP227.java class and finally recompile it.
Have fun !
---

Binary file not shown.

Before

Width:  |  Height:  |  Size: 977 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 600 B

View File

@ -1,22 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<plugin>
<class>net.processone.plugin.openfire.ExporterXEP227</class>
<name>User Import Export XEP-0227</name>
<description>Enables import and export of user data</description>
<author>Vidal Santiago Martinez (original plugin: Ryan Graham)</author>
<version>0.0.1</version>
<date>03/08/2009</date>
<minServerVersion>3.5.0</minServerVersion>
<adminconsole>
<tab id="tab-users">
<sidebar id="user-import-export" name="Import &amp; Export XEP-0227 compliant ">
<item id="import-export-selection" name="User Import &amp; Export XEP-0227 compliant"
url="import-export-selection.jsp"
description="Allows the importing and exporting of Openfire user data in a XEP-0227 format." />
</sidebar>
</tab>
</adminconsole>
</plugin>

View File

@ -1,262 +0,0 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<html>
<head>
<title>User Import/Export XEP-0227 compliant Plugin Readme</title>
<style type="text/css">
/* global font and body settings */
body {
font-size : 100%;
background-color : #d3d6d9;
padding: 0px;
margin: 0px 0px 30px 0px;
}
body, td, th {
font-family : arial, helvetica, sans-serif;
font-size : 10pt;
}
pre, tt, code {
font-family : courier new, monospaced;
font-size : 9pt;
}
#pageContainer {
display: block;
position: relative;
clear: both;
background-color: #fff;
border: 1px solid #999;
padding: 40px;
margin: 30px;
-moz-border-radius: 6px;
}
#pageHeader {
display: block;
position: relative;
height: 80px;
background-color: #e7eaee;
border: 1px solid #cccccc;
border-bottom: none;
-moz-border-radius: 5px 5px 0px 0px;
margin: 10px 0px 0px 0px;
}
#pageBody {
margin: 0px 18px 0px 20px;
}
/* anchors */
a:link {
color: #11568c;
}
a:visited {
color: #571c8d;
}
a:hover {
color: #7a1d42;
text-decoration : underline;
}
a:active {
color: #7a1d42;
}
/* page header elements (logo and navigation) */
.navigation {
display: block;
position: relative;
height: 20px;
background-color: #335588;
border: 1px solid #cccccc;
border-top: none;
color: #ffffff;
font-size: 11px;
line-height: 18px;
padding: 0px 0px 0px 0px;
margin: 0px 0px 25px 0px;
overflow: hidden;
}
.navigation a {
margin: 0px 20px 0px 20px;
}
.navigation a:link { color: #ffffff; }
.navigation a:visited { color: #ffffff; }
.navigation a:hover { color: #ffffff; }
.navigation a:active { color: #ffffff; }
/* headings */
h1 {
display: block;
position: relative;
font-size : 1.7em;
font-weight : bold;
color: #670e15;
padding: 0px;
margin: 30px 0px 0px 20px;
}
h2 {
font-size : 1.3em;
font-weight : bold;
margin: 40px 0px 6px 0px;
padding: 0px;
color: #335588;
}
h3 {
font-size : 1.0em;
font-weight : bold;
margin: 25px 0px 3px 0px;
padding: 0px;
color: #334466;
}
/* general elements */
p {
margin: 0px 0px 15px 0px;
}
ul {
margin: 5px 0px 15px 35px;
}
li {
padding-bottom : 4px;
}
tt {
font-family : courier new;
font-weight : bold;
color : #060;
}
hr {
display: block;
height: 1px;
background-color: #999999;
border: none;
margin: 40px 0px 20px 0px;
}
.footer {
font-size : 8pt;
color : #666;
text-align : center;
margin-top : 2em;
padding-top : 0.5em;
border-top : 1px #CCC solid;
}
.datatable TH {
color : #fff;
background-color : #2A448C;
text-align : left;
}
.datatable TD {
background-color : #FAF6EF;
}
.datatable .name {
background-color : #DCE2F5;
text-align : center;
}
.xmltable TD {
background-color : #EFEFEF;
}
</style>
</head>
<body>
<div id="pageContainer">
<div id="pageHeader">
<h1>User Import/Export XEP-0227 compliant Plugin Readme</h1>
</div>
<div id="pageBody">
<h2>Overview</h2>
<p>The user import/export plugin provides a way to import and export Openfire user data via
the Admin Console. This plugin use for its migration the XEP-0227 standard to be able to migrate its
list of users from other Jabber/XMPP compliant based systems.</p>
<p>This plugin is based in the original plugin developed by Ryan Graham.
It was modified by Vidal Santiago Martinez (from <a href="http://www.process-one.net/">ProcessOne</a>)
to export to a XML file in the XEP-0227 format.
If you are migrating to ejabberd, check additional details in:
<a href="https://support.process-one.net/doc/display/MESSENGER/ejabberd+migration+kit">ejabberd migration kit</a>.
The existing feature to import XML file was not modified, so it is not capable of importing XEP-0227 files.</p>
<h2>Installation</h2>
<p>Copy the OpenfireExporter.jar into the plugins directory of your Openfire installation.
The plugin will then be automatically deployed. To upgrade to a new version, copy the new
OpenfireExporter.jar file over the existing file.</p>
<h2>Configuration</h2>
<p>Nothing to do</p>
<h2>Using the Plugin</h2>
<p>The plugin is accessed via the "User Import &amp; Export XEP-0227 compliant" sidebar item located under the
"Users/Groups" tab in the Admin Console. Note: if you are using a read-only user store such as LDAP
or POP3 this plugin will still work with two caveats:
<ol>
<li>When exporting, the username will be placed in the password element.</li>
<li>When importing, no new users will be created but if the user exists in the user store their roster will be loaded.</li>
<li><strong>Importing</strong> - Select the "Import User Data" option from the user import/export selection
page. On the import page, use the "Browse" button to locate the file that contains the user
information you want to locate and then click on the "Import" button. If the plugin is successful
in importing all user data, you will be presented with the message: "All users added successfully".
If the plugin was not successful in importing all user data you, will receive a message indicating
what might have gone wrong. If during the import process, the plugin detects that you are trying to
import a user that already exists in the system, it will not import that user or any roster
information, except in the case of using a read-only user store.</li>
<li><strong>Exporting</strong> - Select the "Export User Data" option from the user import/export selection
page. User data can be exported either to a file or directly to the screen. To export to a file,
select the "To File" radio button, enter the name you want your export file to be called in the
"Export File Name" and then click on the "Export" button. Note: the plugin will automatically append
an ".xml" extension to the file name if it is not already present. To export to the screen, select
the "To Screen" radio button and then click on the "Export" button. The user data will be placed in
the provided text area.</li>
<li><strong>Migration</strong> - To import user data from another instant messaging system using the plugin,
the import file must conform to the wildfire-user-schema.xsd schema file (located in the classes
directory of the OpenfireExporter.jar). When importing a user data file the plugin will first validate
the file against the schema file. If the plugin cannot validate the import file the user data will
not be imported. During the import process the plugin gives you the ability to update user roster
entries domain names to server name of your Openfire installation. For example, say you have a user
whose roster looks like:
</li>
</ol>
<h2>Example</h2>
<p>
<div class="xmltable">
<table>
<tr>
<td>
&lt;?xml version="1.0" encoding="UTF-8"?&gt;<br/>
&lt;server-data xmlns="http://www.xmpp.org/extensions/xep-0227.html#ns"&gt;<br/>
&lt;host jid="example.org"&gt;<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&lt;user name="testuser1" password="testuser1"&gt;<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;query xmlns="jabber:iq:roster"&gt;<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;item jid="testuser1@example.org" name="testuser1" subscription="both"&gt;<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;group/&gt;<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;/item&gt;<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;/query&gt;<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&lt;/user&gt;<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&lt;user name="santiago" password="santiago"&gt;<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;query xmlns="jabber:iq:roster"&gt;<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;item jid="smartinez@example.org" name="santiago" subscription="both"&gt;<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;group/&gt;<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;/item&gt;<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;/query&gt;<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;vCard xmlns="vcard-temp"&gt;<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;FN&gt;Vidal Santiago Martinez&lt;/FN&gt;<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;NICKNAME&gt;Santiago&lt;/NICKNAME&gt;<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;EMAIL&gt;smartinez@example.org&lt;/EMAIL&gt;<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;URL&gt;www.process-one.net&lt;/URL&gt;<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;/vCard&gt;<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&lt;/user&gt;<br/>
&lt;/host&gt;<br/>
&lt;/server-data&gt;<br/>
</td>
</tr>
</table>
</div>
<br/>
</div>
</div>
</body>
</html>

View File

@ -1,477 +0,0 @@
package net.processone.plugin.openfire;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.io.StringWriter;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import org.apache.commons.fileupload.FileItem;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;
import org.dom4j.io.OutputFormat;
import org.dom4j.io.SAXReader;
import org.dom4j.io.XMLWriter;
import org.jivesoftware.openfire.OfflineMessage;
import org.jivesoftware.openfire.OfflineMessageStore;
import org.jivesoftware.openfire.PrivateStorage;
import org.jivesoftware.openfire.XMPPServer;
import org.jivesoftware.openfire.auth.AuthFactory;
import org.jivesoftware.openfire.container.Plugin;
import org.jivesoftware.openfire.container.PluginManager;
import org.jivesoftware.openfire.roster.RosterItem;
import org.jivesoftware.openfire.roster.RosterItemProvider;
import org.jivesoftware.openfire.user.User;
import org.jivesoftware.openfire.user.UserAlreadyExistsException;
import org.jivesoftware.openfire.user.UserManager;
import org.jivesoftware.openfire.user.UserNotFoundException;
import org.jivesoftware.openfire.user.UserProvider;
import org.jivesoftware.openfire.vcard.VCardManager;
import org.jivesoftware.stringprep.Stringprep;
import org.jivesoftware.stringprep.StringprepException;
import org.jivesoftware.util.Log;
import org.xmpp.packet.JID;
/**
* <p>
* The user import/export plugin provides a way to import and export Openfire
* user data via the Admin Console. This plugin is XEP-0227 compliant
* </p>
* This plugin can export: <li>User data</li> <li>vCard</li> <li>Offline
* messages</li> <br/>
* <p>
* <b>See also:</b> {@link List http://xmpp.org/extensions/xep-0227.html}
* </p>
*
* @author <a href="mailto:smartinez@process-one.net">Vidal Santiago
* Martinez</a>
*/
public class ExporterXEP227 implements Plugin {
private static final String LOAD_ALL_PRIVATE = "SELECT privateData FROM ofPrivate WHERE username=?";
private UserManager userManager;
private UserProvider provider;
private String serverName;
private OfflineMessageStore offlineMessagesStore;
private VCardManager vCardManager;
private PrivateStorage privateStorage;
public ExporterXEP227() {
userManager = XMPPServer.getInstance().getUserManager();
offlineMessagesStore = XMPPServer.getInstance()
.getOfflineMessageStore();
provider = UserManager.getUserProvider();
serverName = XMPPServer.getInstance().getServerInfo().getXMPPDomain();
privateStorage = XMPPServer.getInstance().getPrivateStorage();
vCardManager = VCardManager.getInstance();
}
public void initializePlugin(PluginManager manager, File pluginDirectory) {
}
public void destroyPlugin() {
userManager = null;
provider = null;
serverName = null;
offlineMessagesStore = null;
}
/**
* Convenience method that returns true if this UserProvider is read-only.
*
* @return true if the user provider is read-only.
*/
public boolean isUserProviderReadOnly() {
return provider.isReadOnly();
}
/**
* Converts the user data that is to be exported to a byte[]. If a read-only
* user store is being used a user's password will be the same as their
* username.
*
* @return a byte[] of the user data.
* @throws IOException
* if there's a problem writing to the XMLWriter.
*/
public byte[] exportUsersToByteArray() throws IOException {
ByteArrayOutputStream out = new ByteArrayOutputStream();
XMLWriter writer = new XMLWriter(out, OutputFormat.createPrettyPrint());
writer.write(exportUsers());
return out.toByteArray();
}
/**
* Converts the exported user data to a String. If a read-only user store is
* being used a user's password will be the same as their username.
*
* @return a formatted String representation of the user data.
* @throws IOException
* if there's a problem writing to the XMLWriter.
*/
public String exportUsersToString() throws IOException {
StringWriter stringWriter = new StringWriter();
XMLWriter writer = null;
try {
writer = new XMLWriter(stringWriter, OutputFormat
.createPrettyPrint());
writer.write(exportUsers());
} catch (IOException ioe) {
Log.error(ioe);
throw ioe;
} finally {
if (writer != null) {
writer.close();
}
}
return stringWriter.toString();
}
/**
* Returns a list of usernames that were unable to be imported or whose
* rosters could not imported. Users are not able to be imported for the
* following reasons: <li>Their username is not properly formatted. <li>If a
* read-only user data store is being used and the user could not be found.
* <li>If a writeable user data store is being used and the user already
* exists.
*
* @param file
* a FileItem containing the user data to be imported.
* @param previousDomain
* a String an optional parameter that if supplied will replace
* the user roster entries domain names to server name of current
* Openfire installation.
* @return True if FileItem matches the openfire user schema.
* @throws IOException
* if there is a problem reading the FileItem.
* @throws DocumentException
* if an error occurs during parsing.
*/
public List<String> importUserData(FileItem file, String previousDomain)
throws DocumentException, IOException {
SAXReader reader = new SAXReader();
Document document = reader.read(file.getInputStream());
return importUsers(document, previousDomain);
}
/**
* Returns whether or not the supplied FileItem matches the openfire user
* schema
*
* @param file
* a FileItem to be validated.
* @return True if FileItem matches the openfire user schema.
*/
public boolean validateImportFile(FileItem file) {
try {
return new UserSchemaValidator(file, "wildfire-user-schema.xsd")
.validate();
} catch (Exception e) {
Log.error(e);
return false;
}
}
/**
* Adding heading of an user and its parameters
*
* @param userElement
* DOM element
* @param user
* User object
*/
private void addUser(Element userElement, User user) {
String userName = user.getUsername();
userElement.addAttribute("name", userName);
try {
userElement.addAttribute("password", AuthFactory
.getPassword(userName));
} catch (UserNotFoundException e) {
Log.info("User " + userName
+ " not found, setting their password to their username");
userElement.addAttribute("password", userName);
} catch (UnsupportedOperationException e) {
Log.info("Unable to retrieve " + userName
+ " password, setting their password to their username");
userElement.addAttribute("password", userName);
}
}
/**
* Add roster and its groups to a DOM element
*
* @param userElement
* DOM element
* @param user
* User
*/
private void addRoster(Element userElement, User user) {
Element rosterElement = userElement.addElement("query",
"jabber:iq:roster");
Collection<RosterItem> roster = user.getRoster().getRosterItems();
for (RosterItem ri : roster) {
Element itemElement = rosterElement.addElement("item");
itemElement.addAttribute("jid", ri.getJid().toBareJID());
itemElement.addAttribute("name", ri.getNickname());
itemElement.addAttribute("subscription", ri.getSubStatus()
.getName());
/**
* Adding groups
*/
Element groupElement = itemElement.addElement("group");
List<String> groups = ri.getGroups();
for (String group : groups) {
groupElement.addText(group);
}
}
}
/**
* Adding offline messages, if there are some.
*
* @param hostname
* host name
* @param userElement
* DOM element
* @param userName
* user name
*/
private void addOfflineMessages(String hostname, Element userElement,
String userName) {
Collection<OfflineMessage> offlineMessages = offlineMessagesStore
.getMessages(userName, false);
if (!offlineMessages.isEmpty()) {
Element offlineElement = userElement.addElement("offline-messages");
for (OfflineMessage offMessage : offlineMessages) {
Element messageElement = offlineElement.addElement("message",
"jabber:client");
messageElement.addAttribute("from", offMessage.getFrom()
.toString());
messageElement
.addAttribute("to", offMessage.getTo().toString());
messageElement
.addAttribute("type", offMessage.getType().name());
/**
* Adding text message
*/
Element bodyElement = messageElement.addElement("body");
String body = offMessage.getBody();
bodyElement.addText(body != null ? body : "");
/**
* Adding delay element
*/
Element delayElement = messageElement.addElement("delay",
"urn:xmpp:delay");
delayElement.addAttribute("from", hostname);
delayElement.addAttribute("stamp", offMessage.getCreationDate()
.toString());
delayElement.addText("Offline Storage");
}
}
}
/**
* Adding vcard element
*
* @param userElement
* DOM element
* @param userName
* user name
*/
@SuppressWarnings("unchecked")
private void addVCard(Element userElement, String userName) {
Element vCard = vCardManager.getVCard(userName);
if (vCard != null) {
Element vCardElement = userElement
.addElement("vCard", "vcard-temp");
for (Iterator<Element> iterator = vCard.elementIterator(); iterator
.hasNext();) {
Element element = iterator.next();
vCardElement.addElement(element.getName()).addText(
element.getText());
}
}
}
/**
* Add all the private stored information (XEP-0049)
* <b>Note: this method is not suported in the available openfire releases,
* If you want to use it, you will need to change your openfire.jar file to
* openfire.jar file in this projects lib folder, remove comment to this
* method and recompile the plugin.
*
* </b>
* @param userName User name
* @param userElement User element
*/
private void addPrivateStorage(String userName, Element userElement) {
// Element result = privateStorage.getAll(userName);
// if (result.elements().size() > 0) {
// userElement.add(result.createCopy());
// }
}
/**
* Export the user list and its, Vcard, Offline mesages and roster list to
* an XML representation XEP-0227 compliant
*
* @return DOM document
*/
private Document exportUsers() {
Document document = DocumentHelper.createDocument();
Element root = document.addElement("server-data",
"http://www.xmpp.org/extensions/xep-0227.html#ns");
Element host = root.addElement("host");
host.addAttribute("jid", serverName);
Collection<User> users = userManager.getUsers();
for (User user : users) {
String userName = user.getUsername();
Element userElement = host.addElement("user");
addUser(userElement, user);
addRoster(userElement, user);
addVCard(userElement, userName);
addOfflineMessages(serverName, userElement, userName);
addPrivateStorage(userName, userElement);
}
return document;
}
private List<String> importUsers(Document document, String previousDomain) {
List<String> invalidUsers = new ArrayList<String>();
UserManager userManager = UserManager.getInstance();
RosterItemProvider rosterItemProvider = RosterItemProvider
.getInstance();
Element users = document.getRootElement();
Iterator usersIter = users.elementIterator("User");
while (usersIter.hasNext()) {
Element user = (Element) usersIter.next();
String userName = null;
String password = null;
String email = null;
String name = null;
List<RosterItem> rosterItems = new ArrayList<RosterItem>();
Iterator userElements = user.elementIterator();
while (userElements.hasNext()) {
Element userElement = (Element) userElements.next();
String nameElement = userElement.getName();
if ("Username".equals(nameElement)) {
userName = userElement.getText();
} else if ("Password".equals(nameElement)) {
password = userElement.getText();
} else if ("Name".equals(nameElement)) {
name = userElement.getText();
} else if ("Email".equals(nameElement)) {
email = userElement.getText();
} else if ("Roster".equals(nameElement)) {
Iterator rosterIter = userElement.elementIterator("Item");
while (rosterIter.hasNext()) {
Element rosterElement = (Element) rosterIter.next();
String jid = rosterElement.attributeValue("jid");
String askstatus = rosterElement
.attributeValue("askstatus");
String recvstatus = rosterElement
.attributeValue("recvstatus");
String substatus = rosterElement
.attributeValue("substatus");
String nickname = rosterElement.attributeValue("name");
List<String> groups = new ArrayList<String>();
Iterator groupIter = rosterElement
.elementIterator("Group");
while (groupIter.hasNext()) {
Element group = (Element) groupIter.next();
groups.add(group.getText());
}
// used for migration
if (previousDomain != null) {
jid = jid.replace(previousDomain, serverName);
}
rosterItems.add(new RosterItem(new JID(jid),
RosterItem.SubType.getTypeFromInt(Integer
.parseInt(substatus)),
RosterItem.AskType.getTypeFromInt(Integer
.parseInt(askstatus)),
RosterItem.RecvType.getTypeFromInt(Integer
.parseInt(recvstatus)), nickname,
groups));
}
}
}
if ((userName != null) && (password != null)) {
try {
userName = Stringprep.nodeprep(userName);
if (!isUserProviderReadOnly()) {
userManager.createUser(userName, password, name, email);
}
// Check to see user exists before adding their roster, this
// is for read-only user providers.
userManager.getUser(userName);
for (RosterItem ri : rosterItems) {
rosterItemProvider.createItem(userName, ri);
}
} catch (StringprepException se) {
Log.info("Invalid username " + userName);
invalidUsers.add(userName);
} catch (UserAlreadyExistsException e) {
Log.info("User already exists " + userName);
invalidUsers.add(userName);
} catch (UserNotFoundException e) {
Log.info("User not found " + userName);
invalidUsers.add(userName);
}
}
}
return invalidUsers;
}
}

View File

@ -1,84 +0,0 @@
package net.processone.plugin.openfire;
import java.io.IOException;
import java.net.URL;
import javax.xml.parsers.SAXParserFactory;
import org.apache.commons.fileupload.FileItem;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.io.SAXReader;
import org.dom4j.io.SAXWriter;
import org.jivesoftware.util.Log;
import org.xml.sax.ContentHandler;
import org.xml.sax.ErrorHandler;
import org.xml.sax.Locator;
import org.xml.sax.SAXParseException;
import com.sun.msv.reader.util.GrammarLoader;
import com.sun.msv.reader.util.IgnoreController;
import com.sun.msv.verifier.DocumentDeclaration;
import com.sun.msv.verifier.Verifier;
public class UserSchemaValidator {
private Document doc;
private String schema;
UserSchemaValidator(FileItem usersFile, String schemaFile) throws DocumentException, IOException {
SAXReader reader = new SAXReader();
doc = reader.read(usersFile.getInputStream());
URL schemaURL = this.getClass().getClassLoader().getResource(schemaFile);
schema = schemaURL.toExternalForm();
}
boolean validate() {
try {
SAXParserFactory saxFactory = SAXParserFactory.newInstance();
saxFactory.setNamespaceAware(true);
DocumentDeclaration docDeclaration = GrammarLoader.loadVGM(schema, new IgnoreController() {
public void error(Locator[] locations,
String message,
Exception exception) {
Log.error("ERROR: " + message);
}
public void error(Locator[] locations, String message) {
Log.error("WARNING: " + message);
}
}, saxFactory);
ValidatorErrorHandler validatorErrorHandler = new ValidatorErrorHandler();
Verifier verifier = new Verifier(docDeclaration, validatorErrorHandler);
SAXWriter writer = new SAXWriter((ContentHandler) verifier);
writer.setErrorHandler(validatorErrorHandler);
writer.write(doc);
if (verifier.isValid()) {
return true;
} else {
Log.error(doc.getName() + " is invalid.");
return false;
}
} catch (Exception e) {
Log.error(e);
return false;
}
}
private class ValidatorErrorHandler implements ErrorHandler {
public void error(SAXParseException e) {
Log.error("ERROR:" + e);
}
public void fatalError(SAXParseException e) {
Log.error("Fatal:" + e);
}
public void warning(SAXParseException e) {
Log.error("Warning:" + e);
}
}
}

View File

@ -1,326 +0,0 @@
package org.jivesoftware.openfire;
/**
* $RCSfile$
* $Revision: 1759 $
* $Date: 2005-08-09 19:32:51 -0300 (Tue, 09 Aug 2005) $
*
* Copyright (C) 2004-2008 Jive Software. All rights reserved.
*
* This software is published under the terms of the GNU Public License (GPL),
* a copy of which is included in this distribution, or a commercial license
* agreement with Jive.
*/
import org.dom4j.Document;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;
import org.dom4j.Namespace;
import org.dom4j.QName;
import org.dom4j.io.SAXReader;
import org.jivesoftware.database.DbConnectionManager;
import org.jivesoftware.util.JiveGlobals;
import org.jivesoftware.util.LocaleUtils;
import org.jivesoftware.util.Log;
import org.jivesoftware.openfire.container.BasicModule;
import org.jivesoftware.openfire.event.UserEventDispatcher;
import org.jivesoftware.openfire.event.UserEventListener;
import org.jivesoftware.openfire.user.User;
import java.io.StringReader;
import java.io.StringWriter;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.util.Map;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;
/**
* Private storage for user accounts (JEP-0049). It is used by some XMPP systems
* for saving client settings on the server.
*
* @author Iain Shigeoka
*/
public class PrivateStorage extends BasicModule implements UserEventListener {
private static final String LOAD_PRIVATE = "SELECT privateData FROM ofPrivate WHERE username=? AND namespace=?";
private static final String LOAD_ALL_PRIVATE = "SELECT privateData FROM ofPrivate WHERE username=?";
private static final String INSERT_PRIVATE = "INSERT INTO ofPrivate (privateData,name,username,namespace) VALUES (?,?,?,?)";
private static final String UPDATE_PRIVATE = "UPDATE ofPrivate SET privateData=?, name=? WHERE username=? AND namespace=?";
private static final String DELETE_PRIVATES = "DELETE FROM ofPrivate WHERE username=?";
// Currently no delete supported, we can detect an add of an empty element
// and
// use that to signal a delete but that optimization doesn't seem necessary.
// private static final String DELETE_PRIVATE =
// "DELETE FROM ofPrivate WHERE userID=? AND name=? AND namespace=?";
private boolean enabled = JiveGlobals.getBooleanProperty(
"xmpp.privateStorageEnabled", true);
/**
* Pool of SAX Readers. SAXReader is not thread safe so we need to have a
* pool of readers.
*/
private BlockingQueue<SAXReader> xmlReaders = new LinkedBlockingQueue<SAXReader>();
/**
* Constructs a new PrivateStore instance.
*/
public PrivateStorage() {
super("Private user data storage");
}
/**
* Returns true if private storage is enabled.
*
* @return true if private storage is enabled.
*/
public boolean isEnabled() {
return enabled;
}
/**
* Sets whether private storage is enabled.
*
* @param enabled
* true if this private store is enabled.
*/
public void setEnabled(boolean enabled) {
this.enabled = enabled;
JiveGlobals.setProperty("xmpp.privateStorageEnabled", Boolean
.toString(enabled));
}
/**
* Stores private data. If the name and namespace of the element matches
* another stored private data XML document, then replace it with the new
* one.
*
* @param data
* the data to store (XML element)
* @param username
* the username of the account where private data is being stored
*/
public void add(String username, Element data) {
if (enabled) {
java.sql.Connection con = null;
PreparedStatement pstmt = null;
try {
StringWriter writer = new StringWriter();
data.write(writer);
con = DbConnectionManager.getConnection();
pstmt = con.prepareStatement(LOAD_PRIVATE);
pstmt.setString(1, username);
pstmt.setString(2, data.getNamespaceURI());
ResultSet rs = pstmt.executeQuery();
boolean update = false;
if (rs.next()) {
update = true;
}
rs.close();
pstmt.close();
if (update) {
pstmt = con.prepareStatement(UPDATE_PRIVATE);
} else {
pstmt = con.prepareStatement(INSERT_PRIVATE);
}
pstmt.setString(1, writer.toString());
pstmt.setString(2, data.getName());
pstmt.setString(3, username);
pstmt.setString(4, data.getNamespaceURI());
pstmt.executeUpdate();
} catch (Exception e) {
Log.error(LocaleUtils.getLocalizedString("admin.error"), e);
} 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);
}
}
}
}
/**
* Returns the data stored under a key corresponding to the name and
* namespace of the given element. The Element must be in the form:
* <p>
*
* <code>&lt;name xmlns='namespace'/&gt;</code>
* <p>
*
* If no data is currently stored under the given key, an empty element will
* be returned.
*
* @param data
* an XML document who's element name and namespace is used to
* match previously stored private data.
* @param username
* the username of the account where private data is being
* stored.
* @return the data stored under the given key or the data element.
*/
public Element get(String username, Element data) {
if (enabled) {
Connection con = null;
PreparedStatement pstmt = null;
SAXReader xmlReader = null;
try {
// Get a sax reader from the pool
xmlReader = xmlReaders.take();
con = DbConnectionManager.getConnection();
pstmt = con.prepareStatement(LOAD_PRIVATE);
pstmt.setString(1, username);
pstmt.setString(2, data.getNamespaceURI());
ResultSet rs = pstmt.executeQuery();
if (rs.next()) {
data.clearContent();
String result = rs.getString(1).trim();
Document doc = xmlReader.read(new StringReader(result));
data = doc.getRootElement();
}
rs.close();
} catch (Exception e) {
Log.error(LocaleUtils.getLocalizedString("admin.error"), e);
} finally {
// Return the sax reader to the pool
if (xmlReader != null) {
xmlReaders.add(xmlReader);
}
try {
if (pstmt != null) {
pstmt.close();
}
} catch (Exception e) {
Log.error(e);
}
try {
if (con != null) {
con.close();
}
} catch (Exception e) {
Log.error(e);
}
}
}
return data;
}
public Element getAll(String username) {
QName qName = new QName("", new Namespace("","jabber:iq:private"), "query");
Element data = DocumentHelper.createElement(qName);
if (enabled) {
Connection con = null;
PreparedStatement pstmt = null;
SAXReader xmlReader = null;
try {
// Get a sax reader from the pool
xmlReader = xmlReaders.take();
con = DbConnectionManager.getConnection();
pstmt = con.prepareStatement(LOAD_ALL_PRIVATE);
pstmt.setString(1, username);
ResultSet rs = pstmt.executeQuery();
while (rs.next()) {
String result = rs.getString(1).trim();
Document doc = xmlReader.read(new StringReader(result));
data.add(doc.getRootElement());
}
rs.close();
} catch (Exception e) {
Log.error(LocaleUtils.getLocalizedString("admin.error"), e);
} finally {
// Return the sax reader to the pool
if (xmlReader != null) {
xmlReaders.add(xmlReader);
}
try {
if (pstmt != null) {
pstmt.close();
}
} catch (Exception e) {
Log.error(e);
}
try {
if (con != null) {
con.close();
}
} catch (Exception e) {
Log.error(e);
}
}
}
return data;
}
public void userCreated(User user, Map params) {
// Do nothing
}
public void userDeleting(User user, Map params) {
// Delete all private properties of the user
java.sql.Connection con = null;
PreparedStatement pstmt = null;
try {
con = DbConnectionManager.getConnection();
pstmt = con.prepareStatement(DELETE_PRIVATES);
pstmt.setString(1, user.getUsername());
pstmt.executeUpdate();
} catch (Exception e) {
Log.error(LocaleUtils.getLocalizedString("admin.error"), e);
} 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);
}
}
}
public void userModified(User user, Map params) {
// Do nothing
}
public void start() throws IllegalStateException {
super.start();
// Initialize the pool of sax readers
for (int i = 0; i < 10; i++) {
SAXReader xmlReader = new SAXReader();
xmlReader.setEncoding("UTF-8");
xmlReaders.add(xmlReader);
}
// Add this module as a user event listener so we can delete
// all user properties when a user is deleted
UserEventDispatcher.addListener(this);
}
public void stop() {
super.stop();
// Clean up the pool of sax readers
xmlReaders.clear();
// Remove this module as a user event listener
UserEventDispatcher.removeListener(this);
}
}

View File

@ -1,17 +0,0 @@
<%@ page import="java.io.OutputStream,
org.jivesoftware.openfire.XMPPServer,
net.processone.plugin.openfire.ExporterXEP227"
contentType="application/x-download" %>
<!--NOTE: This JSP file should be implemented with JSTL and Servlet,
Is not a good idea to call your self pages and add scriplet to handle -->
<%String fileName = request.getParameter("fileName");
response.setContentType("application/x-download");
response.setHeader("Content-Disposition","attachment;filename="+fileName+".xml");
ExporterXEP227 plugin = (ExporterXEP227) XMPPServer.getInstance().getPluginManager().getPlugin("openfireexporter");
byte[] content = plugin.exportUsersToByteArray();
OutputStream os = response.getOutputStream();
os.write(content);
os.flush();
os.close();%>

View File

@ -1,137 +0,0 @@
<%@ page
import="java.io.IOException,java.util.*,
net.processone.plugin.openfire.ExporterXEP227,
org.jivesoftware.openfire.XMPPServer,
org.jivesoftware.util.ParamUtils"%>
<%@ taglib uri="http://java.sun.com/jstl/core_rt" prefix="c"%>
<%@ taglib uri="http://java.sun.com/jstl/fmt_rt" prefix="fmt"%>
<!--NOTE: This JSP file should be implemented with JSTL and Servlet,
Is not a good idea to call your self pages and add scriplet to handle -->
<%
boolean exportUsers = request.getParameter("exportUsers") != null;
boolean success = request.getParameter("success") != null;
boolean exportToFile = ParamUtils.getBooleanParameter(request,
"exporttofile", true);
ExporterXEP227 plugin = (ExporterXEP227) XMPPServer.getInstance()
.getPluginManager().getPlugin("openfireexporter");
String exportText = "";
Map<String, String> errors = new HashMap<String, String>();
if (exportUsers) {
if (exportToFile) {
String file = ParamUtils
.getParameter(request, "exportFile");
if ((file == null) || (file.length() <= 0)) {
errors.put("missingFile", "missingFile");
} else {
response.sendRedirect("export-file.jsp?fileName="
+ file);
}
} else {
try {
exportText = plugin.exportUsersToString();
} catch (IOException e) {
errors.put("IOException", "IOException");
}
}
}
%>
<html>
<head>
<title>Export User Data</title>
<meta name="pageID" content="import-export-selection" />
</head>
<body>
<%
if (errors.size() > 0) {
%>
<div class="jive-error">
<table cellpadding="0" cellspacing="0" border="0">
<tbody>
<tr>
<td class="jive-icon"><img src="images/error-16x16.gif"
width="16" height="16" border="0"></td>
<td class="jive-icon-label">
<%
if (errors.containsKey("missingFile")) {
%> Missing or bad file
name. <%
} else if (errors.containsKey("IOException")
|| errors.containsKey("fileNotCreated")) {
%>
Couldn't create export file. <%
}
%>
</td>
</tr>
</tbody>
</table>
</div>
<br>
<%
} else if (ParamUtils.getBooleanParameter(request, "success")) {
%>
<div class="jive-success">
<table cellpadding="0" cellspacing="0" border="0">
<tbody>
<tr>
<td class="jive-icon"><img src="images/success-16x16.gif"
width="16" height="16" border="0"></td>
<td class="jive-icon-label">User data successfully exported.</td>
</tr>
</tbody>
</table>
</div>
<br>
<%
}
%>
<form action="export-user-data.jsp?exportUsers" method="post">
<div class="jive-contentBoxHeader">Export Options</div>
<div class="jive-contentBox">
<p>Select the radio button next to the desired export option and
then click on the Export button.</p>
<table cellpadding="3" cellspacing="0" border="0" width="100%">
<tbody>
<tr>
<td width="1%"><input type="radio" name="exporttofile"
value="true" <%=exportToFile ? "checked" : ""%> id="rb01"></td>
<td width="99%"><label for="rb01"><b>To File</b></label> - Save
user data to the specified file location.</td>
</tr>
<tr>
<td width="1%">&nbsp;</td>
<td width="99%">Export File Name:&nbsp;<input type="text"
size="30" maxlength="150" name="exportFile"></td>
</tr>
<tr>
<td width="1%"><input type="radio" name="exporttofile"
value="false" <%=!exportToFile ? "checked" : ""%> id="rb02"></td>
<td width="99%"><label for="rb02"><b>To Screen</b></label> -
Display user data in the text area below.</td>
</tr>
<tr>
<td width="1%">&nbsp;</td>
<td width="99%"><textarea cols="80" rows="20" wrap=off><%=exportText%></textarea></td>
</tr>
</tbody>
</table>
</div>
<input type="submit" value="Export"></form>
</body>
</html>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 594 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1016 B

View File

@ -1,42 +0,0 @@
<%@ page import="net.processone.plugin.openfire.ExporterXEP227,
org.jivesoftware.openfire.XMPPServer"
%>
<!--NOTE: This JSP file should be implemented with JSTL and Servlet,
Is not a good idea to call your self pages and add scriplet to handle -->
<html>
<head>
<title>Import/Export Selection</title>
<meta name="pageID" content="import-export-selection"/>
</head>
<body>
<jsp:useBean id="pageinfo" scope="request" class="org.jivesoftware.admin.AdminPageBean" />
<%
ExporterXEP227 plugin = (ExporterXEP227) XMPPServer.getInstance().getPluginManager().getPlugin("openfireexporter");
%>
<p>
Openfire plugin improved to export to XEP-227 format.
There is also old code to import, but using a custom Openfire format.
If you are interested you can improve it to also support XEP-227 import.
<ul>
<li><a href="import-user-data.jsp">Import User Data</a></li>
<li><a href="export-user-data.jsp">Export User Data</a></li>
</ul>
<%
if (plugin.isUserProviderReadOnly()) {
%>
Note: because you are using a read-only user data store such as LDAP or POP3 you will only be able to import user roster data, not users themselves.
Please see the <a href="../../plugin-admin.jsp?plugin=openfireexporter&showReadme=true&decorator=none">readme</a> for details.
<%
}
%>
</p>
</body>
</html>

View File

@ -1,168 +0,0 @@
<%@ page import="java.net.MalformedURLException,
java.util.*,
org.dom4j.DocumentException,
org.apache.commons.fileupload.DiskFileUpload,
org.apache.commons.fileupload.FileItem,net.processone.plugin.openfire.ExporterXEP227,
org.jivesoftware.openfire.XMPPServer,
org.jivesoftware.util.ParamUtils"
%>
<!--NOTE: This JSP file should be implemented with JSTL and Servlet,
Is not a good idea to call your self pages and add scriplet to handle -->
<%
boolean importUsers = request.getParameter("importUsers") != null;
ExporterXEP227 plugin = (ExporterXEP227) XMPPServer.getInstance().getPluginManager().getPlugin("openfireexporter");
List<String> duplicateUsers = new ArrayList<String>();
Map<String, String> errors = new HashMap<String, String>();
if (importUsers) {
DiskFileUpload dfu = new DiskFileUpload();
List fileItems = dfu.parseRequest(request);
Iterator i = fileItems.iterator();
FileItem fi = (FileItem) i.next();
FileItem pd = (FileItem) i.next();
String previousDomain = pd.getString();
if (plugin.validateImportFile(fi)) {
try {
if (isEmpty(previousDomain)) {
duplicateUsers.addAll(plugin.importUserData(fi, null));
}
else if (!isEmpty(previousDomain)) {
duplicateUsers.addAll(plugin.importUserData(fi, previousDomain));
}
else {
errors.put("missingDomain", "missingDomain");
}
if (duplicateUsers.size() == 0) {
response.sendRedirect("import-user-data.jsp?success=true");
return;
}
errors.put("invalidUser", "invalidUser");
}
catch (MalformedURLException e) {
errors.put("IOException", "IOException");
}
catch (DocumentException e) {
errors.put("DocumentException", "DocumentException");
}
}
else {
errors.put("invalidUserFile", "invalidUserFile");
}
}
%>
<html>
<head>
<title>Import User Data</title>
<meta name="pageID" content="import-export-selection"/>
</head>
<body>
<% if (errors.size() > 0) { %>
<div class="jive-error">
<table cellpadding="0" cellspacing="0" border="0">
<tbody>
<tr>
<td class="jive-icon"><img src="images/error-16x16.gif" width="16" height="16" border="0"></td>
<td class="jive-icon-label">
<% if (errors.containsKey("missingDomain")) { %>
You must supply both a existing and new domain name.
<% } else if (errors.containsKey("IOException")) { %>
Missing or bad file name.
<% } else if (errors.containsKey("DocumentException")) { %>
Import failed.
<% } else if (errors.containsKey("invalidUserFile")) { %>
The import file does not match the user schema.
<% } else if (errors.containsKey("invalidUser")) { %>
<% if (plugin.isUserProviderReadOnly()) { %>
The following users did not exist in the system or have invalid username so their roster was not loaded:<br>
<% } else { %>
The following users already exist in the system or have invalid username and were not loaded:<br>
<% } %>
<%
Iterator iter = duplicateUsers.iterator();
while (iter.hasNext()) {
String username = (String) iter.next();
%><%= username %><%
if (iter.hasNext()) {
%>,&nbsp;<%
} else {
%>.<%
}
}
} %>
</td>
</tr>
</tbody>
</table>
</div>
<br>
<% } else if (ParamUtils.getBooleanParameter(request, "success")) { %>
<div class="jive-success">
<table cellpadding="0" cellspacing="0" border="0">
<tbody>
<tr>
<td class="jive-icon"><img src="images/success-16x16.gif" width="16" height="16" border="0"></td>
<% if (plugin.isUserProviderReadOnly()) { %>
<td class="jive-icon-label">User roster data added successfully.</td>
<% } else { %>
<td class="jive-icon-label">All users added successfully.</td>
<% } %>
</tr>
</tbody>
</table>
</div>
<br>
<% } %>
Use the form below to import a user data XML file.
<form action="import-user-data.jsp?importUsers" method="post" enctype="multipart/form-data">
<div class="jive-contentBoxHeader">Import</div>
<div class="jive-contentBox">
<p>
Choose a file to import:</p>
<input type="file" name="thefile">
<br><br><br>
<p>
<b>Optional</b> - Use the field below to replace the domain name of user roster entries with the current hostname.
See the migration section of the <a href="../../plugin-admin.jsp?plugin=openfireexporter&showReadme=true&decorator=none">readme</a> for details.
</p>
Replace Domain: <input type="text" size="20" maxlength="150" name="previousDomain" value=""/>
</div>
<input type="submit" value="Import">
</form>
</body>
</html>
<%!
public boolean isEmpty(String s) {
if (s == null) {
return true;
}
if (s.trim().length() == 0) {
return true;
}
return false;
}
%>