Skip to content

Commit ae164d9

Browse files
committed
implement PNG export for dashboard (dossier)
(cherry picked from commit 401274b)
1 parent 2a7dbd6 commit ae164d9

4 files changed

Lines changed: 121 additions & 4 deletions

File tree

knowage-core/src/main/java/it/eng/knowage/api/dossier/AbstractDocumentExecutionWork.java

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,9 @@
2929
import javax.ws.rs.core.MediaType;
3030
import javax.ws.rs.core.Response;
3131

32+
import it.eng.spagobi.engines.config.bo.Engine;
33+
import it.eng.spagobi.engines.config.dao.IEngineDAO;
34+
import it.eng.spagobi.engines.config.metadata.SbiEngines;
3235
import org.apache.commons.io.FileUtils;
3336
import org.apache.commons.io.FilenameUtils;
3437
import org.apache.commons.lang3.StringUtils;
@@ -558,12 +561,21 @@ private String getDashboardServiceUrl(BIObject biObject, String userUniqueIdenti
558561
String docLabel = biObject.getLabel();
559562
String hostUrl = getServiceHostUrl();
560563

564+
IEngineDAO engineDao = DAOFactory.getEngineDAO();
565+
Engine engine = null;
566+
try {
567+
engine = engineDao.loadEngineByLabel(biObject.getEngineLabel());
568+
} catch (EMFUserError emfUserError) {
569+
throw new SpagoBIRuntimeException("Error loading engine with label " + biObject.getEngineLabel(), emfUserError);
570+
}
571+
561572
URIBuilder serviceUrlBuilder = new URIBuilder(hostUrl);
562573
serviceUrlBuilder
563-
.setPath(KnowageSystemConfiguration.getKnowageCockpitEngineContext() + "/api/1.0/pages/execute/png");
574+
.setPath(engine.getUrl());
564575
serviceUrlBuilder.setParameter("user_id", userUniqueIdentifier);
565576
serviceUrlBuilder.setParameter("document", Integer.toString(docId));
566577
serviceUrlBuilder.setParameter("DOCUMENT_LABEL", docLabel);
578+
serviceUrlBuilder.setParameter("SBI_EXECUTION_ROLE", role);
567579
serviceUrlBuilder.setParameter("toolbar", "false");
568580
serviceUrlBuilder.setParameter("role", role);
569581
serviceUrlBuilder.setParameter("menu", "false");

knowage-core/src/main/java/it/eng/knowage/dashboardexport/DashboardExportResource.java

Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
import it.eng.knowage.commons.multitenant.OrganizationImageManager;
55
import it.eng.knowage.engine.api.export.dashboard.excel.DashboardExcelExporter;
66
import it.eng.knowage.engine.api.export.dashboard.pdf.DashboardPdfExporter;
7+
import it.eng.knowage.engine.api.export.dashboard.png.PngExporter;
78
import it.eng.knowage.engine.api.export.nodejs.PdfExporterV2;
89
import it.eng.knowage.export.wrapper.beans.RenderOptions;
910
import it.eng.knowage.export.wrapper.beans.ViewportDimensions;
@@ -36,10 +37,14 @@
3637
import javax.ws.rs.core.MediaType;
3738
import javax.ws.rs.core.Response;
3839

40+
import java.io.ByteArrayInputStream;
3941
import java.io.IOException;
4042
import java.util.*;
43+
import java.util.zip.ZipEntry;
44+
import java.util.zip.ZipInputStream;
4145

4246
import static it.eng.knowage.commons.security.KnowageSystemConfiguration.getKnowageVueContext;
47+
import static it.eng.spagobi.commons.utilities.UserUtilities.getUserProfile;
4348
import static java.nio.charset.StandardCharsets.UTF_8;
4449

4550
@Path("/1.0/dashboardExport")
@@ -230,6 +235,106 @@ public Object callPuppeteer() {
230235
}
231236
}
232237

238+
@POST
239+
@Path("/callPuppeteer")
240+
public Object callPuppeteer(
241+
@Context HttpServletRequest request, @Context HttpServletResponse response) throws JSONException, IOException, EMFUserError, InterruptedException {
242+
response.setContentType(MediaType.TEXT_HTML);
243+
response.setCharacterEncoding(UTF_8.name());
244+
245+
String documentLabel = request.getParameter("DOCUMENT_LABEL");
246+
BIObject biObject;
247+
try {
248+
biObject = DAOFactory.getBIObjectDAO().loadBIObjectByLabel(documentLabel);
249+
} catch (EMFUserError e) {
250+
throw new SpagoBIRuntimeException("Error retrieving document with label " + documentLabel, e);
251+
}
252+
253+
Engine eng = biObject.getEngine();
254+
URIBuilder externalUrl = GeneralUtilities.getBE2BEEngineUrl(eng);
255+
String requestURL = getRequestUrl(biObject, documentLabel, externalUrl, false);
256+
257+
RenderOptions renderOptions = getRenderOptionsForPdfExporter(request);
258+
259+
int documentId = Integer.parseInt(request.getParameter("document"));
260+
String userId = request.getParameter("user_id");
261+
String pdfPageOrientation = request.getParameter(PDF_PAGE_ORIENTATION);
262+
boolean pdfFrontPage = request.getParameter(PDF_FRONT_PAGE) != null
263+
&& Boolean.parseBoolean(request.getParameter(PDF_FRONT_PAGE));
264+
boolean pdfBackPage = request.getParameter(PDF_BACK_PAGE) != null
265+
&& Boolean.parseBoolean(request.getParameter(PDF_BACK_PAGE));
266+
String params = request.getParameter("parameters");
267+
268+
String role = getProfileRole();
269+
270+
String organization = UserProfileManager.getProfile().getOrganization();
271+
272+
PngExporter pngExporter = new PngExporter(documentId, userId, requestURL, renderOptions, pdfPageOrientation,
273+
pdfFrontPage, pdfBackPage, role, organization, params);
274+
byte[] data = pngExporter.getBinaryData();
275+
276+
boolean isZipped = false;
277+
278+
int thresholdEntries = 10000;
279+
int thresholdSize = 1000000000;
280+
double thresholdRatio = 10;
281+
int totalSizeArchive = 0;
282+
int totalEntryArchive = 0;
283+
284+
ZipInputStream zippedInputStream = new ZipInputStream(new ByteArrayInputStream(data));
285+
ZipEntry zipEntry;
286+
287+
while((zipEntry = zippedInputStream.getNextEntry()) != null) {
288+
289+
totalEntryArchive ++;
290+
291+
int nBytes;
292+
byte[] buffer = new byte[2048];
293+
int totalSizeEntry = 0;
294+
295+
while((nBytes = new ZipInputStream(new ByteArrayInputStream(data)).read(buffer)) > 0) {
296+
//out.write(buffer, 0, nBytes);
297+
totalSizeEntry += nBytes;
298+
totalSizeArchive += nBytes;
299+
300+
double compressionRatio = (double) totalSizeEntry / zipEntry.getCompressedSize();
301+
if(compressionRatio > thresholdRatio) {
302+
// ratio between compressed and uncompressed data is highly suspicious, looks like a Zip Bomb Attack
303+
logger.error("Error while unzip file. Invalid archive file");
304+
throw new SpagoBIRuntimeException("Error while unzip file. Invalid archive file");
305+
}
306+
}
307+
308+
if(totalSizeArchive > thresholdSize) {
309+
// the uncompressed data size is too much for the application resource capacity
310+
logger.error("Error while unzip file. Invalid archive file");
311+
throw new SpagoBIRuntimeException("Error while unzip file. Invalid archive file");
312+
}
313+
314+
if(totalEntryArchive > thresholdEntries) {
315+
// too much entries in this archive, can lead to inodes exhaustion of the system
316+
logger.error("Error while unzip file. Invalid archive file");
317+
throw new SpagoBIRuntimeException("Error while unzip file. Invalid archive file");
318+
}
319+
320+
isZipped = new ZipInputStream(new ByteArrayInputStream(data)).getNextEntry() != null;
321+
}
322+
323+
String mimeType;
324+
String contentDisposition;
325+
326+
if (!isZipped) {
327+
mimeType = "image/png";
328+
contentDisposition = "attachment; fileName=" + documentLabel + ".png";
329+
} else {
330+
mimeType = "application/zip";
331+
contentDisposition = "attachment; fileName=" + documentLabel + ".zip";
332+
}
333+
334+
return Response.ok(data, mimeType).header("Content-length", Integer.toString(data.length))
335+
.header("Content-Disposition", contentDisposition).build();
336+
}
337+
233338
private Object createSpreadsheet(BIObject biObject, String documentLabel, URIBuilder externalUrl) throws IOException, InterruptedException, JSONException {
234339

235340
String requestURL = getRequestUrl(biObject, documentLabel, externalUrl, true);

knowagecockpitengine/src/main/java/it/eng/knowage/engine/cockpit/api/export/png/PngExporter.java renamed to knowage-export/src/main/java/it/eng/knowage/engine/api/export/dashboard/png/PngExporter.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
* You should have received a copy of the GNU Affero General Public License
1616
* along with this program. If not, see <http://www.gnu.org/licenses/>.
1717
*/
18-
package it.eng.knowage.engine.cockpit.api.export.png;
18+
package it.eng.knowage.engine.api.export.dashboard.png;
1919

2020
import java.io.ByteArrayOutputStream;
2121
import java.io.IOException;
@@ -47,7 +47,7 @@ public PngExporter(int documentId, String userId, String requestUrl, RenderOptio
4747
protected byte[] handleFile(Path outputDir, BIObject document, List<InputStream> imagesInputStreams)
4848
throws IOException {
4949
LOGGER.debug("IN");
50-
byte[] bytes = null;
50+
byte[] bytes;
5151
if (imagesInputStreams.size() == 1) {
5252
bytes = IOUtils.toByteArray(imagesInputStreams.get(0));
5353
} else {

knowagecockpitengine/src/main/java/it/eng/knowage/engine/cockpit/api/page/PageResource.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@
5454

5555
import it.eng.knowage.commons.multitenant.OrganizationImageManager;
5656
import it.eng.knowage.engine.api.export.dashboard.excel.DashboardExcelExporter;
57+
import it.eng.knowage.engine.api.export.dashboard.png.PngExporter;
5758
import it.eng.knowage.engine.api.export.nodejs.PdfExporterV2;
5859
import it.eng.spagobi.tenant.TenantManager;
5960
import org.apache.http.client.utils.URIBuilder;
@@ -69,7 +70,6 @@
6970
import it.eng.knowage.engine.cockpit.CockpitEngine;
7071
import it.eng.knowage.engine.cockpit.CockpitEngineInstance;
7172
import it.eng.knowage.engine.cockpit.api.AbstractCockpitEngineResource;
72-
import it.eng.knowage.engine.cockpit.api.export.png.PngExporter;
7373
import it.eng.knowage.export.wrapper.beans.RenderOptions;
7474
import it.eng.knowage.export.wrapper.beans.ViewportDimensions;
7575
import it.eng.spago.error.EMFInternalError;

0 commit comments

Comments
 (0)