From 1032c40077d17eeff44972b2c98dfa97d42e792f Mon Sep 17 00:00:00 2001 From: baicaixiaozhan Date: Sun, 18 Jan 2026 20:43:31 +0800 Subject: [PATCH 1/3] fix: Image type recognition failure in FileTypeUtils --- .../fesod/sheet/util/FileTypeUtils.java | 18 ++- .../fesod/sheet/util/FileTypeUtilsTest.java | 113 ++++++++++++++++++ 2 files changed, 127 insertions(+), 4 deletions(-) create mode 100644 fesod-sheet/src/test/java/org/apache/fesod/sheet/util/FileTypeUtilsTest.java diff --git a/fesod-sheet/src/main/java/org/apache/fesod/sheet/util/FileTypeUtils.java b/fesod-sheet/src/main/java/org/apache/fesod/sheet/util/FileTypeUtils.java index 33b47f91a..456be0afe 100644 --- a/fesod-sheet/src/main/java/org/apache/fesod/sheet/util/FileTypeUtils.java +++ b/fesod-sheet/src/main/java/org/apache/fesod/sheet/util/FileTypeUtils.java @@ -33,6 +33,7 @@ public class FileTypeUtils { private static final char[] DIGITS = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' }; private static final int IMAGE_TYPE_MARK_LENGTH = 28; + private static final int IMAGE_TYPE_MARK_MIN_LENGTH = 4; private static final Map FILE_TYPE_MAP; @@ -56,12 +57,21 @@ public static int getImageTypeFormat(byte[] image) { } public static ImageData.ImageType getImageType(byte[] image) { - if (image == null || image.length <= IMAGE_TYPE_MARK_LENGTH) { + if (image == null || image.length < IMAGE_TYPE_MARK_MIN_LENGTH) { return null; } - byte[] typeMarkByte = new byte[IMAGE_TYPE_MARK_LENGTH]; - System.arraycopy(image, 0, typeMarkByte, 0, IMAGE_TYPE_MARK_LENGTH); - return FILE_TYPE_MAP.get(encodeHexStr(typeMarkByte)); + int lengthToCopy = Math.min(image.length, IMAGE_TYPE_MARK_LENGTH); + byte[] typeMarkByte = new byte[lengthToCopy]; + System.arraycopy(image, 0, typeMarkByte, 0, lengthToCopy); + + String hexString = encodeHexStr(typeMarkByte); + for (Map.Entry entry : FILE_TYPE_MAP.entrySet()) { + String magicNumber = entry.getKey(); + if (hexString.startsWith(magicNumber)) { + return entry.getValue(); + } + } + return null; } private static String encodeHexStr(byte[] data) { diff --git a/fesod-sheet/src/test/java/org/apache/fesod/sheet/util/FileTypeUtilsTest.java b/fesod-sheet/src/test/java/org/apache/fesod/sheet/util/FileTypeUtilsTest.java new file mode 100644 index 000000000..d9a5ae2b7 --- /dev/null +++ b/fesod-sheet/src/test/java/org/apache/fesod/sheet/util/FileTypeUtilsTest.java @@ -0,0 +1,113 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.fesod.sheet.util; + +import org.apache.fesod.sheet.metadata.data.ImageData; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.NullAndEmptySource; + +/** + * Tests {@link FileTypeUtils} + */ +class FileTypeUtilsTest { + + @ParameterizedTest + @NullAndEmptySource + void test_getImageType_NullOrEmpty(byte[] input) { + Assertions.assertNull(FileTypeUtils.getImageType(input)); + } + + @Test + void test_getImageType_tooShort() { + byte[] input = new byte[] {(byte) 0xFF, (byte) 0xD8, (byte) 0xFF}; + Assertions.assertNull(FileTypeUtils.getImageType(input)); + } + + @Test + void test_getImageType_safeCopy() { + // JPEG + byte[] input = new byte[10]; + input[0] = (byte) 0xFF; + input[1] = (byte) 0xD8; + input[2] = (byte) 0xFF; + input[3] = (byte) 0xE0; + + Assertions.assertDoesNotThrow(() -> { + ImageData.ImageType type = FileTypeUtils.getImageType(input); + Assertions.assertEquals(ImageData.ImageType.PICTURE_TYPE_JPEG, type); + }); + } + + @Test + void test_getImageType_JPEG() { + // JPEG: ffd8ff + byte[] jpeg = new byte[30]; + jpeg[0] = (byte) 0xFF; + jpeg[1] = (byte) 0xD8; + jpeg[2] = (byte) 0xFF; + + Assertions.assertEquals(ImageData.ImageType.PICTURE_TYPE_JPEG, FileTypeUtils.getImageType(jpeg)); + } + + @Test + void test_getImageType_PNG() { + // PNG: 89504e47 + byte[] png = new byte[30]; + png[0] = (byte) 0x89; + png[1] = (byte) 0x50; + png[2] = (byte) 0x4E; + png[3] = (byte) 0x47; + + Assertions.assertEquals(ImageData.ImageType.PICTURE_TYPE_PNG, FileTypeUtils.getImageType(png)); + } + + @Test + void test_getImageType_unknown() { + byte[] unknown = new byte[30]; + Assertions.assertNull(FileTypeUtils.getImageType(unknown)); + } + + @Test + void test_getImageTypeFormat_success() { + byte[] jpeg = new byte[30]; + jpeg[0] = (byte) 0xFF; + jpeg[1] = (byte) 0xD8; + jpeg[2] = (byte) 0xFF; + + int result = FileTypeUtils.getImageTypeFormat(jpeg); + Assertions.assertEquals(ImageData.ImageType.PICTURE_TYPE_JPEG.getValue(), result); + } + + @Test + void test_getImageTypeFormat_default() { + byte[] unknown = new byte[30]; + + int result = FileTypeUtils.getImageTypeFormat(unknown); + + Assertions.assertEquals(FileTypeUtils.defaultImageType.getValue(), result); + } + + @Test + void test_DefaultConfig() { + Assertions.assertEquals(ImageData.ImageType.PICTURE_TYPE_PNG, FileTypeUtils.defaultImageType); + } +} From f81f08605f8399b6c38fe64e9a5d6d39edda200c Mon Sep 17 00:00:00 2001 From: baicaixiaozhan Date: Wed, 21 Jan 2026 21:46:27 +0800 Subject: [PATCH 2/3] fix: use longest-prefix-first matching for magic numbers --- .../fesod/sheet/util/FileTypeUtils.java | 23 +++++++++++-------- .../fesod/sheet/util/FileTypeUtilsTest.java | 2 +- 2 files changed, 15 insertions(+), 10 deletions(-) diff --git a/fesod-sheet/src/main/java/org/apache/fesod/sheet/util/FileTypeUtils.java b/fesod-sheet/src/main/java/org/apache/fesod/sheet/util/FileTypeUtils.java index 456be0afe..ec9f0a700 100644 --- a/fesod-sheet/src/main/java/org/apache/fesod/sheet/util/FileTypeUtils.java +++ b/fesod-sheet/src/main/java/org/apache/fesod/sheet/util/FileTypeUtils.java @@ -19,6 +19,7 @@ package org.apache.fesod.sheet.util; +import java.util.Comparator; import java.util.HashMap; import java.util.Map; import org.apache.fesod.sheet.metadata.data.ImageData; @@ -33,7 +34,7 @@ public class FileTypeUtils { private static final char[] DIGITS = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' }; private static final int IMAGE_TYPE_MARK_LENGTH = 28; - private static final int IMAGE_TYPE_MARK_MIN_LENGTH = 4; + private static final int IMAGE_TYPE_MARK_MIN_LENGTH = 3; private static final Map FILE_TYPE_MAP; @@ -44,8 +45,8 @@ public class FileTypeUtils { static { FILE_TYPE_MAP = new HashMap<>(); - FILE_TYPE_MAP.put("ffd8ff", ImageData.ImageType.PICTURE_TYPE_JPEG); FILE_TYPE_MAP.put("89504e47", ImageData.ImageType.PICTURE_TYPE_PNG); + FILE_TYPE_MAP.put("ffd8ff", ImageData.ImageType.PICTURE_TYPE_JPEG); } public static int getImageTypeFormat(byte[] image) { @@ -65,13 +66,17 @@ public static ImageData.ImageType getImageType(byte[] image) { System.arraycopy(image, 0, typeMarkByte, 0, lengthToCopy); String hexString = encodeHexStr(typeMarkByte); - for (Map.Entry entry : FILE_TYPE_MAP.entrySet()) { - String magicNumber = entry.getKey(); - if (hexString.startsWith(magicNumber)) { - return entry.getValue(); - } - } - return null; + + return FILE_TYPE_MAP.entrySet().stream() + .sorted(longestPrefixFirst()) + .filter(e -> hexString.startsWith(e.getKey())) + .findFirst() + .map(Map.Entry::getValue) + .orElse(null); + } + + private static Comparator> longestPrefixFirst() { + return (a, b) -> b.getKey().length() - a.getKey().length(); } private static String encodeHexStr(byte[] data) { diff --git a/fesod-sheet/src/test/java/org/apache/fesod/sheet/util/FileTypeUtilsTest.java b/fesod-sheet/src/test/java/org/apache/fesod/sheet/util/FileTypeUtilsTest.java index d9a5ae2b7..e4321ecab 100644 --- a/fesod-sheet/src/test/java/org/apache/fesod/sheet/util/FileTypeUtilsTest.java +++ b/fesod-sheet/src/test/java/org/apache/fesod/sheet/util/FileTypeUtilsTest.java @@ -38,7 +38,7 @@ void test_getImageType_NullOrEmpty(byte[] input) { @Test void test_getImageType_tooShort() { - byte[] input = new byte[] {(byte) 0xFF, (byte) 0xD8, (byte) 0xFF}; + byte[] input = new byte[] {(byte) 0x00, (byte) 0x01}; Assertions.assertNull(FileTypeUtils.getImageType(input)); } From a558c9461ad889d2b65f837b3fb730a119a51e4b Mon Sep 17 00:00:00 2001 From: Bengbengbalabalabeng Date: Thu, 26 Feb 2026 22:41:27 +0800 Subject: [PATCH 3/3] test: add sample image files for FileTypeUtils tests --- .../fesod/sheet/util/FileTypeUtilsTest.java | 41 +++++++++++++++++- .../resources/images/fesod-logo-jpeg.jpeg | Bin 0 -> 22682 bytes .../test/resources/images/fesod-logo-png.png | Bin 0 -> 15935 bytes .../test/resources/images/fesod-logo-svg.svg | 1 + 4 files changed, 40 insertions(+), 2 deletions(-) create mode 100644 fesod-sheet/src/test/resources/images/fesod-logo-jpeg.jpeg create mode 100644 fesod-sheet/src/test/resources/images/fesod-logo-png.png create mode 100644 fesod-sheet/src/test/resources/images/fesod-logo-svg.svg diff --git a/fesod-sheet/src/test/java/org/apache/fesod/sheet/util/FileTypeUtilsTest.java b/fesod-sheet/src/test/java/org/apache/fesod/sheet/util/FileTypeUtilsTest.java index e4321ecab..fcd84924b 100644 --- a/fesod-sheet/src/test/java/org/apache/fesod/sheet/util/FileTypeUtilsTest.java +++ b/fesod-sheet/src/test/java/org/apache/fesod/sheet/util/FileTypeUtilsTest.java @@ -19,8 +19,13 @@ package org.apache.fesod.sheet.util; +import java.io.ByteArrayOutputStream; +import java.io.File; +import java.io.IOException; +import java.io.InputStream; import org.apache.fesod.sheet.metadata.data.ImageData; import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.NullAndEmptySource; @@ -30,6 +35,31 @@ */ class FileTypeUtilsTest { + private byte[] realJpeg; + private byte[] realPng; + private byte[] realSvg; + + @BeforeEach + void setup() throws Exception { + realJpeg = loadImage("fesod-logo-jpeg.jpeg"); + realPng = loadImage("fesod-logo-png.png"); + realSvg = loadImage("fesod-logo-svg.svg"); + } + + private byte[] loadImage(String filename) throws IOException { + try (InputStream is = getClass().getClassLoader().getResourceAsStream("images" + File.separator + filename); ) { + Assertions.assertNotNull(is); + + ByteArrayOutputStream buffer = new ByteArrayOutputStream(); + byte[] data = new byte[4096]; + int n; + while ((n = is.read(data, 0, data.length)) != -1) { + buffer.write(data, 0, n); + } + return buffer.toByteArray(); + } + } + @ParameterizedTest @NullAndEmptySource void test_getImageType_NullOrEmpty(byte[] input) { @@ -66,6 +96,7 @@ void test_getImageType_JPEG() { jpeg[2] = (byte) 0xFF; Assertions.assertEquals(ImageData.ImageType.PICTURE_TYPE_JPEG, FileTypeUtils.getImageType(jpeg)); + Assertions.assertEquals(ImageData.ImageType.PICTURE_TYPE_JPEG, FileTypeUtils.getImageType(realJpeg)); } @Test @@ -78,12 +109,14 @@ void test_getImageType_PNG() { png[3] = (byte) 0x47; Assertions.assertEquals(ImageData.ImageType.PICTURE_TYPE_PNG, FileTypeUtils.getImageType(png)); + Assertions.assertEquals(ImageData.ImageType.PICTURE_TYPE_PNG, FileTypeUtils.getImageType(realPng)); } @Test void test_getImageType_unknown() { byte[] unknown = new byte[30]; Assertions.assertNull(FileTypeUtils.getImageType(unknown)); + Assertions.assertNull(FileTypeUtils.getImageType(realSvg)); } @Test @@ -93,8 +126,12 @@ void test_getImageTypeFormat_success() { jpeg[1] = (byte) 0xD8; jpeg[2] = (byte) 0xFF; - int result = FileTypeUtils.getImageTypeFormat(jpeg); - Assertions.assertEquals(ImageData.ImageType.PICTURE_TYPE_JPEG.getValue(), result); + int typeOfJpeg = FileTypeUtils.getImageTypeFormat(jpeg); + int typeOfRealJpeg = FileTypeUtils.getImageTypeFormat(realJpeg); + int typeOfPng = FileTypeUtils.getImageTypeFormat(realPng); + Assertions.assertEquals(ImageData.ImageType.PICTURE_TYPE_JPEG.getValue(), typeOfJpeg); + Assertions.assertEquals(ImageData.ImageType.PICTURE_TYPE_JPEG.getValue(), typeOfRealJpeg); + Assertions.assertEquals(ImageData.ImageType.PICTURE_TYPE_PNG.getValue(), typeOfPng); } @Test diff --git a/fesod-sheet/src/test/resources/images/fesod-logo-jpeg.jpeg b/fesod-sheet/src/test/resources/images/fesod-logo-jpeg.jpeg new file mode 100644 index 0000000000000000000000000000000000000000..39a983eb56c94922c9afd741aa21d136b34e9630 GIT binary patch literal 22682 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 literal 0 HcmV?d00001 diff --git a/fesod-sheet/src/test/resources/images/fesod-logo-png.png b/fesod-sheet/src/test/resources/images/fesod-logo-png.png new file mode 100644 index 0000000000000000000000000000000000000000..65d71cbce5c9dfdfe94901866f8a6ff64f0af327 GIT binary patch literal 15935 zcmeHuc|6oz^#5m!nxrs~iYFO0%2ElXY-6iIvSvw}<QEC6Y%e zW1otmtR;%EG^S)}>?X_bJ0JSKe!u^}|NgvQy?TAlJ@?#m&pr3t_c`}Yl#P|?>XqwP zA_%hDY(Lo+L9jva@7#*zKnc~Wk%#{KKuRPbF{5aar?!j>G%;y-}Xer|=QF*t4 zjg`MfvpF5{oDTfxwOgF7Fo)1!er$h7*Ftoo_nkUlB*R;nz`E%4V)T1s%7OB57vliu z=)#idfiLl)qgzkeMRyQCS~mBy3kN1*c*hf4Crzg&G4!L7L5SqJ$-V}CeVsJ9eA_a0 zqVqb*nQ_gmpzP>@@P}3T*ft`t7Mez!mt-O^JH({xIYs_{od>o+@^f@ zO9D+4Id@J-+!gb*E2ts-sqLH)4}HxpHA`#WEF%w3Wy?SKvrLDnq4Z{dPk`Qzydp36cZY;in zAhUl3A-GLEvHe_(;c5{Q9V2I0f7rsyfS}NJut50ynaXg*USUGhR?ZHTTXG|iC8%G4TN*?cUSQ^~2J#8u=0ugY zzWM*z2&hEjBw$$Kv3k`b0$N}OA-3=Hdfx!(JZZJJpK|gu4AEWdw+K&k2 zXr||OlnkS|0U71q9D!S7#9q6Pi(yHC9zmR^T10VVIdn9Uq*nh097qIC<2G|!dJUGo z?5`k0`KZ!XiD2YEL`eMf21=U_aQ`st!CWKqj+%oI63kb<%4ra0pd}1FFED#WfJJO? z59Wm;FK9UokAvZlN>Vq_L83OWzpRqIvT+RQ`CFJ^W6p^UhCxR(gv7IDDer_pOwa`u z*29>sz7e`^8lkVpQ&*XBF-;-Bv5fML!5|?=EqgFuqjXIyfP7R)yygH~U4bZ0KLpzD z;l!%LGz(){*k=+{3q}n#!$Fv!M&ZPYpybOetil0yd=!w^0$H6CTL(*7Eg8fjGju)n zaxpd<5xA>q%*<0L`L7_>;V4~?13(6|UA@N4{DG43KxXK!N4eJkIhC3D4@#B@V(pL8 zU5|2uA+BC!W_|V9W~za%Z$Y+AmFy*$yT%O`cDVviDHW8W zfKn0^Q*)T)dgC69=v3>qz6w3t$%P+X7|AiiX#Wae5)mf+w-F5rDMSakyqurhE+I+o zW^uX+Xiz4Yb8^4iov#xvg^%&|iC6_HyZ{w~g9p?4=3L3=_YlQClrP&E@}FZs>s<4Z zq6ItHGip*1xD6j2WEzj}NqES6LUg`G6K$d2Bq1IjJWtd2B@b8#DwvUqvJhK8e5R() za@hNjo;#^M7~EuQX+vnJ{b!fHF3fIJiFU9K#z~McE*2xJTX8f?YX^T_wsM>el5yyG zv#?lpd-3>!1ofOvqpy=BU59c3SJ&TH!JN6+GT1GJH}~_2Sbh!~j-G>tytai&396dQ zJI8~azMtQI?z*~y{sab{EuQgnHz*qLuUMyCQe0&CMynRPahqZgD=g#RoTp+iTHmMd4uuKM6PhSY$s&SuYi4zDT4 ztfZXRoNOz7D#F@ad|!mr|44s)Y;8N~}XhB4p-Z$ULYK3<1%fVaA7C-_Y~xGF&~ za0J>#VXv4RfbI{p^!dW4ANS^FdryBYZO~TXOCZVCXvc#N--N}-v@7hYL*j9)|G;ld zqvidq>9>!4{&fYG_cDYL#h|@H+(TJf4Q2%7jYJS)qnZmo6AAuFa7dtGM%F-2Lt%mh z97moCvlIUAq{JSSEr_ z+ZJ}uA|qmhfHCO z9=q-1iLfp_8JOx_2eWWS7v=L~Z&>ETNn5KaR%6H)b6^|bCx#J;GsRRy^hb#Tf`_2< zXgc$`cjv9wyDd*E#pCEK?39B8C6u?C#Uc|7KZt;5*?k)QcFs~V8Ddaj610y#O+5QM zkjze^;ncunO}4O()(M@n6yIUQl)YYwcRB zk{zsGcJbDapQ&kno@+;Q*mm^z5awOCdb#w1Z*qR(7*~IElPBIk&^h2v{P+}YA4?|D zg+xd_*Sq{?`goT3%G)5)H~l8g29QJD2YGiAUsIm*39KpKryYzegRN0^Jn`vZmh-|p z+o~VzWAu1GC&>&6A@QUlPv@y=AL9qx`kF$ZpXM4?V_by84MO?{)P=q?81^RRcW3#Dr@!3JXvVUh#lT zSYyq_w17jHSS^t)fxP_>`8o^x_J6onkX)bqAv1vdKiohj{vm^Gg+JV$G@<9|A_t;K5U4){WeC>{-%=Q8LA zsAN&83@aW65uL;t_|L{xmwr5{{IMR;>4^d~AQX8W7hnOdX_&ou+4eivs z0kes|;+WGb0bwN9L~^1?^kou3hP_cFCBP|3iYTaA(gnpM(o2Ji8TDX{mj*ot?xqyG z)Da6E;Lf#bE>AED- zMAg<2#g%Teut{&eg)jWL>0CY+A!B{GP{2hukwmazJdA{~=p5Q4R z9%jhoGq)1w)!^)@JMRBQ(BaGs`hX8M#hl=12OIXnRzA$=dM|FWR@{V4o~$zKvQiAT zQBs5^(DhPKeQBU^bR22A+rgr{us*<2DX9jF;<4>5_I-_0)5GsQ$1={rSgZ11VWq3C zIl}OdhQ`(NYa>4fTM}$&RwKyr@lk<3XS4W$zRlv63m}aV+C3NLdXG+5H}25mKARGR^~G8A|v%A1OL>J|33^Rtr?- zBlP9wls9Xi$FKYS=GmHEQnG;yFQs;L`Bo(bVuHN}4yC;q)*qZw{Z0@njFTkMUpd6P z4I-5v%m}yY%?Q`8flduCBf=6FRoEyB1Ed;b7pxY=v#MZG{;@A`tLau<)F?>_Rp6SV zrRjQ(u#f5=Ca|)RR~Lm_Q*nDyiYpPFh)(BClbJ~};g%H_a{?B9`R80K+3B`5i?+C$ z0OQ(6H{+Zy)~!hC!;t5+xNVRozb0oNP`~LAcz~ z*!w|2Bmdd_^e=pHL@@HztH4(0sW8*IG_rg=n%t(!gw15{e=crZ)lyYSjlL5jRvO+R zD&?c?#_5(xx@g&%^L(n)y>mW`y^nqhPMrU2&P-j4m*){7XidYm-3Q6GDF4Kf%Gs`( z4&|{78=|;$(zawol=3FQojlNehh{=%J{9>6XW?NrMc{4jUvT4zSOY9ZU1pIs9x%RE z_39m_rfq$g){iA$N-7Ew$S=!i2)pYrZR3V| zwMD=4wT9sI^Xt~mq0Qo2aHgMAx}sXCL$qqtJK>y@RPoOTkt+~(Z`WYOa=HwzEwB0Y zV_PHR>%dEf2Zg6Bs^M1~JzG@aI(l0k@WWfcE3Q@$6Ab5P9v!N>(dC4v`0|voVEH}q zxS@AzE$P@J?X++WO&$?gl~Mz$}N-gfaBKuj_u>R;L{eS-Jd_m?n!{z%`se6a)KsDVlM|72aRpEJ>S@D$q^ zjGYC>hQvYwZ(ZdytV(p#;olNDcLR44vH}%_5u|-Bl?F3QsfoM|FthZU9aI$_S6AIz@ZZ~Du8!vroSWVWx=3 z<4#Hj+d!43Fp_zUamV}+yRvs#Owp4%Jz?qcHU05hb3~u&`MuGDgD|tLRu6F<@(%eR zQ`LFFqMJE+G0Ua9+|7}jbRx$D67iw0^_k=~pNF!x zRot{XUY3=D#`&k7dm|vv-a*kUv?4EX61uG#T?#*UOW8cM#8WB;lWoKtH6nIKmB#-x z_4l6X66u#I75|{OOgioax*pMYYlObzsq$^tw(f8a4o_vC_T(wEg20xS;1oRqb&kbT zFj5Fk-3=V?p~XYf=ncRGsH39jnnahA zWc2sW-S_UnTN!#b@8BiC={E#eed>g5z;$!YIZdm$~gfA(IBb;#69c%D?F0>z)X};nSd&ZN5GxV#Rnn`;x(NqgE zn}c6@JrPh2p~}fqt2UAYz6{uIqrqZ{CAz5iSU_vp?2`^a>?;bdZA&(E<~&XKfAoIM z1--}c)I10lsJ>+s>U~=%%9xhHwv&b}O3(gskd z0T)1fO3OpfpeWttko%)*Tm`iF)|9QjdC?eXZAw~vv1p@|ZmPsu5xkn97Q%_eLlUt> zfJvB`L-_^{@1UoiuU7#6^{o1r0dcw(7Yb{;R-DPr2t7VH(O?68WX9k_xE?$Cc#MQfu^A6^}mmMDu ziz};lEGxyBP>`?Y>u*ed_ile=j(gZ@BaQzjT5^b($Z>O zow8Dex)`W0%vZ_oUbKJb?r%^{Q#0ViUWT)WH2hQq_f5`&br0%6Rj`dvzmJ5-vjJ*F z_fS*|3#t7ZCv(n~6N}a)s&zwN-u14S5p}zsh113Y!(fIl%`5=9P1xg1xdO3Rd7omQUcRS@*KO)JCs{a^bhNB80+& zmE)xxu_;)@1BdkTyDcm4(w1FKktCf?sVp5U{5e&*VSeEX7G3omoyW8;S_AW!9PDNa zz;&-rzZTpWx>^7mZJxB`hqO7r7_IAP?{hsaOem~HhsTfpVDHKhfiO5&=xrhBW6LkL znN^NYF_PZvVUq#Z-?NkS)eD{dZ^TJ~(o_FqxZ2GFH#ezn3z#fA>8dvjyDu#=w7D zKFk>00889pMeh0O(DywZ*#e2w^_+!I#fmH?5z^@^j^7DL7SJwlb(?JL3TQY}Ol4)S zAf3MC5x`q!LxcnG=b`@kVoj8&)OpRIfJ97Bp)J34fNM1F;4si62PJv4c|89*N+lvx1zyHE~1`?Juj zhw~bQtU-lr5kGfH1Vq>g^B$vVVZy%< z3n{kY2Nxz_ISvbnMoi17Gafg2&_O+ghDE2PJGYOAVMV|>b>$Z49#{qD)xI%6 zKY=E64)T8_J`fmd2C7gCCOklXNS+F`mh#|(RlgQ;&{=F%3A246^}bH z{(0%1$CRZ6E|_VxP-#+imiIU7breau{1zwQ&xd{xAJk+b74|#a^ns^eBeGn6%(ZZ) zoOhSog=7*(GV*eGB_qd4r{UO^e?DLC-aYjl+ygwc@bi{on#RoN6nhu_6^L_=p5TFj zZ$Zn~EV;Soj0po@5T`iis^k*Rbx9wbq^>dUG3ro>UXVW6nFfXc1tZNK&-kT)1w|?`p8tH#m4{5B6*N9DP>Z?YX8=gmBIkj`(Net_`s_NaS zx9lyX!#ME#6~wry1KmT_L&=^lQ`7auiGq5KP6UzdMBf6iHp8jb1hLeJ+q_r&(SE5i z{*%UVsCA>qL0w!;B#}XCmxsHOQovlTzZQ~cA{LN7|9~15)TX|h$Jq-S+WG0B9f^Lb z5oSS;in=w z1@-ZBOUfMQh^1TgVBP={6plB=2G`4yBBA~V5dg-m|F)Zo-mY8)!-IkYjV~;;B;XTZ zCHiU3e)S3<&&1M5`<(r7SD;ch3IPQ~g$C8j)?GpI)S{^A;@cwQTc8z^5@^-uh@lnu z-X)!C&Exz_%6GS=7k}GUoM>nVLU%3-RoA9j@v3CELz1hoB&WCUsKP3^H@FEQ4=g^4 zr>d=rz*(d(YGh)~egzTh`jw?GQ}!#^Q5zw3HkJrp1#J+`H$oDRepx{q3RoAvwx=>9 z4?xGPJ22Ky*_;)C43b2|jPSP5* z5dj3fGzLRAX#)Un$jFF{vOSViH8W^h8qjMq&-EjK{#A=I+sSMrF}R=zW$6IId!4yIq$bELv!R?0idbaqL zyBod~M(ATpUt8b{uH|+v4wbu>f?Eyi?z{B048Gt(0P;uh$PWkDMv;(REvW!^noVjj zPu$`>CAaW0Ah~NIEUKrlmu<8UaxJIDb-$Ltj9d;Aon0JHMigYic!7()qiM?#TM6T# z>8)_Q=3npy;{`4{u;v;H4r=zuqR8b$UIq-e5pc>Ta@Pfht`g)GU!WL_CwG;>7vxAm zP(cB2z=0}oQ{QuEaqxOGwh@%=S;zH#`R=`n&L!{^q6UpyH62%&k?Y`=2{#t68uoBJ zQ`O8tF%3{AL`f+;N9-tC6eLeJm-?j5fBWRzfV=6av~W&O@9rih!q^8m~kLdSO2)Un}GpRet9 z^PLm7zxI*|8r_-Y)dlx=NxrjyfPZpLm26M60&A~>!%P~30Yk5Vly_SH`7dTrS=(>9 zR)+3Iw19TOi{~?Ym^^a`DrA4v*{A((Y3=oEl)lWwrgPEmonVuXyB`q}h|X*A>g54@ zAPqUy@$qhKW=Uyp_7A7eYp5)JP<@r#Rzd%#g->RnhgZj;>a)+g9PHSbSpdCibXm>r z(lel{iyXeOeO4WvQ)#Z1zwKH@3!g^4lloP%YL83=Nh>p~Y}bZQ*TreqMxL7e7@O(# zaQ;ycM@%cDeL-Zo&9U+calg>RTqD0+;b2fAzW@Gk&|L^-b zG~ng*a~L1ovY z&+VZBq8q+vmev!c>q>@Ym&oZfzZ{aH2as?o$fx;tWfT)@vL994VAsTKb_^*ye>hfm z1QrI;an}`s9KR~13OJ8Kk{|07lpE|$SKYy*tD{QoS1xz8cY*z_=hbf=Hy;Crv_J=# zaaiCU3_}OlWq0lOU31V!9@Xd8$NgAU2o9ZBHBj+zP30=>F!PFX{s^$DKVwN!S;Al* zjO_Tad>8z|H1((XP!%SGIIN$KVd$a{VOaE!4FlkeBasb#a9D)dJvLxVNkBKS1IFQC z-kmBwKKOdu{eOh4*%(PE(k(w|9KFUTwWUZh_PuJ3mRz|r9m9`BN1InXzcAnShCbeGMI{H#jx3k{FQ-F#m7 z>DZUGme9B-frc1<@(&yi@+5Ca_j~gZ7f2>oz3fwI)W${^Wqi`5;9BTV7he|CFziyH zVLT~XOeI6EZl>i{f$EbCrWF0pZ*b~v9OH!FFvQDOL9&`JdYkTU=F!*xJ%|m#9C$XM z=^TFC!6E!_e2kw@a7lmO^Y|Hux(yXd{547q9}*2VnCp~d!!Izg9&be;Kuv~}Q%$O( z*}6aAPQk?Ii2GDe{wqo9;!~zztpP`uA|2zITDGp33HQ}$J@=5=i134K3>-g**f*GG z&xp6Z+_h|v1^0(Fkd%{9 zKu3r0w4th?awd7r(g1^%2f6W?Ea2j-Kv#=KZMA)z0`7!(D7?Y!lK<6JOzPwR>9YzwYRwh3aCC-qWD@`-)x1joFyhXsDBnox9c+7G5M(M6N0*F1iY}oO7r1b%wrad3Yqk zU~uhEo~9JR6$X|zH8FL#eC{8ZN-_(3G+$+rEXZOo|NSl~*j^v4o6!tstcO=jX*roN zG+1p;i2JlI+>wpmOVL|BJkheSYuwtjJ7|Zv0K0%@TI0-|Q!yV|1*chF%M`Q2oZB3j zmd*K?&>c3!;PFKBq1Ky*GJqa=^1P`nW2c|{-S!C?x>el`i>eOeZRL1-6XW*iP?}qZ zD+d0%QYDK%HY&W#)YXbNP1&ILg7%^P4WVR2;2s`$0^a079#20cL4{21bmYmjuW71I zGe0l2ffP>va|qy?B{rEkO^BPsD>$kTeLXdg=B)I0+0R@ZdDIfbp|m=$@|$DFVGj> zqyd=KfN<3gc+^;edUMm*X(0-(@D5xeTeB^1*JL(;_XGmq(V!$=smYA3l11;AE!f|; zjActwaQ^{1Uf-Whbq+cD$T6z4j!XzpOPhKAE-=t(rpLHV5DIfI29+qWVSOi62PQZ_ zvN^xm$0UNeyMZnD;i(z8ByteUu`K3n;lJ6H8DnDP4 z#KfZ2w)Ie1?wDx(y1#tusaT2Nt9O~$B*3ogjo7>20Qu)c&KH$2X?Y3`eYKdaM`_z` zM~qYdi;CdDRp1F+{pK<0E00^cL;a~!H*gILUr{j1y5IgO{qRmMhx@SI-KtE-H-D zK#AbGn@p@UAiQU~r#d~YEb)WYPPz<|7zBz{;1@?^pYwJ(U-9~x0k?dRma^TH^ z>)9&VHxj|scfj)jQ%qtFM=6W0f^PW+jh zxmG@*Zj+n1dC2QyfN!qI_*#P3$PDv{A0uqO1cxp?0%?C0Y(*h3| ze^{~)x)Xg~1FH(?;#?(bxp7PZZG@Y9v3_PizTV^R$KISQ`4XGIGKT_ z{2vT0ZT>pxTQxFx3a&{S9x*jOZ*zKimRjU@f?TEnO}A@gZZNT@As7t}!tJ4yfzJ4X zu|r<1-ZB$o?rPZC8V&YPRw&;fu-0ugw$HCE$C`N6?$ad_-3G@K-JL&5fI9I2&#ZN( z99?GL?;m}KZ>}w0_V$%o7YWpXmyz(qYr}lE3+>-Wa^Z4#Q+VIlyLk+CLyhFSAF+76 zx}MCii1^M&TW*sI<;7-aUb1%$m_n;FJZGvI{^Al|pPLglW6zUSJEI$SY+!dV4dfEx z0@168SN8a1!Ot1S;RL8`Cl4lDOHh&ObHeTk>NiOS{KqGn(FghjJmUb&Q^Y`di#d7!b5D#EwdgY^DL{f zE&S!#Svk>b`CevecfxpEG99Z=G(X;PHD;b01OBK+NRPy+_|NI8>IDYA95-Y>T#eIs z?yExxZ~nGLU|FpFu(a=8JD;|1E&YP_tH^c9cYYlwaKywsW@x(#o}_9zecj*yz^f4I zj_VF6!>e*kvg_BPqUx5HU)j4ZztEof+|K06!-6h@dRQImDcgz8=`@_i-nEo3n(GA; z6MBkN!X>0>y^#3PQ*Hh)baIj!%CX6A9v>{WcNK2qUo{$v(p97)c~FBpX=~t|M#E~< zkNJ4VwD`2#lmyQ=hhlR|PKYs-UNvBb+k?-!^Zp)(eS6fR$7uF^I1kfAMs59gKJG1S z0Tn308pj^y`@}I&>_t}?sGB%3`tayoPLwVJI+{^ErdrrC8MU`tCyRp|&PG2q-Gpo$ z$#Ae$wW@{LJt=)I^{G3hRLRmHW>gS(1cSQ%XI@4d#|<~=zV_rHS|G&hquCX-l74ui z^GQVCZYr|jI+)eW!J(9Tg|6`ax5>7rCxy=0K-F_|mKQwm6e-aSX})vkw_RhkEOG_v z^p-guP=dCJ?pKl2tEN?f*d%z|mv=*$aCJYG=40FK;b&hiTK+?fK8;pY9oTniLbvXh z`Vk|b9$vY3q!#RxvVgf;gu81io}~`(*8!fZ${lkUa*T7%XkN?M6{RJe$@eo^ta)bF--H+A zpPyz*4KF}aU}yzssKD_0Z=dIF`LKle0IM6aSV}@ z02Z}6X6<}r@{ulJ6dQLTajgfx28{{7Uiy8$;nA0~MHVK|i5|FQf|o;p-Pvi)ZJ7to zJZEAvcmPs-I@-FaF>T!DJssA^o$H?*-poTz3&XQj2GA6qU$LBgS>am!ka1X2D!eIE z0zn^tZBH6ZE;RaVIr=+BJp94YmU0_5rfCg;8b(c~Kj=bP82T2oBM_zoU<`d@oYh|J zQCmdaP&x5}GKz!ke+|&VJqGE(uIJ|mUO6c~Wft;F#5=+0$aW~g!B10^jC~IF#s5;2 z3wy=WJpZK@x&XqCA6c<%y=vAKs%-J^*J(b}fMYWXU=lkC_Y6;D1!W8bwvy&W!zU8} z*0{oHFRk3R`%J1Hr6_P*)n&mNP7w6|O3jxT_ZAMyH2{20Y#IY#i!+3}quL%~Tswf< zH2~gE03b*01`$Oq5XdMuq>hrC#%io!u0rsDRXW~u4@YeA^)fk%1h^2>1iw*9(u#jq z#n45Lg6ty<(p!|g7oM$}aMc&N0Sz1?#>GQuFGL@A-i-#TFQZ_6YP))|S zNbKBlAw$Y0`?UPm`^JyA-1^&|nSC;*9e0xPI&1TamG7OrF06aWxNhO!>=yl>CC^xe zVSDo}S;>8GIsc5L+n$EHwBo+>qDJ@dhG~_?L|lVN1kV0y%?VeI81fV_^>+pd5FCaT z4siSincxSO8Zm&hV0-*KONcs202Q}daz_n--5V^Jpg6{a@W*-rg>q4%I0c9JLHX8; zQML}|sHO@X*T%Q)1?C@cTk=AF>?q6$eVA`!PRw5h(Pb6j*cV&IAUVRYF2InjWM?c4 za~OVv)RJD~DFFgwz==#Gf>&?kA+BgnD^1LQi}r+2wq$!FF;S!A+9NoZAHy{56CNt`9dfexbrrR9e|yI zM*60$#C%~8VglUoRMrGAA`4#OWh9WhR=~T`&WapUW;3K=Lnqc759zAom9mjKUznmBY#D3by?r-h zeYYdv-)BScqqaH!_XNbov2u8RASQL}<*ko$Cw=~YxrV~*9`u1Vu~CJmrR(~qc+aUO zkN9WEXO(FmB#v7tm#Y`gHdXA8|3JVZtI&cGF>RPYqE#%6wBF*>GnhxG(v7v!-;T-O zq=|(p!Q9i)`e?JPk5_n)2R9TS?DzH9ab(d=G=IE>!V`x;CZ#LdOs@zktTT0 z<9gA1P(L92Kw2XF0#u&U^;#~8bAbC>N9RmAay(wU*NmHXkM9U$*t+$A>$Ilt$T{SHft@1sKHO`Y%ntVAt!75yTdx01|Q($ zsjbHE2j$(I$WN{@9PsLaZ?@RsDe74h<_4S~vOZqmzq7APT&hGrNeJEsj36GamehB7 zg3*2lsLOrmJJcPZ?kxCy;A_hN;wQ5IzblflbsnQt=e>9H(5^|;9A?H=@Z C(dX0v literal 0 HcmV?d00001 diff --git a/fesod-sheet/src/test/resources/images/fesod-logo-svg.svg b/fesod-sheet/src/test/resources/images/fesod-logo-svg.svg new file mode 100644 index 000000000..6c080ff8d --- /dev/null +++ b/fesod-sheet/src/test/resources/images/fesod-logo-svg.svg @@ -0,0 +1 @@ + \ No newline at end of file