From 2dd66bad919114533be8500fbd578598f62a4a86 Mon Sep 17 00:00:00 2001 From: David Bond Date: Sun, 4 Oct 2026 12:53:37 +0100 Subject: [PATCH 1/2] OPS-157454: Restore the main build with warnings-as-errors kept on main failed with about 2,800 errors once 91f6bac9 turned TreatWarningsAsErrors back on. Fixed without switching it off: - Nullable reference types: the vendored projects use annotations (the library and tests already carry some `?` annotations, so `disable` would give CS8632) and the samples use disable. The library's nullability metadata is unchanged from 10.1.9. - CA1416: System.Drawing-dependent public APIs are marked [SupportedOSPlatform("windows")] (AutoFitColumns/AutoFit, AddPicture(Image|FileInfo), ExcelPicture.Image/ImageFormat, SetFromFont, header/footer InsertPicture, background image, VML picture Image). Paths reachable from platform-neutral code are guarded: loading or cross-package copying a System.Drawing picture throws PlatformNotSupportedException off Windows, where it already failed. - CA2022: unchecked Stream.Read calls use ReadAtLeast(..., throwOnEndOfStream: false), which handles short reads and keeps the old no-throw behaviour at end of stream. - WinZipAes moves from RijndaelManaged to Aes and from the Rfc2898DeriveBytes ctor to Rfc2898DeriveBytes.Pbkdf2 (SHA1, same iterations, output split the same way); both verified byte-identical. VBA signature certificates use X509CertificateLoader. Uri.EscapeUriString is replaced by a local helper with identical output, verified on 28,000+ inputs. - CA2200/CS0168 rethrow, CS8981 alias, CS8794 always-true pattern (behaviour kept), bad XML doc params/crefs. - CS1591 suppressed for the library only (2,211 undocumented vendored members); test and sample projects no longer generate documentation files. - Re-applies three fixes from 070eab9f that 91f6bac9 reverted: no MIT licence expression on the LGPL package (NU5033), no Microsoft.Testing.Platform runner in global.json, and SampleWebApp (now on WebApplication hosting, so no obsolete APIs). SampleApp moves to Microsoft.Data.SqlClient. Co-Authored-By: Claude Opus 5.5 (1M context) --- Directory.Build.props | 5 --- Directory.Packages.props | 2 +- PanoramicData.EPPlus.Test/CompoundDoc.cs | 2 ++ PanoramicData.EPPlus.Test/DTS_FailingTests.cs | 3 ++ PanoramicData.EPPlus.Test/DrawingTest.cs | 8 +++++ PanoramicData.EPPlus.Test/Issues.cs | 10 ++++++ .../PanoramicData.EPPlus.Test.csproj | 4 ++- PanoramicData.EPPlus.Test/WorkSheetTests.cs | 10 ++++++ .../Compatibility/ImageCompat.cs | 2 ++ PanoramicData.EPPlus/Drawing/ExcelDrawings.cs | 5 +++ PanoramicData.EPPlus/Drawing/ExcelPicture.cs | 25 +++++++++++--- .../Drawing/Vml/ExcelVmlDrawingPicture.cs | 2 ++ .../Encryption/EncryptionHandler.cs | 8 ++--- PanoramicData.EPPlus/ExcelBackgroundImage.cs | 4 +++ PanoramicData.EPPlus/ExcelCellBase.cs | 4 --- PanoramicData.EPPlus/ExcelColumn.cs | 4 +++ PanoramicData.EPPlus/ExcelHeaderFooter.cs | 4 +++ PanoramicData.EPPlus/ExcelPackage.cs | 2 +- PanoramicData.EPPlus/ExcelRangeBase.cs | 24 ++++--------- PanoramicData.EPPlus/ExcelWorksheets.cs | 5 +++ .../FormulaParsing/CalculateExtentions.cs | 6 ++-- .../Excel/Functions/DoubleArgumentParser.cs | 4 +-- .../Packaging/DotNetZip/CRC32.cs | 2 +- .../Packaging/DotNetZip/WinZipAes.cs | 34 +++++++------------ .../Packaging/DotNetZip/ZipEntry.Read.cs | 2 +- .../Packaging/DotNetZip/ZipEntry.Write.cs | 2 +- .../Packaging/DotNetZip/ZipEntry.cs | 6 ++-- .../Packaging/DotNetZip/ZipFile.Read.cs | 20 +++++------ .../DotNetZip/Zlib/ZlibBaseStream.cs | 2 +- .../Packaging/ZipPackageRelationshipBase.cs | 22 +++++++++++- .../PanoramicData.EPPlus.csproj | 6 ++-- PanoramicData.EPPlus/Style/ExcelFont.cs | 2 ++ PanoramicData.EPPlus/Style/ExcelTextFont.cs | 2 ++ .../Style/XmlAccess/ExcelFontXml.cs | 2 ++ .../CompundDocument/CompoundDocumentFile.cs | 2 +- PanoramicData.EPPlus/VBA/ExcelVBASignature.cs | 2 +- SampleApp/Sample1.cs | 2 ++ SampleApp/Sample12.cs | 4 ++- SampleApp/Sample13.cs | 2 ++ SampleApp/Sample16.cs | 2 ++ SampleApp/Sample3.cs | 4 ++- SampleApp/Sample4.cs | 2 +- SampleApp/Sample6.cs | 6 ++++ SampleApp/Sample7.cs | 4 ++- SampleApp/Sample9.cs | 4 +++ SampleApp/SampleApp.csproj | 5 ++- SampleApp/Sample_Main.cs | 2 ++ SampleWebApp/Controllers/HomeController.cs | 8 ++++- SampleWebApp/Program.cs | 27 ++++++--------- SampleWebApp/SampleWebApp.csproj | 5 ++- SampleWebApp/Startup.cs | 18 ---------- global.json | 5 +-- 52 files changed, 217 insertions(+), 132 deletions(-) delete mode 100644 SampleWebApp/Startup.cs diff --git a/Directory.Build.props b/Directory.Build.props index 79d7533bd..e384f1ad8 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -2,11 +2,6 @@ All - true enable true diff --git a/Directory.Packages.props b/Directory.Packages.props index 4dc4a5064..3c1698e32 100644 --- a/Directory.Packages.props +++ b/Directory.Packages.props @@ -19,7 +19,7 @@ - + diff --git a/PanoramicData.EPPlus.Test/CompoundDoc.cs b/PanoramicData.EPPlus.Test/CompoundDoc.cs index f125bcbba..a69255bfa 100644 --- a/PanoramicData.EPPlus.Test/CompoundDoc.cs +++ b/PanoramicData.EPPlus.Test/CompoundDoc.cs @@ -1,4 +1,5 @@ using Microsoft.VisualStudio.TestTools.UnitTesting; +using System.Runtime.Versioning; using OfficeOpenXml; using OfficeOpenXml.Style; using OfficeOpenXml.Utils.CompundDocument; @@ -163,6 +164,7 @@ public void Issue131() package.Save(); } + [SupportedOSPlatform("windows")] [TestMethod, Ignore] public void Sample7EncrLargeTest() { diff --git a/PanoramicData.EPPlus.Test/DTS_FailingTests.cs b/PanoramicData.EPPlus.Test/DTS_FailingTests.cs index 81eeda59c..533e01ae4 100644 --- a/PanoramicData.EPPlus.Test/DTS_FailingTests.cs +++ b/PanoramicData.EPPlus.Test/DTS_FailingTests.cs @@ -1,4 +1,5 @@ using Microsoft.VisualStudio.TestTools.UnitTesting; +using System.Runtime.Versioning; using OfficeOpenXml; using System.IO; @@ -8,6 +9,7 @@ namespace PanoramicData.EPPlus.Test; public class DTS_FailingTests { + [SupportedOSPlatform("windows")] [TestMethod] public void DeleteWorksheetWithReferencedImage() { @@ -30,6 +32,7 @@ public void DeleteWorksheetWithReferencedImage() } } + [SupportedOSPlatform("windows")] [TestMethod] public void CopyAndDeleteWorksheetWithImage() { diff --git a/PanoramicData.EPPlus.Test/DrawingTest.cs b/PanoramicData.EPPlus.Test/DrawingTest.cs index 2b74962d1..a2846004f 100644 --- a/PanoramicData.EPPlus.Test/DrawingTest.cs +++ b/PanoramicData.EPPlus.Test/DrawingTest.cs @@ -1,4 +1,5 @@ using EPPlusTest.Properties; +using System.Runtime.Versioning; using Microsoft.VisualStudio.TestTools.UnitTesting; using OfficeOpenXml; using OfficeOpenXml.Drawing; @@ -15,6 +16,7 @@ namespace PanoramicData.EPPlus.Test; [TestClass] public class DrawingTest : TestBase { + [SupportedOSPlatform("windows")] [TestMethod] public void RunDrawingTests() { @@ -59,6 +61,7 @@ public void ReadDrawing() Assert.AreEqual(cht.Title.Text, "Test"); } + [SupportedOSPlatform("windows")] public void Picture() { var ws = _pck.Workbook.Worksheets.Add("Picture"); @@ -109,6 +112,7 @@ public void Picture() } //[TestMethod] //[Ignore] + [SupportedOSPlatform("windows")] public void DrawingSizingAndPositioning() { var ws = _pck.Workbook.Worksheets.Add("DrawingPosSize"); @@ -251,6 +255,7 @@ public void PieChart3D() } //[TestMethod] //[Ignore] + [SupportedOSPlatform("windows")] public void Scatter() { var ws = _pck.Workbook.Worksheets.Add("Scatter"); @@ -570,6 +575,7 @@ public void LineMarker() } //[TestMethod] //[Ignore] + [SupportedOSPlatform("windows")] public void Drawings() { var ws = _pck.Workbook.Worksheets.Add("Shapes"); @@ -755,6 +761,7 @@ public void MultiChartSeries() } //[TestMethod] //[Ignore] + [SupportedOSPlatform("windows")] public void DeleteDrawing() { var ws = _pck.Workbook.Worksheets.Add("DeleteDrawing1"); @@ -952,6 +959,7 @@ public void AllDrawingsInsideMarkupCompatibility() // Cleanup: File.Delete(savedPath); } + [SupportedOSPlatform("windows")] public void DrawingRowheightDynamic() { var ws = _pck.Workbook.Worksheets.Add("PicResize"); diff --git a/PanoramicData.EPPlus.Test/Issues.cs b/PanoramicData.EPPlus.Test/Issues.cs index c2feb9bf5..9d1ab1f74 100644 --- a/PanoramicData.EPPlus.Test/Issues.cs +++ b/PanoramicData.EPPlus.Test/Issues.cs @@ -1,4 +1,5 @@ using Microsoft.VisualStudio.TestTools.UnitTesting; +using System.Runtime.Versioning; using OfficeOpenXml; using OfficeOpenXml.Drawing; using OfficeOpenXml.Drawing.Chart; @@ -72,6 +73,7 @@ public void Issue15031() ws.Cells["A1"].Style.Numberformat.Format = "[t]:mm:ss"; ws.Dispose(); } + [SupportedOSPlatform("windows")] [TestMethod] public void Issue15022() { @@ -433,6 +435,7 @@ public void Issue15174() package.SaveAs(new FileInfo(@"C:\temp\bug\MyTemplate2.xlsx")); } + [SupportedOSPlatform("windows")] [Ignore] [TestMethod] public void PictureIssue() @@ -690,6 +693,7 @@ public void Issue15234() } [TestMethod] /**** Pivottable issue ****/ + [SupportedOSPlatform("windows")] public void Issue() { DirectoryInfo outputDir = new(@"c:\ExcelPivotTest"); @@ -699,6 +703,7 @@ public void Issue() BuildPivotTable2(MyFile); } + [SupportedOSPlatform("windows")] private static void LoadData(FileInfo MyFile) { if (MyFile.Exists) @@ -1474,6 +1479,7 @@ public void Issue_8() } + [SupportedOSPlatform("windows")] [TestMethod, Ignore] public void Issuer27() { @@ -1739,6 +1745,7 @@ public void Issue70() workbook.SaveAs(new FileInfo(outputPath)); } + [SupportedOSPlatform("windows")] [TestMethod, Ignore] public void Issue100() { @@ -1852,6 +1859,7 @@ public void Issue181() var a = pck.Workbook.Properties.Author; pck.SaveAs(new FileInfo($@"C:\temp\bug\issue181-saved.xlsx")); } + [SupportedOSPlatform("windows")] [TestMethod, Ignore] public void Issue10() { @@ -2042,6 +2050,7 @@ public void Issue236() _pck.Workbook.Worksheets["Sheet1"].Cells[7, 10].AddComment("test", "Author"); SaveWorksheet("Issue236-Saved.xlsx"); } + [SupportedOSPlatform("windows")] [TestMethod] public void Issue228() { @@ -2199,6 +2208,7 @@ public void Issue333() Assert.AreEqual("2019-03-07", ws.Cells["A1"].Text); } + [SupportedOSPlatform("windows")] [TestMethod] public void Issue445() { diff --git a/PanoramicData.EPPlus.Test/PanoramicData.EPPlus.Test.csproj b/PanoramicData.EPPlus.Test/PanoramicData.EPPlus.Test.csproj index 54f9afc7a..76d1545dd 100644 --- a/PanoramicData.EPPlus.Test/PanoramicData.EPPlus.Test.csproj +++ b/PanoramicData.EPPlus.Test/PanoramicData.EPPlus.Test.csproj @@ -8,7 +8,9 @@ False Package Description - enable + + annotations + false enable diff --git a/PanoramicData.EPPlus.Test/WorkSheetTests.cs b/PanoramicData.EPPlus.Test/WorkSheetTests.cs index 978ac1a93..9b32fda69 100644 --- a/PanoramicData.EPPlus.Test/WorkSheetTests.cs +++ b/PanoramicData.EPPlus.Test/WorkSheetTests.cs @@ -1,4 +1,5 @@ using Microsoft.VisualStudio.TestTools.UnitTesting; +using System.Runtime.Versioning; using OfficeOpenXml; using OfficeOpenXml.Drawing; using OfficeOpenXml.Drawing.Chart; @@ -34,6 +35,7 @@ internal class InhItem : BaseItem [TestClass] public class WorkSheetTest : TestBase { + [SupportedOSPlatform("windows")] [TestMethod] public void RunWorksheetTests() { @@ -402,6 +404,7 @@ public void ReadStreamSaveAsStream() // Use ClassCleanup to run code after all tests in a class have run //[Ignore] //[TestMethod] + [SupportedOSPlatform("windows")] public void LoadData() { var ws = _pck.Workbook.Worksheets.Add("newsheet"); @@ -1137,6 +1140,7 @@ public void FormulaArray() } //[Ignore] //[TestMethod] + [SupportedOSPlatform("windows")] public void PictureURL() { var ws = _pck.Workbook.Worksheets.Add("Pic URL"); @@ -1875,6 +1879,7 @@ public void DefColWidthBug() // return pkg } + [SupportedOSPlatform("windows")] [Ignore] [TestMethod] public void CloseProblem() @@ -2250,6 +2255,7 @@ public void CreatePivotMultData() pck.Save(); } //[Ignore] + [SupportedOSPlatform("windows")] [TestMethod] public void SetBackground() { @@ -2260,6 +2266,7 @@ public void SetBackground() ws.BackgroundImage.SetFromFile(new FileInfo(Path.Combine(_clipartPath, "Vector Drawing.wmf"))); } //[Ignore] + [SupportedOSPlatform("windows")] [TestMethod] public void SetHeaderFooterImage() { @@ -2293,6 +2300,7 @@ public void SetHeaderFooterImage() } //[Ignore] //[TestMethod] + [SupportedOSPlatform("windows")] public void NamedStyles() { var wsSheet = _pck.Workbook.Worksheets.Add("NamedStyles"); @@ -2413,6 +2421,7 @@ public void BuildInStyles() } //[Ignore] //[TestMethod] + [SupportedOSPlatform("windows")] public void AutoFitColumns() { var ws = _pck.Workbook.Worksheets.Add("Autofit"); @@ -2868,6 +2877,7 @@ public void SaveToStream() excelPackage.Save(); var s = stream.ToArray(); } + [SupportedOSPlatform("windows")] [TestMethod, Ignore] public void ColumnsTest() { diff --git a/PanoramicData.EPPlus/Compatibility/ImageCompat.cs b/PanoramicData.EPPlus/Compatibility/ImageCompat.cs index ee72f23df..348e1972f 100644 --- a/PanoramicData.EPPlus/Compatibility/ImageCompat.cs +++ b/PanoramicData.EPPlus/Compatibility/ImageCompat.cs @@ -1,9 +1,11 @@ using System.Drawing; using System.Drawing.Imaging; using System.IO; +using System.Runtime.Versioning; namespace OfficeOpenXml.Compatibility; +[SupportedOSPlatform("windows")] internal class ImageCompat { internal static byte[] GetImageAsByteArray(Image image) diff --git a/PanoramicData.EPPlus/Drawing/ExcelDrawings.cs b/PanoramicData.EPPlus/Drawing/ExcelDrawings.cs index d7fec58e3..66b3d0169 100644 --- a/PanoramicData.EPPlus/Drawing/ExcelDrawings.cs +++ b/PanoramicData.EPPlus/Drawing/ExcelDrawings.cs @@ -38,6 +38,7 @@ using System.Drawing; using System.IO; using System.Xml; +using System.Runtime.Versioning; namespace OfficeOpenXml.Drawing; @@ -247,6 +248,7 @@ eChartType.StockOHLC or /// /// An image. Always saved in then JPeg format /// + [SupportedOSPlatform("windows")] public ExcelPicture AddPicture(string Name, Image image) => AddPicture(Name, image, null); /// /// Add a picture to the worksheet @@ -255,6 +257,7 @@ eChartType.StockOHLC or /// An image. Always saved in then JPeg format /// Picture hyperlink /// + [SupportedOSPlatform("windows")] public ExcelPicture AddPicture(string Name, Image image, Uri Hyperlink) { if (image != null) @@ -283,6 +286,7 @@ public ExcelPicture AddPicture(string Name, Image image, Uri Hyperlink) /// /// The image file /// + [SupportedOSPlatform("windows")] public ExcelPicture AddPicture(string Name, FileInfo ImageFile) => AddPicture(Name, ImageFile, null); /// /// Add a picure to the worksheet @@ -291,6 +295,7 @@ public ExcelPicture AddPicture(string Name, Image image, Uri Hyperlink) /// The image file /// Picture Hyperlink /// + [SupportedOSPlatform("windows")] public ExcelPicture AddPicture(string Name, FileInfo ImageFile, Uri Hyperlink) { if (Worksheet is ExcelChartsheet && _drawings.Count > 0) diff --git a/PanoramicData.EPPlus/Drawing/ExcelPicture.cs b/PanoramicData.EPPlus/Drawing/ExcelPicture.cs index c9b923b07..0b0379189 100644 --- a/PanoramicData.EPPlus/Drawing/ExcelPicture.cs +++ b/PanoramicData.EPPlus/Drawing/ExcelPicture.cs @@ -38,6 +38,7 @@ using System.IO; using System.Text; using System.Xml; +using System.Runtime.Versioning; namespace OfficeOpenXml.Drawing; @@ -60,6 +61,11 @@ internal ExcelPicture(ExcelDrawings drawings, XmlNode node) : Part = drawings.Part.Package.GetPart(UriPic); FileInfo f = new(UriPic.OriginalString); ContentType = GetContentType(f.Extension); + if (!OperatingSystem.IsWindowsVersionAtLeast(6, 1)) + { + throw new PlatformNotSupportedException("Loading a picture uses System.Drawing, which is only supported on Windows."); + } + _image = Image.FromStream(Part.GetStream()); var iby = ImageCompat.GetImageAsByteArray(_image); @@ -85,6 +91,7 @@ internal ExcelPicture(ExcelDrawings drawings, XmlNode node) : } } } + [SupportedOSPlatform("windows")] internal ExcelPicture(ExcelDrawings drawings, XmlNode node, Image image, Uri hyperlink) : base(drawings, node, "xdr:pic/xdr:nvPicPr/xdr:cNvPr/@name") { @@ -107,6 +114,7 @@ internal ExcelPicture(ExcelDrawings drawings, XmlNode node, Image image, Uri hyp SetPosDefaults(image); Packaging.ZipPackage.Flush(); } + [SupportedOSPlatform("windows")] internal ExcelPicture(ExcelDrawings drawings, XmlNode node, FileInfo imageFile, Uri hyperlink) : base(drawings, node, "xdr:pic/xdr:nvPicPr/xdr:cNvPr/@name") { @@ -249,6 +257,7 @@ internal static string GetContentTypeFromBytes(byte[] imageBytes) ".wmf" => "image/x-wmf", _ => "image/jpeg", }; + [SupportedOSPlatform("windows")] internal static ImageFormat GetImageFormat(string contentType) => contentType.ToLower(CultureInfo.InvariantCulture) switch { "image/bmp" => ImageFormat.Bmp, @@ -270,6 +279,7 @@ private static void AddNewPicture(byte[] img, string relID) //_drawings._pics.Add(newPic); } #endregion + [SupportedOSPlatform("windows")] private string SavePicture(Image image) { var img = ImageCompat.GetImageAsByteArray(image); @@ -297,6 +307,7 @@ private string SavePicture(Image image) return RelPic.Id; } + [SupportedOSPlatform("windows")] private void SetPosDefaults(Image image) { EditAs = eEditAs.OneCell; @@ -345,6 +356,7 @@ private string PicStartXml() /// /// The Image /// + [SupportedOSPlatform("windows")] public Image Image { get @@ -371,16 +383,17 @@ public Image Image } } } - ImageFormat _imageFormat = ImageFormat.Jpeg; + ImageFormat _imageFormat; /// /// Image format /// If the picture is created from an Image this type is always Jpeg /// + [SupportedOSPlatform("windows")] public ImageFormat ImageFormat { get { - return _imageFormat; + return _imageFormat ?? ImageFormat.Jpeg; } internal set { @@ -399,7 +412,8 @@ internal string ContentType /// Percent public override void SetSize(int Percent) { - if (Image == null) + // Image is only ever set on Windows. + if (!OperatingSystem.IsWindowsVersionAtLeast(6, 1) || Image == null) { base.SetSize(Percent); } @@ -463,7 +477,10 @@ public override void Dispose() base.Dispose(); Hyperlink = null; // MagicSuite MS-25871: a picture created from raw bytes has no Image - _image?.Dispose(); + if (OperatingSystem.IsWindowsVersionAtLeast(6, 1)) + { + _image?.Dispose(); + } _image = null; } } \ No newline at end of file diff --git a/PanoramicData.EPPlus/Drawing/Vml/ExcelVmlDrawingPicture.cs b/PanoramicData.EPPlus/Drawing/Vml/ExcelVmlDrawingPicture.cs index 313be2d7e..355d507d2 100644 --- a/PanoramicData.EPPlus/Drawing/Vml/ExcelVmlDrawingPicture.cs +++ b/PanoramicData.EPPlus/Drawing/Vml/ExcelVmlDrawingPicture.cs @@ -33,6 +33,7 @@ using System.Xml; using System.Globalization; using System.Drawing; +using System.Runtime.Versioning; namespace OfficeOpenXml.Drawing.Vml; @@ -125,6 +126,7 @@ public string Title /// /// The image /// + [SupportedOSPlatform("windows")] public Image Image { get diff --git a/PanoramicData.EPPlus/Encryption/EncryptionHandler.cs b/PanoramicData.EPPlus/Encryption/EncryptionHandler.cs index cce44bb3a..e5a425159 100644 --- a/PanoramicData.EPPlus/Encryption/EncryptionHandler.cs +++ b/PanoramicData.EPPlus/Encryption/EncryptionHandler.cs @@ -637,7 +637,7 @@ private MemoryStream DecryptBinary(EncryptionInfoBinary encryptionInfo, string p var decryptedData = new byte[size]; - cryptoStream.Read(decryptedData, 0, (int)size); + cryptoStream.ReadAtLeast(decryptedData.AsSpan(0, (int)size), (int)size, throwOnEndOfStream: false); doc.Write(decryptedData, 0, (int)size); } else @@ -672,7 +672,7 @@ private static bool IsPasswordValid(byte[] key, EncryptionInfoBinary encryptionI decryptor, CryptoStreamMode.Read); var decryptedVerifier = new byte[16]; - cryptoStream.Read(decryptedVerifier, 0, 16); + cryptoStream.ReadAtLeast(decryptedVerifier.AsSpan(0, 16), 16, throwOnEndOfStream: false); dataStream = new MemoryStream(encryptionInfo.Verifier.EncryptedVerifierHash); @@ -682,7 +682,7 @@ private static bool IsPasswordValid(byte[] key, EncryptionInfoBinary encryptionI //Decrypt the verifier hash var decryptedVerifierHash = new byte[16]; - cryptoStream.Read(decryptedVerifierHash, 0, (int)16); + cryptoStream.ReadAtLeast(decryptedVerifierHash.AsSpan(0, 16), 16, throwOnEndOfStream: false); //Get the hash for the decrypted verifier var hash = SHA1.HashData(decryptedVerifier); @@ -741,7 +741,7 @@ private static byte[] DecryptAgileFromKey(EncryptionInfoAgile.EncryptionKeyData var decryptedData = new byte[size]; - cryptoStream.Read(decryptedData, 0, (int)size); + cryptoStream.ReadAtLeast(decryptedData.AsSpan(0, (int)size), (int)size, throwOnEndOfStream: false); return decryptedData; } diff --git a/PanoramicData.EPPlus/ExcelBackgroundImage.cs b/PanoramicData.EPPlus/ExcelBackgroundImage.cs index e8f93dc42..97a76ccf4 100644 --- a/PanoramicData.EPPlus/ExcelBackgroundImage.cs +++ b/PanoramicData.EPPlus/ExcelBackgroundImage.cs @@ -36,6 +36,7 @@ using System.Drawing; using System.IO; using System.Xml; +using System.Runtime.Versioning; namespace OfficeOpenXml; @@ -62,6 +63,7 @@ internal ExcelBackgroundImage(XmlNamespaceManager nsm, XmlNode topNode, ExcelWor /// The background image of the worksheet. /// The image will be saved internally as a jpg. /// + [SupportedOSPlatform("windows")] public Image Image { get @@ -97,6 +99,7 @@ public Image Image /// The image file will be saved as a blob, so make sure Excel supports the image format. /// /// The image file. + [SupportedOSPlatform("windows")] public void SetFromFile(FileInfo PictureFile) { DeletePrevImage(); @@ -134,6 +137,7 @@ public void SetFromFile(FileInfo PictureFile) var rel = _workSheet.Part.CreateRelationship(imageURI, Packaging.TargetMode.Internal, ExcelPackage.schemaRelationships + "/image"); SetXmlNodeString(BACKGROUNDPIC_PATH, rel.Id); } + [SupportedOSPlatform("windows")] private void DeletePrevImage() { var relID = GetXmlNodeString(BACKGROUNDPIC_PATH); diff --git a/PanoramicData.EPPlus/ExcelCellBase.cs b/PanoramicData.EPPlus/ExcelCellBase.cs index cfbb991c2..b9ed28c42 100644 --- a/PanoramicData.EPPlus/ExcelCellBase.cs +++ b/PanoramicData.EPPlus/ExcelCellBase.cs @@ -122,8 +122,6 @@ private static string Translate(string value, dlgTransl addressTranslator, int r /// the value to be translated /// /// - /// - /// /// private static string ToR1C1(string part, int row, int col) { @@ -180,8 +178,6 @@ private static string ToR1C1_1(string part, int row, int col) /// /// /// - /// - /// /// private static string ToAbs(string part, int row, int col) { diff --git a/PanoramicData.EPPlus/ExcelColumn.cs b/PanoramicData.EPPlus/ExcelColumn.cs index 7d32c19f5..ed04ac1ae 100644 --- a/PanoramicData.EPPlus/ExcelColumn.cs +++ b/PanoramicData.EPPlus/ExcelColumn.cs @@ -32,6 +32,7 @@ using System; using System.Xml; using OfficeOpenXml.Style; +using System.Runtime.Versioning; namespace OfficeOpenXml; /// @@ -249,6 +250,7 @@ public bool Merged /// Note: Cells containing formulas are ignored since EPPlus don't have a calculation engine. /// Wrapped and merged cells are also ignored. /// + [SupportedOSPlatform("windows")] public void AutoFit() => _worksheet.Cells[1, _columnMin, ExcelPackage.MaxRows, _columnMax].AutoFitColumns(); /// @@ -257,6 +259,7 @@ public bool Merged /// Wrapped and merged cells are also ignored. /// /// Minimum column width + [SupportedOSPlatform("windows")] public void AutoFit(double MinimumWidth) => _worksheet.Cells[1, _columnMin, ExcelPackage.MaxRows, _columnMax].AutoFitColumns(MinimumWidth); /// @@ -266,6 +269,7 @@ public bool Merged /// /// Minimum column width /// Maximum column width + [SupportedOSPlatform("windows")] public void AutoFit(double MinimumWidth, double MaximumWidth) => _worksheet.Cells[1, _columnMin, ExcelPackage.MaxRows, _columnMax].AutoFitColumns(MinimumWidth, MaximumWidth); /// diff --git a/PanoramicData.EPPlus/ExcelHeaderFooter.cs b/PanoramicData.EPPlus/ExcelHeaderFooter.cs index 90ccd62e7..4526393d7 100644 --- a/PanoramicData.EPPlus/ExcelHeaderFooter.cs +++ b/PanoramicData.EPPlus/ExcelHeaderFooter.cs @@ -38,6 +38,7 @@ using System.Drawing; using System.IO; using System.Xml; +using System.Runtime.Versioning; namespace OfficeOpenXml; @@ -121,6 +122,7 @@ private void SetText(string code, string text) /// /// The image object containing the Picture /// Alignment. The image object will be inserted at the end of the Text. + [SupportedOSPlatform("windows")] public ExcelVmlDrawingPicture InsertPicture(Image Picture, PictureAlignment Alignment) { var id = ValidateImage(Alignment); @@ -137,6 +139,7 @@ public ExcelVmlDrawingPicture InsertPicture(Image Picture, PictureAlignment Alig /// /// The image object containing the Picture /// Alignment. The image object will be inserted at the end of the Text. + [SupportedOSPlatform("windows")] public ExcelVmlDrawingPicture InsertPicture(FileInfo PictureFile, PictureAlignment Alignment) { var id = ValidateImage(Alignment); @@ -165,6 +168,7 @@ public ExcelVmlDrawingPicture InsertPicture(FileInfo PictureFile, PictureAlignme return AddImage(Picture, id, ii); } + [SupportedOSPlatform("windows")] private ExcelVmlDrawingPicture AddImage(Image Picture, string id, ExcelPackage.ImageInfo ii) { double width = Picture.Width * 72 / Picture.HorizontalResolution, //Pixel --> Points diff --git a/PanoramicData.EPPlus/ExcelPackage.cs b/PanoramicData.EPPlus/ExcelPackage.cs index 49647a6f6..89b14e7f0 100644 --- a/PanoramicData.EPPlus/ExcelPackage.cs +++ b/PanoramicData.EPPlus/ExcelPackage.cs @@ -1082,7 +1082,7 @@ internal byte[] GetAsByteArray(bool save) var byRet = new byte[Stream.Length]; var pos = Stream.Position; Stream.Seek(0, SeekOrigin.Begin); - Stream.Read(byRet, 0, (int)Stream.Length); + Stream.ReadAtLeast(byRet.AsSpan(0, (int)Stream.Length), (int)Stream.Length, throwOnEndOfStream: false); //Encrypt Workbook? if (Encryption.IsEncrypted) diff --git a/PanoramicData.EPPlus/ExcelRangeBase.cs b/PanoramicData.EPPlus/ExcelRangeBase.cs index a2965b9ac..ce4b3564f 100644 --- a/PanoramicData.EPPlus/ExcelRangeBase.cs +++ b/PanoramicData.EPPlus/ExcelRangeBase.cs @@ -52,6 +52,7 @@ using System.Text; using System.Text.RegularExpressions; using System.Xml; +using System.Runtime.Versioning; namespace OfficeOpenXml; @@ -723,6 +724,7 @@ private ExcelAddressBase GetAddressDim(ExcelRangeBase addr) /// Note: Cells containing formulas must be calculated before autofit is called. /// Wrapped and merged cells are also ignored. /// + [SupportedOSPlatform("windows")] public void AutoFitColumns() => AutoFitColumns(_worksheet.DefaultColWidth); /// @@ -732,6 +734,7 @@ private ExcelAddressBase GetAddressDim(ExcelRangeBase addr) /// /// This method will not work if you run in an environment that does not support GDI /// Minimum column width + [SupportedOSPlatform("windows")] public void AutoFitColumns(double MinimumWidth) => AutoFitColumns(MinimumWidth, double.MaxValue); /// @@ -742,6 +745,7 @@ private ExcelAddressBase GetAddressDim(ExcelRangeBase addr) /// /// Minimum column width /// Maximum column width + [SupportedOSPlatform("windows")] public void AutoFitColumns(double MinimumWidth, double MaximumWidth) { if (_worksheet.Dimension == null) @@ -2565,24 +2569,8 @@ public void Copy(ExcelRangeBase Destination, ExcelRangeCopyOptionFlags? excelRan //Check that the range is not larger than the dimensions of the worksheet. //If so set the copied range to the worksheet dimensions to avoid copying empty cells. - ExcelAddressBase range; - - if (Worksheet.Dimension == null) - { - range = this; - } - else - { - var collideStatus = Collide(Worksheet.Dimension); - if (collideStatus is not eAddressCollition.Equal or not eAddressCollition.Inside) - { - range = Worksheet.Dimension; - } - else - { - range = this; - } - } + // Upstream behaviour kept: its collision test was always true, so any dimension is used. + ExcelAddressBase range = Worksheet.Dimension ?? (ExcelAddressBase)this; if (_fromCol == 1 && _toCol == ExcelPackage.MaxColumns) { diff --git a/PanoramicData.EPPlus/ExcelWorksheets.cs b/PanoramicData.EPPlus/ExcelWorksheets.cs index a9c1534b4..789f24a09 100644 --- a/PanoramicData.EPPlus/ExcelWorksheets.cs +++ b/PanoramicData.EPPlus/ExcelWorksheets.cs @@ -693,6 +693,11 @@ private void CopyDrawing(ExcelWorksheet Copy, ExcelWorksheet workSheet/*, Packag var uri = pic.UriPic; if (!workSheet.Workbook._package.Package.PartExists(uri)) { + if (!OperatingSystem.IsWindowsVersionAtLeast(6, 1)) + { + throw new PlatformNotSupportedException("Copying a picture to another package uses System.Drawing, which is only supported on Windows."); + } + var picPart = workSheet.Workbook._package.Package.CreatePart(uri, pic.ContentType, CompressionLevel.None); pic.Image.Save(picPart.GetStream(FileMode.Create, FileAccess.Write), ExcelPicture.GetImageFormat(pic.ContentType)); } diff --git a/PanoramicData.EPPlus/FormulaParsing/CalculateExtentions.cs b/PanoramicData.EPPlus/FormulaParsing/CalculateExtentions.cs index 36eba8449..38fad32b1 100644 --- a/PanoramicData.EPPlus/FormulaParsing/CalculateExtentions.cs +++ b/PanoramicData.EPPlus/FormulaParsing/CalculateExtentions.cs @@ -143,11 +143,11 @@ private static void CalcChain(ExcelWorkbook wb, FormulaParser parser, Dependency Thread.Sleep(0); } - catch (FormatException fe) + catch (FormatException) { - throw fe; + throw; } - catch (Exception e) + catch (Exception) { var error = ExcelErrorValue.Parse(ExcelErrorValue.Values.Value); SetValue(wb, item, error); diff --git a/PanoramicData.EPPlus/FormulaParsing/Excel/Functions/DoubleArgumentParser.cs b/PanoramicData.EPPlus/FormulaParsing/Excel/Functions/DoubleArgumentParser.cs index bd40b0b54..d5187ab8b 100644 --- a/PanoramicData.EPPlus/FormulaParsing/Excel/Functions/DoubleArgumentParser.cs +++ b/PanoramicData.EPPlus/FormulaParsing/Excel/Functions/DoubleArgumentParser.cs @@ -26,7 +26,7 @@ using System.Globalization; using OfficeOpenXml.FormulaParsing.Utilities; using OfficeOpenXml.FormulaParsing.Exceptions; -using util = OfficeOpenXml.Utils; +using Utils = OfficeOpenXml.Utils; namespace OfficeOpenXml.FormulaParsing.Excel.Functions; @@ -42,7 +42,7 @@ public override object Parse(object obj) } if (obj is double) return obj; - if (obj.IsNumeric()) return util.ConvertUtil.GetValueDouble(obj); + if (obj.IsNumeric()) return Utils.ConvertUtil.GetValueDouble(obj); var str = obj != null ? obj.ToString() : string.Empty; try { diff --git a/PanoramicData.EPPlus/Packaging/DotNetZip/CRC32.cs b/PanoramicData.EPPlus/Packaging/DotNetZip/CRC32.cs index 0b336318c..a6ed2c20b 100644 --- a/PanoramicData.EPPlus/Packaging/DotNetZip/CRC32.cs +++ b/PanoramicData.EPPlus/Packaging/DotNetZip/CRC32.cs @@ -631,7 +631,7 @@ private CrcCalculatorStream /// /// /// - /// Set this at any point before calling . + /// Set this at any point before calling Close(). /// /// public bool LeaveOpen diff --git a/PanoramicData.EPPlus/Packaging/DotNetZip/WinZipAes.cs b/PanoramicData.EPPlus/Packaging/DotNetZip/WinZipAes.cs index 6c07a6e56..735db4726 100644 --- a/PanoramicData.EPPlus/Packaging/DotNetZip/WinZipAes.cs +++ b/PanoramicData.EPPlus/Packaging/DotNetZip/WinZipAes.cs @@ -103,8 +103,8 @@ public static WinZipAesCrypto ReadFromStream(string password, int KeyStrengthInB c._Salt = new byte[saltSizeInBytes]; c._providedPv = new byte[2]; - s.Read(c._Salt, 0, c._Salt.Length); - s.Read(c._providedPv, 0, c._providedPv.Length); + s.ReadAtLeast(c._Salt, c._Salt.Length, throwOnEndOfStream: false); + s.ReadAtLeast(c._providedPv, c._providedPv.Length, throwOnEndOfStream: false); c.PasswordVerificationStored = (short)(c._providedPv[0] + c._providedPv[1] * 256); if (password != null) @@ -177,12 +177,12 @@ private void _GenerateCryptoBytes() { //Console.WriteLine(" provided password: '{0}'", _Password); - var rfc2898 = - new Rfc2898DeriveBytes(_Password, Salt, Rfc2898KeygenIterations); + // WinZip AES: one PBKDF2-HMAC-SHA1 stream split into key, MAC key and 2-byte verifier. + var derived = Rfc2898DeriveBytes.Pbkdf2(_Password, Salt, Rfc2898KeygenIterations, HashAlgorithmName.SHA1, 2 * _KeyStrengthInBytes + 2); - _keyBytes = rfc2898.GetBytes(_KeyStrengthInBytes); // 16 or 24 or 32 ??? - _MacInitializationVector = rfc2898.GetBytes(_KeyStrengthInBytes); - _generatedPv = rfc2898.GetBytes(2); + _keyBytes = derived[.._KeyStrengthInBytes]; + _MacInitializationVector = derived[_KeyStrengthInBytes..(2 * _KeyStrengthInBytes)]; + _generatedPv = derived[(2 * _KeyStrengthInBytes)..]; _cryptoGenerated = true; } @@ -217,7 +217,7 @@ public void ReadAndVerifyMac(Stream s) // read integrityCheckVector. // caller must ensure that the file pointer is in the right spot! _StoredMac = new byte[10]; // aka "authentication code" - s.Read(_StoredMac, 0, _StoredMac.Length); + s.ReadAtLeast(_StoredMac, _StoredMac.Length, throwOnEndOfStream: false); if (_StoredMac.Length != CalculatedMac.Length) invalid = true; @@ -354,12 +354,7 @@ internal class WinZipAesCipherStream : Stream internal HMACSHA1 _mac; - // Use RijndaelManaged from .NET 2.0. - // AesManaged came in .NET 3.5, but we want to limit - // dependency to .NET 2.0. AES is just a restricted form - // of Rijndael (fixed block size of 128, some crypto modes not supported). - - internal RijndaelManaged _aesCipher; + internal Aes _aesCipher; internal ICryptoTransform _xform; private const int BLOCK_SIZE_IN_BYTES = 16; @@ -431,13 +426,10 @@ internal WinZipAesCipherStream(Stream s, WinZipAesCrypto cryptoParams, CryptoMod _mac = new HMACSHA1(_params.MacIv); - _aesCipher = new RijndaelManaged - { - BlockSize = 128, - KeySize = keySizeInBits, // 128, 192, 256 - Mode = CipherMode.ECB, - Padding = PaddingMode.None - }; + _aesCipher = Aes.Create(); + _aesCipher.KeySize = keySizeInBits; // 128, 192, 256 + _aesCipher.Mode = CipherMode.ECB; + _aesCipher.Padding = PaddingMode.None; var iv = new byte[BLOCK_SIZE_IN_BYTES]; // all zeroes diff --git a/PanoramicData.EPPlus/Packaging/DotNetZip/ZipEntry.Read.cs b/PanoramicData.EPPlus/Packaging/DotNetZip/ZipEntry.Read.cs index 9f65affaa..dec25bbb1 100644 --- a/PanoramicData.EPPlus/Packaging/DotNetZip/ZipEntry.Read.cs +++ b/PanoramicData.EPPlus/Packaging/DotNetZip/ZipEntry.Read.cs @@ -44,7 +44,7 @@ private void ReadExtraField() SharedUtilities.Workaround_Ladybug318918(ArchiveStream); var block = new byte[30]; - ArchiveStream.Read(block, 0, block.Length); + ArchiveStream.ReadAtLeast(block, block.Length, throwOnEndOfStream: false); var i = 26; var filenameLength = (short)(block[i++] + block[i++] * 256); var extraFieldLength = (short)(block[i++] + block[i++] * 256); diff --git a/PanoramicData.EPPlus/Packaging/DotNetZip/ZipEntry.Write.cs b/PanoramicData.EPPlus/Packaging/DotNetZip/ZipEntry.Write.cs index c4366b8b1..4319f2c31 100644 --- a/PanoramicData.EPPlus/Packaging/DotNetZip/ZipEntry.Write.cs +++ b/PanoramicData.EPPlus/Packaging/DotNetZip/ZipEntry.Write.cs @@ -2404,7 +2404,7 @@ private void CopyThroughWithRecompute(Stream outstream) var size = 16; if (_InputUsesZip64) size += 8; var Descriptor = new byte[size]; - input.Read(Descriptor, 0, size); + input.ReadAtLeast(Descriptor.AsSpan(0, size), size, throwOnEndOfStream: false); if (_InputUsesZip64 && _container.UseZip64WhenSaving == Zip64Option.Never) { diff --git a/PanoramicData.EPPlus/Packaging/DotNetZip/ZipEntry.cs b/PanoramicData.EPPlus/Packaging/DotNetZip/ZipEntry.cs index 5862ff64c..98d629bbb 100644 --- a/PanoramicData.EPPlus/Packaging/DotNetZip/ZipEntry.cs +++ b/PanoramicData.EPPlus/Packaging/DotNetZip/ZipEntry.cs @@ -1533,7 +1533,7 @@ public DotNetZip.Zlib.CompressionLevel CompressionLevel /// property for each ZipEntry indicates whether encryption was /// actually used (which will have been true if the was set and the property - /// was something other than . + /// was something other than . /// /// public bool UsesEncryption => (_Encryption_FromZipFile != DotNetZip.EncryptionAlgorithm.None); @@ -1550,7 +1550,7 @@ public DotNetZip.Zlib.CompressionLevel CompressionLevel /// Set this property in order to encrypt the entry when the ZipFile is /// saved. When setting this property, you must also set a on the entry. If you set a value other than on this property and do not set a + /// cref="DotNetZip.EncryptionAlgorithm.None"/> on this property and do not set a /// Password then the entry will not be encrypted. The ZipEntry /// data is encrypted as the ZipFile is saved, when you call or one of its cousins on the containing @@ -2481,7 +2481,7 @@ private void SetFdpLoh() } var block = new byte[30]; - ArchiveStream.Read(block, 0, block.Length); + ArchiveStream.ReadAtLeast(block, block.Length, throwOnEndOfStream: false); // At this point we could verify the contents read from the local header // with the contents read from the central header. We could, but don't need to. diff --git a/PanoramicData.EPPlus/Packaging/DotNetZip/ZipFile.Read.cs b/PanoramicData.EPPlus/Packaging/DotNetZip/ZipFile.Read.cs index 509747180..55dabe9ed 100644 --- a/PanoramicData.EPPlus/Packaging/DotNetZip/ZipFile.Read.cs +++ b/PanoramicData.EPPlus/Packaging/DotNetZip/ZipFile.Read.cs @@ -598,7 +598,7 @@ private static void ReadIntoInstance(ZipFile zf) zf._locEndOfCDS = s.Position - 4; var block = new byte[16]; - s.Read(block, 0, block.Length); + s.ReadAtLeast(block, block.Length, throwOnEndOfStream: false); zf._diskNumberWithCd = BitConverter.ToUInt16(block, 2); @@ -666,7 +666,7 @@ private static void Zip64SeekToCentralDirectory(ZipFile zf) // seek back to find the ZIP64 EoCD. // I think this might not work for .NET CF ? s.Seek(-40, SeekOrigin.Current); - s.Read(block, 0, 16); + s.ReadAtLeast(block.AsSpan(0, 16), 16, throwOnEndOfStream: false); var offset64 = BitConverter.ToInt64(block, 8); zf._OffsetOfCentralDirectory = 0xFFFFFFFF; @@ -679,11 +679,11 @@ private static void Zip64SeekToCentralDirectory(ZipFile zf) if (datum != ZipConstants.Zip64EndOfCentralDirectoryRecordSignature) throw new BadReadException(String.Format(" Bad signature (0x{0:X8}) looking for ZIP64 EoCD Record at position 0x{1:X8}", datum, s.Position)); - s.Read(block, 0, 8); + s.ReadAtLeast(block.AsSpan(0, 8), 8, throwOnEndOfStream: false); var Size = BitConverter.ToInt64(block, 0); block = new byte[Size]; - s.Read(block, 0, block.Length); + s.ReadAtLeast(block, block.Length, throwOnEndOfStream: false); offset64 = BitConverter.ToInt64(block, 36); // change for workitem 8098 @@ -846,7 +846,7 @@ private static void ReadCentralDirectoryFooter(ZipFile zf) // 52 bytes block = new byte[8 + 44]; - s.Read(block, 0, block.Length); + s.ReadAtLeast(block, block.Length, throwOnEndOfStream: false); var DataSize = BitConverter.ToInt64(block, 0); // == 44 + the variable length @@ -864,7 +864,7 @@ private static void ReadCentralDirectoryFooter(ZipFile zf) // read the extended block block = new byte[DataSize - 44]; - s.Read(block, 0, block.Length); + s.ReadAtLeast(block, block.Length, throwOnEndOfStream: false); // discard the result signature = SharedUtilities.ReadSignature(s); @@ -872,7 +872,7 @@ private static void ReadCentralDirectoryFooter(ZipFile zf) throw new ZipException("Inconsistent metadata in the ZIP64 Central Directory."); block = new byte[16]; - s.Read(block, 0, block.Length); + s.ReadAtLeast(block, block.Length, throwOnEndOfStream: false); // discard the result signature = SharedUtilities.ReadSignature(s); @@ -889,7 +889,7 @@ private static void ReadCentralDirectoryFooter(ZipFile zf) // read the End-of-Central-Directory-Record block = new byte[16]; - zf.ReadStream.Read(block, 0, block.Length); + zf.ReadStream.ReadAtLeast(block, block.Length, throwOnEndOfStream: false); // off sz data // ------------------------------------------------------- @@ -919,13 +919,13 @@ private static void ReadZipFileComment(ZipFile zf) { // read the comment here var block = new byte[2]; - zf.ReadStream.Read(block, 0, block.Length); + zf.ReadStream.ReadAtLeast(block, block.Length, throwOnEndOfStream: false); var commentLength = (short)(block[0] + block[1] * 256); if (commentLength > 0) { block = new byte[commentLength]; - zf.ReadStream.Read(block, 0, block.Length); + zf.ReadStream.ReadAtLeast(block, block.Length, throwOnEndOfStream: false); // workitem 10392 - prefer ProvisionalAlternateEncoding, // first. The fix for workitem 6513 tried to use UTF8 diff --git a/PanoramicData.EPPlus/Packaging/DotNetZip/Zlib/ZlibBaseStream.cs b/PanoramicData.EPPlus/Packaging/DotNetZip/Zlib/ZlibBaseStream.cs index 673712516..901a0e1de 100644 --- a/PanoramicData.EPPlus/Packaging/DotNetZip/Zlib/ZlibBaseStream.cs +++ b/PanoramicData.EPPlus/Packaging/DotNetZip/Zlib/ZlibBaseStream.cs @@ -392,7 +392,7 @@ private int _ReadAndValidateGzipHeader() if ((header[3] & 0x10) == 0x010) _GzipComment = ReadZeroTerminatedString(); if ((header[3] & 0x02) == 0x02) - Read(_buf1, 0, 1); // CRC16, ignore + ReadAtLeast(_buf1.AsSpan(0, 1), 1, throwOnEndOfStream: false); // CRC16, ignore return totalBytesRead; } diff --git a/PanoramicData.EPPlus/Packaging/ZipPackageRelationshipBase.cs b/PanoramicData.EPPlus/Packaging/ZipPackageRelationshipBase.cs index 8410d2fb4..e33287da4 100644 --- a/PanoramicData.EPPlus/Packaging/ZipPackageRelationshipBase.cs +++ b/PanoramicData.EPPlus/Packaging/ZipPackageRelationshipBase.cs @@ -92,7 +92,7 @@ internal void ReadRelation(string xml, string source) catch { //The URI is not a valid URI. Encode it to make i valid. - rel.TargetUri = new Uri(Uri.EscapeUriString("Invalid:URI " + c.GetAttribute("Target")), UriKind.RelativeOrAbsolute); + rel.TargetUri = new Uri(EscapeUriString("Invalid:URI " + c.GetAttribute("Target")), UriKind.RelativeOrAbsolute); } if (!string.IsNullOrEmpty(source)) @@ -114,4 +114,24 @@ internal void ReadRelation(string xml, string source) _rels.Add(rel); } } + + // Same output as the obsolete Uri.EscapeUriString, which this saved Target text must keep matching. + private static string EscapeUriString(string value) + { + var sb = new StringBuilder(value.Length); + foreach (var b in Encoding.UTF8.GetBytes(value)) + { + var c = (char)b; + if (b < 0x80 && (char.IsAsciiLetterOrDigit(c) || "-._~:/?#[]@!$&'()*+,;=".Contains(c))) + { + sb.Append(c); + } + else + { + sb.Append('%').Append(b.ToString("X2")); + } + } + + return sb.ToString(); + } } \ No newline at end of file diff --git a/PanoramicData.EPPlus/PanoramicData.EPPlus.csproj b/PanoramicData.EPPlus/PanoramicData.EPPlus.csproj index d0ee71082..9203a2b95 100644 --- a/PanoramicData.EPPlus/PanoramicData.EPPlus.csproj +++ b/PanoramicData.EPPlus/PanoramicData.EPPlus.csproj @@ -27,7 +27,10 @@ OpenOfficeXml.Rimland.snk lgpl-3.0.txt - enable + + annotations + + $(NoWarn);CS1591 README.md git True @@ -36,7 +39,6 @@ PanoramicData.EPPlus snupkg en - MIT bin\$(Configuration)\$(TargetFramework)\EPPlusFree.xml diff --git a/PanoramicData.EPPlus/Style/ExcelFont.cs b/PanoramicData.EPPlus/Style/ExcelFont.cs index e9e0c8022..9f3f8f665 100644 --- a/PanoramicData.EPPlus/Style/ExcelFont.cs +++ b/PanoramicData.EPPlus/Style/ExcelFont.cs @@ -31,6 +31,7 @@ *******************************************************************************/ using System; using System.Drawing; +using System.Runtime.Versioning; namespace OfficeOpenXml.Style; @@ -200,6 +201,7 @@ public ExcelVerticalAlignmentFont VerticalAlign /// Set the font from a Font object /// /// + [SupportedOSPlatform("windows")] public void SetFromFont(Font Font) { Name = Font.Name; diff --git a/PanoramicData.EPPlus/Style/ExcelTextFont.cs b/PanoramicData.EPPlus/Style/ExcelTextFont.cs index 5c0f69cfd..4184bf970 100644 --- a/PanoramicData.EPPlus/Style/ExcelTextFont.cs +++ b/PanoramicData.EPPlus/Style/ExcelTextFont.cs @@ -33,6 +33,7 @@ using System.Globalization; using System.Xml; using System.Drawing; +using System.Runtime.Versioning; namespace OfficeOpenXml.Style; @@ -258,6 +259,7 @@ private static string TranslateUnderlineText(eUnderLineType value) /// Set the font style from a font object /// /// + [SupportedOSPlatform("windows")] public void SetFromFont(Font Font) { LatinFont = Font.Name; diff --git a/PanoramicData.EPPlus/Style/XmlAccess/ExcelFontXml.cs b/PanoramicData.EPPlus/Style/XmlAccess/ExcelFontXml.cs index 6aa4724f7..2618816e8 100644 --- a/PanoramicData.EPPlus/Style/XmlAccess/ExcelFontXml.cs +++ b/PanoramicData.EPPlus/Style/XmlAccess/ExcelFontXml.cs @@ -33,6 +33,7 @@ using System.Drawing; using System.Globalization; using System.Xml; +using System.Runtime.Versioning; namespace OfficeOpenXml.Style.XmlAccess; /// @@ -261,6 +262,7 @@ public string VerticalAlign _verticalAlign = value; } } + [SupportedOSPlatform("windows")] public void SetFromFont(System.Drawing.Font Font) { Name = Font.Name; diff --git a/PanoramicData.EPPlus/Utils/CompundDocument/CompoundDocumentFile.cs b/PanoramicData.EPPlus/Utils/CompundDocument/CompoundDocumentFile.cs index 6c3268787..1cd4e973e 100644 --- a/PanoramicData.EPPlus/Utils/CompundDocument/CompoundDocumentFile.cs +++ b/PanoramicData.EPPlus/Utils/CompundDocument/CompoundDocumentFile.cs @@ -113,7 +113,7 @@ public static bool IsCompoundDocument(FileInfo fi) { var fs = fi.OpenRead(); var b = new byte[8]; - fs.Read(b, 0, 8); + fs.ReadAtLeast(b.AsSpan(0, 8), 8, throwOnEndOfStream: false); return IsCompoundDocument(b); } catch diff --git a/PanoramicData.EPPlus/VBA/ExcelVBASignature.cs b/PanoramicData.EPPlus/VBA/ExcelVBASignature.cs index 8984d96e3..6014addf8 100644 --- a/PanoramicData.EPPlus/VBA/ExcelVBASignature.cs +++ b/PanoramicData.EPPlus/VBA/ExcelVBASignature.cs @@ -86,7 +86,7 @@ private void GetSignature() { //Add property values here... case 0x20: - Certificate = new X509Certificate2(value); + Certificate = X509CertificateLoader.LoadCertificate(value); break; default: break; diff --git a/SampleApp/Sample1.cs b/SampleApp/Sample1.cs index c70fe646d..119129ce3 100644 --- a/SampleApp/Sample1.cs +++ b/SampleApp/Sample1.cs @@ -29,6 +29,7 @@ ******************************************************************************* * Jan Källman Added 21 Mar 2010 *******************************************************************************/ +using System.Runtime.Versioning; using OfficeOpenXml; using System.Drawing; using OfficeOpenXml.Style; @@ -41,6 +42,7 @@ class Sample1 /// Sample 1 - simply creates a new workbook from scratch. /// The workbook contains one worksheet with a simple invertory list /// + [SupportedOSPlatform("windows")] public static string RunSample1() { using var package = new ExcelPackage(); diff --git a/SampleApp/Sample12.cs b/SampleApp/Sample12.cs index 7c8c43b59..db4dfb409 100644 --- a/SampleApp/Sample12.cs +++ b/SampleApp/Sample12.cs @@ -26,11 +26,12 @@ * ****************************************************************************** * Jan Källman Added 2011-04-18 *******************************************************************************/ +using System.Runtime.Versioning; using System; using System.Collections.Generic; using System.Linq; using OfficeOpenXml; -using System.Data.SqlClient; +using Microsoft.Data.SqlClient; using OfficeOpenXml.Table.PivotTable; using OfficeOpenXml.Drawing.Chart; namespace SampleApp; @@ -53,6 +54,7 @@ public class SalesDTO public decimal Freight { get; set; } public decimal Total => SubTotal + Tax + Freight; } + [SupportedOSPlatform("windows")] public static string RunSample12(string connectionStr) { var list = new List(); diff --git a/SampleApp/Sample13.cs b/SampleApp/Sample13.cs index b3a529601..3736e720d 100644 --- a/SampleApp/Sample13.cs +++ b/SampleApp/Sample13.cs @@ -26,6 +26,7 @@ * ****************************************************************************** * Jan Källman Added 2011-05-03 *******************************************************************************/ +using System.Runtime.Versioning; using System; using System.Linq; using System.IO; @@ -51,6 +52,7 @@ public class FileDTO public override string ToString() => IsDirectory ? Name + "\t" : Name + "\t" + Size.ToString("#,##0"); } + [SupportedOSPlatform("windows")] public static void RunSample13() { var pck = new ExcelPackage(); diff --git a/SampleApp/Sample16.cs b/SampleApp/Sample16.cs index 92a33918e..d43da6906 100644 --- a/SampleApp/Sample16.cs +++ b/SampleApp/Sample16.cs @@ -26,6 +26,7 @@ * ****************************************************************************** * Jan Källman Added 2018-03-20 *******************************************************************************/ +using System.Runtime.Versioning; using OfficeOpenXml; using OfficeOpenXml.Sparkline; using OfficeOpenXml.Table; @@ -37,6 +38,7 @@ namespace SampleApp; public static class Sample16 { + [SupportedOSPlatform("windows")] public static void RunSample16() { using var package = new ExcelPackage(); diff --git a/SampleApp/Sample3.cs b/SampleApp/Sample3.cs index da82c7d0d..c7640754d 100644 --- a/SampleApp/Sample3.cs +++ b/SampleApp/Sample3.cs @@ -46,9 +46,10 @@ * All code and executables are provided "as is" with no warranty either express or implied. * The author accepts no liability for any damage or loss of business that this product may cause. */ +using System.Runtime.Versioning; using System; using OfficeOpenXml; -using System.Data.SqlClient; +using Microsoft.Data.SqlClient; using System.Drawing; using OfficeOpenXml.Style; @@ -64,6 +65,7 @@ class Sample3 /// The output directory /// The location of the sample template /// The connection string to your copy of the AdventureWorks database + [SupportedOSPlatform("windows")] public static string RunSample3(string connectionString) { var file = Utils.GetFileInfo("Sample3.xlsx"); diff --git a/SampleApp/Sample4.cs b/SampleApp/Sample4.cs index 2bc0b6105..6dec38478 100644 --- a/SampleApp/Sample4.cs +++ b/SampleApp/Sample4.cs @@ -31,7 +31,7 @@ using OfficeOpenXml; using System.IO; -using System.Data.SqlClient; +using Microsoft.Data.SqlClient; using OfficeOpenXml.Drawing.Chart; using OfficeOpenXml.Style; using System.Drawing; diff --git a/SampleApp/Sample6.cs b/SampleApp/Sample6.cs index d502e40b7..ae3e0858f 100644 --- a/SampleApp/Sample6.cs +++ b/SampleApp/Sample6.cs @@ -29,6 +29,7 @@ ******************************************************************************* * Jan Källman Added 25-JAN-2010 *******************************************************************************/ +using System.Runtime.Versioning; using OfficeOpenXml; using OfficeOpenXml.Drawing; using OfficeOpenXml.Drawing.Chart; @@ -71,6 +72,7 @@ public int CompareTo(StatItem other) => Size < other.Size ? -1 : /// Directory to scan /// How many levels? /// Skip the icons in column A. A lot faster + [SupportedOSPlatform("windows")] public static string RunSample6(DirectoryInfo dir, int depth, bool skipIcons) { _maxLevels = depth; @@ -210,6 +212,7 @@ private static void AddComments(ExcelWorksheet ws) /// Package /// /// + [SupportedOSPlatform("windows")] private static void AddGraphs(ExcelPackage pck, int rows, string dir) { var ws = pck.Workbook.Worksheets.Add("Statistics"); @@ -308,6 +311,7 @@ private static void AddGraphs(ExcelPackage pck, int rows, string dir) /// Header text /// Size or Count /// + [SupportedOSPlatform("windows")] private static int AddStatRows(ExcelWorksheet ws, List lst, int startRow, string header, string propertyName) { //Add Headers @@ -405,6 +409,7 @@ private static void AlterColor(ExcelWorksheet ws, int row) } } + [SupportedOSPlatform("windows")] private static int AddDirectory(ExcelWorksheet ws, DirectoryInfo dir, int row, double height, int level, bool skipIcons) { //Get the icon as a bitmap @@ -519,6 +524,7 @@ private static void AddStatistics(FileInfo file) /// /// /// + [SupportedOSPlatform("windows")] private static Bitmap GetIcon(string FileName) { if (File.Exists(FileName)) diff --git a/SampleApp/Sample7.cs b/SampleApp/Sample7.cs index 67aa6bb56..56adeff67 100644 --- a/SampleApp/Sample7.cs +++ b/SampleApp/Sample7.cs @@ -1,4 +1,5 @@ using System; +using System.Runtime.Versioning; using OfficeOpenXml; using OfficeOpenXml.Style; using System.Drawing; @@ -9,9 +10,10 @@ class Sample7 { /// /// This sample load a number of rows, style them and insert a row at the top. - /// A password is set to protect locked cells. Column 3 & 4 will be editable, the rest will be locked. + /// A password is set to protect locked cells. Column 3 and 4 will be editable, the rest will be locked. /// /// + [SupportedOSPlatform("windows")] public static string RunSample7(int rows) { var newFile = Utils.GetFileInfo("sample7.xlsx"); diff --git a/SampleApp/Sample9.cs b/SampleApp/Sample9.cs index 5be8dcc97..67bef558f 100644 --- a/SampleApp/Sample9.cs +++ b/SampleApp/Sample9.cs @@ -29,6 +29,7 @@ ******************************************************************************* * Jan Källman Added 28 Oct 2010 *******************************************************************************/ +using System.Runtime.Versioning; using System; using OfficeOpenXml; using System.IO; @@ -49,6 +50,7 @@ public static class Sample9 /// /// /// + [SupportedOSPlatform("windows")] public static string RunSample9() { var newFile = Utils.GetFileInfo(@"sample9.xlsx"); @@ -63,6 +65,7 @@ public static string RunSample9() return newFile.FullName; } + [SupportedOSPlatform("windows")] private static void LoadFile1(ExcelPackage package) { //Create the Worksheet @@ -129,6 +132,7 @@ private static void LoadFile1(ExcelPackage package) sheet.Cells[sheet.Dimension.Address].AutoFitColumns(); } + [SupportedOSPlatform("windows")] private static void LoadFile2(ExcelPackage package) { //Create the Worksheet diff --git a/SampleApp/SampleApp.csproj b/SampleApp/SampleApp.csproj index 063b067cf..d71be9cd1 100644 --- a/SampleApp/SampleApp.csproj +++ b/SampleApp/SampleApp.csproj @@ -4,6 +4,9 @@ Exe net10.0 enable + + disable + false false en @@ -16,7 +19,7 @@ - + diff --git a/SampleApp/Sample_Main.cs b/SampleApp/Sample_Main.cs index 7fd5f4533..253c801ec 100644 --- a/SampleApp/Sample_Main.cs +++ b/SampleApp/Sample_Main.cs @@ -29,6 +29,7 @@ ******************************************************************************* * Jan Källman Added 10-SEP-2009 *******************************************************************************/ +using System.Runtime.Versioning; using System; using System.IO; @@ -36,6 +37,7 @@ namespace SampleApp; class Sample_Main { + [SupportedOSPlatform("windows")] static void Main(string[] args) { try diff --git a/SampleWebApp/Controllers/HomeController.cs b/SampleWebApp/Controllers/HomeController.cs index 3d7b5c818..ee97dca63 100644 --- a/SampleWebApp/Controllers/HomeController.cs +++ b/SampleWebApp/Controllers/HomeController.cs @@ -1,4 +1,5 @@ using Microsoft.AspNetCore.Hosting; +using System.Runtime.Versioning; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Mvc; using OfficeOpenXml; @@ -11,13 +12,14 @@ namespace SampleWebApp.Controllers; -public class HomeController(IHostingEnvironment hostingEnvironment) : Controller +public class HomeController(IWebHostEnvironment hostingEnvironment) : Controller { private const string XlsxContentType = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"; /// /// /Home/FileReport /// + [SupportedOSPlatform("windows")] public IActionResult FileReport() { var fileDownloadName = "report.xlsx"; @@ -36,6 +38,7 @@ public IActionResult FileReport() /// /// An in-memory report /// + [SupportedOSPlatform("windows")] public IActionResult InMemoryReport() { byte[] reportBytes; @@ -50,6 +53,7 @@ public IActionResult InMemoryReport() /// /// /Home/ReadFile /// + [SupportedOSPlatform("windows")] public IActionResult ReadFile() { var fileDownloadName = "report.xlsx"; @@ -82,6 +86,7 @@ public async Task FileUpload(IFormFile file) /// /// /Home/DataTableReport /// + [SupportedOSPlatform("windows")] public IActionResult DataTableReport() { var dataTable = new DataTable("Users"); @@ -137,6 +142,7 @@ private static string readExcelPackageToString(ExcelPackage package, ExcelWorksh return sb.ToString(); } + [SupportedOSPlatform("windows")] private ExcelPackage createExcelPackage() { var package = new ExcelPackage(); diff --git a/SampleWebApp/Program.cs b/SampleWebApp/Program.cs index 400c5bf80..7e6c63312 100644 --- a/SampleWebApp/Program.cs +++ b/SampleWebApp/Program.cs @@ -1,19 +1,12 @@ -using System.IO; -using Microsoft.AspNetCore.Hosting; +using Microsoft.AspNetCore.Builder; +using Microsoft.Extensions.DependencyInjection; -namespace SampleWebApp; +var builder = WebApplication.CreateBuilder(args); +builder.Services.AddControllersWithViews(); -public class Program -{ - public static void Main(string[] args) - { - var host = new WebHostBuilder() - .UseKestrel() - .UseContentRoot(Directory.GetCurrentDirectory()) - .UseIISIntegration() - .UseStartup() - .Build(); - - host.Run(); - } -} \ No newline at end of file +var app = builder.Build(); +app.UseDeveloperExceptionPage(); +app.UseDefaultFiles(); +app.UseStaticFiles(); +app.MapDefaultControllerRoute(); +app.Run(); diff --git a/SampleWebApp/SampleWebApp.csproj b/SampleWebApp/SampleWebApp.csproj index 6078e1161..9c4297e7b 100644 --- a/SampleWebApp/SampleWebApp.csproj +++ b/SampleWebApp/SampleWebApp.csproj @@ -5,7 +5,10 @@ - enable + disable + + disable + false false en diff --git a/SampleWebApp/Startup.cs b/SampleWebApp/Startup.cs deleted file mode 100644 index ec28a89cc..000000000 --- a/SampleWebApp/Startup.cs +++ /dev/null @@ -1,18 +0,0 @@ -using Microsoft.AspNetCore.Builder; -using Microsoft.AspNetCore.Hosting; -using Microsoft.Extensions.DependencyInjection; - -namespace SampleWebApp; - -public class Startup -{ - public void ConfigureServices(IServiceCollection services) => services.AddMvc(); - - public void Configure(IApplicationBuilder app, IHostingEnvironment env) - { - app.UseDeveloperExceptionPage(); - app.UseMvcWithDefaultRoute(); - app.UseDefaultFiles(); - app.UseStaticFiles(); - } -} \ No newline at end of file diff --git a/global.json b/global.json index 6f6823064..9ee2bff7c 100644 --- a/global.json +++ b/global.json @@ -2,8 +2,5 @@ "sdk": { "rollForward": "latestMinor", "version": "10.0.102" - }, - "test": { - "runner": "Microsoft.Testing.Platform" } -} \ No newline at end of file +} From 5faee2cda5f2468985d13b375dcfe2fd3e66ca49 Mon Sep 17 00:00:00 2001 From: David Bond Date: Sun, 4 Oct 2026 12:58:44 +0100 Subject: [PATCH 2/2] OPS-157454: Address Codacy findings on the build fix Only show the developer exception page in Development in SampleWebApp, and mark WinZip AES's ECB use as intended: it is the block primitive for CTR mode, with HMAC-SHA1 for integrity. Co-Authored-By: Claude Opus 5.5 (1M context) --- PanoramicData.EPPlus/Packaging/DotNetZip/WinZipAes.cs | 3 ++- SampleWebApp/Program.cs | 7 ++++++- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/PanoramicData.EPPlus/Packaging/DotNetZip/WinZipAes.cs b/PanoramicData.EPPlus/Packaging/DotNetZip/WinZipAes.cs index 735db4726..8daf53c63 100644 --- a/PanoramicData.EPPlus/Packaging/DotNetZip/WinZipAes.cs +++ b/PanoramicData.EPPlus/Packaging/DotNetZip/WinZipAes.cs @@ -428,7 +428,8 @@ internal WinZipAesCipherStream(Stream s, WinZipAesCrypto cryptoParams, CryptoMod _aesCipher = Aes.Create(); _aesCipher.KeySize = keySizeInBits; // 128, 192, 256 - _aesCipher.Mode = CipherMode.ECB; + // WinZip AES is CTR mode: ECB only encrypts single counter blocks, and HMAC-SHA1 provides integrity. + _aesCipher.Mode = CipherMode.ECB; // nosemgrep _aesCipher.Padding = PaddingMode.None; var iv = new byte[BLOCK_SIZE_IN_BYTES]; // all zeroes diff --git a/SampleWebApp/Program.cs b/SampleWebApp/Program.cs index 7e6c63312..2bb383976 100644 --- a/SampleWebApp/Program.cs +++ b/SampleWebApp/Program.cs @@ -1,11 +1,16 @@ using Microsoft.AspNetCore.Builder; using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Hosting; var builder = WebApplication.CreateBuilder(args); builder.Services.AddControllersWithViews(); var app = builder.Build(); -app.UseDeveloperExceptionPage(); +if (app.Environment.IsDevelopment()) +{ + app.UseDeveloperExceptionPage(); +} + app.UseDefaultFiles(); app.UseStaticFiles(); app.MapDefaultControllerRoute();