Commit 2e8c10ea authored by Guus der Kinderen's avatar Guus der Kinderen Committed by daryl herzmann

New inVerse plugin (#825)

A new Openfire plugin, that bundles the third party 'inVerse' web client.
parent 59d93d8f
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<html>
<head>
<title>inVerse Plugin Changelog</title>
<style type="text/css">
BODY {
font-size : 100%;
}
BODY, TD, TH {
font-family : tahoma, verdana, arial, helvetica, sans-serif;
font-size : 0.8em;
}
H2 {
font-size : 10pt;
font-weight : bold;
padding-left : 1em;
}
A:hover {
text-decoration : none;
}
H1 {
font-family : tahoma, arial, helvetica, sans-serif;
font-size : 1.4em;
font-weight: bold;
border-bottom : 1px #ccc solid;
padding-bottom : 2px;
}
TT {
font-family : courier new;
font-weight : bold;
color : #060;
}
PRE {
font-family : courier new;
font-size : 100%;
}
</style>
</head>
<body>
<h1>
inVerse Plugin Changelog
</h1>
<p><b>3.0.3 Alpha 1</b> -- June 19th, 2017</p>
<ul>
<li>Initial release.</li>
<li>Based on <a href="https://github.com/jcbrand/converse.js/commit/068be7bfeead28f3df2585873fa66f5e2d58c6dc">commit 068be7b</a>
of Converse, which is a commit newer than the 3.0.2 release, which was the latest official release at the time.</li>
</ul>
</body>
</html>
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
version="3.1">
<servlet>
<servlet-name>config</servlet-name>
<servlet-class>org.igniterealtime.openfire.plugin.inverse.ConfigServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>config</servlet-name>
<url-pattern>/config.json</url-pattern>
</servlet-mapping>
</web-app>
\ No newline at end of file
<!doctype html>
<html class="no-js" lang="en">
<head>
<meta charset="utf-8"/>
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
<title>inVerse</title>
<link rel="shortcut icon" type="image/ico" href="inverse/css/images/favicon.ico"/>
<link type="text/css" rel="stylesheet" media="screen" href="inverse/css/inverse.min.css" />
<![if gte IE 9]>
<script src="inverse/dist/inverse.min.js"></script>
<![endif]>
</head>
<body>
<div class="content">
<div class="inner-content">
<h1 class="brand-heading"><i class="icon-conversejs"></i> inVerse</h1>
</div>
</div>
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js"></script>
<script>
$( document ).ready( function()
{
var config = {};
$.getJSON( 'config.json', function ( config )
{
converse.initialize( config );
});
});
</script>
</body>
</html>
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="24px" height="12px" viewBox="0 0 24 12" zoomAndPan="disable">
<line x1="0" y1="0" x2="12" y2="12" style="stroke:#ccc;stroke-width:1.5" />
<line x1="24" y1="0" x2="12" y2="12" style="stroke:#ccc;stroke-width:1.5" />
</svg>
\ No newline at end of file
<!--
Tessellate 1.0 by HTML5 UP
html5up.net | @n33co
Free for personal and commercial use under the CCA 3.0 license (html5up.net/license)
-->
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="1000px" height="1000px" viewBox="0 0 1000 1000" zoomAndPan="disable">
<style type="text/css"><![CDATA[
line
{
stroke: rgba(255,255,255,0.1);
stroke-width: 0.85px;
}
]]></style>
<line x1="-180" y1="0" x2="820" y2="1000" />
<line x1="-380" y1="0" x2="620" y2="1000" />
<line x1="-530" y1="0" x2="470" y2="1000" />
<line x1="-655" y1="0" x2="345" y2="1000" />
<line x1="-755" y1="0" x2="245" y2="1000" />
<line x1="-830" y1="0" x2="170" y2="1000" />
<line x1="-880" y1="0" x2="120" y2="1000" />
<line x1="-920" y1="0" x2="80" y2="1000" />
<line x1="-950" y1="0" x2="50" y2="1000" />
<line x1="-970" y1="0" x2="30" y2="1000" />
<line x1="-985" y1="0" x2="15" y2="1000" />
<line x1="-995" y1="0" x2="5" y2="1000" />
</svg>
\ No newline at end of file
<!--
Tessellate 1.0 by HTML5 UP
html5up.net | @n33co
Free for personal and commercial use under the CCA 3.0 license (html5up.net/license)
-->
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="1000px" height="1000px" viewBox="0 0 1000 1000" zoomAndPan="disable">
<style type="text/css"><![CDATA[
line
{
stroke: rgba(255,255,255,0.1);
stroke-width: 0.85px;
}
]]></style>
<line x1="180" y1="0" x2="1180" y2="1000" />
<line x1="380" y1="0" x2="1380" y2="1000" />
<line x1="530" y1="0" x2="1530" y2="1000" />
<line x1="655" y1="0" x2="1655" y2="1000" />
<line x1="755" y1="0" x2="1775" y2="1000" />
<line x1="830" y1="0" x2="1830" y2="1000" />
<line x1="880" y1="0" x2="1880" y2="1000" />
<line x1="920" y1="0" x2="1920" y2="1000" />
<line x1="950" y1="0" x2="1970" y2="1000" />
<line x1="970" y1="0" x2="1970" y2="1000" />
<line x1="985" y1="0" x2="1985" y2="1000" />
<line x1="995" y1="0" x2="1995" y2="1000" />
</svg>
\ No newline at end of file
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="24px" height="12px" viewBox="0 0 24 12" zoomAndPan="disable">
<line x1="0" y1="0" x2="12" y2="12" style="stroke:rgba(255,255,255,0.65);stroke-width:1" />
<line x1="24" y1="0" x2="12" y2="12" style="stroke:rgba(255,255,255,0.65);stroke-width:1" />
</svg>
\ No newline at end of file
This diff is collapsed.
This diff is collapsed.
<?xml version="1.0" encoding="UTF-8"?>
<plugin>
<class>org.igniterealtime.openfire.plugin.inverse.InversePlugin</class>
<name>inVerse</name>
<description>Adds the (third-party) inVerse web client to Openfire.</description>
<author>Guus der Kinderen</author>
<version>3.0.3 Alpha 1</version>
<date>06/19/2017</date>
<minServerVersion>4.1.5</minServerVersion>
<adminconsole>
<tab id="tab-server">
<sidebar id="webclients" name="${admin.sidebar.webclients.name}" description="${admin.sidebar.webclients.description}">
<item id="inverse-config" name="${admin.sidebar.webclients.item.inverse.name}" description="${admin.sidebar.webclients.item.inverse.description}" url="inverse-config.jsp"/>
</sidebar>
</tab>
</adminconsole>
</plugin>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<artifactId>plugins</artifactId>
<groupId>org.igniterealtime.openfire</groupId>
<version>4.2.0-SNAPSHOT</version>
</parent>
<groupId>org.igniterealtime.openfire.plugins</groupId>
<artifactId>inverse</artifactId>
<name>Inverse Webchat Plugin</name>
<version>3.0.3-Alpha-1</version>
<build>
<sourceDirectory>src/java</sourceDirectory>
<plugins>
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
</plugin>
<!-- Compiles the Openfire Admin Console JSP pages. -->
<plugin>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-jspc-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
<dependencies>
<dependency>
<artifactId>json</artifactId>
<groupId>org.json</groupId>
<version>20160810</version>
</dependency>
</dependencies>
</project>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<html>
<head>
<title>inVerse Plugin Readme</title>
<style type="text/css">
BODY {
font-size : 100%;
}
BODY, TD, TH {
font-family : tahoma, verdana, arial, helvetica, sans-serif;
font-size : 0.8em;
}
H3 {
font-size : 10pt;
font-style: italic;
color: #004444;
}
H2 {
font-size : 10pt;
font-weight : bold;
}
A:hover {
text-decoration : none;
}
H1 {
font-family : tahoma, arial, helvetica, sans-serif;
font-size : 1.4em;
font-weight: bold;
border-bottom : 1px #ccc solid;
padding-bottom : 2px;
}
TT {
font-family : courier new;
font-weight : bold;
color : #060;
}
PRE {
font-family : courier new;
font-size : 100%;
}
#datatable TH {
color : #fff;
background-color : #2A448C;
text-align : left;
}
#datatable TD {
background-color : #FAF6EF;
}
#datatable .name {
background-color : #DCE2F5;
}
</style>
</head>
<body>
<h1>
inVerse Plugin Readme
</h1>
<h2>Overview</h2>
<p>
The inVerse plugin adds the web client to Openfire. inVerse is a third party web client implementation. It's project
home page is <a href="https://github.com/jcbrand/inverse.js">https://github.com/jcbrand/inverse.js</a>
</p>
<h2>Installation</h2>
<p>
Copy inverse.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 inverse.jar file over the existing file.
</p>
<h2>Configuration</h2>
<p>
The plugin is configured via the Openfire Admin Console. After installation, a new Admin Console page is available.
The page can be found under the "Server" tab and "Web Clients" sub-tab. The name of the page is "inVerse".
</p>
<p>
inVerse depends on HTTP binding, and will not work if the HTTP binding service of Openfire is disabled.
</p>
<h2>Using the Plugin</h2>
<p>
When properly configured, the inVerse web client will be made available on the same ports as the HTTP binding
interface. The exact URLs for your instance of Openfire are displayed on the inVerse Configuration Admin Console page.
By default, these URLs are:
</p>
<ul>
<li><tt>http://&lt;your-server-name&gt;:7070/inverse/</tt> (unencrypted HTTP)</li>
<li><tt>https://&lt;your-server-name&gt;:7443/inverse/</tt> (encrypted HTTPS)</li>
</ul>
<p>
After opening one of these addresses in a browser, the user is presented with a login form.
</p>
</body>
</html>
admin.sidebar.webclients.name=Web Clients
admin.sidebar.webclients.description=Manage Web Clients
admin.sidebar.webclients.item.inverse.name=inVerse
admin.sidebar.webclients.item.inverse.description=Manage inVerse Webchat
global.click_edit=Click to edit...
global.save_settings=Save Settings
admin.error=Internal server error
global.csrf.failed=CSRF Error: No changes made, you'll need to retry.
warning.httpbinding.disabled=The HTTP Binding service appears to be disabled! inVerse will not work without this service. {0}Please enable the HTTP Binding service here!{1}
properties.save.success=Properties successfully saved.
config.page.title=inVerse Web Client Configuration
config.page.description=This page allows you to configure the inVerse web chat application.
config.page.link.unsecure=End-users can use inVerse (using an unencrypted HTTP connection) by opening the following address in a browser: <a href="{0}">{0}</a>.
config.page.link.secure=inVerse is available via an encrypted HTTPS address at: <a href="{0}">{0}</a>.
config.page.debug.header=Webclient Debug Setting
config.page.debug.description=If set to true, debugging output will be logged to the browser console.
config.page.debug.enabled=Enabled
config.page.debug.enabled_info=Debug information will be printed to the Javascript console of the client browser.
config.page.debug.disabled=Disabled
config.page.debug.disabled_info=Client-sided debug information will not be generated.
config.page.general.header=Web Client Settings
config.page.general.description=Use this form to apply configuration changes to the inVerse web client.
config.page.default_domain.description=Specify a domain to act as the default for user JIDs. This allows users to log \
in with only the username part of their JID, instead of the full JID. For example, if <tt>default_domain</tt> \
is <tt>example.org</tt>, then the user: <tt>johnny@example.org</tt> can log in with only <tt>johnny</tt>. JIDs \
with other domains are still allowed but need to be provided in full. To specify only one domain and disallow other\
domains, see the <em>locked domain</em> option.
config.page.default_domain.label=Default Domain
config.page.locked_domain.label=Locked Domain
config.page.locked_domain.description=When enabled, users from domains other than the one specified cannot use the client.
config.page.language.header=inVerse Language
config.page.language.description=The selection made here affects the language of the inVerse user interface.
\ No newline at end of file
/*
* Copyright (C) 2017 Ignite Realtime Foundation. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.igniterealtime.openfire.plugin.inverse;
import org.jivesoftware.openfire.XMPPServer;
import org.jivesoftware.util.JiveGlobals;
import org.jivesoftware.util.StringUtils;
import org.json.JSONArray;
import org.json.JSONObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.xmpp.packet.JID;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.Writer;
import java.util.HashSet;
import java.util.Set;
/**
* Generates a JSON object that contains configuration for the inVerse web application.
*
* @author Guus der Kinderen, guus@gmail.com
*/
public class ConfigServlet extends HttpServlet
{
private static final Logger Log = LoggerFactory.getLogger( ConfigServlet.class );
public void doGet( HttpServletRequest request, HttpServletResponse response ) throws ServletException, IOException
{
Log.trace( "Processing doGet()" );
final String defaultDomain = JiveGlobals.getProperty( "inverse.config.default_domain", XMPPServer.getInstance().getServerInfo().getXMPPDomain() );
final boolean lockedDomain = JiveGlobals.getBooleanProperty( "inverse.config.locked_domain", false );
final String endpoint = request.getScheme() + "://" + request.getServerName() + ":" + request.getServerPort() + "/http-bind/";
final boolean debug = JiveGlobals.getBooleanProperty( "inverse.config.debug", false );
// The language of the inVerse UI.
final Language language = InversePlugin.getLanguage();
final JSONObject config = new JSONObject();
config.put( "auto_away", 300); // TODO make configurable.
config.put( "notify_all_room_messages", new JSONArray() ); // TODO make configurable.
config.put( "i18n", language.getCode() );
config.put( lockedDomain ? "locked_domain" : "default_domain", defaultDomain );
if ( XMPPServer.getInstance().getIQRegisterHandler().isInbandRegEnabled() )
{
config.put( "registration_domain", defaultDomain );
}
config.put( "domain_placeholder", defaultDomain );
config.put( "bosh_service_url", endpoint );
config.put( "debug", debug );
final JSONArray whitelistedPlugins = new JSONArray(); // TODO make configurable.
whitelistedPlugins.put( "converse-singleton" );
whitelistedPlugins.put( "converse-inverse" );
config.put( "whitelisted_plugins", whitelistedPlugins );
final JSONArray blacklistedPlugins = new JSONArray(); // TODO make configurable.
blacklistedPlugins.put( "converse-minimize" );
blacklistedPlugins.put( "converse-dragresize" );
config.put( "blacklisted_plugins", blacklistedPlugins );
config.put( "auto_reconnect", true ); // TODO make configurable.
config.put( "message_carbons", true ); // TODO make configurable.
config.put( "message_archiving", "always" ); // TODO make configurable.
config.put( "roster_groups", true ); // TODO make configurable.
// inVerse.js requires some hard-coded converse.js configuration options (look in the upstream source of
// src/converse-inverse.js at the settings in passed into `updateSettings`). We should not allow overrides of
// these configu options (if only, because inVerse will override them anyways):
// chatview_avatar_height: 44,
// chatview_avatar_width: 44,
// hide_open_bookmarks: true,
// show_controlbox_by_default: true,
// sticky_controlbox: true,
try ( final Writer writer = response.getWriter() )
{
writer.write( config.toString( 2 ) );
writer.flush();
}
}
}
\ No newline at end of file
/*
* Copyright (C) 2017 Ignite Realtime Foundation. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.igniterealtime.openfire.plugin.inverse;
import org.apache.tomcat.InstanceManager;
import org.apache.tomcat.SimpleInstanceManager;
import org.eclipse.jetty.apache.jsp.JettyJasperInitializer;
import org.eclipse.jetty.plus.annotation.ContainerInitializer;
import org.eclipse.jetty.webapp.WebAppContext;
import org.jivesoftware.admin.AuthCheckFilter;
import org.jivesoftware.openfire.container.Plugin;
import org.jivesoftware.openfire.container.PluginManager;
import org.jivesoftware.openfire.http.HttpBindManager;
import org.jivesoftware.util.JiveGlobals;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.File;
import java.util.*;
/**
* An Openfire plugin that integrates the Inverse web client.
*
* @author Guus der Kinderen, guus.der.kinderen@gmail.com
*/
public class InversePlugin implements Plugin
{
private static final Logger Log = LoggerFactory.getLogger( InversePlugin.class );
private final String[] publicResources = new String[]
{
"inverse/inverse",
"inverse/index.html",
"inverse/config.json"
};
private WebAppContext context = null;
@Override
public void initializePlugin( PluginManager manager, File pluginDirectory )
{
for ( final String publicResource : publicResources )
{
AuthCheckFilter.addExclude( publicResource );
}
// Add the Webchat sources to the same context as the one that's providing the BOSH interface.
context = new WebAppContext( null, pluginDirectory.getPath() + File.separator + "classes/", "/inverse" );
context.setClassLoader( this.getClass().getClassLoader() );
// Ensure the JSP engine is initialized correctly (in order to be able to cope with Tomcat/Jasper precompiled JSPs).
final List<ContainerInitializer> initializers = new ArrayList<>();
initializers.add( new ContainerInitializer( new JettyJasperInitializer(), null ) );
context.setAttribute("org.eclipse.jetty.containerInitializers", initializers);
context.setAttribute( InstanceManager.class.getName(), new SimpleInstanceManager());
HttpBindManager.getInstance().addJettyHandler( context );
}
@Override
public void destroyPlugin()
{
if ( context != null )
{
HttpBindManager.getInstance().removeJettyHandler( context );
context.destroy();
context = null;
}
for ( final String publicResource : publicResources )
{
AuthCheckFilter.removeExclude( publicResource );
}
}
public static Language getLanguage()
{
final String inverseLanguage = JiveGlobals.getProperty( "inverse.config.language" );
if ( inverseLanguage != null )
{
final Language result = Language.byConverseCode( inverseLanguage );
if ( result != null )
{
return result;
}
else
{
Log.warn( "The value '{}' of property 'inverse.config.language' cannot be mapped to a language code that is understood by Inverse.", inverseLanguage );
}
}
final Language result = Language.byLocale( JiveGlobals.getLocale() );
if ( result != null )
{
return result;
}
else
{
Log.warn( "The Openfire locale '{}' cannot be mapped to a language code that is understood by Inverse.", JiveGlobals.getLocale() );
}
return Language.English;
}
}
/*
* Copyright (C) 2017 Ignite Realtime Foundation. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.igniterealtime.openfire.plugin.inverse;
import java.util.Locale;
/**
* Languages as defined by Converse.JS.
*
* @author Guus der Kinderen, guus.der.kinderen@gmail.com
*/
public enum Language
{
Afrikaans ("af"),
Bahasa_Indonesia ("id"),
BrazilianPortuguese ("pt_br"),
Catalan ("ca"),
Chinese ("zh"),
Dutch ("nl"),
English ("en"),
French ("fr"),
German ("de"),
Hebrew ("he"),
Hungarian ("hu"),
Italian ("it"),
Japanese ("ja"),
Norwegian ("nb"),
Polish ("pl"),
Russian ("ru"),
Spanish ("es"),
Ukrainian ("uk");
private final String code;
Language( String code )
{
this.code = code;
}
public String getCode()
{
return code;
}
public static Language byConverseCode( final String converseCode )
{
for ( final Language language : values() )
{
if ( language.getCode().equalsIgnoreCase( converseCode ) )
{
return language;
}
}
return null;
}
public static Language byLocale( final Locale locale )
{
for ( final Language language : values() )
{
if ( locale.getLanguage().equals( new Locale( language.getCode() ).getLanguage() ) )
{
return language;
}
}
return null;
}
}
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
version="3.1">
</web-app>
\ No newline at end of file
This diff is collapsed.
......@@ -23,6 +23,7 @@
<module>fastpath</module>
<module>gojara</module>
<module>hazelcast</module>
<module>inverse</module>
<!-- jnsapi not in Maven Central-->
<!--<module>jingleNodes</module>-->
<module>jmxweb</module>
......
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