diff --git a/.github/workflows/gitleaks.yaml b/.github/workflows/gitleaks.yaml index d9a8e36..c115f77 100644 --- a/.github/workflows/gitleaks.yaml +++ b/.github/workflows/gitleaks.yaml @@ -1,4 +1,4 @@ -name: Secret Value found! +name: Secret Value found!! on: push: public: @@ -32,7 +32,7 @@ jobs: - name: Install the report tool packages if: steps.gitleaks.outcome != 'success' run: | - nuget install "Syncfusion.Email" -source "https://nexus.syncfusion.com/repository/nuget-hosted/" - dir $GITHUB_WORKSPACE/Syncfusion.Email.1.0.0/lib/netcoreapp3.1 - dotnet $GITHUB_WORKSPACE/Syncfusion.Email.1.0.0/lib/netcoreapp3.1/Email.dll "citeam@syncfusion.com" "$GITHUB_REF_NAME" ${{ secrets.NETWORKCREDENTIALS }} ${{ secrets.NETWORKKEY }} "$GITHUB_WORKSPACE" + nuget install "Syncfusion.Email" -source ${{ secrets.NexusFeedLink }} -ExcludeVersion + dir $GITHUB_WORKSPACE/Syncfusion.Email/lib/netcoreapp3.1 + dotnet $GITHUB_WORKSPACE/Syncfusion.Email/lib/netcoreapp3.1/GitleaksReportMail.dll ${{ secrets.CITEAMCREDENTIALS }} "$GITHUB_REF_NAME" ${{ secrets.NETWORKCREDENTIALS }} ${{ secrets.NETWORKKEY }} "$GITHUB_WORKSPACE" ${{ secrets.ORGANIZATIONNAME }} exit 1 \ No newline at end of file diff --git a/ASP.NET Core/EJ2APIServices_NET6.sln b/ASP.NET Core/EJ2APIServices_NET6.sln new file mode 100644 index 0000000..b5e5ec6 --- /dev/null +++ b/ASP.NET Core/EJ2APIServices_NET6.sln @@ -0,0 +1,25 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 15 +VisualStudioVersion = 15.0.27004.2009 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "EJ2APIServices", "src\EJ2APIServices_NET6.csproj", "{D2F1360E-DF8C-4AD2-A8CC-942A180D6762}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {D2F1360E-DF8C-4AD2-A8CC-942A180D6762}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {D2F1360E-DF8C-4AD2-A8CC-942A180D6762}.Debug|Any CPU.Build.0 = Debug|Any CPU + {D2F1360E-DF8C-4AD2-A8CC-942A180D6762}.Release|Any CPU.ActiveCfg = Release|Any CPU + {D2F1360E-DF8C-4AD2-A8CC-942A180D6762}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {00388905-5E88-4BCF-B5FC-E4CAB5FA88EE} + EndGlobalSection +EndGlobal diff --git a/ASP.NET Core/EJ2APIServices.sln b/ASP.NET Core/EJ2APIServices_NET8.sln similarity index 92% rename from ASP.NET Core/EJ2APIServices.sln rename to ASP.NET Core/EJ2APIServices_NET8.sln index cf3da83..e8e47e9 100644 --- a/ASP.NET Core/EJ2APIServices.sln +++ b/ASP.NET Core/EJ2APIServices_NET8.sln @@ -3,7 +3,7 @@ Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio 15 VisualStudioVersion = 15.0.27004.2009 MinimumVisualStudioVersion = 10.0.40219.1 -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "EJ2APIServices", "src\EJ2APIServices.csproj", "{D2F1360E-DF8C-4AD2-A8CC-942A180D6762}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "EJ2APIServices", "src\EJ2APIServices_NET8.csproj", "{D2F1360E-DF8C-4AD2-A8CC-942A180D6762}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution diff --git a/ASP.NET Core/src/Controllers/DocumentEditorController.cs b/ASP.NET Core/src/Controllers/DocumentEditorController.cs index 83557e5..18d8286 100644 --- a/ASP.NET Core/src/Controllers/DocumentEditorController.cs +++ b/ASP.NET Core/src/Controllers/DocumentEditorController.cs @@ -1,29 +1,24 @@ using System; -using System.Collections.Generic; -using System.Linq; -using System.Threading.Tasks; using Microsoft.AspNetCore.Mvc; -using System.Net.Http; -using System.Text; -using System.IO; +using System.Text.RegularExpressions; using Microsoft.AspNetCore.Cors; -using Microsoft.AspNetCore.Hosting; -using Microsoft.AspNetCore.Http; using Syncfusion.EJ2.DocumentEditor; using WDocument = Syncfusion.DocIO.DLS.WordDocument; using WFormatType = Syncfusion.DocIO.FormatType; using Syncfusion.EJ2.SpellChecker; using EJ2APIServices; +using SkiaSharp; +using BitMiracle.LibTiff.Classic; -namespace SyncfusionDocument.Controllers +namespace EJ2APIServices.Controllers { [Route("api/[controller]")] public class DocumentEditorController : Controller { - private readonly IHostingEnvironment _hostingEnvironment; - string path; + private readonly IWebHostEnvironment _hostingEnvironment; + string? path; - public DocumentEditorController(IHostingEnvironment hostingEnvironment) + public DocumentEditorController(IWebHostEnvironment hostingEnvironment) { _hostingEnvironment = hostingEnvironment; path = Startup.path; @@ -35,7 +30,7 @@ public DocumentEditorController(IHostingEnvironment hostingEnvironment) [Route("Import")] public string Import(IFormCollection data) { - if (data.Files.Count == 0) + if (data.Files.Count == 0) return null; Stream stream = new MemoryStream(); IFormFile file = data.Files[0]; @@ -59,11 +54,82 @@ public string Import(IFormCollection data) //Converts Metafile to raster image. private static void OnMetafileImageParsed(object sender, MetafileImageParsedEventArgs args) { + if (args.IsMetafile) + { + //MetaFile image conversion(EMF and WMF) //You can write your own method definition for converting metafile to raster image using any third-party image converter. args.ImageStream = ConvertMetafileToRasterImage(args.MetafileStream); + } + else + { + //TIFF image conversion + args.ImageStream = TiffToPNG(args.MetafileStream); + + } } - private static Stream ConvertMetafileToRasterImage(Stream ImageStream) + // Converting Tiff to Png image using Bitmiracle https://www.nuget.org/packages/BitMiracle.LibTiff.NET + private static MemoryStream TiffToPNG(Stream tiffStream) + { + MemoryStream imageStream = new MemoryStream(); + using (Tiff tif = Tiff.ClientOpen("in-memory", "r", tiffStream, new TiffStream())) + { + // Find the width and height of the image + FieldValue[] value = tif.GetField(BitMiracle.LibTiff.Classic.TiffTag.IMAGEWIDTH); + int width = value[0].ToInt(); + + value = tif.GetField(BitMiracle.LibTiff.Classic.TiffTag.IMAGELENGTH); + int height = value[0].ToInt(); + + // Read the image into the memory buffer + int[] raster = new int[height * width]; + if (!tif.ReadRGBAImage(width, height, raster)) + { + throw new Exception("Could not read image"); + } + + // Create a bitmap image using SkiaSharp. + using (SKBitmap sKBitmap = new SKBitmap(width, height, SKImageInfo.PlatformColorType, SKAlphaType.Premul)) + { + // Convert a RGBA value to byte array. + byte[] bitmapData = new byte[sKBitmap.RowBytes * sKBitmap.Height]; + for (int y = 0; y < sKBitmap.Height; y++) + { + int rasterOffset = y * sKBitmap.Width; + int bitsOffset = (sKBitmap.Height - y - 1) * sKBitmap.RowBytes; + + for (int x = 0; x < sKBitmap.Width; x++) + { + int rgba = raster[rasterOffset++]; + bitmapData[bitsOffset++] = (byte)((rgba >> 16) & 0xff); + bitmapData[bitsOffset++] = (byte)((rgba >> 8) & 0xff); + bitmapData[bitsOffset++] = (byte)(rgba & 0xff); + bitmapData[bitsOffset++] = (byte)((rgba >> 24) & 0xff); + } + } + + // Convert a byte array to SKColor array. + SKColor[] sKColor = new SKColor[bitmapData.Length / 4]; + int index = 0; + for (int i = 0; i < bitmapData.Length; i++) + { + sKColor[index] = new SKColor(bitmapData[i + 2], bitmapData[i + 1], bitmapData[i], bitmapData[i + 3]); + i += 3; + index += 1; + } + + // Set the SKColor array to SKBitmap. + sKBitmap.Pixels = sKColor; + + // Save the SKBitmap to PNG image stream. + sKBitmap.Encode(SKEncodedImageFormat.Png, 100).SaveTo(imageStream); + imageStream.Flush(); + } + } + return imageStream; + } + + private static Stream ConvertMetafileToRasterImage(Stream ImageStream) { //Here we are loading a default raster image as fallback. Stream imgStream = GetManifestResourceStream("ImageNotFound.jpg"); @@ -92,7 +158,7 @@ private static Stream GetManifestResourceStream(string fileName) [Route("SpellCheck")] public string SpellCheck([FromBody] SpellCheckJsonData spellChecker) { - try + try { SpellChecker spellCheck = new SpellChecker(); spellCheck.GetSuggestions(spellChecker.LanguageID, spellChecker.TexttoCheck, spellChecker.CheckSpelling, spellChecker.CheckSuggestion, spellChecker.AddWord); diff --git a/ASP.NET Core/src/EJ2APIServices.csproj b/ASP.NET Core/src/EJ2APIServices.csproj deleted file mode 100644 index f5939e2..0000000 --- a/ASP.NET Core/src/EJ2APIServices.csproj +++ /dev/null @@ -1,43 +0,0 @@ - - - - netcoreapp2.0 - false - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/ASP.NET Core/src/EJ2APIServices_NET6.csproj b/ASP.NET Core/src/EJ2APIServices_NET6.csproj new file mode 100644 index 0000000..bae506a --- /dev/null +++ b/ASP.NET Core/src/EJ2APIServices_NET6.csproj @@ -0,0 +1,27 @@ + + + + net6.0 + enable + enable + + + + + + + + + + + + + + + + + + + + + diff --git a/ASP.NET Core/src/EJ2APIServices_NET8.csproj b/ASP.NET Core/src/EJ2APIServices_NET8.csproj new file mode 100644 index 0000000..ac08dc6 --- /dev/null +++ b/ASP.NET Core/src/EJ2APIServices_NET8.csproj @@ -0,0 +1,27 @@ + + + + net8.0 + enable + enable + + + + + + + + + + + + + + + + + + + + + diff --git a/ASP.NET Core/src/Models/EEJ2SERVICEEJ2WEBSERVICESSRCAPP_DATADIAGRAMMDFContext.cs b/ASP.NET Core/src/Models/EEJ2SERVICEEJ2WEBSERVICESSRCAPP_DATADIAGRAMMDFContext.cs index 7d2910b..4988669 100644 --- a/ASP.NET Core/src/Models/EEJ2SERVICEEJ2WEBSERVICESSRCAPP_DATADIAGRAMMDFContext.cs +++ b/ASP.NET Core/src/Models/EEJ2SERVICEEJ2WEBSERVICESSRCAPP_DATADIAGRAMMDFContext.cs @@ -24,4 +24,4 @@ protected override void OnModelCreating(ModelBuilder modelBuilder) }); } } -} +} \ No newline at end of file diff --git a/ASP.NET Core/src/Startup.cs b/ASP.NET Core/src/Startup.cs index 7d38ed7..59ba43e 100644 --- a/ASP.NET Core/src/Startup.cs +++ b/ASP.NET Core/src/Startup.cs @@ -1,35 +1,18 @@ using System; -using System.Collections.Generic; -using System.Linq; -using System.Threading.Tasks; -using Microsoft.AspNetCore.Builder; -using Microsoft.AspNetCore.Hosting; -using Microsoft.Extensions.Configuration; -using Microsoft.Extensions.DependencyInjection; -using Microsoft.Extensions.Logging; -using Microsoft.Extensions.Options; -using Microsoft.EntityFrameworkCore; -using Microsoft.Data.Edm; -using Microsoft.AspNet.OData.Builder; -using Microsoft.AspNet.OData.Extensions; -using Microsoft.AspNetCore.Routing; -using Microsoft.OData.UriParser; -using Microsoft.AspNetCore.Cors.Infrastructure; -using EJ2APIServices.Models; -using EJ2APIServices.Controllers; -using Syncfusion.EJ2.SpellChecker; using System.IO; +using Microsoft.AspNetCore.Mvc; +using Microsoft.AspNetCore.ResponseCompression; +using Newtonsoft.Json.Serialization; +using Syncfusion.EJ2.SpellChecker; using Newtonsoft.Json; - namespace EJ2APIServices { public class Startup { - private string _contentRootPath = ""; - internal static string path; + internal static string? path; - public Startup(IConfiguration configuration, IHostingEnvironment env) + public Startup(IConfiguration configuration, IWebHostEnvironment env) { var builder = new ConfigurationBuilder() .SetBasePath(env.ContentRootPath) @@ -38,82 +21,84 @@ public Startup(IConfiguration configuration, IHostingEnvironment env) .AddEnvironmentVariables(); Configuration = builder.Build(); - _contentRootPath = env.ContentRootPath; path = Configuration["SPELLCHECK_DICTIONARY_PATH"]; - string jsonFileName = Configuration["SPELLCHECK_JSON_FILENAME"]; + string? jsonFileName = Configuration["SPELLCHECK_JSON_FILENAME"]; //check the spell check dictionary path environment variable value and assign default data folder //if it is null. - path = string.IsNullOrEmpty(path) ? Path.Combine(env.ContentRootPath, "App_Data") : Path.Combine(env.ContentRootPath, path); + path = string.IsNullOrEmpty(path) ? Path.Combine(env.ContentRootPath, "Data") : Path.Combine(env.ContentRootPath, path); //Set the default spellcheck.json file if the json filename is empty. jsonFileName = string.IsNullOrEmpty(jsonFileName) ? Path.Combine(path, "spellcheck.json") : Path.Combine(path, jsonFileName); - if (System.IO.File.Exists(jsonFileName)) + if (File.Exists(jsonFileName)) { - string jsonImport = System.IO.File.ReadAllText(jsonFileName); - List spellChecks = JsonConvert.DeserializeObject>(jsonImport); + string jsonImport = File.ReadAllText(jsonFileName); + List? spellChecks = JsonConvert.DeserializeObject>(jsonImport); List spellDictCollection = new List(); - string personalDictPath = null; + string? personalDictPath = null; //construct the dictionary file path using customer provided path and dictionary name - foreach (var spellCheck in spellChecks) + if (spellChecks != null) { - spellDictCollection.Add(new DictionaryData(spellCheck.LanguadeID, Path.Combine(path, spellCheck.DictionaryPath), Path.Combine(path, spellCheck.AffixPath))); - personalDictPath = Path.Combine(path, spellCheck.PersonalDictPath); + foreach (var spellCheck in spellChecks) + { + spellDictCollection.Add(new DictionaryData(spellCheck.LanguadeID, Path.Combine(path, spellCheck.DictionaryPath), Path.Combine(path, spellCheck.AffixPath))); + personalDictPath = Path.Combine(path, spellCheck.PersonalDictPath); + } } SpellChecker.InitializeDictionaries(spellDictCollection, personalDictPath, 3); } } public IConfiguration Configuration { get; } - + readonly string MyAllowSpecificOrigins = "MyPolicy"; // This method gets called by the runtime. Use this method to add services to the container. public void ConfigureServices(IServiceCollection services) { - services.AddOData(); - services.AddMvc().AddJsonOptions(x => { - x.SerializerSettings.ContractResolver = null; + services.AddControllers(); + services.AddMemoryCache(); + services.AddControllers().AddNewtonsoftJson(options => + { + // Use the default property (Pascal) casing + options.SerializerSettings.ContractResolver = new DefaultContractResolver(); }); services.AddCors(options => { - options.AddPolicy("AllowAllOrigins", builder => + options.AddPolicy(MyAllowSpecificOrigins, + builder => { builder.AllowAnyOrigin() - .AllowAnyMethod() - .AllowAnyHeader(); + .AllowAnyMethod() + .AllowAnyHeader(); }); }); - string connection = Configuration.GetConnectionString("Test"); - if (connection.Contains("%CONTENTROOTPATH%")) - { - connection = connection.Replace("%CONTENTROOTPATH%", _contentRootPath); - - } - services.AddEntityFrameworkNpgsql().AddDbContext(options => options.UseNpgsql(connection)); - // Add framework services. - services.AddMvc(); + services.Configure(options => options.Level = System.IO.Compression.CompressionLevel.Optimal); + services.AddResponseCompression(); } // This method gets called by the runtime. Use this method to configure the HTTP request pipeline. - public void Configure(IApplicationBuilder app, IHostingEnvironment env) + public void Configure(IApplicationBuilder app, IWebHostEnvironment env) { - app.UseDeveloperExceptionPage(); - app.UseCors("AllowAllOrigins"); + //Register Syncfusion license + string licenseKey = string.Empty; + Syncfusion.Licensing.SyncfusionLicenseProvider.RegisterLicense(licenseKey); + if (env.IsDevelopment()) { app.UseDeveloperExceptionPage(); } - - app.UseMvc(b => + else + { + app.UseHsts(); + } + app.UseHttpsRedirection(); + app.UseRouting(); + app.UseAuthorization(); + app.UseCors(MyAllowSpecificOrigins); + app.UseResponseCompression(); + app.UseEndpoints(endpoints => { - b.Count().Filter().OrderBy().Expand().Select().MaxTop(null); + endpoints.MapControllers().RequireCors("MyPolicy"); }); - } - - } - - public class ServerPath - { - public static string MapPath = ""; } -} +} \ No newline at end of file diff --git a/ASP.NET Core/src/web.config b/ASP.NET Core/src/web.config index a130cac..2d9ed3f 100644 --- a/ASP.NET Core/src/web.config +++ b/ASP.NET Core/src/web.config @@ -10,9 +10,9 @@ - + - + diff --git a/Java/build.gradle b/Java/build.gradle index 99ffdd3..f45e3c0 100644 --- a/Java/build.gradle +++ b/Java/build.gradle @@ -22,6 +22,8 @@ dependencies { implementation 'com.syncfusion:syncfusion-ej2-spellchecker:+' implementation 'com.syncfusion:syncfusion-docio:+' implementation 'com.syncfusion:syncfusion-javahelper:+' + implementation group: 'com.twelvemonkeys.imageio', name: 'imageio-tiff', version: '3.7.0' + implementation group: 'com.twelvemonkeys.imageio', name: 'imageio-jpeg', version: '3.7.0' compile 'com.google.code.gson:gson:2.8.6' testImplementation 'org.apache.httpcomponents:httpclient' testImplementation('org.springframework.boot:spring-boot-starter-test') { diff --git a/Java/src/main/java/ej2/webservices/WordEditorController.java b/Java/src/main/java/ej2/webservices/WordEditorController.java index 5fba110..0760695 100644 --- a/Java/src/main/java/ej2/webservices/WordEditorController.java +++ b/Java/src/main/java/ej2/webservices/WordEditorController.java @@ -7,8 +7,17 @@ import java.nio.file.Paths; import java.util.ArrayList; import java.util.List; + +import javax.imageio.ImageIO; +import javax.imageio.ImageReader; +import javax.imageio.ImageWriter; +import javax.imageio.spi.IIORegistry; + +import java.awt.image.BufferedImage; +import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.FileOutputStream; +import java.io.InputStream; import org.springframework.core.io.ByteArrayResource; import org.springframework.core.io.Resource; @@ -24,6 +33,7 @@ import com.syncfusion.javahelper.system.collections.generic.ListSupport; import com.syncfusion.javahelper.system.io.StreamSupport; import com.syncfusion.javahelper.system.reflection.AssemblySupport; +import com.twelvemonkeys.imageio.plugins.tiff.TIFFImageReaderSpi; import com.google.gson.Gson; import com.google.gson.JsonArray; import com.google.gson.JsonObject; @@ -118,8 +128,44 @@ public void remove(MetafileImageParsedEventHandler delegate) throws Exception { // Converts Metafile to raster image. private static void onMetafileImageParsed(Object sender, MetafileImageParsedEventArgs args) throws Exception { - // You can write your own method definition for converting Metafile to raster image using any third-party image converter. - args.setImageStream(convertMetafileToRasterImage(args.getMetafileStream())); + if(args.getIsMetafile()) { + // You can write your own method definition for converting Metafile to raster image using any third-party image converter. + args.setImageStream(convertMetafileToRasterImage(args.getMetafileStream())); + }else { + InputStream inputStream = StreamSupport.toStream(args.getMetafileStream()); + // Use ByteArrayOutputStream to collect data into a byte array + ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); + + // Read data from the InputStream and write it to the ByteArrayOutputStream + byte[] buffer = new byte[1024]; + int bytesRead; + while ((bytesRead = inputStream.read(buffer)) != -1) { + byteArrayOutputStream.write(buffer, 0, bytesRead); + } + + // Convert the ByteArrayOutputStream to a byte array + byte[] tiffData = byteArrayOutputStream.toByteArray(); + // Read TIFF image from byte array + ByteArrayInputStream tiffInputStream = new ByteArrayInputStream(tiffData); + IIORegistry.getDefaultInstance().registerServiceProvider(new TIFFImageReaderSpi()); + + // Create ImageReader and ImageWriter instances + ImageReader tiffReader = ImageIO.getImageReadersByFormatName("TIFF").next(); + ImageWriter pngWriter = ImageIO.getImageWritersByFormatName("PNG").next(); + + // Set up input and output streams + tiffReader.setInput(ImageIO.createImageInputStream(tiffInputStream)); + ByteArrayOutputStream pngOutputStream = new ByteArrayOutputStream(); + pngWriter.setOutput(ImageIO.createImageOutputStream(pngOutputStream)); + + // Read the TIFF image and write it as a PNG + BufferedImage image = tiffReader.read(0); + pngWriter.write(image); + pngWriter.dispose(); + byte[] jpgData = pngOutputStream.toByteArray(); + InputStream jpgStream = new ByteArrayInputStream(jpgData); + args.setImageStream(StreamSupport.toStream(jpgStream)); + } } private static StreamSupport convertMetafileToRasterImage(StreamSupport ImageStream) throws Exception {