Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

OF-2211 JDBCVCardProvider implementation. #1818

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions i18n/src/main/resources/openfire_i18n.properties
Original file line number Diff line number Diff line change
Expand Up @@ -1684,6 +1684,7 @@ system_property.xmpp.server.outgoing.threads-timeout=Amount of time after which
system_property.xmpp.server.outgoing.queue=Maximum amount of outbound server-to-server connections that can be in process of establishment in the thread pool (surplus connections will be created on the calling thread, possibly / gracefully slowing down other operations considerably)
system_property.cluster-monitor.service-enabled=Set to true to send messages to admins on cluster events, otherwise false
system_property.ldap.override.avatar=Set to true to save avatars in the local database, otherwise false
system_property.jdbc.override.avatar=Set to true to save avatars in the local database, otherwise false
system_property.xmpp.domain=The XMPP domain of this server. Do not change this property directly, instead re-run the setup process.
system_property.plugins.upload.magic-number.values.enabled=Enables verification of 'magic bytes' when processing uploaded data that is expected to be an Openfire plugin.
system_property.plugins.upload.magic-number.values.expected-value=A list of hexadecimal representations of 'magic byte' sequences that can be used to identify an uploaded plugin file.
Expand Down
1 change: 1 addition & 0 deletions i18n/src/main/resources/openfire_i18n_de.properties
Original file line number Diff line number Diff line change
Expand Up @@ -1171,6 +1171,7 @@ system_property.xmpp.client.idle.ping=Auf true setzen, um inaktive Clients anzup
system_property.cluster-monitor.service-enabled=Auf true setzen, um Nachrichten an Administratoren bei \
Cluster-Ereignissen zu senden, ansonsten false.
system_property.ldap.override.avatar=Auf true setzen, um Avatare in der lokalen Datenbank zu speichern, ansonsten false.
system_property.jdbc.override.avatar=Auf true setzen, um Avatare in der lokalen Datenbank zu speichern, ansonsten false.
system_property.xmpp.domain=Die XMPP-Domäne dieses Servers. Ändern Sie diese Eigenschaft nicht direkt, \
sondern führen Sie den Setup-Prozess erneut aus.
system_property.provider.admin.className=Die Klasse, die verwendet werden soll, um Openfire-Administratoren zu \
Expand Down
1 change: 1 addition & 0 deletions i18n/src/main/resources/openfire_i18n_es.properties
Original file line number Diff line number Diff line change
Expand Up @@ -1144,6 +1144,7 @@ system_property.xmpp.client.idle=Tiempo en milisegundos hasta que las sesiones i
system_property.xmpp.client.idle.ping=Configurar en true para hacer ping a los clientes, en otro caso en false
system_property.cluster-monitor.service-enabled=Configurar en true para enviar mensajes a los administradores en caso de ocurrir eventos con el cluster, en otro caso false
system_property.ldap.override.avatar=Configurar en true para guardar avatares en la base de datos local, en otro caso false
system_property.jdbc.override.avatar=Configurar en true para guardar avatares en la base de datos local, en otro caso false
system_property.xmpp.domain=El dominio XMPP de este servidor. No cambie esta propiedad directamente, en su lugar ejecute nuevamente el proceso de instalación.
system_property.provider.admin.className=La clase a usar para autorizar administradores de Openfire
system_property.provider.group.className=La clase a usar para determinar los grupos de los usuarios de Openfire
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@
import org.jivesoftware.openfire.vcard.PhotoResizer;
import org.jivesoftware.openfire.vcard.VCardManager;
import org.jivesoftware.openfire.vcard.VCardProvider;
import org.jivesoftware.openfire.vcard.VCardTemplate;
import org.jivesoftware.openfire.vcard.VCard;
import org.jivesoftware.util.Base64;
import org.jivesoftware.util.*;
import org.slf4j.Logger;
Expand All @@ -33,8 +35,6 @@
import javax.naming.directory.DirContext;
import javax.naming.ldap.Rdn;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
* Read-only LDAP provider for vCards.Configuration consists of adding a provider:
Expand Down Expand Up @@ -124,11 +124,6 @@ public class LdapVCardProvider implements VCardProvider, PropertyEventListener {
*/
private DefaultVCardProvider defaultProvider = null;

/**
* A regular expression that matches values enclosed in { and }, applying a group to the value that's surrounded.
*/
public static final Pattern PATTERN = Pattern.compile("(\\{)([\\d\\D&&[^}]]+)(})");

public LdapVCardProvider() {
// Convert XML based provider setup to Database based
JiveGlobals.migrateProperty("ldap.vcard-mapping");
Expand Down Expand Up @@ -473,128 +468,4 @@ public void xmlPropertySet(String property, Map params) {
public void xmlPropertyDeleted(String property, Map params) {
//Ignore
}

/**
* Class to hold a <code>Document</code> representation of a vcard mapping
* and unique attribute placeholders. Used by <code>VCard</code> to apply
* a <code>Map</code> of ldap attributes to ldap values via
* <code>MessageFormat</code>
*
* @author rkelly
*/
static class VCardTemplate {

private Document document;

private String[] attributes;

public VCardTemplate(Document document) {
Set<String> set = new HashSet<>();
this.document = document;
treeWalk(this.document.getRootElement(), set);
attributes = set.toArray(new String[0]);
}

public String[] getAttributes() {
return attributes;
}

public Document getDocument() {
return document;
}

private void treeWalk(Element rootElement, Set<String> set) {
for ( final Element element : rootElement.elements() ) {
final String value = element.getTextTrim();
if ( value != null && !value.isEmpty()) {
final Matcher matcher = PATTERN.matcher(value);
while (matcher.find()) {
final String match = matcher.group(2);
Log.trace("Found attribute '{}'", match);
set.add(match);
}
}
treeWalk(element, set);
}
}
}

/**
* vCard class that converts vcard data using a template.
*/
static class VCard {

private VCardTemplate template;

public VCard(VCardTemplate template) {
this.template = template;
}

public Element getVCard(Map<String, String> map) {
Document document = (Document) template.getDocument().clone();
Element element = document.getRootElement();
return treeWalk(element, map);
}

private Element treeWalk(Element rootElement, Map<String, String> map) {
for ( final Element element : rootElement.elements() ) {
String elementText = element.getTextTrim();
if (elementText != null && !"".equals(elementText)) {
String format = element.getStringValue();

// A map that will hold all replacements for placeholders
final Map<String,String> replacements = new HashMap<>();

// find all placeholders, and look up what they should be replaced with.
final Matcher matcher = PATTERN.matcher(format);
while (matcher.find()) {
final String group = matcher.group();
final String attribute = matcher.group(2);
final String value = map.get(attribute);
replacements.put( group, value );
}

// perform the replacement.
for ( Map.Entry<String, String> entry : replacements.entrySet() ) {
final String placeholder = entry.getKey();
final String replacement = entry.getValue() != null ? entry.getValue() : "";
format = format.replace(placeholder, replacement);
Log.trace("Replaced attribute '{}' with '{}'", placeholder, replacement);
}

// When 'prioritized' replacements are used, the resulting value now will have those filled out:
// example: (|()(valueB)(valueC))
// From this format, only the first non-empty value enclosed in brackets needs to be used.
final int start = format.indexOf("(|(");
final int end = format.indexOf("))");
if ( start > -1 && end > start ) {
// Take the substring that is: (|()(valueB)(valueC))
final String filter = format.substring(start, end + "))".length());

// Take the substring that is: )(valueB)(valueC
final String values = filter.substring("(|(".length(), filter.length() - "))".length() );

// Split on ")(" to get the individual values.
final String[] splitted = values.split("\\)\\(");

// find the first non-empty string.
String firstValue = "";
for ( final String split : splitted ) {
if ( split != null && !split.isEmpty() ) {
firstValue = split;
break;
}
}

// Replace the original filter with just the first matching value.
format = format.replace(filter, firstValue);
}

element.setText(format);
}
treeWalk(element, map);
}
return rootElement;
}
}
}
Loading