package org.igniterealtime.openfire.plugin; import org.dom4j.Document; import org.dom4j.DocumentException; import org.dom4j.Element; import org.dom4j.io.SAXReader; import org.jivesoftware.openfire.container.Plugin; import org.jivesoftware.openfire.container.PluginManager; import org.jivesoftware.openfire.plugin.spark.BookmarkInterceptor; import org.jivesoftware.util.JiveGlobals; import org.jivesoftware.util.Version; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.io.*; import java.util.jar.JarFile; import java.util.zip.ZipEntry; /** * A plugin that implements XEP-0048 "Bookmarks". * * @author Guus der Kinderen, guus.der.kinderen@gmail.com * @see <a href="http://xmpp.org/extensions/xep-0048.html">XEP-0048 Bookmarks</a> */ public class BookmarksPlugin implements Plugin { private final static Logger Log = LoggerFactory.getLogger( BookmarksPlugin.class ); private BookmarkInterceptor bookmarkInterceptor; public void initializePlugin( PluginManager manager, File pluginDirectory ) { boolean foundIncompatiblePlugin = false; try { // Check if we Enterprise is installed and stop loading this plugin if found if ( checkForEnterprisePlugin() ) { System.out.println( "Enterprise plugin found. Stopping Bookmarks Plugin." ); foundIncompatiblePlugin = true; } // Check if we ClientControl (version <= 1.3.1) is installed and stop loading this plugin if found if ( checkForIncompatibleClientControlPlugin() ) { System.out.println( "ClientControl plugin v1.3.1 or earlier found. Stopping Bookmarks Plugin." ); foundIncompatiblePlugin = true; } } catch ( Exception ex ) { Log.warn( "An exception occurred while determining if there are incompatible plugins. Assuming everything is OK.", ex ); } if ( foundIncompatiblePlugin ) { throw new IllegalStateException( "This plugin cannot run next to the Enterprise plugin (any version) or the ClientControl plugin v1.3.1 or earlier." ); } // Create and start the bookmark interceptor, which adds server-managed bookmarks when // a user requests their bookmark list. bookmarkInterceptor = new BookmarkInterceptor(); bookmarkInterceptor.start(); } public void destroyPlugin() { if ( bookmarkInterceptor != null ) { bookmarkInterceptor.stop(); bookmarkInterceptor = null; } } /** * Checks if there's a plugin named "enterprise" in the Openfire plugin directory. * * @return true if the enterprise plugin is found, otherwise false. */ private static boolean checkForEnterprisePlugin() throws IOException { return getPluginJar( "enterprise" ) != null; } /** * Checks if there's a plugin named "clientControl" in the Openfire plugin directory of which the version is equal * to or earlier than 1.3.1. * * @return true if the clientControl plugin (<= 1.3.1) is found, otherwise false. */ private static boolean checkForIncompatibleClientControlPlugin() throws IOException, DocumentException { final JarFile jar = getPluginJar( "clientControl" ); if ( jar == null ) { return false; } final ZipEntry pluginXml = jar.getEntry( "plugin.xml" ); if ( pluginXml == null ) { // Odd - not a plugin? Log.warn( "Found a clientControl.jar file that does not appear to include a plugin.xml.", jar.getName() ); return false; } final File tempFile = File.createTempFile( "plugin-xml", "xml" ); try ( final InputStream is = jar.getInputStream( pluginXml ); final FileOutputStream os = new FileOutputStream( tempFile ) ) { while ( is.available() > 0 ) { os.write( is.read() ); } final SAXReader saxReader = new SAXReader(); saxReader.setEncoding( "UTF-8" ); final Document pluginXML = saxReader.read( tempFile ); Element element = (Element) pluginXML.selectSingleNode( "/plugin/version" ); if ( element != null ) { final Version version = new Version( element.getTextTrim() ); return !version.isNewerThan( new Version( "1.3.1" ) ); } } return false; } /** * Returns the plugin JAR for the plugin of the provided name. * * @param pluginName the name of the plugin (cannot be null or empty). * @return The plugin JAR file, or null when not found. */ private static JarFile getPluginJar( final String pluginName ) throws IOException { File pluginDir = new File( JiveGlobals.getHomeDirectory(), "plugins" ); File[] jars = pluginDir.listFiles( new FileFilter() { public boolean accept( File pathname ) { return pathname.getName().equalsIgnoreCase( pluginName + ".jar" ); } } ); final File jar; if ( jars.length > 0 ) { return new JarFile( jars[ 0 ] ); } else { return null; } } }