Skip to content

Commit

Permalink
SAK-40200
Browse files Browse the repository at this point in the history
  • Loading branch information
bjones86 committed Jul 6, 2018
1 parent a01b175 commit 17beba5
Show file tree
Hide file tree
Showing 39 changed files with 202 additions and 63 deletions.
5 changes: 5 additions & 0 deletions admin-tools/src/bundle/sites.properties
Original file line number Diff line number Diff line change
Expand Up @@ -255,3 +255,8 @@ sitedi.addeditgroups = Add/Edit groups
term=term

sitedi.custom = Custom Page Order?:

# site title error messages
siteTitle.htmlStrippedToEmpty=Site title cannot contain HTML. Please provide a valid site title.
siteTitle.maxLength=Title length cannot exceed {0} characters. Please provide a shorter title.
siteTitle.Empty = Please specify a site title.
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,8 @@
import org.sakaiproject.site.api.Group;
import org.sakaiproject.site.api.Site;
import org.sakaiproject.site.api.SitePage;
import static org.sakaiproject.site.api.SiteService.SITE_TITLE_MAX_LENGTH;
import org.sakaiproject.site.api.SiteService.SiteTitleValidationStatus;
import org.sakaiproject.site.api.ToolConfiguration;
import org.sakaiproject.site.cover.SiteService;
import org.sakaiproject.tool.api.Session;
Expand All @@ -78,6 +80,7 @@
import org.sakaiproject.user.api.User;
import org.sakaiproject.user.api.UserNotDefinedException;
import org.sakaiproject.user.cover.UserDirectoryService;
import org.sakaiproject.util.FormattedText;
import org.sakaiproject.util.ResourceLoader;
import org.sakaiproject.util.Validator;

Expand Down Expand Up @@ -1371,7 +1374,6 @@ private boolean readSiteForm(RunData data, SessionState state)
{
// read the form
String id = StringUtils.trimToNull(data.getParameters().getString("id"));
String title = StringUtils.trimToNull(data.getParameters().getString("title"));
String type = StringUtils.trimToNull(data.getParameters().getString("type"));
String shortDescription = StringUtils.trimToNull(data.getParameters().getString("shortDescription"));
String description = StringUtils.trimToNull(data.getParameters().getString("description"));
Expand All @@ -1385,6 +1387,22 @@ private boolean readSiteForm(RunData data, SessionState state)
boolean pubView = data.getParameters().getBoolean("pubView");
boolean customOrder = data.getParameters().getBoolean("customOrder");

// Site title is editable; cannot but null/empty after HTML stripping, and cannot exceed max length
String titleOrig = data.getParameters().getString("title");
String titleStripped = FormattedText.stripHtmlFromText(titleOrig, true, true);
SiteTitleValidationStatus status = SiteService.validateSiteTitle(titleOrig, titleStripped);

if (SiteTitleValidationStatus.STRIPPED_TO_EMPTY.equals(status)) {
addAlert(state, rb.getString("siteTitle.htmlStrippedToEmpty"));
return false;
} else if (SiteTitleValidationStatus.EMPTY.equals(status)) {
addAlert(state, rb.getString("siteTitle.Empty"));
return false;
} else if (SiteTitleValidationStatus.TOO_LONG.equals(status)) {
addAlert(state, rb.getFormattedMessage("siteTitle.maxLength", new Object[]{SITE_TITLE_MAX_LENGTH}));
return false;
}

// get the site
Site site = (Site) state.getAttribute("site");

Expand Down Expand Up @@ -1474,7 +1492,7 @@ private boolean readSiteForm(RunData data, SessionState state)
}
}

site.setTitle(title);
site.setTitle(titleStripped);
site.setShortDescription(shortDescription);
site.setDescription(description);
site.setJoinable(joinable);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,8 +42,6 @@
import net.oauth.server.OAuthServlet;
import net.oauth.signature.OAuthSignatureMethod;

import org.json.simple.JSONObject;
import org.json.simple.JSONArray;

import org.tsugi.basiclti.BasicLTIConstants;
import org.tsugi.basiclti.BasicLTIUtil;
Expand All @@ -53,7 +51,6 @@
import org.tsugi.contentitem.objects.ContentItemResponse;

import org.tsugi.jackson.JacksonUtil;
import com.fasterxml.jackson.core.JsonProcessingException;

import org.sakaiproject.authz.api.SecurityAdvisor;
import org.sakaiproject.authz.cover.SecurityService;
Expand All @@ -77,16 +74,17 @@
import org.sakaiproject.exception.IdUnusedException;
import org.sakaiproject.site.api.Site;
import org.sakaiproject.site.api.SitePage;
import static org.sakaiproject.site.api.SiteService.SITE_TITLE_MAX_LENGTH;
import org.sakaiproject.site.api.SiteService.SiteTitleValidationStatus;
import org.sakaiproject.site.api.ToolConfiguration;
import org.sakaiproject.site.cover.SiteService;
import org.sakaiproject.tool.api.Session;
import org.sakaiproject.tool.api.Tool;
import org.sakaiproject.tool.cover.SessionManager;
import org.sakaiproject.tool.cover.ToolManager;
import org.sakaiproject.user.api.Preferences;
import org.sakaiproject.user.api.PreferencesEdit;
import org.sakaiproject.user.api.User;
import org.sakaiproject.user.cover.UserDirectoryService;
import org.sakaiproject.util.FormattedText;
import org.sakaiproject.util.ResourceLoader;

import org.springframework.context.ApplicationContext;
Expand Down Expand Up @@ -778,9 +776,21 @@ protected Site findOrCreateSite(Map payload, boolean trustedConsumer) throws LTI
log.debug("siteId={}", siteId);
}

final String context_title = (String) payload.get(BasicLTIConstants.CONTEXT_TITLE);
final String context_title_orig = (String) payload.get(BasicLTIConstants.CONTEXT_TITLE);
final String context_label = (String) payload.get(BasicLTIConstants.CONTEXT_LABEL);

// Site title is editable; cannot but null/empty after HTML stripping, and cannot exceed max length
String context_title = FormattedText.stripHtmlFromText(context_title_orig, true, true);
SiteTitleValidationStatus status = SiteService.validateSiteTitle(context_title_orig, context_title);

if (SiteTitleValidationStatus.STRIPPED_TO_EMPTY.equals(status)) {
log.warn("Provided context_title is empty after HTML stripping: {}", context_title_orig);
} else if (SiteTitleValidationStatus.EMPTY.equals(status)) {
log.warn("Provided context_title is empty after trimming: {}", context_title_orig);
} else if (SiteTitleValidationStatus.TOO_LONG.equals(status)) {
log.warn("Provided context_title is longer than max site title length of {}: {}", SITE_TITLE_MAX_LENGTH, context_title_orig);
}

Site site = null;

// Get the site if it exists
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1362,4 +1362,27 @@ public boolean isAsc()
* @param siteIds site Ids on which to insert the specified property name-value pair
*/
public void saveSitePropertyOnSites(String propertyName, String propertyValue, String... siteIds);

/**
* Defines the maximum character length of a site title.
*/
public static final int SITE_TITLE_MAX_LENGTH = 99;

/**
* Defines the possible results which can be returned from the {@link validateSiteTitle()} method.
*/
public enum SiteTitleValidationStatus {
OK,
TOO_LONG,
EMPTY,
STRIPPED_TO_EMPTY
}

/**
* Given the original and stripped site titles, determine that validation status of the stripped string.
* @param orig the original, unaltered text as input by the user
* @param stripped the HTML stripped text, produced by passing the original text through FormattedText.stripHtmlFromText(text, true, true).
* @return {@link SiteTitleValidationStatus}
*/
public SiteTitleValidationStatus validateSiteTitle(String orig, String stripped);
}
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@

import org.sakaiproject.component.cover.ComponentManager;
import org.sakaiproject.site.api.Site;
import org.sakaiproject.site.api.SiteService.SiteTitleValidationStatus;

/**
* <p>
Expand Down Expand Up @@ -585,4 +586,18 @@ public static String getUserSpecificSiteTitle(Site site, String userId, List<Str

return service.getUserSpecificSiteTitle(site, userId, siteProviders);
}

/**
* Given the original and stripped site titles, determine that validation status of the stripped string.
* @param orig the original, unaltered text as input by the user
* @param stripped the HTML stripped text
* @return {@link SiteTitleValidationStatus}
*/
public static SiteTitleValidationStatus validateSiteTitle(String orig, String stripped)
{
org.sakaiproject.site.api.SiteService service = getInstance();
if (service == null) { return null; }

return service.validateSiteTitle(orig, stripped);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3807,4 +3807,22 @@ public void notifySiteParticipant(String filter) {
action.notify(notification, event);
}
}

/**
* {@inheritDoc}
*/
public SiteTitleValidationStatus validateSiteTitle(String orig, String stripped) {
orig = StringUtils.trimToEmpty(orig);
stripped = StringUtils.trimToEmpty(stripped);

if (!orig.equals(stripped) && StringUtils.isBlank(stripped)) {
return SiteTitleValidationStatus.STRIPPED_TO_EMPTY;
} else if (StringUtils.isBlank(stripped)) {
return SiteTitleValidationStatus.EMPTY;
} else if (stripped.length() > SITE_TITLE_MAX_LENGTH) {
return SiteTitleValidationStatus.TOO_LONG;
} else {
return SiteTitleValidationStatus.OK;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
import org.sakaiproject.api.common.edu.person.SakaiPerson;
import org.sakaiproject.profile2.model.MimeTypeByteArray;
import org.sakaiproject.site.api.Site;
import org.sakaiproject.site.api.SiteService.SiteTitleValidationStatus;
import org.sakaiproject.tool.api.Tool;
import org.sakaiproject.user.api.User;

Expand Down Expand Up @@ -1060,4 +1061,12 @@ public interface SakaiProxy {
* @return <code>true</code> if the profile2.onlineStatus.enabled flag is set, otherwise returns <code>false</code>.
*/
public boolean isOnlineStatusEnabledGlobally();

/**
* Given the original and stripped site titles, determine that validation status of the stripped string.
* @param orig the original, unaltered text as input by the user
* @param stripped the HTML stripped text
* @return {@link SiteTitleValidationStatus}
*/
public SiteTitleValidationStatus validateSiteTitle(String orig, String stripped);
}
2 changes: 2 additions & 0 deletions profile2/bundle/src/resources/ProfileApplication.properties
Original file line number Diff line number Diff line change
Expand Up @@ -184,6 +184,8 @@ error.wall.post.empty = You tried to make an empty post
error.wall.post.failed = Post failed
error.worksite.create.failed = Worksite creation failed
error.worksite.no.title = You must give the site a name
error.worksite.title.maxLength = Title length cannot exceed {0} characters. Please provide a shorter title.
error.worksite.title.htmlStrippedToEmpty = Site title cannot contain HTML. Please provide a valid site title.

exception.heading.session.expired = Session expired
exception.text.session.expired = Unfortunately, your session has expired. Try refreshing the page or logout then login again to restart your session.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1773,6 +1773,14 @@ public boolean isOnlineStatusEnabledGlobally() {
ProfileConstants.SAKAI_PROP_PROFILE2_ONLINE_STATUS_ENABLED);
}

/**
* {@inheritDoc}
*/
@Override
public SiteService.SiteTitleValidationStatus validateSiteTitle(String orig, String stripped) {
return this.siteService.validateSiteTitle(orig, stripped);
}

// PRIVATE METHODS FOR SAKAIPROXY

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@
import java.util.Collections;
import java.util.List;

import org.apache.commons.lang.StringUtils;
import org.apache.wicket.AttributeModifier;
import org.apache.wicket.ajax.AjaxRequestTarget;
import org.apache.wicket.ajax.markup.html.form.AjaxButton;
Expand All @@ -33,8 +32,10 @@
import org.apache.wicket.markup.html.form.TextField;
import org.apache.wicket.markup.html.panel.FeedbackPanel;
import org.apache.wicket.markup.html.panel.Panel;
import org.apache.wicket.model.IModel;
import org.apache.wicket.model.Model;
import org.apache.wicket.model.ResourceModel;
import org.apache.wicket.model.StringResourceModel;
import org.apache.wicket.model.util.CollectionModel;
import org.apache.wicket.model.util.ListModel;
import org.apache.wicket.spring.injection.annot.SpringBean;
Expand All @@ -45,6 +46,8 @@
import org.sakaiproject.profile2.tool.components.IconWithClueTip;
import org.sakaiproject.profile2.util.ProfileConstants;
import org.sakaiproject.profile2.util.ProfileUtils;
import static org.sakaiproject.site.api.SiteService.SITE_TITLE_MAX_LENGTH;
import org.sakaiproject.site.api.SiteService.SiteTitleValidationStatus;

/**
* Panel for creating a worksite from a group of people.
Expand Down Expand Up @@ -123,17 +126,32 @@ protected void onSubmit(AjaxRequestTarget target, Form<?> form) {
@Override
protected void onSubmit(AjaxRequestTarget target, Form<?> form) {

if (StringUtils.isBlank(siteNameField.getValue())) {
formFeedback.setDefaultModel(new ResourceModel(
"error.worksite.no.title"));
formFeedback.add(new AttributeModifier("class", true,
new Model<String>("alertMessage")));
// Site title is editable; cannot but null/empty after HTML stripping, and cannot exceed max length
String titleOrig = siteNameField.getValue();
String titleStripped = ProfileUtils.stripHtmlFromText(titleOrig, true, true);
SiteTitleValidationStatus status = sakaiProxy.validateSiteTitle(titleOrig, titleStripped);

boolean titleError = false;
IModel errorMsg = null;
if (SiteTitleValidationStatus.STRIPPED_TO_EMPTY.equals(status)) {
errorMsg = new ResourceModel("error.worksite.title.htmlStrippedToEmpty");
titleError = true;
} else if (SiteTitleValidationStatus.EMPTY.equals(status)) {
errorMsg = new ResourceModel("error.worksite.no.title");
titleError = true;
} else if (SiteTitleValidationStatus.TOO_LONG.equals(status)) {
errorMsg = new StringResourceModel("error.worksite.title.maxLength", null, new Object[] {SITE_TITLE_MAX_LENGTH});
titleError = true;
}

if (titleError) {
formFeedback.setDefaultModel(errorMsg);
formFeedback.add(new AttributeModifier("class", true, new Model<>("alertMessage")));
target.add(formFeedback);
return;
}

if (true == worksiteLogic.createWorksite(ProfileUtils.stripHtml(siteNameField
.getValue()), sakaiProxy.getCurrentUserId(),
if (true == worksiteLogic.createWorksite(titleStripped, sakaiProxy.getCurrentUserId(),
new ArrayList<Person>(palette.getModelCollection()),
true)) {

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -431,7 +431,23 @@ public static String stripAndCleanHtml(String s) {
//so we escape anything that is left
return StringEscapeUtils.escapeHtml(stripped);
}


/**
* Strips html/xml tags from a string and returns the cleaned version.
*
* @param text any text (if this is null or empty then the input text is returned unchanged)
* @param smartSpacing if true then try to make the text represent the intent of the html,
* trims out duplicate spaces, converts block type html into a space, etc.,
* else just removes html tags and leaves all other parts of the string intact,
* NOTE: false is also slightly faster
* @param stripEscapeSequences if true, strips out any escape sequences such as '&nbsp;'
* @return the cleaned string
* @see #convertFormattedTextToPlaintext(String) for alternative mechanism
*/
public static String stripHtmlFromText(String text, boolean smartSpacing, boolean stripEscapeSequences) {
return FormattedText.stripHtmlFromText(text, smartSpacing, stripEscapeSequences);
}

/**
* Trims text to the given maximum number of displayed characters.
* Supports HTML and preserves formatting.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -214,7 +214,6 @@ java.coursesite=Gunea erabiltzaile honentzat:
java.date=Eguna:
java.delete=Kendu
java.dontperm=ezin da kendu. Ez duzu baimenik gune hau kentzeko.
java.dupli=Eman, arren, titulu bat gune bikoiztuari.
java.duplicate=Bikoiztu gunea
java.editc=Editatu klasearen zerrenda
java.editsite=Editatu gunearen informazioa
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -263,7 +263,6 @@ java.coursesite=Kurssajt f\u00f6r
java.date=Datum\:
java.delete=Radera sajt
java.dontperm=kan inte tas bort. Du har inte beh\u00f6righet att radera denna sajt.
java.dupli=Du m\u00e5ste ange en titel f\u00f6r den kopierade sajten.
java.duplicate=Kopiera sajt
java.editc=Redigera deltagarlista
java.editsite=Redigera sajtinformation
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -214,7 +214,6 @@ java.classes=H\u00E3y ch\u1ECDn l\u1EDBp (es) \u0111\u1EC3 x\u00F3a.
addconf.number=\#
list.steasc=Ph\u00E2n lo\u1EA1i theo h\u1EA1n t\u0103ng d\u1EA7n
java.cannot=Kh\u00F4ng th\u1EC3 t\u00ECm th\u1EA5y c\u00E1c trang web \u0111\u1ECBnh
java.dupli=Xin vui l\u00F2ng ghi r\u00F5 ti\u00EAu \u0111\u1EC1 cho c\u00E1c trang web tr\u00F9ng l\u1EB7p.
sitinfimp.youcan=B\u1EA1n c\u00F3 th\u1EC3 ch\u1ECDn \u0111\u1EC3 nh\u1EADp nguy\u00EAn li\u1EC7u ch\u1EC9 t\u1EEB c\u00E1c trang web kh\u00E1c m\u00E0 b\u1EA1n s\u1EDF h\u1EEFu. B\u1EA1n c\u00F3 th\u1EC3 k\u1EBFt h\u1EE3p t\u00E0i li\u1EC7u t\u1EEB nhi\u1EC1u h\u01A1n m\u1ED9t trang web.
java.email2=email
addrc.confirming=X\u00E1c nh\u1EADn c\u00E1c c\u00F4ng c\u1EE5 ch\u1EC9nh s\u1EEDa cho trang web
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -134,7 +134,6 @@ java.reqfields = Please enter the required fields.
java.specify = Please specify site title.
java.pleasechoice = Please select the notification choice.
### (moot) java.atleast = Please choose at least one import for importing.
java.dupli = Please specify title for the duplicated site.
java.siteinval = Site id is invalid.
java.sitebeenused = Site id has been used.
java.allowcreate = You are not allowed to create a new site.
Expand Down Expand Up @@ -1136,6 +1135,9 @@ sitinfimp.wikinote=(Existing content will be archived and can be accessed from t
### limit of site group title ####
site_group_title_length_limit=Title length cannot exceed {0} characters. Please provide a shorter title.

# site title can't contain HTML
siteTitle.htmlStrippedToEmpty=Site title cannot contain HTML. Please provide a valid site title.

print=Printable Version
description.linebreak = Site Description contains non-html line breaks and have been updated. Please review the changes and save to see the new format.

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -187,7 +187,6 @@ java.classes=\u064A\u0631\u062C\u0649 \u0625\u062E\u062A\u064A\u0627\u0631 \u064
addconf.number=\#
list.steasc=\u0627\u0644\u062A\u0631\u062A\u064A\u0628 \u062D\u0633\u0628 \u0627\u0644\u062F\u0648\u0631\u0629 \u0635\u0639\u0648\u062F\u0627
java.cannot=\u0644\u0627 \u064A\u0645\u0643\u0646 \u0625\u064A\u062C\u0627\u062F \u0627\u0644\u0645\u0648\u0642\u0639 \u0627\u0644\u0645\u062D\u062F\u062F
java.dupli=\u064A\u0631\u062C\u0649 \u062A\u062D\u062F\u064A\u062F \u0639\u0646\u0648\u0627\u0646 \u0627\u0644\u0645\u0648\u0642\u0639 \u0627\u0644\u0645\u0646\u0633\u0648\u062E.
sitinfimp.youcan=\u064A\u0645\u0643\u0646\u0643\u0645 \u0625\u062E\u062A\u064A\u0627\u0631 \u0625\u0639\u0627\u062F\u0629 \u0625\u0633\u062A\u062E\u062F\u0627\u0645 \u0627\u0644\u0645\u0648\u0627\u062F \u0645\u0646 \u0627\u0644\u0645\u0648\u0627\u0642\u0639 \u0627\u0644\u0623\u062E\u0631\u0649 \u0627\u0644\u062A\u064A \u062A\u0645\u062A\u0644\u0643\u0648\u0646\u0647\u0627. \u064A\u0645\u0643\u0646\u0643\u0645 \u0627\u0644\u062C\u0645\u0639 \u0628\u064A\u0646 \u0627\u0644\u0645\u0648\u0627\u062F \u0645\u0646 \u0623\u0643\u062B\u0631 \u0645\u0646 \u0645\u0648\u0642\u0639 \u0648\u0627\u062D\u062F.
java.email2=\u0627\u0644\u0628\u0631\u064A\u062F \u0627\u0644\u0625\u0644\u0643\u062A\u0631\u0648\u0646\u064A
addrc.confirming=\u062A\u0623\u0643\u064A\u062F \u0623\u062F\u0648\u0627\u062A \u0627\u0644\u0645\u0648\u0642\u0639
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -134,7 +134,6 @@ java.reqfields=Introdu\u00efu els camps obligatoris.
java.specify=Especifiqueu el t\u00edtol de l'espai.
java.pleasechoice=Seleccioneu l'opci\u00f3 de notificaci\u00f3.
### (moot) java.atleast = Please choose at least one import for importing.
java.dupli=Especifiqueu un nom per a l'espai duplicat.
java.siteinval=L'identificador de l'espai no \u00e9s v\u00e0lid.
java.sitebeenused=L'identificador de l'espai ja ha estat utilitzat.
java.allowcreate=No esteu autoritzats a crear un espai nou.
Expand Down
Loading

0 comments on commit 17beba5

Please sign in to comment.