public HybridUserProvider() {

    // Migrate user provider properties
    JiveGlobals.migrateProperty("hybridUserProvider.primaryProvider.className");
    JiveGlobals.migrateProperty("hybridUserProvider.secondaryProvider.className");
    JiveGlobals.migrateProperty("hybridUserProvider.tertiaryProvider.className");

    userproviders = new ArrayList<UserProvider>();

    // Load primary, secondary, and tertiary user providers.
    String primaryClass = JiveGlobals.getProperty("hybridUserProvider.primaryProvider.className");
    if (primaryClass == null) {
      Log.error(
          "A primary UserProvider must be specified via openfire.xml or the system properties");
      return;
    }
    try {
      Class c = ClassUtils.forName(primaryClass);
      UserProvider primaryProvider = (UserProvider) c.newInstance();
      userproviders.add(primaryProvider);
      Log.debug("Primary user provider: " + primaryClass);
    } catch (Exception e) {
      Log.error(
          "Unable to load primary user provider: "
              + primaryClass
              + ". Users in this provider will be disabled.",
          e);
      return;
    }
    String secondaryClass =
        JiveGlobals.getProperty("hybridUserProvider.secondaryProvider.className");
    if (secondaryClass != null) {
      try {
        Class c = ClassUtils.forName(secondaryClass);
        UserProvider secondaryProvider = (UserProvider) c.newInstance();
        userproviders.add(secondaryProvider);
        Log.debug("Secondary user provider: " + secondaryClass);
      } catch (Exception e) {
        Log.error("Unable to load secondary user provider: " + secondaryClass, e);
      }
    }
    String tertiaryClass = JiveGlobals.getProperty("hybridUserProvider.tertiaryProvider.className");
    if (tertiaryClass != null) {
      try {
        Class c = ClassUtils.forName(tertiaryClass);
        UserProvider tertiaryProvider = (UserProvider) c.newInstance();
        userproviders.add(tertiaryProvider);
        Log.debug("Tertiary user provider: " + tertiaryClass);
      } catch (Exception e) {
        Log.error("Unable to load tertiary user provider: " + tertiaryClass, e);
      }
    }
  }
 static {
   // Fill out the allowedIPs with the system property
   String allowed = JiveGlobals.getProperty("xmpp.client.login.allowed", "");
   StringTokenizer tokens = new StringTokenizer(allowed, ", ");
   while (tokens.hasMoreTokens()) {
     String address = tokens.nextToken().trim();
     allowedIPs.put(address, "");
   }
   String allowedAnonym = JiveGlobals.getProperty("xmpp.client.login.allowedAnonym", "");
   tokens = new StringTokenizer(allowedAnonym, ", ");
   while (tokens.hasMoreTokens()) {
     String address = tokens.nextToken().trim();
     allowedAnonymIPs.put(address, "");
   }
 }
Example #3
0
  /**
   * Returns a full JID based off of a username passed in.
   *
   * <p>If it already looks like a JID, returns what was passed in.
   *
   * @param username Username to turn into a JID.
   * @return Converted username.
   */
  public String generateFullJID(String username) {
    if (username.indexOf("@") > -1) {
      return username;
    }

    if (getTransport().getType().equals(TransportType.gtalk)) {
      return username + "@" + "gmail.com";
    } else if (getTransport().getType().equals(TransportType.facebook)) {
      return username + "@" + "chat.facebook.com";
    } else if (getTransport().getType().equals(TransportType.renren)) {
      return username + "@" + "renren.com";
    } else if (getTransport().getType().equals(TransportType.livejournal)) {
      return username + "@" + "livejournal.com";
    } else {
      String connecthost =
          JiveGlobals.getProperty(
              "plugin.gateway." + getTransport().getType() + ".connecthost",
              (getTransport().getType().equals(TransportType.gtalk)
                  ? "talk.google.com"
                  : getTransport().getType().equals(TransportType.facebook)
                      ? "chat.facebook.com"
                      : "jabber.org"));
      return username + "@" + connecthost;
    }
  }
Example #4
0
 /**
  * Forwards the received message to the list of users defined in the property
  * <b>xmpp.forward.admins</b>. The property may include bare JIDs or just usernames separated by
  * commas or white spaces. When using bare JIDs the target user may belong to a remote server.
  *
  * <p>If the property <b>xmpp.forward.admins</b> was not defined then the message will be sent to
  * all the users allowed to enter the admin console.
  *
  * @param packet the message to forward.
  */
 private void sendMessageToAdmins(Message packet) {
   String jids = JiveGlobals.getProperty("xmpp.forward.admins");
   if (jids != null && jids.trim().length() > 0) {
     // Forward the message to the users specified in the "xmpp.forward.admins" property
     StringTokenizer tokenizer = new StringTokenizer(jids, ", ");
     while (tokenizer.hasMoreTokens()) {
       String username = tokenizer.nextToken();
       Message forward = packet.createCopy();
       if (username.contains("@")) {
         // Use the specified bare JID address as the target address
         forward.setTo(username);
       } else {
         forward.setTo(username + "@" + serverName);
       }
       route(forward);
     }
   } else {
     // Forward the message to the users allowed to log into the admin console
     for (JID jid : XMPPServer.getInstance().getAdmins()) {
       Message forward = packet.createCopy();
       forward.setTo(jid);
       route(forward);
     }
   }
 }
Example #5
0
  /** Loads the provider names from the jive properties config file. */
  private static void loadProviders() {
    if (factory == null) {
      // Use className as a convenient object to get a lock on.
      synchronized (classNames) {
        if (factory == null) {
          try {
            Class[] providers = new Class[classNames.length];
            for (int i = 0; i < classNames.length; i++) {
              // Convert XML based provider setup to Database based
              JiveGlobals.migrateProperty(propNames[i]);

              String className = classNames[i];
              // See if the classname has been set as a Jive property.
              String classNameProp = JiveGlobals.getProperty(propNames[i]);
              if (classNameProp != null) {
                className = classNameProp;
              }
              try {
                providers[i] = ClassUtils.forName(className);
              } catch (Exception e) {
                Log.error("Exception loading class: " + className, e);
              }
            }
            setProviders(providers);
          } catch (Exception e) {
            Log.error("Exception loading class: " + classNames, e);
          }
        }
      }
    }
  }
  /**
   * Returns true if the principal is explicity authorized to the JID
   *
   * @param principal The autheticated principal requesting authorization.
   * @return The name of the default username to use.
   */
  @Override
  public String map(String principal) {
    if (principal.contains("@")) {
      String realm = principal.substring(principal.lastIndexOf('@') + 1);
      String username = principal.substring(0, principal.lastIndexOf('@'));

      if (realm.length() > 0) {
        if (realm.equals(JiveGlobals.getProperty("xmpp.domain"))) {
          Log.debug("DefaultAuthorizationMapping: realm = xmpp.domain");
          return username;
        } else if (realm.equals(JiveGlobals.getProperty("sasl.realm"))) {
          Log.debug("DefaultAuthorizationMapping: ream = sasl.realm");
          return username;
        } else {
          for (String approvedRealm : approvedRealms) {
            if (realm.equals(approvedRealm)) {
              Log.debug(
                  "DefaultAuthorizationMapping: realm ("
                      + realm
                      + ") = "
                      + approvedRealm
                      + " which is approved");
              return username;
            } else {
              Log.debug(
                  "DefaultAuthorizationPolicy: realm ("
                      + realm
                      + ") != "
                      + approvedRealm
                      + " which is approved");
            }
          }
        }
        Log.debug("DefaultAuthorizationMapping: No approved mappings found.");
        return principal;
      } else {
        Log.debug("DefaultAuthorizationMapping: Realm has no length");
      }
    } else {
      Log.debug("DefaultAuthorizationMapping: No realm found");
    }
    return principal;
  }
Example #7
0
 /**
  * Returns a username based off of a registered name (possible JID) passed in.
  *
  * <p>If it already looks like a username, returns what was passed in.
  *
  * @param regName Registered name to turn into a username.
  * @return Converted registered name.
  */
 public String generateUsername(String regName) {
   if (regName.equals("{PLATFORM}")) {
     return JiveGlobals.getProperty("plugin.gateway.facebook.platform.apikey")
         + "|"
         + JiveGlobals.getProperty("plugin.gateway.facebook.platform.apisecret");
   } else if (regName.indexOf("@") > -1) {
     if (getTransport().getType().equals(TransportType.gtalk)) {
       return regName;
     } else {
       return regName.substring(0, regName.indexOf("@"));
     }
   } else {
     if (getTransport().getType().equals(TransportType.gtalk)) {
       return regName + "@gmail.com";
     } else {
       return regName;
     }
   }
 }
  static {
    String propertyValue = JiveGlobals.getProperty(JIVE_CROWD_GROUPS_CACHE_TTL_SECS);
    int ttl =
        (propertyValue == null || propertyValue.trim().length() == 0)
            ? CACHE_TTL
            : Integer.parseInt(propertyValue);

    crowdGroupSync.scheduleAtFixedRate(new GroupSynch(), 0, ttl, TimeUnit.SECONDS);

    JiveGlobals.setProperty(JIVE_CROWD_GROUPS_CACHE_TTL_SECS, String.valueOf(ttl));
  }
  public DefaultAuthorizationMapping() {
    approvedRealms = new Vector<>();

    String realmList = JiveGlobals.getProperty("sasl.approvedRealms");
    if (realmList != null) {
      StringTokenizer st = new StringTokenizer(realmList, " ,\t\n\r\f");
      while (st.hasMoreTokens()) {
        approvedRealms.add(st.nextToken());
      }
    }
  }
Example #10
0
  static {
    String algorithm = JiveGlobals.getProperty("xmpp.socket.ssl.algorithm", "TLS");
    String storeType = JiveGlobals.getProperty("xmpp.socket.ssl.storeType", "jks");

    // Get the keystore location. The default location is security/keystore
    keyStoreLocation =
        JiveGlobals.getProperty(
            "xmpp.socket.ssl.keystore",
            "resources" + File.separator + "security" + File.separator + "keystore");
    keyStoreLocation = JiveGlobals.getHomeDirectory() + File.separator + keyStoreLocation;

    // Get the keystore password. The default password is "changeit".
    keypass = JiveGlobals.getProperty("xmpp.socket.ssl.keypass", "changeit");
    keypass = keypass.trim();

    // Get the truststore location; default at security/truststore
    trustStoreLocation =
        JiveGlobals.getProperty(
            "xmpp.socket.ssl.truststore",
            "resources" + File.separator + "security" + File.separator + "truststore");
    trustStoreLocation = JiveGlobals.getHomeDirectory() + File.separator + trustStoreLocation;

    // Get the truststore passwprd; default is "changeit".
    trustpass = JiveGlobals.getProperty("xmpp.socket.ssl.trustpass", "changeit");
    trustpass = trustpass.trim();

    try {
      keyStore = KeyStore.getInstance(storeType);
      keyStore.load(new FileInputStream(keyStoreLocation), keypass.toCharArray());

      trustStore = KeyStore.getInstance(storeType);
      trustStore.load(new FileInputStream(trustStoreLocation), trustpass.toCharArray());

      sslFactory =
          (SSLJiveServerSocketFactory)
              SSLJiveServerSocketFactory.getInstance(algorithm, keyStore, trustStore);
    } catch (Exception e) {
      Log.error(
          "SSLConfig startup problem.\n"
              + "  storeType: ["
              + storeType
              + "]\n"
              + "  keyStoreLocation: ["
              + keyStoreLocation
              + "]\n"
              + "  keypass: ["
              + keypass
              + "]\n"
              + "  trustStoreLocation: ["
              + trustStoreLocation
              + "]\n"
              + "  trustpass: ["
              + trustpass
              + "]",
          e);
      keyStore = null;
      trustStore = null;
      sslFactory = null;
    }
  }
Example #11
0
  public void startTLS(boolean clientMode, String remoteServer, ClientAuth authentication)
      throws Exception {
    boolean c2s = (remoteServer == null);
    KeyStore ksKeys = SSLConfig.getKeyStore();
    String keypass = SSLConfig.getKeyPassword();

    KeyStore ksTrust = (c2s ? SSLConfig.getc2sTrustStore() : SSLConfig.gets2sTrustStore());
    String trustpass = (c2s ? SSLConfig.getc2sTrustPassword() : SSLConfig.gets2sTrustPassword());
    if (c2s) Log.debug("NIOConnection: startTLS: using c2s");
    else Log.debug("NIOConnection: startTLS: using s2s");
    // KeyManager's decide which key material to use.
    KeyManager[] km = SSLJiveKeyManagerFactory.getKeyManagers(ksKeys, keypass);

    // TrustManager's decide whether to allow connections.
    TrustManager[] tm = SSLJiveTrustManagerFactory.getTrustManagers(ksTrust, trustpass);

    if (clientMode || authentication == ClientAuth.needed || authentication == ClientAuth.wanted) {
      // We might need to verify a certificate from our peer, so get different TrustManager[]'s
      if (c2s) {
        // Check if we can trust certificates presented by the client
        tm = new TrustManager[] {new ClientTrustManager(ksTrust)};
      } else {
        // Check if we can trust certificates presented by the server
        tm = new TrustManager[] {new ServerTrustManager(remoteServer, ksTrust, this)};
      }
    }

    String algorithm = JiveGlobals.getProperty(ConnectionSettings.Client.TLS_ALGORITHM, "TLS");
    SSLContext tlsContext = SSLContext.getInstance(algorithm);

    tlsContext.init(km, tm, null);

    SslFilter filter = new SslFilter(tlsContext);
    filter.setUseClientMode(clientMode);
    // Disable SSLv3 due to POODLE vulnerability.
    filter.setEnabledProtocols(new String[] {"TLSv1", "TLSv1.1", "TLSv1.2"});
    if (authentication == ClientAuth.needed) {
      filter.setNeedClientAuth(true);
    } else if (authentication == ClientAuth.wanted) {
      // Just indicate that we would like to authenticate the client but if client
      // certificates are self-signed or have no certificate chain then we are still
      // good
      filter.setWantClientAuth(true);
    }
    ioSession.getFilterChain().addAfter(EXECUTOR_FILTER_NAME, TLS_FILTER_NAME, filter);
    ioSession.setAttribute(SslFilter.DISABLE_ENCRYPTION_ONCE, Boolean.TRUE);

    if (!clientMode) {
      // Indicate the client that the server is ready to negotiate TLS
      deliverRawText("<proceed xmlns=\"urn:ietf:params:xml:ns:xmpp-tls\"/>");
    }
  }
Example #12
0
  public String getMemoryData() {
    try {
      String port = JiveGlobals.getProperty("httpbind.port.plain", "7070");
      String host = XMPPServer.getInstance().getServerInfo().getHostname();
      String username = JiveGlobals.getProperty("jmxweb.admin.username", "admin");
      String password = JiveGlobals.getProperty("jmxweb.admin.password", "admin");

      URL url =
          new URL(
              "http://"
                  + username
                  + ":"
                  + password
                  + "@"
                  + host
                  + ":"
                  + port
                  + "/jolokia/read/java.lang:type=Memory/HeapMemoryUsage");
      HttpURLConnection conn = (HttpURLConnection) url.openConnection();
      conn.setRequestMethod("GET");
      conn.setRequestProperty("Accept", "application/json");
      if (conn.getResponseCode() != 200) {
        throw new RuntimeException(
            "HTTP Call Failed : HTTP error code : " + conn.getResponseCode());
      }
      BufferedReader br = new BufferedReader(new InputStreamReader((conn.getInputStream())));
      while ((line = br.readLine()) != null) {
        resultString.append(line);
      }
      Log.info("Memory data: " + resultString.toString());
      conn.disconnect();

    } catch (MalformedURLException e) {
      e.printStackTrace();
    } catch (IOException e) {
      e.printStackTrace();
    }
    return resultString.toString();
  }
 /**
  * Returns whether TLS is mandatory, optional or is disabled for clients. When TLS is mandatory
  * clients are required to secure their connections or otherwise their connections will be closed.
  * On the other hand, when TLS is disabled clients are not allowed to secure their connections
  * using TLS. Their connections will be closed if they try to secure the connection. in this last
  * case.
  *
  * @return whether TLS is mandatory, optional or is disabled.
  */
 public static SocketConnection.TLSPolicy getTLSPolicy() {
   // Set the TLS policy stored as a system property
   String policyName =
       JiveGlobals.getProperty("xmpp.client.tls.policy", Connection.TLSPolicy.optional.toString());
   SocketConnection.TLSPolicy tlsPolicy;
   try {
     tlsPolicy = Connection.TLSPolicy.valueOf(policyName);
   } catch (IllegalArgumentException e) {
     Log.error("Error parsing xmpp.client.tls.policy: " + policyName, e);
     tlsPolicy = Connection.TLSPolicy.optional;
   }
   return tlsPolicy;
 }
Example #14
0
  public Packet doAction(Packet packet) throws PacketRejectedException {
    SessionManager sessionManager = SessionManager.getInstance();
    ClientSession clientSession = sessionManager.getSession(packet.getFrom());
    Packet rejectPacket;
    String pfFrom = JiveGlobals.getProperty("pf.From", "packetfilter");

    if (packet instanceof Message) {
      Message in = (Message) packet.createCopy();
      if (clientSession != null && in.getBody() != null) {

        in.setFrom(new JID(pfFrom));
        String rejectMessage =
            JiveGlobals.getProperty(
                "pf.rejectMessage", "Your message was rejected by the packet filter");
        in.setBody(rejectMessage);
        in.setType(Message.Type.error);
        in.setTo(packet.getFrom());
        String rejectSubject = JiveGlobals.getProperty("pf.rejectSubject", "Rejected");
        in.setSubject(rejectSubject);
        clientSession.process(in);
      }

    } else if (packet instanceof Presence) {
      rejectPacket = new Presence();
      rejectPacket.setTo(packet.getFrom());
      rejectPacket.setError(PacketError.Condition.forbidden);

    } else if (packet instanceof IQ) {
      rejectPacket = new IQ();
      rejectPacket.setTo(packet.getFrom());
      rejectPacket.setError(PacketError.Condition.forbidden);
    }
    if (doLog()) {
      Log.info("Rejecting packet from " + packet.getFrom() + " to " + packet.getTo());
    }
    throw new PacketRejectedException();
  }
  public NativeAuthProvider() {
    // Convert XML based provider setup to Database based
    JiveGlobals.migrateProperty("nativeAuth.domain");

    this.domain = JiveGlobals.getProperty("nativeAuth.domain");

    // Configure the library path so that we can load the shaj native library
    // from the Openfire lib directory.
    // Find the root path of this class.
    try {
      String binaryPath =
          (new URL(Shaj.class.getProtectionDomain().getCodeSource().getLocation(), "."))
              .openConnection()
              .getPermission()
              .getName();
      binaryPath = (new File(binaryPath)).getCanonicalPath();

      // Add the binary path to "java.library.path".
      String newLibPath = binaryPath + File.pathSeparator + System.getProperty("java.library.path");
      System.setProperty("java.library.path", newLibPath);
      Field fieldSysPath = ClassLoader.class.getDeclaredField("sys_paths");
      fieldSysPath.setAccessible(true);
      fieldSysPath.set(System.class.getClassLoader(), null);
    } catch (Exception e) {
      Log.error(e);
    }

    // Configure Shaj to log output to the Openfire logger.
    com.cenqua.shaj.log.Log.Factory.setInstance(
        new com.cenqua.shaj.log.Log() {
          public boolean isDebug() {
            return Log.isDebugEnabled();
          }

          public void error(String string) {
            Log.error(string);
          }

          public void error(String string, Throwable throwable) {
            Log.error(string, throwable);
          }

          public void debug(String string) {
            Log.debug("NativeAuthProvider: " + string);
          }
        });
  }
  /**
   * Initializes the server's security audit provider, based on configuration and defaults to
   * DefaultSecurityAuditProvider if the specified provider is not valid or not specified.
   */
  private void initProvider() {
    // Convert XML based provider setup to Database based
    JiveGlobals.migrateProperty("provider.securityAudit.className");

    String className =
        JiveGlobals.getProperty(
            "provider.securityAudit.className",
            "org.jivesoftware.openfire.security.DefaultSecurityAuditProvider");
    // Check if we need to reset the provider class
    if (provider == null || !className.equals(provider.getClass().getName())) {
      try {
        Class c = ClassUtils.forName(className);
        provider = (SecurityAuditProvider) c.newInstance();
      } catch (Exception e) {
        Log.error("Error loading security audit provider: " + className, e);
        provider = new DefaultSecurityAuditProvider();
      }
    }
  }
  public CrowdGroupProvider() {
    String propertyValue = JiveGlobals.getProperty(JIVE_CROWD_GROUPS_CACHE_TTL_SECS);
    int ttl =
        (propertyValue == null || propertyValue.trim().length() == 0)
            ? CACHE_TTL
            : Integer.parseInt(propertyValue);

    Cache<String, Collection<JID>> groupMembershipCache =
        CacheFactory.createLocalCache(GROUP_MEMBERSHIP_CACHE_NAME);
    groupMembershipCache.setMaxCacheSize(-1);
    groupMembershipCache.setMaxLifetime(ttl * 1000); // msecs instead of sec - see Cache API

    Cache<JID, Collection<String>> userMembershipCache =
        CacheFactory.createLocalCache(USER_MEMBERSHIP_CACHE_NAME);
    userMembershipCache.setMaxCacheSize(-1);
    userMembershipCache.setMaxLifetime(ttl * 1000); // msecs instead of sec - see Cache API

    Cache<String, org.jivesoftware.openfire.crowd.jaxb.Group> groupCache =
        CacheFactory.createLocalCache(GROUP_CACHE_NAME);
    groupCache.setMaxCacheSize(-1);
    groupCache.setMaxLifetime(ttl * 1000); // msecs instead of sec - see Cache API
  }
Example #18
0
  public void chatSupportFinished(Workgroup workgroup, String sessionID) {
    Log.debug("Chat Support Finished, sending transcripts");

    final EmailService emailService = EmailService.getInstance();

    String property = JiveGlobals.getProperty("mail.configured");
    if (!ModelUtil.hasLength(property)) {
      Log.debug("Mail settings are not configured, transcripts will not be sent.");
      return;
    }

    final ChatSession chatSession = ChatTranscriptManager.getChatSession(sessionID);
    if (chatSession == null || chatSession.getFirstSession() == null) {
      return;
    }

    final StringBuilder builder = new StringBuilder();

    SimpleDateFormat formatter = new SimpleDateFormat("MM/dd/yyy hh:mm a");

    // Get duration of conversation
    Date date = new Date(chatSession.getFirstSession().getStartTime());
    int duration = getChatDuration(date, chatSession);

    TreeMap<String, List<String>> map =
        new TreeMap<String, List<String>>(chatSession.getMetadata());

    String body = JiveGlobals.getProperty("chat.transcript.body");

    if (ModelUtil.hasLength(body)) {
      builder.append(body).append("\n\n");
    }

    builder.append("formname=chat transcript\n");
    extractAndDisplay(builder, "question", map);
    display(builder, "fullname", chatSession.getCustomerName());
    extractAndDisplay(builder, "email", map);
    extractAndDisplay(builder, "Location", map);
    extractAndDisplay(builder, "userID", map);
    extractAndDisplay(builder, "username", map);
    extractAndDisplay(builder, "workgroup", map);
    display(builder, "chatduration", String.valueOf(duration));
    display(builder, "chatdate", formatter.format(date));
    if (chatSession.getFirstSession() != null
        && chatSession.getFirstSession().getAgentJID() != null) {
      try {
        display(builder, "agent", new JID(chatSession.getFirstSession().getAgentJID()).toBareJID());
      } catch (Exception e) {
        Log.debug("Could not display agent in transcript.", e);
      }
    }
    for (Iterator<Map.Entry<String, List<String>>> iterator = map.entrySet().iterator();
        iterator.hasNext(); ) {
      Map.Entry<String, List<String>> entry = iterator.next();
      display(builder, entry.getKey(), getListItem(entry.getValue()));
    }
    builder.append("ctranscript=\n");
    builder.append(ChatTranscriptManager.getTextTranscriptFromSessionID(sessionID));

    String subject = JiveGlobals.getProperty("chat.transcript.subject");
    String from = JiveGlobals.getProperty("chat.transcript.from");
    String to = JiveGlobals.getProperty("chat.transcript.to");

    if (!ModelUtil.hasLength(subject) || !ModelUtil.hasLength(from)) {
      Log.debug(
          "Transcript settings (chat.transcript.subject, chat.transcript.from) are not configured, "
              + "transcripts will not be sent.");
      return;
    }

    if (ModelUtil.hasLength(to)) {
      emailService.sendMessage(
          "Chat Transcript", to, "Chat Transcript", from, subject, builder.toString(), null);
      Log.debug("Transcript sent to " + to);
    }

    // NOTE: Do not sent to the customer. They will receive a prompt for a seperate chat transcript
    // that does not contain agent information.

    // Send to Agents
    UserManager um = UserManager.getInstance();
    for (Iterator<AgentChatSession> iterator = chatSession.getAgents(); iterator.hasNext(); ) {
      AgentChatSession agentSession = iterator.next();
      try {
        User user = um.getUser(new JID(agentSession.getAgentJID()).getNode());
        emailService.sendMessage(
            "Chat Transcript",
            user.getEmail(),
            "Chat Transcript",
            from,
            subject,
            builder.toString(),
            null);
        Log.debug("Transcript sent to agent " + agentSession.getAgentJID());
      } catch (UserNotFoundException e) {
        Log.error(
            "Email Transcript Not Sent:"
                + "Could not load agent user object for jid "
                + agentSession.getAgentJID());
      }
    }
  }
public class QQListener implements IQQListener {

  static Logger Log = Logger.getLogger(QQListener.class);

  private static String defaultGroupName =
      JiveGlobals.getProperty("plugin.gateway.qq.defaultRosterName", "Friends");
  //    public static final SimpleDateFormat sdf = new SimpleDateFormat(
  //            "yyyy-MM-dd HH:mm:ss");
  private List<String> groupNames = new ArrayList<String>();
  // private Map<Integer, QQFriend> friends = new HashMap<Integer, QQFriend>();
  private Map<Integer, String> friendGroup = new HashMap<Integer, String>();
  //    private Map<Integer,
  //                ClusterInfo> clusters = new HashMap<Integer, ClusterInfo>();
  //    private Map<Integer,
  //                Map<Integer, String>> clusterMembers = new Hashtable<Integer,
  //            Map<Integer, String>>(); //group members

  /**
   * Creates a QQ session listener affiliated with a session.
   *
   * @param session The QQSession instance we are associated with.
   */
  public QQListener(QQSession session) {
    this.qqSessionRef = new WeakReference<QQSession>(session);
  }

  /** The transport session we are affiliated with. */
  WeakReference<QQSession> qqSessionRef;

  /**
   * Returns the QQ session this listener is attached to.
   *
   * @return QQ session we are attached to.
   */
  public QQSession getSession() {
    return qqSessionRef.get();
  }

  public void qqEvent(QQEvent e) {
    Log.debug("QQ: Received - " + e.getSource() + " Event ID: 0x" + Integer.toHexString(e.type));
    switch (e.type) {
      case QQEvent.LOGIN_OK:
        processSuccessfulLogin();
        break;
      case QQEvent.LOGIN_FAIL:
        getSession().setFailureStatus(ConnectionFailureReason.USERNAME_OR_PASSWORD_INCORRECT);
        getSession().sessionDisconnectedNoReconnect(null);
        break;
      case QQEvent.LOGIN_UNKNOWN_ERROR:
      case QQEvent.ERROR_CONNECTION_BROKEN:
        getSession().setFailureStatus(ConnectionFailureReason.UNKNOWN);
        getSession().sessionDisconnected(null);
        break;
      case QQEvent.USER_STATUS_CHANGE_OK:
        processStatusChangeOK((ChangeStatusReplyPacket) e.getSource());
        break;
      case QQEvent.USER_STATUS_CHANGE_FAIL:
        getSession().sessionDisconnected(null);
        break;
      case QQEvent.FRIEND_DOWNLOAD_GROUPS_OK:
        processGroupFriend(e);
        break;
      case QQEvent.FRIEND_GET_GROUP_NAMES_OK:
        processGroupNames(e);
        break;
      case QQEvent.USER_GET_INFO_OK:
        processFriendInfo(e);
        break;
        //        case QQEvent.QQ_GET_CLUSTER_INFO_SUCCESS:
        //            processClusterInfo(e);
        //            break;
        //        case QQEvent.QQ_GET_MEMBER_INFO_SUCCESS:
        //            processClusterMemberInfo(e);
        //            break;
        //        case QQEvent.QQ_RECEIVE_CLUSTER_IM:
        //            processClusterIM(e);
        //            break;
      case QQEvent.IM_RECEIVED:
        processNormalIM((ReceiveIMPacket) e.getSource());
        break;
      case QQEvent.ERROR_NETWORK:
      case QQEvent.ERROR_RUNTIME:
        getSession().setFailureStatus(ConnectionFailureReason.CAN_NOT_CONNECT);
        getSession().sessionDisconnected(null);
        break;
      case QQEvent.FRIEND_GET_ONLINE_OK:
        processFriendOnline((_08GetOnlineOpReplyPacket) e.getSource());
        break;
      case QQEvent.FRIEND_STATUS_CHANGED:
        processFriendChangeStatus((FriendChangeStatusPacket) e.getSource());
        break;
      case QQEvent.FRIEND_GET_LIST_OK:
        processFriendList((GetFriendListReplyPacket) e.getSource());
        break;
      case QQEvent.LOGIN_TOUCH:
        getSession().getQQClient().sendToken1();
      default:
        break;
    }
  }

  private void processFriendList(GetFriendListReplyPacket p) {
    Log.debug("QQ: processing friend list");
    // For whatever reason, this no longer returns anything useful.  So we go another route to get
    // info on our peeps.
    //        try {
    //            for (QQFriend f : p.friends) {
    //                Log.debug("Found QQ friend: "+f);
    //                friends.put(f.qqNum, f);
    //
    //                String groupName = friendGroup.get(f.qqNum);
    //                if (groupName == null || groupName.trim().length() < 1) {
    //                    groupName = defaultGroupName;
    //                }
    //                List<String> gl = new ArrayList<String>();
    //                gl.add(groupName);
    //                QQBuddy qqBuddy = new QQBuddy(getSession().getBuddyManager(), f, f.nick, gl);
    //                getSession().getBuddyManager().storeBuddy(qqBuddy);
    //            }
    //            if (p.position != 0xFFFF) {
    //                getSession().getQQClient().user_GetList(p.position);
    //            }
    //        } catch (Exception ex) {
    //            Log.error("Failed to process friend list: ", ex);
    //        }

    // Lets try the actual sync.
    try {
      getSession()
          .getTransport()
          .syncLegacyRoster(getSession().getJID(), getSession().getBuddyManager().getBuddies());
    } catch (UserNotFoundException ex) {
      Log.debug("Unable to sync QQ contact list for " + getSession().getJID());
    }

    getSession().getBuddyManager().activate();

    getSession().getQQClient().user_GetOnline();
  }

  private void processGroupFriend(QQEvent e) {
    Log.debug("QQ: Processing group friend.");
    try {
      DownloadGroupFriendReplyPacket p = (DownloadGroupFriendReplyPacket) e.getSource();
      for (DownloadFriendEntry entry : p.friends) {
        //                if (entry.isCluster()) {
        //                    getSession().getQQClient().getClusterInfo(entry.qqNum);
        //                } else {
        if (groupNames != null && groupNames.size() > entry.group) {
          String groupName = groupNames.get(entry.group);
          friendGroup.put(entry.qqNum, groupName);
          List<String> gl = new ArrayList<String>();
          gl.add(groupName);
          QQBuddy qqBuddy = new QQBuddy(getSession().getBuddyManager(), entry.qqNum, gl);
          getSession().getBuddyManager().storeBuddy(qqBuddy);
        } else {
          friendGroup.put(entry.qqNum, defaultGroupName);
          List<String> gl = new ArrayList<String>();
          gl.add(defaultGroupName);
          QQBuddy qqBuddy = new QQBuddy(getSession().getBuddyManager(), entry.qqNum, gl);
          getSession().getBuddyManager().storeBuddy(qqBuddy);
        }
        //                }
        getSession().getQQClient().user_GetInfo(entry.qqNum);
      }
      //            if (p.beginFrom != 0) {
      //                getSession().getQQClient().getClusterOnlineMember(p.beginFrom);
      //            }
    } catch (Exception ex) {
      Log.error("Failed to process group friend: ", ex);
    }
    getSession().getQQClient().user_GetList();
  }

  private void processFriendInfo(QQEvent e) {
    Log.debug("QQ: Processing friend info request");
    GetUserInfoReplyPacket p = (GetUserInfoReplyPacket) e.getSource();
    try {
      QQBuddy buddy =
          getSession()
              .getBuddyManager()
              .getBuddy(
                  getSession().getTransport().convertIDToJID(String.valueOf(p.contactInfo.qq)));
      buddy.setNickname(p.contactInfo.nick);
      buddy.contactInfo = p.contactInfo;
      getSession().getBuddyManager().storeBuddy(buddy);
    } catch (NotFoundException nfe) {
      Log.debug("QQ: Received buddy " + p.contactInfo.qq + " that we don't know about.");
    }
  }

  private void processGroupNames(QQEvent e) {
    Log.debug("QQ: Processing group names");
    try {
      groupNames.clear();
      groupNames.add(defaultGroupName);
      GroupDataOpReplyPacket p = (GroupDataOpReplyPacket) e.getSource();
      groupNames.addAll(p.groupNames);
    } catch (Exception ex) {
      Log.error("Failed to process group names: ", ex);
    }
    getSession().getQQClient().user_DownloadGroups(0);
  }

  //    private void processClusterInfo(QQEvent e) {
  //        try {
  //            ClusterCommandReplyPacket p = (ClusterCommandReplyPacket) e.
  //                                          getSource();
  //            ClusterInfo info = p.info;
  //            if (QQ.QQ_CLUSTER_TYPE_PERMANENT == info.type) {
  //                clusters.put(info.externalId, info);
  //            }
  //            List<String> gl = new ArrayList<String>();
  //            gl.add(JiveGlobals.getProperty("plugin.gateway.qq.qqGroupName",
  //                                           "QQ Group"));
  //            TransportBuddy tb = new TransportBuddy(getSession().getBuddyManager(),
  //                    String.valueOf(info.externalId), info.name, gl);
  //            getSession().getBuddyManager().storeBuddy(tb);
  //            Presence pp = new Presence();
  //
  // pp.setFrom(getSession().getTransport().convertIDToJID(String.valueOf(info.externalId)));
  //            pp.setTo(getSession().getJID());
  //            pp.setShow(Presence.Show.chat);
  //            getSession().getTransport().sendPacket(pp);
  //            qqclient.getClusterMemberInfo(info.clusterId, p.members);
  //        } catch (Exception ex) {
  //            Log.error("Failed to process cluster info: ", ex);
  //        }
  //    }
  //
  //    private void processClusterMemberInfo(QQEvent e) {
  //        try {
  //            ClusterCommandReplyPacket p = (ClusterCommandReplyPacket) e.
  //                                          getSource();
  //            Map<Integer, String> cmm = new HashMap<Integer, String>();
  //            for (Object obj : p.memberInfos) {
  //                QQFriend m = (QQFriend) obj;
  //                cmm.put(m.qqNum, m.nick);
  //            }
  //            int clusterId = 0;
  //            for (ClusterInfo c : clusters.values()) {
  //                if (c.clusterId == p.clusterId) {
  //                    clusterId = c.externalId;
  //                }
  //            }
  //            clusterMembers.put(clusterId, cmm);
  //        } catch (Exception ex) {
  //            Log.error("Failed to process cluster member info: ", ex);
  //        }
  //    }

  private void processSuccessfulLogin() {
    Log.debug("QQ: Processing successful login");
    getSession().setLoginStatus(TransportLoginStatus.LOGGED_IN);

    getSession().getQQClient().user_GetGroupNames();
  }

  private void processStatusChangeOK(ChangeStatusReplyPacket p) {
    Log.debug("QQ: Processing status change success");
    //        if (!getSession().isLoggedIn()) {
    //            getSession().setLoginStatus(TransportLoginStatus.LOGGED_IN);
    //            getSession().getQQClient().getFriendList();
    //            getSession().getQQClient().downloadGroup();
    //            getSession().getQQClient().getFriendOnline();
    //        }
  }

  //    private void processClusterIM(QQEvent e) {
  //        try {
  //            ReceiveIMPacket p = (ReceiveIMPacket) e.getSource();
  //            ClusterIM im = p.clusterIM;
  //            if (clusters.get(im.externalId) == null) {
  //                qqclient.downloadGroup();
  //            }
  //            String sDate = sdf.format(new Date(im.sendTime));
  //            String clusterName = "";
  //            try {
  //                clusterName = clusters.get(im.externalId).name;
  //            } catch (Exception ex) {
  //                Log.debug("Failed to get cluster name: ", ex);
  //            }
  //            String senderName = " ";
  //            try {
  //                senderName = clusterMembers.get(im.externalId).get(im.sender);
  //            } catch (Exception ex) {
  //                Log.debug("Failed to get sender name: ", ex);
  //            }
  //            String msg = clusterName + "[" + im.externalId + "]"
  //                         + senderName + "(" + im.sender + ") "
  //                         + sDate + ":\n"
  //                         + new String(im.messageBytes) + "\n";
  //            Message m = new Message();
  //            m.setType(Message.Type.chat);
  //            m.setTo(getSession().getJID());
  //
  // m.setFrom(getSession().getTransport().convertIDToJID(String.valueOf(im.externalId)));
  //            String b = " ";
  //            try {
  //                b = new String(msg);
  //            } catch (Exception ex) {
  //                Log.debug("Failed to string-ify message: ", ex);
  //            }
  //            m.setBody(b);
  //            getSession().getTransport().sendPacket(m);
  //        } catch (Exception ex) {
  //            Log.error("Failed to handle cluster IM: ", ex);
  //        }
  //    }

  /**
   * Handles a standard instant message being sent to us.
   *
   * @param p Event of the message.
   */
  private void processNormalIM(ReceiveIMPacket p) {
    Log.debug("QQ: Processing normal IM received.");
    NormalIM im = p.normalIM;
    getSession()
        .getTransport()
        .sendMessage(
            getSession().getJID(),
            getSession().getTransport().convertIDToJID(String.valueOf(p.normalHeader.sender)),
            im.message);
  }

  /**
   * Handles an event when a friend has come online.
   *
   * @param p Event to be handled.
   */
  private void processFriendOnline(_08GetOnlineOpReplyPacket p) {
    Log.debug("QQ: Processing friend online notification");
    try {
      for (FriendOnlineEntry f : p.onlineFriends) {
        Log.debug("QQ: Got an online friend");
        if (getSession().getBuddyManager().isActivated()) {
          try {
            QQBuddy qqBuddy =
                getSession()
                    .getBuddyManager()
                    .getBuddy(
                        getSession().getTransport().convertIDToJID(String.valueOf(f.status.qqNum)));
            qqBuddy.setPresenceAndStatus(
                ((QQTransport) getSession().getTransport()).convertQQStatusToXMPP(f.status.status),
                null);
          } catch (NotFoundException ee) {
            // Not in our list.
            Log.debug(
                "QQ: Received presense notification for contact we don't care about: "
                    + String.valueOf(f.status.qqNum));
          }
        } else {
          getSession()
              .getBuddyManager()
              .storePendingStatus(
                  getSession().getTransport().convertIDToJID(String.valueOf(f.status.qqNum)),
                  ((QQTransport) getSession().getTransport())
                      .convertQQStatusToXMPP(f.status.status),
                  null);
        }
      }
      //            if (!p.finished) {
      //                qqclient.getUser().user_GetOnline(p.position);
      //            }
    } catch (Exception ex) {
      Log.error("Failed to handle friend online event: ", ex);
    }
  }

  /**
   * Handles an event where a friend changes their status.
   *
   * @param p Event representing change.
   */
  private void processFriendChangeStatus(FriendChangeStatusPacket p) {
    Log.debug("QQ: Processing friend status change event");
    try {
      if (getSession().getBuddyManager().isActivated()) {
        try {
          QQBuddy qqBuddy =
              getSession()
                  .getBuddyManager()
                  .getBuddy(getSession().getTransport().convertIDToJID(String.valueOf(p.friendQQ)));
          qqBuddy.setPresenceAndStatus(
              ((QQTransport) getSession().getTransport()).convertQQStatusToXMPP(p.status), null);
        } catch (NotFoundException ee) {
          // Not in our list.
          Log.debug(
              "QQ: Received presense notification for contact we don't care about: "
                  + String.valueOf(p.friendQQ));
        }
      } else {
        getSession()
            .getBuddyManager()
            .storePendingStatus(
                getSession().getTransport().convertIDToJID(String.valueOf(p.friendQQ)),
                ((QQTransport) getSession().getTransport()).convertQQStatusToXMPP(p.status),
                null);
      }
    } catch (Exception ex) {
      Log.error("Failed to handle friend status change event: ", ex);
    }
  }
}
  public void _jspService(HttpServletRequest request, HttpServletResponse response)
      throws java.io.IOException, ServletException {

    JspFactory _jspxFactory = null;
    PageContext pageContext = null;
    HttpSession session = null;
    ServletContext application = null;
    ServletConfig config = null;
    JspWriter out = null;
    Object page = this;
    JspWriter _jspx_out = null;
    PageContext _jspx_page_context = null;

    try {
      _jspxFactory = JspFactory.getDefaultFactory();
      response.setContentType("text/html");
      pageContext = _jspxFactory.getPageContext(this, request, response, null, true, 8192, true);
      _jspx_page_context = pageContext;
      application = pageContext.getServletContext();
      config = pageContext.getServletConfig();
      session = pageContext.getSession();
      out = pageContext.getOut();
      _jspx_out = out;

      out.write('\r');
      out.write('\n');
      try {
        out.write("\r\n\r\n ");

        String wgID = request.getParameter("wgID");
        final WorkgroupManager workgroupManager = WorkgroupManager.getInstance();
        Workgroup workgroup = workgroupManager.getWorkgroup(new JID(wgID));

        OfflineSettingsManager offlineManager = new OfflineSettingsManager();
        String redirectValue = request.getParameter("redirectToPage");
        String statusMessage = "";

        OfflineSettings offlineSettings = null;

        boolean emailConfigured = false;

        String property = JiveGlobals.getProperty("mail.configured");
        if (ModelUtil.hasLength(property)) {
          emailConfigured = true;
        }

        boolean delete = request.getParameter("delete") != null;
        boolean save = request.getParameter("save") != null && !delete;

        if (save) {
          String emailAddress = request.getParameter("email");
          String subject = request.getParameter("subject");
          String header = request.getParameter("headerField");
          offlineSettings =
              offlineManager.saveOfflineSettings(
                  workgroup, redirectValue, emailAddress, subject, header);
          if (offlineSettings != null) {
            statusMessage = "Offline settings have been saved.";
          }
        } else if (delete) {
          statusMessage = "Offline settings have been deleted.";
          offlineSettings =
              offlineManager.saveOfflineSettings(workgroup, redirectValue, "", "", "");
        } else {
          try {
            offlineSettings = offlineManager.getOfflineSettings(workgroup);
          } catch (OfflineSettingsNotFound offlineSettingsNotFound) {
            offlineSettings = new OfflineSettings();
          }
        }

        out.write("\r\n<html>\r\n    <head>\r\n        <title>");
        out.print("Offline Settings for " + wgID);
        out.write(
            "</title>\r\n        <meta name=\"subPageID\" content=\"workgroup-offline\"/>\r\n        <meta name=\"extraParams\" content=\"");
        out.print("wgID=" + wgID);
        out.write(
            "\"/>\r\n        <!--<meta name=\"helpPage\" content=\"set_an_offline_policy_for_a_workgroup.html\"/>-->\r\n\r\n        <script>\r\n        function saveOfflineSettings(){\r\n             var todo = document.offline.todo;\r\n             if(todo[0].checked){\r\n                 var url = document.offline.redirectToPage.value;\r\n                 if(!Jtrim(url)){\r\n                   alert(\"Please specify the URL to forward to.\");\r\n                   document.offline.redirectToPage.focus();\r\n                   return;\r\n                 }\r\n                 document.offline.email.value = \"\";\r\n                 document.offline.subject.value = \"\";\r\n                 document.offline.headerField.value = \"\";\r\n\r\n                 document.offline.submit();\r\n             }\r\n             else if(todo[1].checked){\r\n               var email = document.offline.email.value;\r\n               var subject = document.offline.subject.value;\r\n               var message = document.offline.headerField.value;\r\n               document.offline.redirectToPage.value = '';\r\n");
        out.write(
            "\r\n               if(!Jtrim(email) || !Jtrim(subject) || !Jtrim(message)){\r\n                 alert(\"All fields are required.\");\r\n                 return;\r\n               }\r\n                document.offline.submit();\r\n             }\r\n        }\r\n\r\n\r\n\r\n         function Jtrim(st) {\r\n             var len = st.length;\r\n             var begin = 0, end = len - 1;\r\n             while (st.charAt(begin) == \" \" && begin < len) {\r\n                 begin++;\r\n             }\r\n             while (st.charAt(end) == \" \" && end > begin) {\r\n                 end--;\r\n             }\r\n             return st.substring(begin, end + 1);\r\n         }\r\n        </script>\r\n    </head>\r\n    <body>\r\n    Specify action to take when this workgroup has no available agents to take incoming chat requests.\r\n    ");
        if (statusMessage != null && !statusMessage.equals("")) {
          out.write("\r\n    <div class=\"success\">\r\n        ");
          out.print(statusMessage);
          out.write("\r\n    </div>\r\n    ");
        }
        out.write("\r\n\r\n      ");
        if (!emailConfigured) {
          out.write(
              "\r\n            <div class=\"error\">\r\n                Email form will not be displayed until you configure your <a href=\"../../system-email.jsp\">email settings</a>.\r\n            </div>\r\n    ");
        }
        out.write("\r\n\r\n    <div id=\"offline_message\">");
        out.print(statusMessage);
        out.write(
            "</div>\r\n    <p/>\r\n    <form action=\"workgroup-offline.jsp\" method=\"get\" name=\"offline\">\r\n    <input type=\"hidden\" name=\"wgID\" value=\"");
        out.print(wgID);
        out.write(
            "\" />\r\n    <div>\r\n        <div class=\"jive-contentBoxHeader\">\r\n        Offline Workgroup Action\r\n        </div>\r\n        <table width=\"100%\" cellpadding=\"3\" cellspacing=\"0\" border=\"0\" class=\"jive-contentBox\">\r\n                <tr valign=\"top\">\r\n                ");
        String checked = offlineSettings.redirects() ? "checked" : "";
        out.write(
            "\r\n                            <td width=\"1%\">\r\n                                <input type=\"radio\" name=\"todo\" value=\"redirectToPage\" ");
        out.print(checked);
        out.write(
            " />\r\n                            </td>\r\n                            <td nowrap><b>Redirect To Web Page</b>\r\n                               </td>\r\n                            <td class=\"c2\">\r\n                                <input type=\"text\" name=\"redirectToPage\" size=\"40\" value=\"");
        out.print(offlineSettings.getRedirectURL());
        out.write(
            "\" /><br/>\r\n                                 <span class=\"jive-description\">e.g. http://www.jivesoftware.com/contact.html</span>\r\n                            </td>\r\n                </tr>\r\n                <tr>\r\n                    <td nowrap width=\"1%\">\r\n                         <input type=\"radio\" name=\"todo\" value=\"showEmailPage\" ");
        out.print(!offlineSettings.redirects() ? "checked" : "");
        out.write(
            "/>\r\n                         <td><b>Display Email Form</b></td>\r\n                     </td>\r\n                     <td>&nbsp;</td>\r\n                </tr>\r\n                <!-- Email Address -->\r\n                <tr valign=\"top\">\r\n                    <td>&nbsp;</td>\r\n                    <td>Email Address:</td>\r\n                    <td>\r\n                        <input type=\"text\" size=\"40\" name=\"email\" value=\"");
        out.print(offlineSettings.getEmailAddress());
        out.write(
            "\" /><br/>\r\n                        <span class=\"jive-description\">Email address to send all offline messages to.</span>\r\n                    </td>\r\n                </tr>\r\n                <!-- End of Email Address -->\r\n                <!-- Subject Line -->\r\n                 <tr valign=\"top\">\r\n                    <td>&nbsp;</td>\r\n                    <td>Subject:</td>\r\n                    <td>\r\n                        <input type=\"text\" size=\"40\" name=\"subject\" value=\"");
        out.print(offlineSettings.getSubject());
        out.write(
            "\"/><br/>\r\n                        <span class=\"jive-description\">The subject of all offline email messages.</span>\r\n                    </td>\r\n                </tr>\r\n                <!--  End Of Subject Line -->\r\n                <tr valign=\"top\">\r\n                     <td>&nbsp;</td>\r\n                    <td>Offline Text:</td>\r\n                    <td>\r\n                        <textarea name=\"headerField\" cols=\"40\" rows=\"5\">");
        out.print(offlineSettings.getOfflineText());
        out.write(
            "</textarea><br/>\r\n                        <span class=\"jive-description\">Text to display to the user in the email form.</span>\r\n                    </td>\r\n                </tr>\r\n                    <input type=\"hidden\" name=\"save\" value=\"save\">\r\n                 <tr>\r\n                </tr>\r\n            ");
        out.write(
            "\r\n            </table>\r\n            <table><tr>\r\n                 <td colspan=\"1\"> <input type=\"button\" name=\"save\" value=\"Save Changes\" onclick=\"return saveOfflineSettings();\" /></td>\r\n                <td colspan=\"1\"> <input type=\"submit\" name=\"delete\" value=\"Delete Changes\" /></td>\r\n            </tr></table>\r\n       </div>\r\n    </form>\r\n\r\n</body>\r\n</html>\r\n\r\n");
      } catch (Exception ex) {
        ex.printStackTrace();
      }
    } catch (Throwable t) {
      if (!(t instanceof SkipPageException)) {
        out = _jspx_out;
        if (out != null && out.getBufferSize() != 0) out.clearBuffer();
        if (_jspx_page_context != null) _jspx_page_context.handlePageException(t);
      }
    } finally {
      if (_jspxFactory != null) _jspxFactory.releasePageContext(_jspx_page_context);
    }
  }
 @Override
 public String getProperty(String name) {
   return JiveGlobals.getProperty(name);
 }
  private void init() {
    // Register the trust manager to use when using HTTPS
    Protocol easyhttps =
        new Protocol("https", (ProtocolSocketFactory) new SSLProtocolSocketFactory(this), 443);
    Protocol.registerProtocol("https", easyhttps);

    // Convert XML based provider setup to Database based
    JiveGlobals.migrateProperty("clearspace.uri");
    JiveGlobals.migrateProperty("clearspace.sharedSecret");

    // Make sure that all Clearspace components are set up, unless they were overridden
    // Note that the auth provider is our way of knowing that we are set up with Clearspace,
    // so don't bother checking to set it.
    if (isEnabled()) {
      if (JiveGlobals.getProperty("provider.user.className") == null) {
        JiveGlobals.setProperty(
            "provider.user.className",
            "org.jivesoftware.openfire.clearspace.ClearspaceUserProvider");
      }
      if (JiveGlobals.getProperty("provider.group.className") == null) {
        JiveGlobals.setProperty(
            "provider.group.className",
            "org.jivesoftware.openfire.clearspace.ClearspaceGroupProvider");
      }
      if (JiveGlobals.getProperty("provider.vcard.className") == null) {
        JiveGlobals.setProperty(
            "provider.vcard.className",
            "org.jivesoftware.openfire.clearspace.ClearspaceVCardProvider");
      }
      if (JiveGlobals.getProperty("provider.lockout.className") == null) {
        JiveGlobals.setProperty(
            "provider.lockout.className",
            "org.jivesoftware.openfire.clearspace.ClearspaceLockOutProvider");
      }
      if (JiveGlobals.getProperty("provider.securityAudit.className") == null) {
        JiveGlobals.setProperty(
            "provider.securityAudit.className",
            "org.jivesoftware.openfire.clearspace.ClearspaceSecurityAuditProvider");
      }
      if (JiveGlobals.getProperty("provider.admin.className") == null) {
        JiveGlobals.setProperty(
            "provider.admin.className",
            "org.jivesoftware.openfire.clearspace.ClearspaceAdminProvider");
      }
    }

    this.uri = properties.get("clearspace.uri");
    if (uri != null) {
      if (!this.uri.endsWith("/")) {
        this.uri = this.uri + "/";
      }
      // Updates the host/port attributes based on the uri
      updateHostPort();
    }
    sharedSecret = properties.get("clearspace.sharedSecret");

    // Creates the cache maps
    userIDCache = new DefaultCache<String, Long>("clearspace.userid", 1000, JiveConstants.DAY);
    groupIDCache = new DefaultCache<String, Long>("clearspace.groupid", 1000, JiveConstants.DAY);
    usernameCache = new DefaultCache<Long, String>("clearspace.username", 1000, JiveConstants.DAY);

    if (Log.isDebugEnabled()) {
      StringBuilder buf = new StringBuilder();
      buf.append("Created new ClearspaceManager() instance, fields:\n");
      buf.append("\t URI: ").append(uri).append("\n");
      buf.append("\t sharedSecret: ").append(sharedSecret).append("\n");

      Log.debug("ClearspaceManager: " + buf.toString());
    }

    // Init nonce cache
    nonceCache = CacheFactory.createCache("Clearspace SSO Nonce");
    // Init nonce generator
    nonceGenerator = new Random();
  }
  public void _jspService(HttpServletRequest request, HttpServletResponse response)
      throws java.io.IOException, ServletException {

    JspFactory _jspxFactory = null;
    PageContext pageContext = null;
    HttpSession session = null;
    ServletContext application = null;
    ServletConfig config = null;
    JspWriter out = null;
    Object page = this;
    JspWriter _jspx_out = null;
    PageContext _jspx_page_context = null;

    try {
      _jspxFactory = JspFactory.getDefaultFactory();
      response.setContentType("text/html");
      pageContext =
          _jspxFactory.getPageContext(this, request, response, "error.jsp", true, 8192, true);
      _jspx_page_context = pageContext;
      application = pageContext.getServletContext();
      config = pageContext.getServletConfig();
      session = pageContext.getSession();
      out = pageContext.getOut();
      _jspx_out = out;

      out.write("\n\n\n\n\n\n\n\n\n");
      out.write('\n');
      org.jivesoftware.util.WebManager webManager = null;
      synchronized (_jspx_page_context) {
        webManager =
            (org.jivesoftware.util.WebManager)
                _jspx_page_context.getAttribute("webManager", PageContext.PAGE_SCOPE);
        if (webManager == null) {
          webManager = new org.jivesoftware.util.WebManager();
          _jspx_page_context.setAttribute("webManager", webManager, PageContext.PAGE_SCOPE);
        }
      }
      out.write('\n');
      webManager.init(request, response, session, application, out);
      out.write('\n');
      out.write('\n');
      // Get paramters
      boolean doTest = request.getParameter("test") != null;
      boolean cancel = request.getParameter("cancel") != null;
      boolean sent = ParamUtils.getBooleanParameter(request, "sent");
      boolean success = ParamUtils.getBooleanParameter(request, "success");
      String from = ParamUtils.getParameter(request, "from");
      String to = ParamUtils.getParameter(request, "to");
      String subject = ParamUtils.getParameter(request, "subject");
      String body = ParamUtils.getParameter(request, "body");

      // Cancel if requested
      if (cancel) {
        response.sendRedirect("system-email.jsp");
        return;
      }

      // Variable to hold messaging exception, if one occurs
      Exception mex = null;

      // Validate input
      Map<String, String> errors = new HashMap<String, String>();
      if (doTest) {
        if (from == null) {
          errors.put("from", "");
        }
        if (to == null) {
          errors.put("to", "");
        }
        if (subject == null) {
          errors.put("subject", "");
        }
        if (body == null) {
          errors.put("body", "");
        }

        EmailService service = EmailService.getInstance();

        // Validate host - at a minimum, it needs to be set:
        String host = service.getHost();
        if (host == null) {
          errors.put("host", "");
        }

        // if no errors, continue
        if (errors.size() == 0) {
          // Create a message
          MimeMessage message = service.createMimeMessage();
          // Set the date of the message to be the current date
          SimpleDateFormat format =
              new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss Z", java.util.Locale.US);
          format.setTimeZone(JiveGlobals.getTimeZone());
          message.setHeader("Date", format.format(new Date()));

          // Set to and from.
          message.setRecipient(Message.RecipientType.TO, new InternetAddress(to, null));
          message.setFrom(new InternetAddress(from, null));
          message.setSubject(subject);
          message.setText(body);
          // Send the message, wrap in a try/catch:
          try {
            service.sendMessagesImmediately(Collections.singletonList(message));
            // success, so indicate this:
            response.sendRedirect("system-emailtest.jsp?sent=true&success=true");
            return;
          } catch (MessagingException me) {
            me.printStackTrace();
            mex = me;
          }
        }
      }

      // Set var defaults
      Collection<JID> jids = webManager.getXMPPServer().getAdmins();
      User user = null;
      if (!jids.isEmpty()) {
        for (JID jid : jids) {
          if (webManager.getXMPPServer().isLocal(jid)) {
            user = webManager.getUserManager().getUser(jid.getNode());
            if (user.getEmail() != null) {
              break;
            }
          }
        }
      }
      if (from == null) {
        from = user.getEmail();
      }
      if (to == null) {
        to = user.getEmail();
      }
      if (subject == null) {
        subject = "Test email sent via Openfire";
      }
      if (body == null) {
        body = "This is a test message.";
      }

      out.write("\n\n<html>\n    <head>\n        <title>");
      if (_jspx_meth_fmt_message_0(_jspx_page_context)) return;
      out.write(
          "</title>\n        <meta name=\"pageID\" content=\"system-email\"/>\n    </head>\n    <body>\n\n<script language=\"JavaScript\" type=\"text/javascript\">\nvar clicked = false;\nfunction checkClick(el) {\n    if (!clicked) {\n        clicked = true;\n        return true;\n    }\n    return false;\n}\n</script>\n\n<p>\n");
      if (_jspx_meth_fmt_message_1(_jspx_page_context)) return;
      out.write("\n</p>\n\n");
      if (JiveGlobals.getProperty("mail.smtp.host") == null) {
        out.write(
            "\n\n    <div class=\"jive-error\">\n    <table cellpadding=\"0\" cellspacing=\"0\" border=\"0\">\n    <tbody>\n        <tr>\n        \t<td class=\"jive-icon\"><img src=\"images/error-16x16.gif\" width=\"16\" height=\"16\" border=\"0\" alt=\"\"></td>\n\t        <td class=\"jive-icon-label\">\n\t\t        ");
        if (_jspx_meth_fmt_message_2(_jspx_page_context)) return;
        out.write("\n\t        </td>\n        </tr>\n    </tbody>\n    </table>\n    </div>\n\n");
      }
      out.write('\n');
      out.write('\n');
      if (doTest || sent) {
        out.write("\n\n    ");
        if (success) {
          out.write(
              "\n\n        <div class=\"jive-success\">\n        <table cellpadding=\"0\" cellspacing=\"0\" border=\"0\">\n        <tbody>\n            <tr>\n            \t<td class=\"jive-icon\"><img src=\"images/success-16x16.gif\" width=\"16\" height=\"16\" border=\"0\" alt=\"\"></td>\n            \t<td class=\"jive-icon-label\">");
          if (_jspx_meth_fmt_message_3(_jspx_page_context)) return;
          out.write(
              "</td>\n            </tr>\n        </tbody>\n        </table>\n        </div>\n\n    ");
        } else {
          out.write(
              "\n\n        <div class=\"jive-error\">\n        <table cellpadding=\"0\" cellspacing=\"0\" border=\"0\">\n        <tbody>\n            <tr><td class=\"jive-icon\"><img src=\"images/error-16x16.gif\" width=\"16\" height=\"16\" border=\"0\" alt=\"\"></td>\n            <td class=\"jive-icon-label\">\n                ");
          if (_jspx_meth_fmt_message_4(_jspx_page_context)) return;
          out.write("\n                ");
          if (mex != null) {
            out.write("\n                    ");
            if (mex instanceof AuthenticationFailedException) {
              out.write("\n                    \t");
              if (_jspx_meth_fmt_message_5(_jspx_page_context)) return;
              out.write("                        \n                    ");
            } else {
              out.write("\n                        (Message: ");
              out.print(mex.getMessage());
              out.write(")\n                    ");
            }
            out.write("\n                ");
          }
          out.write(
              "\n            </td></tr>\n        </tbody>\n        </table>\n        </div>\n\n    ");
        }
        out.write("\n\n    <br>\n\n");
      }
      out.write(
          "\n\n<form action=\"system-emailtest.jsp\" method=\"post\" name=\"f\" onsubmit=\"return checkClick(this);\">\n\n<table cellpadding=\"3\" cellspacing=\"0\" border=\"0\">\n<tbody>\n    <tr>\n        <td>\n            ");
      if (_jspx_meth_fmt_message_6(_jspx_page_context)) return;
      out.write(":\n        </td>\n        <td>\n            ");
      String host = JiveGlobals.getProperty("mail.smtp.host");
      if (host == null) {

        out.write("\n                <i>");
        if (_jspx_meth_fmt_message_7(_jspx_page_context)) return;
        out.write("</i>\n            ");

      } else {

        out.write("\n                ");
        out.print(host);
        out.write(':');
        out.print(JiveGlobals.getIntProperty("mail.smtp.port", 25));
        out.write("\n\n                ");
        if (JiveGlobals.getBooleanProperty("mail.smtp.ssl", false)) {
          out.write("\n\n                    (");
          if (_jspx_meth_fmt_message_8(_jspx_page_context)) return;
          out.write(")\n\n                ");
        }
        out.write("\n            ");
      }
      out.write("\n        </td>\n    </tr>\n    <tr>\n        <td>\n            ");
      if (_jspx_meth_fmt_message_9(_jspx_page_context)) return;
      out.write(
          ":\n        </td>\n        <td>\n            <input type=\"hidden\" name=\"from\" value=\"");
      out.print(from);
      out.write("\">\n            ");
      out.print(StringUtils.escapeHTMLTags(from));
      out.write(
          "\n            <span class=\"jive-description\">\n            (<a href=\"user-edit-form.jsp?username="******"\">Update Address</a>)\n            </span>\n        </td>\n    </tr>\n    <tr>\n        <td>\n            ");
      if (_jspx_meth_fmt_message_10(_jspx_page_context)) return;
      out.write(
          ":\n        </td>\n        <td>\n            <input type=\"text\" name=\"to\" value=\"");
      out.print(((to != null) ? to : ""));
      out.write(
          "\"\n             size=\"40\" maxlength=\"100\">\n        </td>\n    </tr>\n    <tr>\n        <td>\n            ");
      if (_jspx_meth_fmt_message_11(_jspx_page_context)) return;
      out.write(
          ":\n        </td>\n        <td>\n            <input type=\"text\" name=\"subject\" value=\"");
      out.print(((subject != null) ? subject : ""));
      out.write(
          "\"\n             size=\"40\" maxlength=\"100\">\n        </td>\n    </tr>\n    <tr valign=\"top\">\n        <td>\n            ");
      if (_jspx_meth_fmt_message_12(_jspx_page_context)) return;
      out.write(
          ":\n        </td>\n        <td>\n            <textarea name=\"body\" cols=\"45\" rows=\"5\" wrap=\"virtual\">");
      out.print(body);
      out.write(
          "</textarea>\n        </td>\n    </tr>\n    <tr>\n        <td colspan=\"2\">\n            <br>\n            <input type=\"submit\" name=\"test\" value=\"");
      if (_jspx_meth_fmt_message_13(_jspx_page_context)) return;
      out.write("\">\n            <input type=\"submit\" name=\"cancel\" value=\"");
      if (_jspx_meth_fmt_message_14(_jspx_page_context)) return;
      out.write(
          "\">\n        </td>\n    </tr>\n</tbody>\n</table>\n\n</form>\n\n    </body>\n</html>");
    } catch (Throwable t) {
      if (!(t instanceof SkipPageException)) {
        out = _jspx_out;
        if (out != null && out.getBufferSize() != 0) out.clearBuffer();
        if (_jspx_page_context != null) _jspx_page_context.handlePageException(t);
      }
    } finally {
      if (_jspxFactory != null) _jspxFactory.releasePageContext(_jspx_page_context);
    }
  }
  /**
   * Creates a new session that will receive packets. The new session will be authenticated before
   * being returned. If the authentication process fails then the answer will be <tt>null</tt>.
   *
   * <p>
   *
   * @param serverName hostname of this server.
   * @param reader reader on the new established connection with the remote server.
   * @param connection the new established connection with the remote server.
   * @return a new session that will receive packets or null if a problem occured while
   *     authenticating the remote server or when acting as the Authoritative Server during a Server
   *     Dialback authentication process.
   * @throws org.xmlpull.v1.XmlPullParserException if an error occurs while parsing the XML.
   * @throws java.io.IOException if an input/output error occurs while using the connection.
   */
  public static LocalIncomingServerSession createSession(
      String serverName, XMPPPacketReader reader, SocketConnection connection)
      throws XmlPullParserException, IOException {
    XmlPullParser xpp = reader.getXPPParser();

    String version = xpp.getAttributeValue("", "version");
    int[] serverVersion = version != null ? decodeVersion(version) : new int[] {0, 0};

    try {
      // Get the stream ID for the new session
      StreamID streamID = SessionManager.getInstance().nextStreamID();
      // Create a server Session for the remote server
      LocalIncomingServerSession session =
          SessionManager.getInstance().createIncomingServerSession(connection, streamID);

      // Send the stream header
      StringBuilder openingStream = new StringBuilder();
      openingStream.append("<stream:stream");
      openingStream.append(" xmlns:db=\"jabber:server:dialback\"");
      openingStream.append(" xmlns:stream=\"http://etherx.jabber.org/streams\"");
      openingStream.append(" xmlns=\"jabber:server\"");
      openingStream.append(" from=\"").append(serverName).append("\"");
      openingStream.append(" id=\"").append(streamID).append("\"");
      openingStream.append(" version=\"1.0\">");
      connection.deliverRawText(openingStream.toString());

      if (serverVersion[0] >= 1) {
        // Remote server is XMPP 1.0 compliant so offer TLS and SASL to establish the connection
        // (and server dialback)

        // Indicate the TLS policy to use for this connection
        Connection.TLSPolicy tlsPolicy =
            ServerDialback.isEnabled()
                ? Connection.TLSPolicy.optional
                : Connection.TLSPolicy.required;
        boolean hasCertificates = false;
        try {
          hasCertificates = SSLConfig.getKeyStore().size() > 0;
        } catch (Exception e) {
          Log.error(e.getMessage(), e);
        }
        if (Connection.TLSPolicy.required == tlsPolicy && !hasCertificates) {
          Log.error(
              "Server session rejected. TLS is required but no certificates " + "were created.");
          return null;
        }
        connection.setTlsPolicy(hasCertificates ? tlsPolicy : Connection.TLSPolicy.disabled);
      }

      // Indicate the compression policy to use for this connection
      String policyName =
          JiveGlobals.getProperty(
              "xmpp.server.compression.policy", Connection.CompressionPolicy.disabled.toString());
      Connection.CompressionPolicy compressionPolicy =
          Connection.CompressionPolicy.valueOf(policyName);
      connection.setCompressionPolicy(compressionPolicy);

      StringBuilder sb = new StringBuilder();

      if (serverVersion[0] >= 1) {
        // Remote server is XMPP 1.0 compliant so offer TLS and SASL to establish the connection
        // (and server dialback)
        // Don't offer stream-features to pre-1.0 servers, as it confuses them. Sending features to
        // Openfire < 3.7.1 confuses it too - OF-443)
        sb.append("<stream:features>");

        if (JiveGlobals.getBooleanProperty("xmpp.server.tls.enabled", true)) {
          sb.append("<starttls xmlns=\"urn:ietf:params:xml:ns:xmpp-tls\">");
          if (!ServerDialback.isEnabled()) {
            // Server dialback is disabled so TLS is required
            sb.append("<required/>");
          }
          sb.append("</starttls>");
        }

        // Include available SASL Mechanisms
        sb.append(SASLAuthentication.getSASLMechanisms(session));

        if (ServerDialback.isEnabled()) {
          // Also offer server dialback (when TLS is not required). Server dialback may be offered
          // after TLS has been negotiated and a self-signed certificate is being used
          sb.append("<dialback xmlns=\"urn:xmpp:features:dialback\"/>");
        }

        sb.append("</stream:features>");
      }

      connection.deliverRawText(sb.toString());

      // Set the domain or subdomain of the local server targeted by the remote server
      session.setLocalDomain(serverName);
      return session;
    } catch (Exception e) {
      Log.error("Error establishing connection from remote server:" + connection, e);
      connection.close();
      return null;
    }
  }
 /**
  * Returns the default secret key that connection managers should present while trying to
  * establish a new connection.
  *
  * @return the default secret key that connection managers should present while trying to
  *     establish a new connection.
  */
 public static String getDefaultSecret() {
   return JiveGlobals.getProperty("xmpp.multiplex.defaultSecret");
 }
Example #26
0
  /**
   * Create an XMPP Session instance.
   *
   * @param registration Registration information used for logging in.
   * @param jid JID associated with this session.
   * @param transport Transport instance associated with this session.
   * @param priority Priority of this session.
   */
  public XMPPSession(
      Registration registration, JID jid, XMPPTransport transport, Integer priority) {
    super(registration, jid, transport, priority);
    setSupportedFeature(SupportedFeature.attention);
    setSupportedFeature(SupportedFeature.chatstates);

    Log.debug(
        "Creating " + getTransport().getType() + " session for " + registration.getUsername());
    String connecthost;
    Integer connectport;
    String domain;

    connecthost =
        JiveGlobals.getProperty(
            "plugin.gateway." + getTransport().getType() + ".connecthost",
            (getTransport().getType().equals(TransportType.gtalk)
                ? "talk.google.com"
                : getTransport().getType().equals(TransportType.facebook)
                    ? "chat.facebook.com"
                    : "jabber.org"));
    connectport =
        JiveGlobals.getIntProperty(
            "plugin.gateway." + getTransport().getType() + ".connectport", 5222);

    if (getTransport().getType().equals(TransportType.gtalk)) {
      domain = "gmail.com";
    } else if (getTransport().getType().equals(TransportType.facebook)) {
      // if (connecthost.equals("www.facebook.com")) {
      connecthost = "chat.facebook.com";
      // }
      // if (connectport.equals(80)) {
      connectport = 5222;
      // }
      domain = "chat.facebook.com";
    } else if (getTransport().getType().equals(TransportType.renren)) {
      connecthost = "talk.renren.com";
      connectport = 5222;
      domain = "renren.com";
    } else {
      domain = connecthost;
    }

    // For different domains other than 'gmail.com', which is given with Google Application services
    if (registration.getUsername().indexOf("@") > -1) {
      domain = registration.getUsername().substring(registration.getUsername().indexOf("@") + 1);
    }

    // If administrator specified "*" for domain, allow user to connect to anything.
    if (connecthost.equals("*")) {
      connecthost = domain;
    }

    config = new ConnectionConfiguration(connecthost, connectport, domain);
    config.setCompressionEnabled(
        JiveGlobals.getBooleanProperty(
            "plugin.gateway." + getTransport().getType() + ".usecompression", false));

    if (getTransport().getType().equals(TransportType.facebook)) {
      // SASLAuthentication.supportSASLMechanism("PLAIN", 0);
      // config.setSASLAuthenticationEnabled(false);
      // config.setSecurityMode(ConnectionConfiguration.SecurityMode.enabled);
    }

    // instead, send the initial presence right after logging in. This
    // allows us to use a different presence mode than the plain old
    // 'available' as initial presence.
    config.setSendPresence(false);

    if (getTransport().getType().equals(TransportType.gtalk)
        && JiveGlobals.getBooleanProperty("plugin.gateway.gtalk.mailnotifications", true)) {
      ProviderManager.getInstance()
          .addIQProvider(
              GoogleMailBoxPacket.MAILBOX_ELEMENT,
              GoogleMailBoxPacket.MAILBOX_NAMESPACE,
              new GoogleMailBoxPacket.Provider());
      ProviderManager.getInstance()
          .addExtensionProvider(
              GoogleNewMailExtension.ELEMENT_NAME,
              GoogleNewMailExtension.NAMESPACE,
              new GoogleNewMailExtension.Provider());
    }
  }