Skip to content

Commit a19b62d

Browse files
authored
Merge pull request #385 from Adobe-Marketing-Cloud/develop
v1.7.0 Release
2 parents dd113f9 + 7a3e49c commit a19b62d

File tree

53 files changed

+936
-155
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

53 files changed

+936
-155
lines changed

CHANGELOG.md

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,23 @@ All notable changes to this project will be documented in this file.
44
The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/)
55
and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html).
66

7+
## [v1.7.0]
8+
9+
### Fixed
10+
- 0163: User menu disappears when the profile is aleady loaded in previeous requests
11+
- 0340/0358: Corrected URL escaping to handle paths/assets file names using extended and unusual characters.
12+
- 0381: Fixed updating of dynamic service references to multiple share services
13+
14+
### Changed
15+
- 0359: Expanded org.apache.sling.xss to [1.2.0,3) to support AEM 6.5 (uses version 2.0.1) and removed unneeded legacy acom.adobe.acs.commons.email;resolution:=optional import.
16+
- 0374: Added ability to add extra or blacklist Metadata Properties from the Metadata Properties DataSource via OSGi configuration
17+
- 0376: Replaced use of com.adobe.cq.commerce.common.ValueMapDecorator with org.apache.sling.api.wrappers.ValueMapDecorator
18+
- 0378: Date range filter includes the end date (evaluated at 12:59:59PM)
19+
20+
### Added
21+
- 0366: Use sharer email as Reply-To when sharing assets via email
22+
- 0371: Added Horizontal Masonry Card results.
23+
724
## [v1.6.12]
825

926
### Fixed

core/pom.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -172,7 +172,7 @@
172172
<exportScr>true</exportScr>
173173
<instructions>
174174
<Import-Package>
175-
com.adobe.acs.commons.email;resolution:=optional,
175+
org.apache.sling.xss;version="[1.2,3)",
176176
*
177177
</Import-Package>
178178
<_plugin>org.apache.sling.bnd.models.ModelsScannerPlugin</_plugin>

core/src/main/java/com/adobe/aem/commons/assetshare/components/actions/impl/ActionHelperImpl.java

Lines changed: 2 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,6 @@
2222
import com.adobe.aem.commons.assetshare.components.actions.ActionHelper;
2323
import com.adobe.aem.commons.assetshare.configuration.Config;
2424
import com.adobe.aem.commons.assetshare.content.AssetModel;
25-
import com.adobe.granite.asset.api.AssetException;
2625
import com.day.cq.wcm.api.WCMMode;
2726
import org.apache.sling.api.SlingHttpServletRequest;
2827
import org.apache.sling.api.request.RequestParameter;
@@ -31,10 +30,6 @@
3130
import org.osgi.service.component.annotations.Component;
3231
import org.osgi.service.component.annotations.Reference;
3332

34-
import javax.net.ssl.StandardConstants;
35-
import java.io.UnsupportedEncodingException;
36-
import java.net.URLDecoder;
37-
import java.nio.charset.StandardCharsets;
3833
import java.util.ArrayList;
3934
import java.util.Collection;
4035

@@ -50,22 +45,14 @@ public final Collection<AssetModel> getAssetsFromQueryParameter(final SlingHttpS
5045

5146
if (requestParameters != null) {
5247
for (final RequestParameter requestParameter : requestParameters) {
53-
String path = requestParameter.getString();
54-
55-
try {
56-
path = URLDecoder.decode(path, StandardCharsets.UTF_8.name());
57-
} catch (UnsupportedEncodingException ex) {
58-
throw new AssetException("Could not UTF-8 encode the asset path.", requestParameter.getString());
59-
}
60-
61-
final Resource resource = request.getResourceResolver().getResource(path);
48+
final Resource resource = request.getResourceResolver().getResource(requestParameter.getString());
6249
if (resource != null) {
6350
final AssetModel asset = modelFactory.getModelFromWrappedRequest(request, resource, AssetModel.class);
51+
6452
if (asset != null) {
6553
assets.add(asset);
6654
}
6755
}
68-
6956
}
7057
}
7158

core/src/main/java/com/adobe/aem/commons/assetshare/components/actions/share/EmailShare.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,8 @@ public interface EmailShare extends Share {
2929

3030
String PN_USE_SHARER_NAME_AS_SIGNATURE = "useSharerSignature";
3131

32+
String PN_USE_SHARER_EMAIL_AS_REPLY_TO = "replyToSharer";
33+
3234
/**
3335
* For example, in the default ASC Email Share implementation, this is the valuemap for the Email Share Modal Component.
3436
*

core/src/main/java/com/adobe/aem/commons/assetshare/components/actions/share/ShareException.java

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ public class ShareException extends Exception {
2626
/**
2727
* Creates a new ShareException with a custom message.
2828
*
29-
* @param message the exception messsage.
29+
* @param message the exception message.
3030
*/
3131
public ShareException(String message) {
3232
super(message);
@@ -40,4 +40,15 @@ public ShareException(String message) {
4040
public ShareException(Exception e) {
4141
super(e);
4242
}
43+
44+
/**
45+
* Creates a new ShareException with a custom message.
46+
*
47+
* @param message the exception message.
48+
* @param ex the cause exception
49+
*/
50+
public ShareException(String message, Throwable ex) {
51+
super(message, ex);
52+
}
53+
4354
}

core/src/main/java/com/adobe/aem/commons/assetshare/components/actions/share/impl/EmailShareServiceImpl.java

Lines changed: 76 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -39,13 +39,16 @@
3939
import com.adobe.granite.security.user.UserProperties;
4040
import com.adobe.granite.security.user.UserPropertiesManager;
4141
import com.day.cq.commons.Externalizer;
42+
import com.day.cq.dam.api.Asset;
4243
import com.day.cq.dam.commons.util.DamUtil;
44+
import com.day.text.Text;
4345
import org.apache.commons.lang3.ArrayUtils;
4446
import org.apache.commons.lang3.StringUtils;
4547
import org.apache.jackrabbit.api.security.user.Authorizable;
4648
import org.apache.sling.api.SlingHttpServletRequest;
4749
import org.apache.sling.api.SlingHttpServletResponse;
4850
import org.apache.sling.api.resource.Resource;
51+
import org.apache.sling.api.resource.ResourceResolver;
4952
import org.apache.sling.api.resource.ValueMap;
5053
import org.apache.sling.api.scripting.SlingBindings;
5154
import org.apache.sling.models.factory.ModelFactory;
@@ -111,13 +114,14 @@ public boolean accepts(final SlingHttpServletRequest request) {
111114

112115
@Override
113116
public final void share(final SlingHttpServletRequest request, final SlingHttpServletResponse response, final ValueMap shareParameters) throws ShareException {
114-
117+
115118
/** Work around for regression issue introduced in AEM 6.4 **/
116119
SlingBindings bindings = new SlingBindings();
117120
//intentionally setting the second argument to 'null' since there is no SlingScript to pass in
118121
bindings.setSling( new ScriptHelper(bundleContext, null, request, response));
119122
request.setAttribute(SlingBindings.class.getName(), bindings);
120-
123+
UserProperties userProperties = getUserProperties(request);
124+
121125
final EmailShare emailShare = request.adaptTo(EmailShare.class);
122126

123127
shareParameters.putAll(xssProtectUserData(emailShare.getUserData()));
@@ -126,10 +130,12 @@ public final void share(final SlingHttpServletRequest request, final SlingHttpSe
126130
shareParameters.putAll(emailShare.getConfiguredData());
127131

128132
// Except for signature which we may or may not want to use from configured data, depending on flags in configured data
129-
try {
130-
shareParameters.put(SIGNATURE, getSignature(request));
131-
} catch (RepositoryException e) {
132-
throw new ShareException("Could not obtain user display name for " + request.getResourceResolver().getUserID());
133+
shareParameters.put(SIGNATURE, getSignature(emailShare, userProperties));
134+
135+
// set reply to address, if any
136+
String replyToAddress = getReplyToAddress(emailShare, userProperties);
137+
if (StringUtils.isNotEmpty(replyToAddress)) {
138+
shareParameters.put(EmailService.REPLY_TO, replyToAddress);
133139
}
134140

135141
share(request.adaptTo(Config.class), shareParameters, StringUtils.defaultIfBlank(emailShare.getEmailTemplatePath(), cfg.emailTemplate()));
@@ -138,14 +144,12 @@ public final void share(final SlingHttpServletRequest request, final SlingHttpSe
138144
private final void share(final Config config, final ValueMap shareParameters, final String emailTemplatePath) throws ShareException {
139145
final String[] emailAddresses = StringUtils.split(shareParameters.get(EMAIL_ADDRESSES, ""), ",");
140146
final String[] assetPaths = Arrays.stream(shareParameters.get(ASSET_PATHS, ArrayUtils.EMPTY_STRING_ARRAY))
141-
.map(path -> {
142-
try {
143-
return URLDecoder.decode(path, StandardCharsets.UTF_8.name());
144-
} catch (UnsupportedEncodingException e) {
145-
log.warn("Could not decode path [ {} ] as UTF-8; Using path as is,.", path);
146-
return path;
147-
}
148-
}).filter(StringUtils::isNotBlank)
147+
.filter(StringUtils::isNotBlank)
148+
.map(path -> config.getResourceResolver().getResource(path))
149+
.filter(Objects::nonNull)
150+
.map(DamUtil::resolveToAsset)
151+
.filter(Objects::nonNull)
152+
.map(Asset::getPath)
149153
.toArray(String[]::new);
150154

151155
// Check to ensure the minimum set of e-mail parameters are provided; Throw exception if not.
@@ -154,7 +158,7 @@ private final void share(final Config config, final ValueMap shareParameters, fi
154158
} else if (ArrayUtils.isEmpty(assetPaths)) {
155159
throw new ShareException("At least one asset is required to share");
156160
}
157-
161+
158162
// Convert provided params to <String, String>; anything that needs to be accessed in its native type should be accessed and manipulated via shareParameters.get(..)
159163
final Map<String, String> emailParameters = new HashMap<String, String>();
160164
for (final String key : shareParameters.keySet()) {
@@ -179,13 +183,18 @@ private final String getAssetLinkListHtml(final Config config, final String[] as
179183
if (assetResource != null && DamUtil.isAsset(assetResource)) {
180184
final AssetModel asset = modelFactory.getModelFromWrappedRequest(config.getRequest(), assetResource, AssetModel.class);
181185

186+
// Unescape else gets double-escaped and the link breaks
182187
String url = assetDetailsResolver.getFullUrl(config, asset);
183188

184189
if (StringUtils.isBlank(url)) {
185190
log.warn("Could not determine an Asset Details page path for asset at [ {} ]", assetPath);
186191
continue;
187192
}
188193

194+
// Unescape the URL since externalizer also escapes, resulting in a breaking, double-escaped URLs
195+
// This is required since assetDetailsResolver.getFullUrl(config, asset) performs its own escaping.
196+
url = Text.unescape(url);
197+
189198
if (isAuthor()) {
190199
url = externalizer.authorLink(config.getResourceResolver(), url);
191200
} else {
@@ -209,29 +218,64 @@ public boolean isAuthor() {
209218
return slingSettingsService.getRunModes().contains("author");
210219
}
211220

212-
private String getSignature(final SlingHttpServletRequest request) throws RepositoryException {
213-
if (request == null) {
214-
return cfg.signature();
221+
private String getSignature(final EmailShare emailShare, final UserProperties userProperties) throws ShareException {
222+
boolean useSharerDisplayNameAsSignature = emailShare.getProperties().get(EmailShareImpl.PN_USE_SHARER_NAME_AS_SIGNATURE, false);
223+
224+
if (useSharerDisplayNameAsSignature && userProperties != null) {
225+
try {
226+
return StringUtils.trimToNull(userProperties.getDisplayName());
227+
}
228+
catch (RepositoryException ex) {
229+
throw new ShareException("Could not obtain user display name for '" + userProperties.getAuthorizableID() + "'", ex);
230+
}
215231
}
216232

217-
final EmailShare emailShare = request.adaptTo(EmailShare.class);
233+
return StringUtils.defaultIfBlank(emailShare.getConfiguredData().get(EmailShareImpl.PN_SIGNATURE, String.class), cfg.signature());
234+
}
218235

219-
boolean useSharerDisplayNameAsSignature = emailShare.getProperties().get(EmailShareImpl.PN_USE_SHARER_NAME_AS_SIGNATURE, false);
236+
private String getReplyToAddress(final EmailShare emailShare, final UserProperties userProperties) throws ShareException {
237+
boolean replyToSharer = emailShare.getProperties().get(EmailShare.PN_USE_SHARER_EMAIL_AS_REPLY_TO, false);
238+
if (replyToSharer && userProperties != null) {
220239

221-
if (useSharerDisplayNameAsSignature) {
222-
final String currentUser = request.getResourceResolver().getUserID();
223-
if (!"anonymous".equalsIgnoreCase(currentUser) && !"admin".equalsIgnoreCase(currentUser)) {
224-
final UserPropertiesManager upm = request.getResourceResolver().adaptTo(UserPropertiesManager.class);
225-
final Authorizable authorizable = request.getResourceResolver().adaptTo(Authorizable.class);
226-
final UserProperties userProperties = upm.getUserProperties(authorizable, "profile");
240+
try {
241+
return userProperties.getProperty(UserProperties.EMAIL);
242+
}
243+
catch (RepositoryException ex) {
244+
throw new ShareException("Could not obtain email address for '" + userProperties.getAuthorizableID() + "'", ex);
245+
}
246+
}
227247

228-
if (userProperties != null) {
229-
return StringUtils.trimToNull(userProperties.getDisplayName());
230-
}
231-
}
248+
return null;
249+
}
250+
251+
private UserProperties getUserProperties(SlingHttpServletRequest request) {
252+
if(!isValidUser(request)) {
253+
return null;
232254
}
233255

234-
return StringUtils.defaultIfBlank(emailShare.getConfiguredData().get(EmailShareImpl.PN_SIGNATURE, String.class), cfg.signature());
256+
ResourceResolver resolver = request.getResourceResolver();
257+
final UserPropertiesManager upm = resolver.adaptTo(UserPropertiesManager.class);
258+
final Authorizable authorizable = resolver.adaptTo(Authorizable.class);
259+
260+
try {
261+
return upm.getUserProperties(authorizable, "profile");
262+
}
263+
catch (RepositoryException ex) {
264+
log.warn("Cannot get user profile properties of user '{}'", resolver.getUserID());
265+
return null;
266+
}
267+
}
268+
269+
private boolean isValidUser(SlingHttpServletRequest request) {
270+
if (request == null) {
271+
return false;
272+
}
273+
274+
final String currentUser = request.getResourceResolver().getUserID();
275+
boolean anonymous = StringUtils.equalsIgnoreCase(currentUser, "anonymous");
276+
boolean admin = StringUtils.equalsIgnoreCase(currentUser, "admin");
277+
278+
return (!anonymous && !admin);
235279
}
236280

237281
/**
@@ -248,7 +292,7 @@ private Map<String, Object> xssProtectUserData(Map<String, Object> dirtyUserData
248292
cleanUserData.put(entry.getKey(), xssCleanData((String[]) entry.getValue()));
249293
} else if (entry.getValue() instanceof String) {
250294
cleanUserData.put(entry.getKey(), xssCleanData((String) entry.getValue()));
251-
}
295+
}
252296
}
253297

254298
return cleanUserData;

core/src/main/java/com/adobe/aem/commons/assetshare/components/actions/share/impl/ShareServlet.java

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ public class ShareServlet extends SlingAllMethodsServlet {
5656
private ShareService defaultShareService;
5757

5858
@Reference(policyOption = ReferencePolicyOption.GREEDY)
59-
private transient Collection<ShareService> shareServices;
59+
private volatile Collection<ShareService> volatileShareServices;
6060

6161
@Override
6262
protected final void doPost(SlingHttpServletRequest request, SlingHttpServletResponse response)
@@ -74,6 +74,7 @@ private final void share(SlingHttpServletRequest request, SlingHttpServletRespon
7474
final AtomicInteger counter = new AtomicInteger(0);
7575

7676
// Call all accepting ShareService implementations
77+
final Collection<ShareService> shareServices = this.volatileShareServices;
7778
shareServices.stream()
7879
.filter(Objects::nonNull)
7980
.filter(shareService -> shareService.accepts(request))
@@ -100,4 +101,4 @@ private final void share(SlingHttpServletRequest request, SlingHttpServletRespon
100101
response.setStatus(SlingHttpServletResponse.SC_INTERNAL_SERVER_ERROR);
101102
}
102103
}
103-
}
104+
}

core/src/main/java/com/adobe/aem/commons/assetshare/components/actions/share/package-info.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
*
1818
*/
1919

20-
@Version("2.0.0")
20+
@Version("2.1.0")
2121
package com.adobe.aem.commons.assetshare.components.actions.share;
2222

2323
import org.osgi.annotation.versioning.Version;

core/src/main/java/com/adobe/aem/commons/assetshare/components/details/impl/ImageImpl.java

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
import com.adobe.aem.commons.assetshare.content.AssetModel;
2424
import com.adobe.aem.commons.assetshare.util.MimeTypeHelper;
2525
import com.day.cq.dam.api.Rendition;
26+
import com.day.text.Text;
2627
import org.apache.commons.lang3.StringUtils;
2728
import org.apache.sling.api.SlingHttpServletRequest;
2829
import org.apache.sling.api.resource.Resource;
@@ -33,6 +34,8 @@
3334
import org.apache.sling.models.annotations.injectorspecific.OSGiService;
3435
import org.apache.sling.models.annotations.injectorspecific.Self;
3536
import org.apache.sling.models.annotations.injectorspecific.ValueMapValue;
37+
import org.slf4j.Logger;
38+
import org.slf4j.LoggerFactory;
3639

3740
import javax.annotation.PostConstruct;
3841
import java.net.URLDecoder;
@@ -45,6 +48,7 @@
4548
defaultInjectionStrategy = DefaultInjectionStrategy.OPTIONAL
4649
)
4750
public class ImageImpl extends AbstractEmptyTextComponent implements Image {
51+
private static final Logger log = LoggerFactory.getLogger(ImageImpl.class);
4852
protected static final String RESOURCE_TYPE = "asset-share-commons/components/details/image";
4953

5054
@Self
@@ -101,7 +105,8 @@ public String getSrc() {
101105
}
102106
}
103107

104-
return src;
108+
src = StringUtils.replace(src, "%20", " ");
109+
return Text.escapePath(src);
105110
}
106111

107112
@Override
@@ -110,7 +115,7 @@ public String getAlt() {
110115
}
111116

112117
@Override
113-
public String getFallback() { return fallbackSrc; }
118+
public String getFallback() { return Text.escapePath(fallbackSrc); }
114119

115120
@Override
116121
public boolean isEmpty() {

core/src/main/java/com/adobe/aem/commons/assetshare/components/details/impl/RenditionsImpl.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
import com.adobe.cq.wcm.core.components.models.form.OptionItem;
2727
import com.adobe.cq.wcm.core.components.models.form.Options;
2828
import com.day.cq.dam.commons.util.UIHelper;
29+
import com.day.text.Text;
2930
import org.apache.commons.lang3.StringUtils;
3031
import org.apache.sling.api.SlingHttpServletRequest;
3132
import org.apache.sling.commons.mime.MimeTypeService;
@@ -155,7 +156,7 @@ public RenditionImpl(String label, com.day.cq.dam.api.Rendition assetRendition,
155156
this.label = label;
156157
this.size = UIHelper.getSizeLabel(assetRendition.getSize());
157158
this.mimeType = assetRendition.getMimeType();
158-
this.path = assetRendition.getPath();
159+
this.path = Text.escapePath(assetRendition.getPath());
159160
this.name = assetRendition.getName();
160161
this.exists = exists;
161162
this.licensed = licensed;

0 commit comments

Comments
 (0)