diff --git a/docs-core/src/main/java/com/sismics/docs/core/listener/async/FileCreatedAsyncListener.java b/docs-core/src/main/java/com/sismics/docs/core/listener/async/FileCreatedAsyncListener.java index 6d63bff3..b8948753 100644 --- a/docs-core/src/main/java/com/sismics/docs/core/listener/async/FileCreatedAsyncListener.java +++ b/docs-core/src/main/java/com/sismics/docs/core/listener/async/FileCreatedAsyncListener.java @@ -54,6 +54,7 @@ public class FileCreatedAsyncListener { FormatHandler formatHandler = FormatHandlerUtil.find(file.getMimeType()); if (formatHandler == null) { log.error("Format unhandled: " + file.getMimeType()); + FileUtil.endProcessingFile(file.getId()); return; } @@ -65,6 +66,7 @@ public class FileCreatedAsyncListener { }); if (user.get() == null) { // The user has been deleted meanwhile + FileUtil.endProcessingFile(file.getId()); return; } diff --git a/docs-web/src/main/java/com/sismics/docs/rest/resource/FileResource.java b/docs-web/src/main/java/com/sismics/docs/rest/resource/FileResource.java index 3955cc82..8e8c629e 100644 --- a/docs-web/src/main/java/com/sismics/docs/rest/resource/FileResource.java +++ b/docs-web/src/main/java/com/sismics/docs/rest/resource/FileResource.java @@ -40,6 +40,7 @@ import javax.ws.rs.core.StreamingOutput; import java.io.IOException; import java.io.InputStream; import java.net.URISyntaxException; +import java.net.URLDecoder; import java.nio.file.Files; import java.nio.file.Paths; import java.nio.file.StandardCopyOption; @@ -119,7 +120,7 @@ public class FileResource extends BaseResource { try { String name = fileBodyPart.getContentDisposition() != null ? - fileBodyPart.getContentDisposition().getFileName() : null; + URLDecoder.decode(fileBodyPart.getContentDisposition().getFileName(), "UTF-8") : null; String fileId = FileUtil.createFile(name, unencryptedFile, fileSize, documentDto == null ? null : documentDto.getLanguage(), principal.getId(), documentId); @@ -449,7 +450,7 @@ public class FileResource extends BaseResource { * @apiGroup File * @apiParam {String} id File ID * @apiParam {String} share Share ID - * @apiParam {String="web","thumb"} [size] Size variation + * @apiParam {String="web","thumb","content"} [size] Size variation * @apiSuccess {Object} file The file data is the whole response * @apiError (client) SizeError Size must be web or thumb * @apiError (client) ForbiddenError Access denied or document not visible @@ -469,12 +470,10 @@ public class FileResource extends BaseResource { @QueryParam("size") String size) { authenticate(); - if (size != null) { - if (!Lists.newArrayList("web", "thumb").contains(size)) { - throw new ClientException("SizeError", "Size must be web or thumb"); - } + if (size != null && !Lists.newArrayList("web", "thumb", "content").contains(size)) { + throw new ClientException("SizeError", "Size must be web, thumb or content"); } - + // Get the file File file = findFile(fileId, shareId); @@ -484,6 +483,12 @@ public class FileResource extends BaseResource { String mimeType; boolean decrypt; if (size != null) { + if (size.equals("content")) { + return Response.ok(Strings.nullToEmpty(file.getContent())) + .header(HttpHeaders.CONTENT_TYPE, "text/plain") + .build(); + } + storedFile = DirectoryUtil.getStorageDirectory().resolve(fileId + "_" + size); mimeType = MimeType.IMAGE_JPEG; // Thumbnails are JPEG decrypt = true; // Thumbnails are encrypted diff --git a/docs-web/src/main/webapp/src/app/docs/controller/document/DocumentEdit.js b/docs-web/src/main/webapp/src/app/docs/controller/document/DocumentEdit.js index 047c2fd6..7563aec0 100644 --- a/docs-web/src/main/webapp/src/app/docs/controller/document/DocumentEdit.js +++ b/docs-web/src/main/webapp/src/app/docs/controller/document/DocumentEdit.js @@ -153,7 +153,7 @@ angular.module('docs').controller('DocumentEdit', function($rootScope, $scope, $ var file = $scope.newFiles[key]; var formData = new FormData(); formData.append('id', data.id); - formData.append('file', file, file.name); + formData.append('file', file, encodeURIComponent(file.name)); // Send the file $.ajax({ diff --git a/docs-web/src/main/webapp/src/app/docs/controller/document/FileModalView.js b/docs-web/src/main/webapp/src/app/docs/controller/document/FileModalView.js index b62627f3..c5846aa4 100644 --- a/docs-web/src/main/webapp/src/app/docs/controller/document/FileModalView.js +++ b/docs-web/src/main/webapp/src/app/docs/controller/document/FileModalView.js @@ -70,6 +70,13 @@ angular.module('docs').controller('FileModalView', function ($uibModalInstance, window.open('../api/file/' + $stateParams.fileId + '/data'); }; + /** + * Open the file content a new window. + */ + $scope.openFileContent = function () { + window.open('../api/file/' + $stateParams.fileId + '/data?size=content'); + }; + /** * Print the file. */ diff --git a/docs-web/src/main/webapp/src/lib/angular.file-upload.js b/docs-web/src/main/webapp/src/lib/angular.file-upload.js index 41567747..9f1af539 100644 --- a/docs-web/src/main/webapp/src/lib/angular.file-upload.js +++ b/docs-web/src/main/webapp/src/lib/angular.file-upload.js @@ -1,4 +1,8 @@ /**! + * ======================================================================= + * Sismics Docs patch applied to encode filenames with encodeURIComponent. + * ======================================================================= + * * AngularJS file upload directives and services. Supoorts: file upload/drop/paste, resume, cancel/abort, * progress, resize, thumbnail, preview, validation and CORS * @author Danial @@ -272,7 +276,7 @@ ngFileUpload.service('UploadBase', ['$http', '$q', '$timeout', function ($http, key = split[0]; } config._fileKey = config._fileKey || key; - formData.append(key, file, file.ngfName || file.name); + formData.append(key, file, file.ngfName || encodeURIComponent(file.name)); } else { if (angular.isObject(val)) { if (val.$$ngfCircularDetection) throw 'ngFileUpload: Circular reference in config.data. Make sure specified data for Upload.upload() has no circular reference: ' + key; diff --git a/docs-web/src/main/webapp/src/partial/docs/document.view.content.html b/docs-web/src/main/webapp/src/partial/docs/document.view.content.html index e6788318..c6dc3b95 100644 --- a/docs-web/src/main/webapp/src/partial/docs/document.view.content.html +++ b/docs-web/src/main/webapp/src/partial/docs/document.view.content.html @@ -60,7 +60,7 @@
-
+
- - +
diff --git a/docs-web/src/main/webapp/src/style/main.less b/docs-web/src/main/webapp/src/style/main.less index b55baf59..2d7b4abd 100644 --- a/docs-web/src/main/webapp/src/style/main.less +++ b/docs-web/src/main/webapp/src/style/main.less @@ -429,6 +429,8 @@ input[readonly].share-link { } .settings-content { + margin-bottom: 10px; + .well { box-shadow: 0 7px 14px 0 rgba(50,50,93,.1), 0 3px 6px 0 rgba(0,0,0,.07); background: none; diff --git a/docs-web/src/test/java/com/sismics/docs/rest/TestDocumentResource.java b/docs-web/src/test/java/com/sismics/docs/rest/TestDocumentResource.java index 5a96673e..545351a4 100644 --- a/docs-web/src/test/java/com/sismics/docs/rest/TestDocumentResource.java +++ b/docs-web/src/test/java/com/sismics/docs/rest/TestDocumentResource.java @@ -580,6 +580,16 @@ public class TestDocumentResource extends BaseJerseyTest { Assert.assertTrue(fileBytes.length > 0); // Images rendered from PDF differ in size from OS to OS due to font issues Assert.assertEquals(MimeType.IMAGE_JPEG, MimeTypeUtil.guessMimeType(fileBytes, null)); + // Get the content data + response = target().path("/file/" + file1Id + "/data") + .queryParam("size", "content") + .request() + .cookie(TokenBasedSecurityFilter.COOKIE_NAME, documentPlainToken) + .get(); + Assert.assertEquals(Status.OK, Status.fromStatusCode(response.getStatus())); + is = (InputStream) response.getEntity(); + Assert.assertTrue(new String(ByteStreams.toByteArray(is)).contains("love")); + // Export a document in PDF format response = target().path("/document/" + document1Id + "/pdf") .queryParam("margin", "10") diff --git a/docs-web/src/test/java/com/sismics/docs/rest/TestFileResource.java b/docs-web/src/test/java/com/sismics/docs/rest/TestFileResource.java index 17b3f8e3..f0a9c6cd 100644 --- a/docs-web/src/test/java/com/sismics/docs/rest/TestFileResource.java +++ b/docs-web/src/test/java/com/sismics/docs/rest/TestFileResource.java @@ -106,6 +106,14 @@ public class TestFileResource extends BaseJerseyTest { Assert.assertEquals(MimeType.IMAGE_JPEG, MimeTypeUtil.guessMimeType(fileBytes, null)); Assert.assertTrue(fileBytes.length > 0); + // Get the content data + response = target().path("/file/" + file1Id + "/data") + .queryParam("size", "content") + .request() + .cookie(TokenBasedSecurityFilter.COOKIE_NAME, file1Token) + .get(); + Assert.assertEquals(Status.OK, Status.fromStatusCode(response.getStatus())); + // Get the web data response = target().path("/file/" + file1Id + "/data") .queryParam("size", "web")