diff --git a/docs/threepids/notification/template-generator.md b/docs/threepids/notification/template-generator.md index 0f157c1..f8a148e 100644 --- a/docs/threepids/notification/template-generator.md +++ b/docs/threepids/notification/template-generator.md @@ -19,29 +19,33 @@ All placeholders **MUST** be surrounded with `%` in the template. Per example, t ### Global The following placeholders are available in every template: -| Placeholder | Purpose | -|---------------------|------------------------------------------------------------------------------| -| `DOMAIN` | Identity server authoritative domain, as configured in `matrix.domain` | -| `DOMAIN_PRETTY` | Same as `DOMAIN` with the first letter upper case and all other lower case | -| `FROM_EMAIL` | Email address configured in `threepid.medium.<3PID medium>.identity.from` | -| `FROM_NAME` | Name configured in `threepid.medium.<3PID medium>.identity.name` | -| `RECIPIENT_MEDIUM` | The 3PID medium, like `email` or `msisdn` | -| `RECIPIENT_ADDRESS` | The address to which the notification is sent | +| Placeholder | Purpose | +|---------------------------------|------------------------------------------------------------------------------| +| `DOMAIN` | Identity server authoritative domain, as configured in `matrix.domain` | +| `DOMAIN_PRETTY` | Same as `DOMAIN` with the first letter upper case and all other lower case | +| `FROM_EMAIL` | Email address configured in `threepid.medium.<3PID medium>.identity.from` | +| `FROM_NAME` | Name configured in `threepid.medium.<3PID medium>.identity.name` | +| `RECIPIENT_MEDIUM` | The 3PID medium, like `email` or `msisdn` | +| `RECIPIENT_MEDIUM_URL_ENCODED` | URL encoded value of `RECIPIENT_MEDIUM` | +| `RECIPIENT_ADDRESS` | The address to which the notification is sent | +| `RECIPIENT_ADDRESS_URL_ENCODED` | URL encoded value of `RECIPIENT_ADDRESS` | ### Room invitation Specific placeholders: -| Placeholder | Purpose | -|---------------------|------------------------------------------------------------------------------------------| -| `SENDER_ID` | Matrix ID of the user who made the invite | -| `SENDER_NAME` | Display name of the user who made the invite, if not available/set, empty | -| `SENDER_NAME_OR_ID` | Display name of the user who made the invite. If not available/set, its Matrix ID | -| `INVITE_MEDIUM` | The 3PID medium for the invite. | -| `INVITE_ADDRESS` | The 3PID address for the invite. | -| `ROOM_ID` | The Matrix ID of the Room in which the invite took place | -| `ROOM_NAME` | The Name of the room in which the invite took place. If not available/set, empty | -| `ROOM_NAME_OR_ID` | The Name of the room in which the invite took place. If not available/set, its Matrix ID | -| `REGISTER_URL` | The URL to provide to the user allowing them to register their account, if needed | +| Placeholder | Purpose | +|------------------------------|-----------------------------------------------------------------------------------| +| `SENDER_ID` | Matrix ID of the user who made the invite | +| `SENDER_NAME` | Display name of the user who made the invite, if not available/set, empty | +| `SENDER_NAME_OR_ID` | Display name of the user who made the invite. If not available/set, its Matrix ID | +| `INVITE_MEDIUM` | The 3PID medium for the invite. | +| `INVITE_MEDIUM_URL_ENCODED` | URL encoded value of `INVITE_MEDIUM` | +| `INVITE_ADDRESS` | The 3PID address for the invite. | +| `INVITE_ADDRESS_URL_ENCODED` | URL encoded value of `INVITE_ADDRESS` | +| `ROOM_ID` | The Matrix ID of the Room in which the invite took place | +| `ROOM_NAME` | The Name of the room in which the invite took place. If not available/set, empty | +| `ROOM_NAME_OR_ID` | The Name of the room in which the invite took place. If not available/set, its ID | +| `REGISTER_URL` | The URL to provide to the user allowing them to register their account, if needed | ### Validation of 3PID Session Specific placeholders: diff --git a/src/main/java/io/kamax/mxisd/threepid/generator/PlaceholderNotificationGenerator.java b/src/main/java/io/kamax/mxisd/threepid/generator/PlaceholderNotificationGenerator.java index 40ba9f5..14849c1 100644 --- a/src/main/java/io/kamax/mxisd/threepid/generator/PlaceholderNotificationGenerator.java +++ b/src/main/java/io/kamax/mxisd/threepid/generator/PlaceholderNotificationGenerator.java @@ -27,6 +27,7 @@ import io.kamax.mxisd.http.IsAPIv1; import io.kamax.mxisd.invitation.IMatrixIdInvite; import io.kamax.mxisd.invitation.IThreePidInviteReply; import io.kamax.mxisd.threepid.session.IThreePidSession; +import io.kamax.mxisd.util.RestClientUtils; import org.apache.commons.lang.WordUtils; import org.apache.commons.lang3.StringUtils; @@ -56,7 +57,9 @@ public abstract class PlaceholderNotificationGenerator { .replace("%DOMAIN%", mxCfg.getDomain()) .replace("%DOMAIN_PRETTY%", domainPretty) .replace("%RECIPIENT_MEDIUM%", recipient.getMedium()) - .replace("%RECIPIENT_ADDRESS%", recipient.getAddress()); + .replace("%RECIPIENT_MEDIUM_URL_ENCODED%", RestClientUtils.urlEncode(recipient.getMedium())) + .replace("%RECIPIENT_ADDRESS%", recipient.getAddress()) + .replace("%RECIPIENT_ADDRESS_URL_ENCODED%", RestClientUtils.urlEncode(recipient.getAddress())); } protected String populateForInvite(IMatrixIdInvite invite, String input) { @@ -98,7 +101,9 @@ public abstract class PlaceholderNotificationGenerator { .replace("%SENDER_NAME%", senderName) .replace("%SENDER_NAME_OR_ID%", senderNameOrId) .replace("%INVITE_MEDIUM%", tpid.getMedium()) + .replace("%INVITE_MEDIUM_URL_ENCODED%", RestClientUtils.urlEncode(tpid.getMedium())) .replace("%INVITE_ADDRESS%", tpid.getAddress()) + .replace("%INVITE_ADDRESS_URL_ENCODED%", RestClientUtils.urlEncode(tpid.getAddress())) .replace("%ROOM_ID%", invite.getInvite().getRoomId()) .replace("%ROOM_NAME%", roomName) .replace("%ROOM_NAME_OR_ID%", roomNameOrId); diff --git a/src/main/java/io/kamax/mxisd/util/RestClientUtils.java b/src/main/java/io/kamax/mxisd/util/RestClientUtils.java index ca20b98..bf8aad1 100644 --- a/src/main/java/io/kamax/mxisd/util/RestClientUtils.java +++ b/src/main/java/io/kamax/mxisd/util/RestClientUtils.java @@ -25,12 +25,22 @@ import org.apache.http.client.methods.HttpPost; import org.apache.http.entity.ContentType; import org.apache.http.entity.StringEntity; +import java.io.UnsupportedEncodingException; +import java.net.URLEncoder; import java.nio.charset.StandardCharsets; public class RestClientUtils { private static Gson gson = GsonUtil.build(); + public static String urlEncode(String value) { + try { + return URLEncoder.encode(value, StandardCharsets.UTF_8.name()); + } catch (UnsupportedEncodingException e) { + throw new RuntimeException(e); + } + } + public static HttpPost post(String url, String body) { StringEntity entity = new StringEntity(body, StandardCharsets.UTF_8); entity.setContentType(ContentType.APPLICATION_JSON.toString()); diff --git a/src/test/java/io/kamax/mxisd/test/util/RestClientUtilsTest.java b/src/test/java/io/kamax/mxisd/test/util/RestClientUtilsTest.java new file mode 100644 index 0000000..abf4b6c --- /dev/null +++ b/src/test/java/io/kamax/mxisd/test/util/RestClientUtilsTest.java @@ -0,0 +1,36 @@ +/* + * mxisd - Matrix Identity Server Daemon + * Copyright (C) 2019 Kamax Sarl + * + * https://www.kamax.io/ + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package io.kamax.mxisd.test.util; + +import io.kamax.mxisd.util.RestClientUtils; +import org.junit.Test; + +import static org.junit.Assert.assertEquals; + +public class RestClientUtilsTest { + + @Test + public void urlEncode() { + String encoded = RestClientUtils.urlEncode("john+doe@example.org"); + assertEquals("john%2Bdoe%40example.org", encoded); + } + +}