| /* ==================================================================== |
| 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.poi.hssf.record; |
| |
| import static org.apache.poi.hssf.record.TestcaseRecordInputStream.confirmRecordEncoding; |
| import static org.junit.jupiter.api.Assertions.assertArrayEquals; |
| import static org.junit.jupiter.api.Assertions.assertEquals; |
| import static org.junit.jupiter.api.Assertions.assertNotEquals; |
| import static org.junit.jupiter.api.Assertions.assertNotNull; |
| |
| import java.io.ByteArrayInputStream; |
| import java.io.DataInputStream; |
| import java.io.IOException; |
| import java.util.Arrays; |
| |
| import org.apache.poi.hpsf.ClassID; |
| import org.apache.poi.hpsf.ClassIDPredefined; |
| import org.apache.poi.util.HexDump; |
| import org.apache.poi.util.HexRead; |
| import org.apache.poi.util.LittleEndianByteArrayInputStream; |
| import org.apache.poi.util.LittleEndianByteArrayOutputStream; |
| import org.junit.jupiter.api.Test; |
| |
| /** |
| * Test HyperlinkRecord |
| */ |
| final class TestHyperlinkRecord { |
| |
| //link to http://www.lakings.com/ |
| private static final byte[] data1 = { |
| 0x02, 0x00, //First row of the hyperlink |
| 0x02, 0x00, //Last row of the hyperlink |
| 0x00, 0x00, //First column of the hyperlink |
| 0x00, 0x00, //Last column of the hyperlink |
| |
| //16-byte GUID. Seems to be always the same. Does not depend on the hyperlink type |
| (byte)0xD0, (byte)0xC9, (byte)0xEA, 0x79, (byte)0xF9, (byte)0xBA, (byte)0xCE, 0x11, |
| (byte)0x8C, (byte)0x82, 0x00, (byte)0xAA, 0x00, 0x4B, (byte)0xA9, 0x0B, |
| |
| 0x02, 0x00, 0x00, 0x00, //integer, always 2 |
| |
| // flags. Define the type of the hyperlink: |
| // HyperlinkRecord.HLINK_URL | HyperlinkRecord.HLINK_ABS | HyperlinkRecord.HLINK_LABEL |
| 0x17, 0x00, 0x00, 0x00, |
| |
| 0x08, 0x00, 0x00, 0x00, //length of the label including the trailing '\0' |
| |
| //label: |
| 0x4D, 0x00, 0x79, 0x00, 0x20, 0x00, 0x4C, 0x00, 0x69, 0x00, 0x6E, 0x00, 0x6B, 0x00, 0x00, 0x00, |
| |
| //16-byte link moniker: HyperlinkRecord.URL_MONIKER |
| (byte)0xE0, (byte)0xC9, (byte)0xEA, 0x79, (byte)0xF9, (byte)0xBA, (byte)0xCE, 0x11, |
| (byte)0x8C, (byte)0x82, 0x00, (byte)0xAA, 0x00, 0x4B, (byte)0xA9, 0x0B, |
| |
| //count of bytes in the address including the tail |
| 0x48, 0x00, 0x00, 0x00, //integer |
| |
| //the actual link, terminated by '\u0000' |
| 0x68, 0x00, 0x74, 0x00, 0x74, 0x00, 0x70, 0x00, 0x3A, 0x00, 0x2F, 0x00, |
| 0x2F, 0x00, 0x77, 0x00, 0x77, 0x00, 0x77, 0x00, 0x2E, 0x00, 0x6C, 0x00, |
| 0x61, 0x00, 0x6B, 0x00, 0x69, 0x00, 0x6E, 0x00, 0x67, 0x00, 0x73, 0x00, |
| 0x2E, 0x00, 0x63, 0x00, 0x6F, 0x00, 0x6D, 0x00, 0x2F, 0x00, 0x00, 0x00, |
| |
| //standard 24-byte tail of a URL link. Seems to always be the same for all URL HLINKs |
| 0x79, 0x58, (byte)0x81, (byte)0xF4, 0x3B, 0x1D, 0x7F, 0x48, (byte)0xAF, 0x2C, |
| (byte)0x82, 0x5D, (byte)0xC4, (byte)0x85, 0x27, 0x63, 0x00, 0x00, 0x00, |
| 0x00, (byte)0xA5, (byte)0xAB, 0x00, 0x00 |
| }; |
| |
| //link to a file in the current directory: link1.xls |
| private static final byte[] data2 = { |
| 0x00, 0x00, |
| 0x00, 0x00, |
| 0x00, 0x00, |
| 0x00, 0x00, |
| //16-bit GUID. Seems to be always the same. Does not depend on the hyperlink type |
| (byte)0xD0, (byte)0xC9, (byte)0xEA, 0x79, (byte)0xF9, (byte)0xBA, (byte)0xCE, 0x11, |
| (byte)0x8C, (byte)0x82, 0x00, (byte)0xAA, 0x00, 0x4B, (byte)0xA9, 0x0B, |
| |
| 0x02, 0x00, 0x00, 0x00, //integer, always 2 |
| |
| 0x15, 0x00, 0x00, 0x00, //options: HyperlinkRecord.HLINK_URL | HyperlinkRecord.HLINK_LABEL |
| |
| 0x05, 0x00, 0x00, 0x00, //length of the label |
| //label |
| 0x66, 0x00, 0x69, 0x00, 0x6C, 0x00, 0x65, 0x00, 0x00, 0x00, |
| |
| //16-byte link moniker: HyperlinkRecord.FILE_MONIKER |
| 0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, (byte)0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46, |
| |
| 0x00, 0x00, //level |
| 0x0A, 0x00, 0x00, 0x00, //length of the path ) |
| |
| //path to the file (plain ISO-8859 bytes, NOT UTF-16LE!) |
| 0x6C, 0x69, 0x6E, 0x6B, 0x31, 0x2E, 0x78, 0x6C, 0x73, 0x00, |
| |
| //standard 24-byte tail of a file link |
| (byte)0xFF, (byte)0xFF, (byte)0xAD, (byte)0xDE, 0x00, 0x00, 0x00, 0x00, |
| 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
| 0x00, 0x00, 0x00, 0x00, |
| |
| 0x00, 0x00, 0x00, 0x00, // length of address link field |
| }; |
| |
| // mailto:ebgans@mail.ru?subject=Hello,%20Ebgans! |
| private static final byte[] data3 = { |
| 0x01, 0x00, |
| 0x01, 0x00, |
| 0x00, 0x00, |
| 0x00, 0x00, |
| |
| //16-bit GUID. Seems to be always the same. Does not depend on the hyperlink type |
| (byte)0xD0, (byte)0xC9, (byte)0xEA, 0x79, (byte)0xF9, (byte)0xBA, (byte)0xCE, 0x11, |
| (byte)0x8C, (byte)0x82, 0x00, (byte)0xAA, 0x00, 0x4B, (byte)0xA9, 0x0B, |
| |
| 0x02, 0x00, 0x00, 0x00, //integer, always 2 |
| |
| 0x17, 0x00, 0x00, 0x00, //options: HyperlinkRecord.HLINK_URL | HyperlinkRecord.HLINK_ABS | HyperlinkRecord.HLINK_LABEL |
| |
| 0x06, 0x00, 0x00, 0x00, //length of the label |
| 0x65, 0x00, 0x6D, 0x00, 0x61, 0x00, 0x69, 0x00, 0x6C, 0x00, 0x00, 0x00, //label |
| |
| //16-byte link moniker: HyperlinkRecord.URL_MONIKER |
| (byte)0xE0, (byte)0xC9, (byte)0xEA, 0x79, (byte)0xF9, (byte)0xBA, (byte)0xCE, 0x11, |
| (byte)0x8C, (byte)0x82, 0x00, (byte)0xAA, 0x00, 0x4B, (byte)0xA9, 0x0B, |
| |
| //length of the address including the tail. |
| 0x76, 0x00, 0x00, 0x00, |
| |
| //the address is terminated by '\u0000' |
| 0x6D, 0x00, 0x61, 0x00, 0x69, 0x00, 0x6C, 0x00, 0x74, 0x00, 0x6F, 0x00, |
| 0x3A, 0x00, 0x65, 0x00, 0x62, 0x00, 0x67, 0x00, 0x61, 0x00, 0x6E, 0x00, |
| 0x73, 0x00, 0x40, 0x00, 0x6D, 0x00, 0x61, 0x00, 0x69, 0x00, 0x6C, 0x00, |
| 0x2E, 0x00, 0x72, 0x00, 0x75, 0x00, 0x3F, 0x00, 0x73, 0x00, 0x75, 0x00, |
| 0x62, 0x00, 0x6A, 0x00, 0x65, 0x00, 0x63, 0x00, 0x74, 0x00, 0x3D, 0x00, |
| 0x48, 0x00, 0x65, 0x00, 0x6C, 0x00, 0x6C, 0x00, 0x6F, 0x00, 0x2C, 0x00, |
| 0x25, 0x00, 0x32, 0x00, 0x30, 0x00, 0x45, 0x00, 0x62, 0x00, 0x67, 0x00, |
| 0x61, 0x00, 0x6E, 0x00, 0x73, 0x00, 0x21, 0x00, 0x00, 0x00, |
| |
| //standard 24-byte tail of a URL link |
| 0x79, 0x58, (byte)0x81, (byte)0xF4, 0x3B, 0x1D, 0x7F, 0x48, (byte)0xAF, (byte)0x2C, |
| (byte)0x82, 0x5D, (byte)0xC4, (byte)0x85, 0x27, 0x63, 0x00, 0x00, 0x00, |
| 0x00, (byte)0xA5, (byte)0xAB, 0x00, 0x00 |
| }; |
| |
| //link to a place in worksheet: Sheet1!A1 |
| private static final byte[] data4 = { |
| 0x03, 0x00, |
| 0x03, 0x00, |
| 0x00, 0x00, |
| 0x00, 0x00, |
| |
| //16-bit GUID. Seems to be always the same. Does not depend on the hyperlink type |
| (byte)0xD0, (byte)0xC9, (byte)0xEA, 0x79, (byte)0xF9, (byte)0xBA, (byte)0xCE, 0x11, |
| (byte)0x8C, (byte)0x82, 0x00, (byte)0xAA, 0x00, 0x4B, (byte)0xA9, 0x0B, |
| |
| 0x02, 0x00, 0x00, 0x00, //integer, always 2 |
| |
| 0x1C, 0x00, 0x00, 0x00, //flags: HyperlinkRecord.HLINK_LABEL | HyperlinkRecord.HLINK_PLACE |
| |
| 0x06, 0x00, 0x00, 0x00, //length of the label |
| |
| 0x70, 0x00, 0x6C, 0x00, 0x61, 0x00, 0x63, 0x00, 0x65, 0x00, 0x00, 0x00, //label |
| |
| 0x0A, 0x00, 0x00, 0x00, //length of the document link including trailing zero |
| |
| //link: Sheet1!A1 |
| 0x53, 0x00, 0x68, 0x00, 0x65, 0x00, 0x65, 0x00, 0x74, 0x00, 0x31, 0x00, 0x21, |
| 0x00, 0x41, 0x00, 0x31, 0x00, 0x00, 0x00 |
| }; |
| |
| private static final byte[] dataLinkToWorkbook = HexRead.readFromString( |
| "01 00 01 00 01 00 01 00 " + |
| "D0 C9 EA 79 F9 BA CE 11 8C 82 00 AA 00 4B A9 0B " + |
| "02 00 00 00 " + |
| "1D 00 00 00 " + // options: LABEL | PLACE | FILE_OR_URL |
| // label: "My Label" |
| "09 00 00 00 " + |
| "4D 00 79 00 20 00 4C 00 61 00 62 00 65 00 6C 00 00 00 " + |
| "03 03 00 00 00 00 00 00 C0 00 00 00 00 00 00 46 " + // file GUID |
| "00 00 " + // file options |
| // shortFileName: "YEARFR~1.XLS" |
| "0D 00 00 00 " + |
| "59 45 41 52 46 52 7E 31 2E 58 4C 53 00 " + |
| // FILE_TAIL - unknown byte sequence |
| "FF FF AD DE 00 00 00 00 " + |
| "00 00 00 00 00 00 00 00 " + |
| "00 00 00 00 00 00 00 00 " + |
| // field len, char data len |
| "2E 00 00 00 " + |
| "28 00 00 00 " + |
| "03 00 " + // unknown ushort |
| // _address: "yearfracExamples.xls" |
| "79 00 65 00 61 00 72 00 66 00 72 00 61 00 63 00 " + |
| "45 00 78 00 61 00 6D 00 70 00 6C 00 65 00 73 00 " + |
| "2E 00 78 00 6C 00 73 00 " + |
| // textMark: "Sheet1!B6" |
| "0A 00 00 00 " + |
| "53 00 68 00 65 00 65 00 74 00 31 00 21 00 42 00 " + |
| "36 00 00 00" |
| ); |
| |
| private static final byte[] dataTargetFrame = HexRead.readFromString( |
| "0E 00 0E 00 00 00 00 00 " + |
| "D0 C9 EA 79 F9 BA CE 11 8C 82 00 AA 00 4B A9 0B " + |
| "02 00 00 00 " + |
| "83 00 00 00 " + // options: TARGET_FRAME | ABS | FILE_OR_URL |
| // targetFrame: "_blank" |
| "07 00 00 00 " + |
| "5F 00 62 00 6C 00 61 00 6E 00 6B 00 00 00 " + |
| // url GUID |
| "E0 C9 EA 79 F9 BA CE 11 8C 82 00 AA 00 4B A9 0B " + |
| // address: "http://www.regnow.com/softsell/nph-softsell.cgi?currency=USD&item=7924-37" |
| "94 00 00 00 " + |
| "68 00 74 00 74 00 70 00 3A 00 2F 00 2F 00 77 00 " + |
| "77 00 77 00 2E 00 72 00 65 00 67 00 6E 00 6F 00 " + |
| "77 00 2E 00 63 00 6F 00 6D 00 2F 00 73 00 6F 00 " + |
| "66 00 74 00 73 00 65 00 6C 00 6C 00 2F 00 6E 00 " + |
| "70 00 68 00 2D 00 73 00 6F 00 66 00 74 00 73 00 " + |
| "65 00 6C 00 6C 00 2E 00 63 00 67 00 69 00 3F 00 " + |
| "63 00 75 00 72 00 72 00 65 00 6E 00 63 00 79 00 " + |
| "3D 00 55 00 53 00 44 00 26 00 69 00 74 00 65 00 " + |
| "6D 00 3D 00 37 00 39 00 32 00 34 00 2D 00 33 00 " + |
| "37 00 00 00" |
| ); |
| |
| |
| private static final byte[] dataUNC = HexRead.readFromString( |
| "01 00 01 00 01 00 01 00 " + |
| "D0 C9 EA 79 F9 BA CE 11 8C 82 00 AA 00 4B A9 0B " + |
| "02 00 00 00 " + |
| "1F 01 00 00 " + // options: UNC_PATH | LABEL | TEXT_MARK | ABS | FILE_OR_URL |
| "09 00 00 00 " + // label: "My Label" |
| "4D 00 79 00 20 00 6C 00 61 00 62 00 65 00 6C 00 00 00 " + |
| // note - no moniker GUID |
| "27 00 00 00 " + // "\\\\MyServer\\my-share\\myDir\\PRODNAME.xls" |
| "5C 00 5C 00 4D 00 79 00 53 00 65 00 72 00 76 00 " + |
| "65 00 72 00 5C 00 6D 00 79 00 2D 00 73 00 68 00 " + |
| "61 00 72 00 65 00 5C 00 6D 00 79 00 44 00 69 00 " + |
| "72 00 5C 00 50 00 52 00 4F 00 44 00 4E 00 41 00 " + |
| "4D 00 45 00 2E 00 78 00 6C 00 73 00 00 00 " + |
| |
| "0C 00 00 00 " + // textMark: PRODNAME!C2 |
| "50 00 52 00 4F 00 44 00 4E 00 41 00 4D 00 45 00 21 00 " + |
| "43 00 32 00 00 00" |
| ); |
| |
| |
| /** |
| * From Bugzilla 47498 |
| */ |
| private static final byte[] data_47498 = { |
| 0x02, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, (byte)0xD0, (byte)0xC9, |
| (byte)0xEA, 0x79, (byte)0xF9, (byte)0xBA, (byte)0xCE, 0x11, (byte)0x8C, |
| (byte)0x82, 0x00, (byte)0xAA, 0x00, 0x4B, (byte)0xA9, 0x0B, 0x02, 0x00, |
| 0x00, 0x00, 0x15, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x50, 0x00, |
| 0x44, 0x00, 0x46, 0x00, 0x00, 0x00, (byte)0xE0, (byte)0xC9, (byte)0xEA, |
| 0x79, (byte)0xF9, (byte)0xBA, (byte)0xCE, (byte)0x11, (byte)0x8C, (byte)0x82, |
| 0x00, (byte)0xAA, 0x00, 0x4B, (byte)0xA9, 0x0B, 0x28, 0x00, 0x00, 0x00, |
| 0x74, 0x00, 0x65, 0x00, 0x73, 0x00, 0x74, 0x00, 0x66, 0x00, 0x6F, 0x00, |
| 0x6C, 0x00, 0x64, 0x00, 0x65, 0x00, 0x72, 0x00, 0x2F, 0x00, 0x74, 0x00, |
| 0x65, 0x00, 0x73, 0x00, 0x74, 0x00, 0x2E, 0x00, 0x50, 0x00, 0x44, 0x00, |
| 0x46, 0x00, 0x00, 0x00 |
| }; |
| |
| |
| private void confirmGUID(ClassID expectedGuid, ClassID actualGuid) { |
| assertEquals(expectedGuid, actualGuid); |
| } |
| |
| @Test |
| void testReadURLLink(){ |
| RecordInputStream is = TestcaseRecordInputStream.create(HyperlinkRecord.sid, data1); |
| HyperlinkRecord link = new HyperlinkRecord(is); |
| assertEquals(2, link.getFirstRow()); |
| assertEquals(2, link.getLastRow()); |
| assertEquals(0, link.getFirstColumn()); |
| assertEquals(0, link.getLastColumn()); |
| confirmGUID(ClassIDPredefined.STD_MONIKER.getClassID(), link.getGuid()); |
| confirmGUID(ClassIDPredefined.URL_MONIKER.getClassID(), link.getMoniker()); |
| assertEquals(2, link.getLabelOptions()); |
| int opts = HyperlinkRecord.HLINK_URL | HyperlinkRecord.HLINK_ABS | HyperlinkRecord.HLINK_LABEL; |
| assertEquals(0x17, opts); |
| assertEquals(opts, link.getLinkOptions()); |
| assertEquals(0, link.getFileOptions()); |
| |
| assertEquals("My Link", link.getLabel()); |
| assertEquals("http://www.lakings.com/", link.getAddress()); |
| } |
| |
| @Test |
| void testReadFileLink(){ |
| RecordInputStream is = TestcaseRecordInputStream.create(HyperlinkRecord.sid, data2); |
| HyperlinkRecord link = new HyperlinkRecord(is); |
| assertEquals(0, link.getFirstRow()); |
| assertEquals(0, link.getLastRow()); |
| assertEquals(0, link.getFirstColumn()); |
| assertEquals(0, link.getLastColumn()); |
| confirmGUID(ClassIDPredefined.STD_MONIKER.getClassID(), link.getGuid()); |
| confirmGUID(ClassIDPredefined.FILE_MONIKER.getClassID(), link.getMoniker()); |
| assertEquals(2, link.getLabelOptions()); |
| int opts = HyperlinkRecord.HLINK_URL | HyperlinkRecord.HLINK_LABEL; |
| assertEquals(0x15, opts); |
| assertEquals(opts, link.getLinkOptions()); |
| |
| assertEquals("file", link.getLabel()); |
| assertEquals("link1.xls", link.getShortFilename()); |
| assertEquals("link1.xls", link.getAddress()); |
| } |
| |
| @Test |
| void testReadEmailLink(){ |
| RecordInputStream is = TestcaseRecordInputStream.create(HyperlinkRecord.sid, data3); |
| HyperlinkRecord link = new HyperlinkRecord(is); |
| assertEquals(1, link.getFirstRow()); |
| assertEquals(1, link.getLastRow()); |
| assertEquals(0, link.getFirstColumn()); |
| assertEquals(0, link.getLastColumn()); |
| confirmGUID(ClassIDPredefined.STD_MONIKER.getClassID(), link.getGuid()); |
| confirmGUID(ClassIDPredefined.URL_MONIKER.getClassID(), link.getMoniker()); |
| assertEquals(2, link.getLabelOptions()); |
| int opts = HyperlinkRecord.HLINK_URL | HyperlinkRecord.HLINK_ABS | HyperlinkRecord.HLINK_LABEL; |
| assertEquals(0x17, opts); |
| assertEquals(opts, link.getLinkOptions()); |
| |
| assertEquals("email", link.getLabel()); |
| assertEquals("mailto:ebgans@mail.ru?subject=Hello,%20Ebgans!", link.getAddress()); |
| } |
| |
| @Test |
| void testReadDocumentLink(){ |
| RecordInputStream is = TestcaseRecordInputStream.create(HyperlinkRecord.sid, data4); |
| HyperlinkRecord link = new HyperlinkRecord(is); |
| assertEquals(3, link.getFirstRow()); |
| assertEquals(3, link.getLastRow()); |
| assertEquals(0, link.getFirstColumn()); |
| assertEquals(0, link.getLastColumn()); |
| confirmGUID(ClassIDPredefined.STD_MONIKER.getClassID(), link.getGuid()); |
| assertEquals(2, link.getLabelOptions()); |
| int opts = HyperlinkRecord.HLINK_LABEL | HyperlinkRecord.HLINK_PLACE; |
| assertEquals(0x1C, opts); |
| assertEquals(opts, link.getLinkOptions()); |
| |
| assertEquals("place", link.getLabel()); |
| assertEquals("Sheet1!A1", link.getTextMark()); |
| assertEquals("Sheet1!A1", link.getAddress()); |
| } |
| |
| private void serialize(byte[] data){ |
| RecordInputStream is = TestcaseRecordInputStream.create(HyperlinkRecord.sid, data); |
| HyperlinkRecord link = new HyperlinkRecord(is); |
| byte[] bytes1 = link.serialize(); |
| is = TestcaseRecordInputStream.create(bytes1); |
| link = new HyperlinkRecord(is); |
| byte[] bytes2 = link.serialize(); |
| assertEquals(bytes1.length, bytes2.length); |
| assertArrayEquals(bytes1, bytes2); |
| } |
| |
| @Test |
| void testSerialize(){ |
| serialize(data1); |
| serialize(data2); |
| serialize(data3); |
| serialize(data4); |
| } |
| |
| @Test |
| void testCreateURLRecord() { |
| HyperlinkRecord link = new HyperlinkRecord(); |
| link.newUrlLink(); |
| link.setFirstRow((short)2); |
| link.setLastRow((short)2); |
| link.setLabel("My Link"); |
| link.setAddress("http://www.lakings.com/"); |
| |
| byte[] tmp = link.serialize(); |
| byte[] ser = Arrays.copyOfRange(tmp, 4, tmp.length); |
| assertEquals(data1.length, ser.length); |
| assertArrayEquals(data1, ser); |
| } |
| |
| @Test |
| void testCreateFileRecord() { |
| HyperlinkRecord link = new HyperlinkRecord(); |
| link.newFileLink(); |
| link.setFirstRow((short)0); |
| link.setLastRow((short)0); |
| link.setLabel("file"); |
| link.setShortFilename("link1.xls"); |
| |
| byte[] tmp = link.serialize(); |
| byte[] ser = Arrays.copyOfRange(tmp, 4, tmp.length); |
| assertEquals(data2.length, ser.length); |
| assertArrayEquals(data2, ser); |
| } |
| |
| @Test |
| void testCreateDocumentRecord() { |
| HyperlinkRecord link = new HyperlinkRecord(); |
| link.newDocumentLink(); |
| link.setFirstRow((short)3); |
| link.setLastRow((short)3); |
| link.setLabel("place"); |
| link.setTextMark("Sheet1!A1"); |
| |
| byte[] tmp = link.serialize(); |
| byte[] ser = Arrays.copyOfRange(tmp, 4, tmp.length); |
| assertEquals(data4.length, ser.length); |
| assertArrayEquals(data4, ser); |
| } |
| |
| @Test |
| void testCreateEmailtRecord() { |
| HyperlinkRecord link = new HyperlinkRecord(); |
| link.newUrlLink(); |
| link.setFirstRow((short)1); |
| link.setLastRow((short)1); |
| link.setLabel("email"); |
| link.setAddress("mailto:ebgans@mail.ru?subject=Hello,%20Ebgans!"); |
| |
| byte[] tmp = link.serialize(); |
| byte[] ser = Arrays.copyOfRange(tmp, 4, tmp.length); |
| assertEquals(data3.length, ser.length); |
| assertArrayEquals(data3, ser); |
| } |
| |
| @Test |
| void testClone() { |
| byte[][] data = {data1, data2, data3, data4}; |
| for (final byte[] d : data) { |
| RecordInputStream is = TestcaseRecordInputStream.create(HyperlinkRecord.sid, d); |
| HyperlinkRecord link = new HyperlinkRecord(is); |
| HyperlinkRecord clone = link.copy(); |
| assertArrayEquals(link.serialize(), clone.serialize()); |
| } |
| |
| } |
| |
| @SuppressWarnings("squid:S2699") |
| @Test |
| void testReserializeTargetFrame() { |
| RecordInputStream in = TestcaseRecordInputStream.create(HyperlinkRecord.sid, dataTargetFrame); |
| HyperlinkRecord hr = new HyperlinkRecord(in); |
| byte[] ser = hr.serialize(); |
| confirmRecordEncoding(HyperlinkRecord.sid, dataTargetFrame, ser); |
| } |
| |
| @Test |
| void testReserializeLinkToWorkbook() { |
| |
| RecordInputStream in = TestcaseRecordInputStream.create(HyperlinkRecord.sid, dataLinkToWorkbook); |
| HyperlinkRecord hr = new HyperlinkRecord(in); |
| byte[] ser = hr.serialize(); |
| confirmRecordEncoding(HyperlinkRecord.sid, dataLinkToWorkbook, ser); |
| assertNotEquals("Identified bug in reading workbook link", "YEARFR~1.XLS", hr.getAddress()); |
| assertEquals("yearfracExamples.xls", hr.getAddress()); |
| } |
| |
| @Test |
| void testReserializeUNC() { |
| |
| RecordInputStream in = TestcaseRecordInputStream.create(HyperlinkRecord.sid, dataUNC); |
| HyperlinkRecord hr = new HyperlinkRecord(in); |
| byte[] ser = hr.serialize(); |
| confirmRecordEncoding(HyperlinkRecord.sid, dataUNC, ser); |
| assertNotNull(hr.toString()); |
| } |
| |
| @Test |
| void testGUID() throws IOException { |
| ClassID g; |
| g = new ClassID("3F2504E0-4F89-11D3-9A0C-0305E82C3301"); |
| confirmGUID(g, 0x3F2504E0, 0x4F89, 0x11D3, 0x9A0C0305E82C3301L); |
| assertEquals("{3F2504E0-4F89-11D3-9A0C-0305E82C3301}", g.toString()); |
| |
| g = new ClassID("13579BDF-0246-8ACE-0123-456789ABCDEF"); |
| confirmGUID(g, 0x13579BDF, 0x0246, 0x8ACE, 0x0123456789ABCDEFL); |
| assertEquals("{13579BDF-0246-8ACE-0123-456789ABCDEF}", g.toString()); |
| |
| byte[] buf = new byte[16]; |
| g.write(new LittleEndianByteArrayOutputStream(buf, 0)); |
| String expectedDump = "[DF, 9B, 57, 13, 46, 02, CE, 8A, 01, 23, 45, 67, 89, AB, CD, EF]"; |
| assertEquals(expectedDump, HexDump.toHex(buf)); |
| |
| // STD Moniker |
| g = createFromStreamDump("[D0, C9, EA, 79, F9, BA, CE, 11, 8C, 82, 00, AA, 00, 4B, A9, 0B]"); |
| assertEquals("{79EAC9D0-BAF9-11CE-8C82-00AA004BA90B}", g.toString()); |
| // URL Moniker |
| g = createFromStreamDump("[E0, C9, EA, 79, F9, BA, CE, 11, 8C, 82, 00, AA, 00, 4B, A9, 0B]"); |
| assertEquals("{79EAC9E0-BAF9-11CE-8C82-00AA004BA90B}", g.toString()); |
| // File Moniker |
| g = createFromStreamDump("[03, 03, 00, 00, 00, 00, 00, 00, C0, 00, 00, 00, 00, 00, 00, 46]"); |
| assertEquals("{00000303-0000-0000-C000-000000000046}", g.toString()); |
| } |
| |
| private static ClassID createFromStreamDump(String s) { |
| return new ClassID(new LittleEndianByteArrayInputStream(HexRead.readFromString(s))); |
| } |
| |
| private void confirmGUID(ClassID g, int d1, int d2, int d3, long d4) throws IOException { |
| try (DataInputStream dis = new DataInputStream(new ByteArrayInputStream(g.getBytes()))) { |
| assertEquals(d1, dis.readInt()); |
| assertEquals(d2, dis.readShort() & 0xFFFF); |
| assertEquals(d3, dis.readShort() & 0xFFFF); |
| assertEquals(d4, dis.readLong()); |
| } |
| } |
| |
| @Test |
| void test47498(){ |
| RecordInputStream is = TestcaseRecordInputStream.create(HyperlinkRecord.sid, data_47498); |
| HyperlinkRecord link = new HyperlinkRecord(is); |
| assertEquals(2, link.getFirstRow()); |
| assertEquals(2, link.getLastRow()); |
| assertEquals(0, link.getFirstColumn()); |
| assertEquals(0, link.getLastColumn()); |
| confirmGUID(ClassIDPredefined.STD_MONIKER.getClassID(), link.getGuid()); |
| confirmGUID(ClassIDPredefined.URL_MONIKER.getClassID(), link.getMoniker()); |
| assertEquals(2, link.getLabelOptions()); |
| int opts = HyperlinkRecord.HLINK_URL | HyperlinkRecord.HLINK_LABEL; |
| assertEquals(opts, link.getLinkOptions()); |
| assertEquals(0, link.getFileOptions()); |
| |
| assertEquals("PDF", link.getLabel()); |
| assertEquals("testfolder/test.PDF", link.getAddress()); |
| |
| byte[] ser = link.serialize(); |
| confirmRecordEncoding(HyperlinkRecord.sid, data_47498, ser); |
| } |
| } |