Skip to content

Commit

Permalink
SAK-46622 Limit docx to html conversions to 10MB (sakaiproject#10074)
Browse files Browse the repository at this point in the history
  • Loading branch information
adrianfish authored Dec 14, 2021
1 parent 25d9bed commit 44b4cfb
Show file tree
Hide file tree
Showing 6 changed files with 67 additions and 24 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -5736,3 +5736,8 @@ rubrics.integration.token-secret=12345678900909091234
# If it is zero, no rotation happens
# DEFAULT: 30 days
# lti.advantage.key.rotation.days=30

# OOTB file conversion. This is the poor man's alternative to the fileconversionservice. By default
# it is limited to files < 10MB in size. You can up that here.
# DEFAULT: 10
# ootbconversion.sizelimitmb=100
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@
import org.sakaiproject.content.api.ResourceTypeRegistry;
import org.sakaiproject.content.tool.ListItem;
import org.sakaiproject.entity.api.ResourcePropertiesEdit;
import org.sakaiproject.entitybroker.entityprovider.extension.ActionReturn;
import org.sakaiproject.entitybroker.exception.EntityException;
import org.sakaiproject.entity.api.EntityManager;
import org.sakaiproject.entity.api.EntityPermissionException;
Expand Down Expand Up @@ -267,15 +268,15 @@ public List<EntityContent> getResources(EntityView view, Map<String, Object> par
}

@EntityCustomAction(action="htmlForRef", viewKey=EntityView.VIEW_SHOW)
public String getHtmlForRef(EntityView view, Map<String, Object> params) throws EntityPermissionException {
public ActionReturn getHtmlForRef(EntityView view, Map<String, Object> params) throws EntityPermissionException {

String ref = (String) params.get("ref");

if (StringUtils.isBlank(ref)) {
throw new EntityException("You need to supply the ref parameter.", null, HttpServletResponse.SC_BAD_REQUEST);
}

return contentHostingService.getHtmlForRef(ref).orElse("");
return new ActionReturn(contentHostingService.getHtmlForRef(ref));
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -272,6 +272,13 @@ public interface ContentHostingService extends EntityProducer
*/
public static final String PREVIEW = "PREVIEW";

// These are used by the built in getHtmlForRef converter. NOT the fileconversionservice. Used
// as a key in the returned content map to indicate the status of the conversiont.
public static final String CONVERSION_TOO_BIG = "CONVERSION_TOO_BIG";
public static final String CONVERSION_OK = "CONVERSION_OK";
public static final String CONVERSION_FAILED = "CONVERSION_FAILED";
public static final String CONVERSION_NOT_SUPPORTED = "CONVERSION_NOT_SUPPORTED";

public static final String SAK_PROP_MAX_UPLOAD_FILE_SIZE = "content.upload.max";

/**
Expand Down Expand Up @@ -2137,7 +2144,7 @@ public void restoreResource(String id) throws PermissionException, IdUsedExcepti

public String expandMacros(String url);

public Optional<String> getHtmlForRef(String ref);
public Map<String,String> getHtmlForRef(String ref);

/**
* Get the name of the "instructor" upload folder name for direct-upload.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14328,11 +14328,23 @@ public String expandMacros(String url) {
return url;
}

public Optional<String> getHtmlForRef(String ref) {
public Map<String, String> getHtmlForRef(String ref) {

Map<String, String> map = new HashMap<>();

try {
ContentResource cr = getResource(ref);

long contentLength = cr.getContentLength();

long limit = m_serverConfigurationService.getLong("ootbconversion.sizelimitmb", 10L) * 1024L * 1024L;

if (contentLength > limit) {
log.warn("{} is larger than {}, returning an empty Optional ...", ref, limit);
map.put("status", CONVERSION_TOO_BIG);
return map;
}

byte[] content = cr.getContent();
String contentType = cr.getContentType();

Expand All @@ -14344,25 +14356,31 @@ public Optional<String> getHtmlForRef(String ref) {
if (log.isDebugEnabled()) {
result.getWarnings().forEach(w -> log.debug("Warning while converting {} to html: {}", ref, w));
}
return Optional.of(html);
map.put("status", CONVERSION_OK);
map.put("content", html);
return map;
}
case ODT_MIMETYPE:
try (InputStream in = cr.streamContent()) {
OdfTextDocument document = OdfTextDocument.loadDocument(in);
StringWriter sw = new StringWriter();
XHTMLConverter.getInstance().convert( document, sw, null );
return Optional.of(sw.toString());
} catch ( Throwable e ) {
e.printStackTrace();
map.put("status", CONVERSION_OK);
map.put("content", sw.toString());
return map;
} catch (Throwable e) {
log.error("Failed to convert ref {}", ref, e);
}

return Optional.of("");
break;
default:
map.put("status", CONVERSION_NOT_SUPPORTED);
return map;
}
} catch (Exception e) {
log.error("Failed to get html for ref {}", ref, e);
}
return Optional.empty();
map.put("status", CONVERSION_FAILED);
return map;
}

/**
Expand Down
Original file line number Diff line number Diff line change
@@ -1,2 +1,4 @@
document_not_supported=The document type is not supported. Please use the file link above.
document_too_big=The document was too large to convert. Please use the file link above.
failed_to_load_document=Failed to load document. Please use the file link above.
viewing=Viewing
36 changes: 23 additions & 13 deletions webcomponents/tool/src/main/frontend/js/sakai-document-viewer.js
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,8 @@ class SakaiDocumentViewer extends SakaiElement {

this.i18n = t;
this.documentFailureMessage = `<div>${this.i18n.failed_to_load_document}</div>`;
this.documentTooBigMessage = `<div>${this.i18n.document_too_big}</div>`;
this.documentNotSupportedMessage = `<div>${this.i18n.document_not_supported}</div>`;
});
}

Expand Down Expand Up @@ -115,23 +117,31 @@ class SakaiDocumentViewer extends SakaiElement {
const contentIndex = ref.indexOf("/content/");
ref = contentIndex >= 0 ? ref.substring(contentIndex + 8) : ref;

fetch(`/direct/content/${portal.siteId}/htmlForRef.html?ref=${ref}`,
{cache: "no-cache", credentials: "same-origin"})
fetch(`/direct/content/${portal.siteId}/htmlForRef.json?ref=${ref}`,
{cache: "no-cache", contentcredentials: "same-origin"})
.then(r => {

if (!r.ok) {
this.documentMarkup = this.documentFailureMessage;
throw new Error("Failed to load preview");
} else {
return r.text();
if (r.ok) {
return r.json();
}
})
.then(html => {

if (html) {
this.documentMarkup = html;
} else {
this.documentMarkup = this.documentFailureMessage;
this.documentMarkup = this.documentFailureMessage;
throw new Error("Failed to load preview");
})
.then(data => {

switch (data.status) {
case "CONVERSION_OK":
this.documentMarkup = data.content;
break;
case "CONVERSION_TOO_BIG":
this.documentMarkup = this.documentTooBigMessage;
break;
case "CONVERSION_NOT_SUPPORTED":
this.documentMarkup = this.documentNotSupportedMessage;
break;
default:
this.documentMarkup = this.documentFailureMessage;
}
})
.catch (error => console.error(error));
Expand Down

0 comments on commit 44b4cfb

Please sign in to comment.