diff --git a/changelog.html b/changelog.html
index 2e8ad3caa..1e507efaf 100644
--- a/changelog.html
+++ b/changelog.html
@@ -46,12 +46,14 @@
1.7.2 -- (TBD)
+ - [#6] - Fix Openfire 4.8.0 incompatibility
+ - [#5] - Guard against unloaded images
1.7.1 -- November 12, 2020
diff --git a/plugin.xml b/plugin.xml
index 708cde9f2..053c2b8d1 100644
--- a/plugin.xml
+++ b/plugin.xml
@@ -6,7 +6,7 @@
Exposes presence information through HTTP.
Jive Software
${project.version}
- 11/12/2020
+ 2024-01-19
4.1.1
diff --git a/src/java/org/jivesoftware/openfire/plugin/PresencePlugin.java b/src/java/org/jivesoftware/openfire/plugin/PresencePlugin.java
index af9a76592..f04c89cef 100644
--- a/src/java/org/jivesoftware/openfire/plugin/PresencePlugin.java
+++ b/src/java/org/jivesoftware/openfire/plugin/PresencePlugin.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2004-2008 Jive Software. All rights reserved.
+ * Copyright (C) 2004-2008 Jive Software, 2024 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.
@@ -225,11 +225,14 @@ public Presence getPresence(String sender, String jid) throws UserNotFoundExcept
// Return component presence
return presence;
}
- if (targetJID.getNode() == null ||
- !UserManager.getInstance().isRegisteredUser(targetJID.getNode())) {
+
+ if (targetJID.getNode() == null) {
// Sender is requesting presence information of an anonymous user
throw new UserNotFoundException("Username is null");
}
+ // throws UserNotFound if the user doesn't exist.
+ User user = userManager.getUser(targetJID.getNode());
+
if (!isPresencePublic()) {
if (sender == null) {
throw new UserNotFoundException("Sender is null");
@@ -243,7 +246,6 @@ public Presence getPresence(String sender, String jid) throws UserNotFoundExcept
}
}
}
- User user = userManager.getUser(targetJID.getNode());
return presenceManager.getPresence(user);
}
}
diff --git a/src/java/org/jivesoftware/openfire/plugin/presence/ImagePresenceProvider.java b/src/java/org/jivesoftware/openfire/plugin/presence/ImagePresenceProvider.java
index cbe13bf95..098b15745 100644
--- a/src/java/org/jivesoftware/openfire/plugin/presence/ImagePresenceProvider.java
+++ b/src/java/org/jivesoftware/openfire/plugin/presence/ImagePresenceProvider.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2004-2008 Jive Software. All rights reserved.
+ * Copyright (C) 2004-2008 Jive Software, 2024 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.
@@ -59,9 +59,9 @@ class ImagePresenceProvider extends PresenceInfoProvider {
private static final Logger Log = LoggerFactory.getLogger(ImagePresenceProvider.class);
- private PresenceStatusServlet servlet;
- private Map imageCache = new HashMap();
- private Map imageTypeCache = new HashMap();
+ private final PresenceStatusServlet servlet;
+ private final Map imageCache = new HashMap<>();
+ private final Map imageTypeCache = new HashMap<>();
public ImagePresenceProvider(PresenceStatusServlet servlet) {
this.servlet = servlet;
@@ -71,29 +71,29 @@ public ImagePresenceProvider(PresenceStatusServlet servlet) {
public void sendInfo(HttpServletRequest request,
HttpServletResponse response, Presence presence) throws IOException {
if (presence == null) {
- writeImageContent(request, response, "offline", servlet.offline);
+ writeImageContent(request, response, "offline", servlet.getOffline());
}
else if (presence.getShow() == null) {
- writeImageContent(request, response, "available", servlet.available);
+ writeImageContent(request, response, "available", servlet.getAvailable());
}
else if (presence.getShow().equals(org.xmpp.packet.Presence.Show.away)) {
- writeImageContent(request, response, "away", servlet.away);
+ writeImageContent(request, response, "away", servlet.getAway());
}
else if (presence.getShow().equals(org.xmpp.packet.Presence.Show.chat)) {
- writeImageContent(request, response, "chat", servlet.chat);
+ writeImageContent(request, response, "chat", servlet.getChat());
}
else if (presence.getShow().equals(org.xmpp.packet.Presence.Show.dnd)) {
- writeImageContent(request, response, "dnd", servlet.dnd);
+ writeImageContent(request, response, "dnd", servlet.getDnd());
}
else if (presence.getShow().equals(org.xmpp.packet.Presence.Show.xa)) {
- writeImageContent(request, response, "xa", servlet.xa);
+ writeImageContent(request, response, "xa", servlet.getXa());
}
}
@Override
public void sendUserNotFound(HttpServletRequest request, HttpServletResponse response)
throws IOException {
- writeImageContent(request, response, "forbidden", servlet.offline);
+ writeImageContent(request, response, "forbidden", servlet.getOffline());
}
private void writeImageContent(HttpServletRequest request, HttpServletResponse response,
@@ -122,8 +122,8 @@ private void writeImageContent(String url, byte[] defaultContent, HttpServletRes
URLConnection connection = new URL(url).openConnection();
InputStream in = connection.getInputStream();
ByteArrayOutputStream bytes = new ByteArrayOutputStream();
- byte buffer[] = new byte[1024 * 4];
- int last_read_bytes = 0;
+ byte[] buffer = new byte[1024 * 4];
+ int last_read_bytes;
while ((last_read_bytes = in.read(buffer)) != -1) {
bytes.write(buffer, 0, last_read_bytes);
}
diff --git a/src/java/org/jivesoftware/openfire/plugin/presence/PresenceStatusServlet.java b/src/java/org/jivesoftware/openfire/plugin/presence/PresenceStatusServlet.java
index e7dd0ffee..8697cc18d 100644
--- a/src/java/org/jivesoftware/openfire/plugin/presence/PresenceStatusServlet.java
+++ b/src/java/org/jivesoftware/openfire/plugin/presence/PresenceStatusServlet.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2004-2008 Jive Software. All rights reserved.
+ * Copyright (C) 2004-2008 Jive Software, 2024 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.
@@ -56,12 +56,12 @@ public class PresenceStatusServlet extends HttpServlet {
private ImagePresenceProvider imageProvider;
private TextPresenceProvider textProvider;
- byte available[];
- byte away[];
- byte chat[];
- byte dnd[];
- byte offline[];
- byte xa[];
+ private byte[] available;
+ private byte[] away;
+ private byte[] chat;
+ private byte[] dnd;
+ private byte[] offline;
+ private byte[] xa;
@Override
public void init(ServletConfig servletConfig) throws ServletException {
@@ -71,13 +71,7 @@ public void init(ServletConfig servletConfig) throws ServletException {
xmlProvider = new XMLPresenceProvider();
imageProvider = new ImagePresenceProvider(this);
textProvider = new TextPresenceProvider();
- available = loadResource("/images/user-green-16x16.gif");
- away = loadResource("/images/user-yellow-16x16.gif");
- chat = loadResource("/images/user-green-16x16.gif");
- dnd = loadResource("/images/user-red-16x16.gif");
- offline = loadResource("/images/user-clear-16x16.gif");
- xa = loadResource("/images/user-yellow-16x16.gif");
- // Exclude this servlet from requering the user to login
+ // Exclude this servlet from requiring the user to login
AuthCheckFilter.addExclude("presence/status");
}
@@ -91,48 +85,37 @@ protected void doGet(HttpServletRequest request, HttpServletResponse response)
try {
Presence presence = plugin.getPresence(sender, jid);
- if ("image".equals(type)) {
- imageProvider.sendInfo(request, response, presence);
- }
- else if ("xml".equals(type)) {
- xmlProvider.sendInfo(request, response, presence);
- }
- else if ("text".equals(type)) {
- textProvider.sendInfo(request, response, presence);
- }
- else {
- Log.warn("The presence servlet received an invalid request of type: " + type);
- // TODO Do something
+ switch (type) {
+ case "image":
+ imageProvider.sendInfo(request, response, presence);
+ break;
+ case "xml":
+ xmlProvider.sendInfo(request, response, presence);
+ break;
+ case "text":
+ textProvider.sendInfo(request, response, presence);
+ break;
+ default:
+ Log.warn("The presence servlet received an invalid request of type: " + type);
+ // TODO Do something
+ break;
}
}
- catch (UserNotFoundException e) {
- if ("image".equals(type)) {
- imageProvider.sendUserNotFound(request, response);
- }
- else if ("xml".equals(type)) {
- xmlProvider.sendUserNotFound(request, response);
- }
- else if ("text".equals(type)) {
- textProvider.sendUserNotFound(request, response);
- }
- else {
- Log.warn("The presence servlet received an invalid request of type: " + type);
- // TODO Do something
- }
- }
- catch (IllegalArgumentException e) {
- if ("image".equals(type)) {
- imageProvider.sendUserNotFound(request, response);
- }
- else if ("xml".equals(type)) {
- xmlProvider.sendUserNotFound(request, response);
- }
- else if ("text".equals(type)) {
- textProvider.sendUserNotFound(request, response);
- }
- else {
- Log.warn("The presence servlet received an invalid request of type: " + type);
- // TODO Do something
+ catch (UserNotFoundException | IllegalArgumentException e) {
+ switch (type) {
+ case "image":
+ imageProvider.sendUserNotFound(request, response);
+ break;
+ case "xml":
+ xmlProvider.sendUserNotFound(request, response);
+ break;
+ case "text":
+ textProvider.sendUserNotFound(request, response);
+ break;
+ default:
+ Log.warn("The presence servlet received an invalid request of type: " + type);
+ // TODO Do something
+ break;
}
}
}
@@ -144,7 +127,7 @@ protected void doPost(HttpServletRequest request, HttpServletResponse response)
}
@Override
- public void destroy() {
+ public synchronized void destroy() {
super.destroy();
available = null;
away = null;
@@ -158,17 +141,65 @@ public void destroy() {
private byte[] loadResource(String path) {
ServletContext context = getServletContext();
- InputStream in = context.getResourceAsStream(path);
- ByteArrayOutputStream out = new ByteArrayOutputStream();
- try {
+ try (InputStream in = context.getResourceAsStream(path);
+ ByteArrayOutputStream out = new ByteArrayOutputStream())
+ {
for (int i = in.read(); i > -1; i = in.read()) {
out.write(i);
}
+ return out.toByteArray();
}
- catch (IOException e) {
- Log.error("error loading:" + path);
+ catch (Throwable e) {
+ Log.error("error loading: {}", path, e);
+ }
+ return null;
+ }
+
+ public synchronized byte[] getAvailable()
+ {
+ if (available == null) {
+ available = loadResource("/images/user-green-16x16.gif");
}
- return out.toByteArray();
+ return available;
}
+ public synchronized byte[] getAway()
+ {
+ if (away == null) {
+ away = loadResource("/images/user-yellow-16x16.gif");
+ }
+ return away;
+ }
+
+ public synchronized byte[] getChat()
+ {
+ if (chat == null) {
+ chat = loadResource("/images/user-green-16x16.gif");
+ }
+ return chat;
+ }
+
+ public synchronized byte[] getDnd()
+ {
+ if (dnd == null) {
+ dnd = loadResource("/images/user-red-16x16.gif");
+ }
+ return dnd;
+ }
+
+ public synchronized byte[] getOffline()
+ {
+ if (offline == null) {
+ offline = loadResource("/images/user-clear-16x16.gif");
+ }
+ return offline;
+ }
+
+ public byte[] getXa()
+ {
+ if (xa == null) {
+ xa = loadResource("/images/user-yellow-16x16.gif");
+ }
+ return xa;
+ }
}