1<%@ page contentType="text/html; charset=UTF-8" %> 2<%-- 3 - 4 - Copyright (C) 2004-2008 Jive Software. All rights reserved. 5 - 6 - Licensed under the Apache License, Version 2.0 (the "License"); 7 - you may not use this file except in compliance with the License. 8 - You may obtain a copy of the License at 9 - 10 - http://www.apache.org/licenses/LICENSE-2.0 11 - 12 - Unless required by applicable law or agreed to in writing, software 13 - distributed under the License is distributed on an "AS IS" BASIS, 14 - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 - See the License for the specific language governing permissions and 16 - limitations under the License. 17--%> 18 19<%@ page import="org.jivesoftware.openfire.SessionManager, 20 org.jivesoftware.openfire.SessionResultFilter, 21 org.jivesoftware.openfire.session.ClientSession, 22 org.jivesoftware.util.JiveGlobals, 23 org.jivesoftware.util.ParamUtils, 24 org.jivesoftware.util.CookieUtils, 25 org.jivesoftware.util.StringUtils" 26 errorPage="error.jsp" 27%> 28<%@ page import="java.util.Date" %> 29<%@ page import="org.jivesoftware.util.ListPager" %> 30<%@ page import="java.util.function.Predicate" %> 31<%@ page import="java.net.UnknownHostException" %> 32<%@ page import="java.util.Collection" %> 33<%@ page import="java.util.List" %> 34<%@ page import="java.util.ArrayList" %> 35<%@ page import="org.jivesoftware.openfire.cluster.ClusterManager" %> 36<%@ page import="org.slf4j.LoggerFactory" %> 37 38<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %> 39<%@ taglib uri="http://java.sun.com/jsp/jstl/fmt" prefix="fmt" %> 40<%! 41 private static final String NONE = LocaleUtils.getLocalizedString("global.none"); 42 43 private static final int[] REFRESHES = {0, 10, 30, 60, 90}; 44 private static final String[] REFRESHES_LABELS = {NONE,"10","30","60","90"}; 45%> 46<jsp:useBean id="webManager" class="org.jivesoftware.util.WebManager" /> 47<% webManager.init(request, response, session, application, out ); %> 48 49<% // Get parameters 50 int refresh = ParamUtils.getIntParameter(request,"refresh",webManager.getRefreshValue("session-summary", 0)); 51 pageContext.setAttribute("refresh", refresh); 52 boolean close = ParamUtils.getBooleanParameter(request,"close"); 53 int order = ParamUtils.getIntParameter(request, "order", 54 webManager.getPageProperty("session-summary", "console.order", SessionResultFilter.ASCENDING)); 55 String jid = ParamUtils.getParameter(request,"jid"); 56 57 if (request.getParameter("refresh") != null) { 58 webManager.setRefreshValue("session-summary", refresh); 59 } 60 61 if (request.getParameter("order") != null) { 62 webManager.setPageProperty("session-summary", "console.order", order); 63 } 64 65 // Get the user manager 66 SessionManager sessionManager = webManager.getSessionManager(); 67 68 Cookie csrfCookie = CookieUtils.getCookie(request, "csrf"); 69 String csrfParam = ParamUtils.getParameter(request, "csrf"); 70 71 if (close) { 72 if (csrfCookie == null || csrfParam == null || !csrfCookie.getValue().equals(csrfParam)) { 73 close = false; 74 } 75 } 76 csrfParam = StringUtils.randomString(15); 77 CookieUtils.setCookie(request, response, "csrf", csrfParam, -1); 78 pageContext.setAttribute("csrf", csrfParam); 79 // Close a connection if requested 80 if (close) { 81 JID address = new JID(jid); 82 try { 83 Session sess = sessionManager.getSession(address); 84 sess.close(); 85 // Log the event 86 webManager.logEvent("closed session for address "+address, null); 87 // wait one second 88 Thread.sleep(1000L); 89 } 90 catch (Exception e) { 91 // Session might have disappeared on its own 92 LoggerFactory.getLogger("session-summary.jsp").warn("Unable to manually close session for address: {}", address, e); 93 } 94 // Redirect back to this page 95 response.sendRedirect("session-summary.jsp?close=success"); 96 return; 97 } 98 99 SessionResultFilter sessionResultFilter = SessionResultFilter.createDefaultSessionFilter(); 100 sessionResultFilter.setSortOrder(order); 101 // Filter out the dodgy looking sessions 102 List<ClientSession> sessions = new ArrayList<>(sessionManager.getSessions( sessionResultFilter)); 103 104 // By default, display all nodes 105 Predicate<ClientSession> filter = clientSession -> true; 106 final String searchName = ParamUtils.getStringParameter(request, "searchName", ""); 107 if(!searchName.trim().isEmpty()) { 108 final String searchCriteria = searchName.trim(); 109 filter = filter.and(clientSession -> StringUtils.containsIgnoringCase(clientSession.getAddress().getNode(), searchCriteria)); 110 } 111 final String searchResource = ParamUtils.getStringParameter(request, "searchResource", ""); 112 if(!searchResource.trim().isEmpty()) { 113 final String searchCriteria = searchResource.trim(); 114 filter = filter.and(clientSession -> StringUtils.containsIgnoringCase(clientSession.getAddress().getResource(), searchCriteria)); 115 } 116 final String searchVersion = ParamUtils.getStringParameter(request, "searchVersion", ""); 117 if(!searchVersion.trim().isEmpty()) { 118 final String searchCriteria = searchVersion.trim(); 119 // TODO: Fix this filter 120 filter = filter.and(clientSession -> StringUtils.containsIgnoringCase(clientSession.getAddress().getResource(), searchCriteria)); 121 } 122 final String searchNode = ParamUtils.getStringParameter(request, "searchNode", ""); 123 if(searchNode.equals("local")) { 124 filter = filter.and(LocalClientSession.class::isInstance); 125 } else if (searchNode.equals("remote")) { 126 filter = filter.and(clientSession -> !LocalClientSession.class.isInstance(clientSession)); 127 } 128 final String searchStatus = ParamUtils.getStringParameter(request, "searchStatus", ""); 129 if(!searchStatus.isEmpty()) { 130 filter = filter.and(clientSession -> { 131 if (searchStatus.equals("detached")) { 132 return clientSession instanceof LocalSession && ((LocalSession) clientSession).isDetached(); 133 } 134 switch (clientSession.getStatus()) { 135 case Session.STATUS_CLOSED: 136 return "closed".equals(searchStatus); 137 case Session.STATUS_CONNECTED: 138 return "connected".equals(searchStatus); 139 case Session.STATUS_AUTHENTICATED: 140 return "authenticated".equals(searchStatus); 141 default: 142 return "unknown".equals(searchStatus); 143 } 144 }); 145 } 146 final String searchPresence = ParamUtils.getStringParameter(request, "searchPresence", ""); 147 if(!searchPresence.isEmpty()) { 148 filter = filter.and(clientSession -> { 149 final Presence presence = clientSession.getPresence(); 150 if (!presence.isAvailable()) { 151 return "offline".equals(searchPresence); 152 } 153 final Presence.Show show = presence.getShow(); 154 if (show == null) { 155 return "online".equals(searchPresence); 156 } 157 switch (show) { 158 case away: 159 return "away".equals(searchPresence); 160 case chat: 161 return "chat".equals(searchPresence); 162 case dnd: 163 return "dnd".equals(searchPresence); 164 case xa: 165 return "xa".equals(searchPresence); 166 default: 167 return "unknown".equals(searchPresence); 168 } 169 }); 170 } 171 final String searchPriority = ParamUtils.getStringParameter(request, "searchPriority", ""); 172 if (!searchPriority.trim().isEmpty()) { 173 int intValue; 174 try { 175 intValue = Integer.parseInt(searchPriority.trim()); 176 } catch (final NumberFormatException e) { 177 // If we can't parse it, use a default which no session can actually have 178 intValue = Integer.MIN_VALUE; 179 } 180 final int searchCriteria = intValue; 181 filter = filter.and(clientSession -> clientSession.getPresence().getPriority() == searchCriteria); 182 } 183 final String searchHostAddress = ParamUtils.getStringParameter(request, "searchHostAddress", ""); 184 if(!searchHostAddress.trim().isEmpty()) { 185 final String searchCriteria = searchHostAddress.trim(); 186 filter = filter.and(clientSession -> { 187 try { 188 return StringUtils.containsIgnoringCase(clientSession.getHostAddress(), searchCriteria); 189 } catch (final UnknownHostException e) { 190 return false; 191 } 192 }); 193 } 194 195 final ListPager<ClientSession> listPager = new ListPager<>(request, response, sessions, filter, 196 "refresh", "searchName", "searchResource", "searchVersion", "searchNode", "searchStatus", "searchPresence", "searchPriority", "searchHostAddress"); 197 pageContext.setAttribute("listPager", listPager); 198 pageContext.setAttribute("searchName", searchName); 199 pageContext.setAttribute("searchResource", searchResource); 200 pageContext.setAttribute("searchVersion", searchVersion); 201 pageContext.setAttribute("searchNode", searchNode); 202 pageContext.setAttribute("searchStatus", searchStatus); 203 pageContext.setAttribute("searchPresence", searchPresence); 204 pageContext.setAttribute("searchPriority", searchPriority); 205 pageContext.setAttribute("searchHostAddress", searchHostAddress); 206 pageContext.setAttribute("clusteringEnabled", ClusterManager.isClusteringStarted() || ClusterManager.isClusteringStarting() ); 207%> 208<html> 209 <head> 210 <title><fmt:message key="session.summary.title"/></title> 211 <meta name="pageID" content="session-summary"/> 212 <meta name="helpPage" content="view_active_client_sessions.html"/> 213 <c:if test="${refresh > 0}"> 214 <meta http-equiv="refresh" content="${refresh}"> 215 </c:if> 216 </head> 217 <body> 218 219<% if ("success".equals(request.getParameter("close"))) { %> 220 221 <p class="jive-success-text"> 222 <fmt:message key="session.summary.close" /> 223 </p> 224 225<% } %> 226 227<table cellpadding="0" cellspacing="0" border="0" width="100%"> 228<tbody> 229 <tr valign="top"> 230 <td width="99%"> 231 <fmt:message key="session.summary.active" />: <b>${listPager.totalItemCount}</b> 232 <c:if test="${listPager.filtered}"> 233 <fmt:message key="session.summary.filtered_session_count" />: <c:out value="${listPager.filteredItemCount}"/> 234 </c:if> 235 <c:if test="${listPager.totalPages > 1}"> 236 -- <fmt:message key="global.showing" /> <c:out value="${listPager.firstItemNumberOnPage}"/>-<c:out value="${listPager.lastItemNumberOnPage}"/> 237 <p><fmt:message key="global.pages" />: [ ${listPager.pageLinks} ] 238 </c:if> 239 -- <fmt:message key="session.summary.sessions_per_page" />: 240 ${listPager.pageSizeSelection} 241 </td> 242 <td width="1%" nowrap> 243 <label for="refresh"><fmt:message key="global.refresh" />:</label> 244 <select size="1" id="refresh" name="refresh" onchange="submitForm();"> 245 <% for (int j=0; j<REFRESHES.length; j++) { 246 String selected = REFRESHES[j] == refresh ? " selected" : ""; 247 %> 248 <option value="<%= REFRESHES[j] %>"<%= selected %>><%= REFRESHES_LABELS[j] %> 249 250 <% } %> 251 </select> 252 (<fmt:message key="global.seconds" />) 253 254 </td> 255 </tr> 256</tbody> 257</table> 258<br> 259 260 261<div class="jive-table"> 262<table cellpadding="0" cellspacing="0" border="0" width="100%"> 263<thead> 264 <tr> 265 <th> </th> 266 <th nowrap> 267 <% 268 if (sessionResultFilter.getSortField() == SessionResultFilter.SORT_USER) { 269 if (sessionResultFilter.getSortOrder() == SessionResultFilter.DESCENDING) { 270 %> 271 <table border="0"><tr valign="middle"><th> 272 <a href="session-summary.jsp?order=<%=SessionResultFilter.ASCENDING %>"> 273 <fmt:message key="session.details.name" /></a> 274 </th><th> 275 <a href="session-summary.jsp?order=<%=SessionResultFilter.ASCENDING %>"> 276 <img src="images/sort_descending.gif" border="0" width="16" height="16" alt=""></a> 277 </th></tr></table> 278 <% 279 } 280 else { 281 %> 282 <table border="0"><tr valign="middle"><th> 283 <a href="session-summary.jsp?order=<%=SessionResultFilter.DESCENDING %>"> 284 <fmt:message key="session.details.name" /></a> 285 </th><th> 286 <a href="session-summary.jsp?order=<%=SessionResultFilter.DESCENDING %>"> 287 <img src="images/sort_ascending.gif" width="16" height="16" border="0" alt=""></a> 288 </th></tr></table> 289 <% 290 } 291 } 292 else { 293 %> 294 <fmt:message key="session.details.name" /> 295 <% 296 } 297 %> 298 </th> 299 <th nowrap><fmt:message key="session.details.resource" /></th> 300 <th nowrap><fmt:message key="session.details.version" /></th> 301 <c:if test="${clusteringEnabled}"> 302 <th nowrap><fmt:message key="session.details.node" /></th> 303 </c:if> 304 <th nowrap colspan="2"><fmt:message key="session.details.status" /></th> 305 <th nowrap colspan="2"><fmt:message key="session.details.presence" /></th> 306 <th nowrap><fmt:message key="session.details.priority" /></th> 307 <th nowrap><fmt:message key="session.details.clientip" /></th> 308 <th nowrap><fmt:message key="session.details.close_connect" /></th> 309 </tr> 310 <tr> 311 <td nowrap></td> 312 <td nowrap> 313 <input type="search" 314 id="searchName" 315 size="20" 316 value="<c:out value="${searchName}"/>"/> 317 <img src="images/search-16x16.png" 318 width="16" height="16" 319 alt="search" title="search" 320 style="vertical-align: middle;" 321 onclick="submitForm();" 322 > 323 </td> 324 <td nowrap> 325 <input type="search" 326 id="searchResource" 327 size="20" 328 value="<c:out value="${searchResource}"/>"/> 329 <img src="images/search-16x16.png" 330 width="16" height="16" 331 alt="search" title="search" 332 style="vertical-align: middle;" 333 onclick="submitForm();" 334 > 335 </td> 336 <td nowrap> 337 <input type="search" 338 id="searchVersion" 339 size="20" 340 value="<c:out value="${searchVersion}"/>"/> 341 <img src="images/search-16x16.png" 342 width="16" height="16" 343 alt="search" title="search" 344 style="vertical-align: middle;" 345 onclick="submitForm();" 346 > 347 </td> 348 <c:if test="${clusteringEnabled}"> 349 <td nowrap> 350 <select id="searchNode" onchange="submitForm();"> 351 <option <c:if test='${searchNode eq ""}'>selected</c:if> value=""></option> 352 <option <c:if test='${searchNode eq "local"}'>selected </c:if>value="local"><fmt:message key="session.details.local"/></option> 353 <option <c:if test='${searchNode eq "remote"}'>selected </c:if>value="remote"><fmt:message key="session.details.remote"/></option> 354 </select> 355 </td> 356 </c:if> 357 <td nowrap colspan="2"> 358 <select id="searchStatus" onchange="submitForm();"> 359 <option <c:if test='${searchStatus eq ""}'>selected</c:if> value=""></option> 360 <option <c:if test='${searchStatus eq "closed"}'>selected</c:if> value="closed"><fmt:message key="session.details.close"/></option> 361 <option <c:if test='${searchStatus eq "connected"}'>selected</c:if> value="connected"><fmt:message key="session.details.connect"/></option> 362 <option <c:if test='${searchStatus eq "authenticated"}'>selected</c:if> value="authenticated"><fmt:message key="session.details.authenticated"/></option> 363 <option <c:if test='${searchStatus eq "detached"}'>selected</c:if> value="detached"><fmt:message key="session.details.local"/> & <fmt:message key="session.details.sm-detached"/></option> 364 <option <c:if test='${searchStatus eq "unknown"}'>selected</c:if> value="unknown"><fmt:message key="session.details.unknown"/></option> 365 </select> 366 </td> 367 <td nowrap colspan="2"> 368 <select id="searchPresence" onchange="submitForm();"> 369 <option <c:if test='${searchPresence eq ""}'>selected</c:if> value=""></option> 370 <option <c:if test='${searchPresence eq "online"}'>selected</c:if> value="online"><fmt:message key="session.details.online"/></option> 371 <option <c:if test='${searchPresence eq "away"}'>selected</c:if> value="away"><fmt:message key="session.details.away"/></option> 372 <option <c:if test='${searchPresence eq "xa"}'>selected</c:if> value="xa"><fmt:message key="session.details.extended"/></option> 373 <option <c:if test='${searchPresence eq "offline"}'>selected</c:if> value="offline"><fmt:message key="user.properties.offline"/></option> 374 <option <c:if test='${searchPresence eq "chat"}'>selected</c:if> value="chat"><fmt:message key="session.details.chat_available"/></option> 375 <option <c:if test='${searchPresence eq "dnd"}'>selected</c:if> value="dnd"><fmt:message key="session.details.not_disturb"/></option> 376 <option <c:if test='${searchPresence eq "unknown"}'>selected</c:if> value="unknown"><fmt:message key="session.details.unknown"/></option> 377 </select> 378 </td> 379 <td nowrap> 380 <input type="search" 381 id="searchPriority" 382 size="5" 383 min="-128" 384 max="127" 385 value="<c:out value="${searchPriority}"/>"/> 386 <img src="images/search-16x16.png" 387 width="16" height="16" 388 alt="search" title="search" 389 style="vertical-align: middle;" 390 onclick="submitForm();" 391 > 392 </td> 393 <td nowrap> 394 <input type="search" 395 id="searchHostAddress" 396 size="20" 397 value="<c:out value="${searchHostAddress}"/>"/> 398 <img src="images/search-16x16.png" 399 width="16" height="16" 400 alt="search" title="search" 401 style="vertical-align: middle;" 402 onclick="submitForm();" 403 > 404 </td> 405 <td nowrap></td> 406 </tr> 407</thead> 408<tbody> 409 <% 410 if (sessions.isEmpty()) { 411 %> 412 <tr> 413 <td colspan="11"> 414 415 <fmt:message key="session.summary.not_session" /> 416 417 </td> 418 </tr> 419 420 <% } %> 421 422 <% 423 // needed in session-row.jspf 424 int count = listPager.getFirstItemNumberOnPage(); 425 final boolean current = false; 426 final String linkURL = "session-details.jsp"; 427 for (final ClientSession sess : listPager.getItemsOnCurrentPage()) { 428 %> 429 <%@ include file="session-row.jspf" %> 430 <% count++; 431 } %> 432 433</tbody> 434</table> 435</div> 436 437<c:if test="${listPager.totalPages > 1}"> 438<p><fmt:message key="global.pages" />: [ ${listPager.pageLinks} ]</p> 439</c:if> 440 441<br> 442<p> 443<fmt:message key="session.summary.last_update" />: <%= JiveGlobals.formatDateTime(new Date()) %> 444</p> 445 446${listPager.jumpToPageForm} 447 448<script type="text/javascript"> 449 ${listPager.pageFunctions} 450</script> 451 </body> 452</html> 453