using System; using System.Collections.Generic; using System.Runtime.Serialization; using System.ServiceModel; using System.Web.Hosting; using System.Text; using System.IO; using System.Configuration; using System.Collections; using System.Drawing; using System.Drawing.Drawing2D; using System.Drawing.Imaging; using FastReport; using FastReport.Utils; using FastReport.Data; using FastReport.Export.Pdf; using FastReport.Export.OoXML; using FastReport.Export.RichText; using FastReport.Export.Odf; using FastReport.Export.Mht; using FastReport.Export.Csv; using FastReport.Export.Dbf; using FastReport.Export.Xml; using FastReport.Export.Text; using FastReport.Export.Html; using FastReport.Export.XAML; using FastReport.Export.Image; using FastReport.Export; using System.Net; using System.ServiceModel.Web; namespace FastReport.Service { public partial class ReportService : IFastReportService { public string About() { string s = "FastReport.NET Service " + Config.Version; return s; } public bool CheckPreparedReport(string uuid) { if (!PreparedPathExists()) throw new WebFaultException(new ErrorHandler { Cause = "Upload disabled", ErrorCode = 102 }, System.Net.HttpStatusCode.InternalServerError); string preparedPath = GetPreparedPath(); string preparedFile = GetPreparedFileName(uuid); return File.Exists(Path.Combine(preparedPath, preparedFile)); } public string PutPreparedReport(Stream preparedReport) { if (!PreparedPathExists()) throw new WebFaultException(new ErrorHandler { Cause = "Upload disabled", ErrorCode = 102 }, System.Net.HttpStatusCode.InternalServerError); string uuid = ""; string preparedPath = GetPreparedPath(); if (Directory.Exists(preparedPath)) { MemoryStream preparedStream = PreparePostStream(preparedReport); if (preparedReport != null && preparedStream.Length > 0) { using (Report r = new Report()) { Config.WebMode = true; try { MemoryStream checkPrepared = new MemoryStream(); preparedStream.WriteTo(checkPrepared); checkPrepared.Position = 0; r.LoadPrepared(checkPrepared); preparedStream.Position = 0; string tempUuid = Guid.NewGuid().ToString(); StorePrepared(tempUuid, preparedPath, preparedStream); uuid = tempUuid; } catch (Exception e) { throw new WebFaultException(new ErrorHandler { Cause = e.Message, ErrorCode = 100 }, System.Net.HttpStatusCode.InternalServerError); } } } else { throw new WebFaultException(new ErrorHandler { Cause = "Empty input data", ErrorCode = 101 }, System.Net.HttpStatusCode.BadRequest); } } else throw new WebFaultException(new ErrorHandler { Cause = "Upload directory not found", ErrorCode = 107 }, System.Net.HttpStatusCode.BadRequest); return uuid; } public string PutReport(Stream report) { if (!PreparedPathExists()) throw new WebFaultException(new ErrorHandler { Cause = "Upload disabled", ErrorCode = 102 }, System.Net.HttpStatusCode.InternalServerError); string uuid = ""; string preparedPath = GetPreparedPath(); if (Directory.Exists(preparedPath)) { MemoryStream reportStream = PreparePostStream(report); if (report != null && reportStream.Length > 0) { using (Report r = new Report()) { Config.WebMode = true; try { reportStream.Position = 0; r.Load(reportStream); r.PreparePhase1(); r.PreparePhase2(); MemoryStream reportPrepared = new MemoryStream(); r.SavePrepared(reportPrepared); string tempUuid = Guid.NewGuid().ToString(); StorePrepared(tempUuid, preparedPath, reportPrepared); uuid = tempUuid; } catch (Exception e) { throw new WebFaultException(new ErrorHandler { Cause = e.Message, ErrorCode = 100 }, System.Net.HttpStatusCode.InternalServerError); } } } else { throw new WebFaultException(new ErrorHandler { Cause = "Empty input data", ErrorCode = 101 }, System.Net.HttpStatusCode.BadRequest); } } else throw new WebFaultException(new ErrorHandler { Cause = "Upload directory not found", ErrorCode = 107 }, System.Net.HttpStatusCode.BadRequest); return uuid; } private void StorePrepared(string uuid, string preparedPath, MemoryStream preparedStream) { if (Directory.Exists(preparedPath)) { int storageTimeoutInMinutes = 0; string s = ConfigurationManager.AppSettings["FastReport.PreparedCleanupDelay"]; if (Int32.TryParse(s, out storageTimeoutInMinutes)) CleanStorage(preparedPath, "*.fpx", storageTimeoutInMinutes, 1); string fileName = GetPreparedFileName(uuid); string fullPath = Path.Combine(preparedPath, fileName); using (FileStream fileStream = new FileStream(fullPath, FileMode.Create)) preparedStream.WriteTo(fileStream); } } private int CleanStorage(string FileStoragePath, string maskStorage, int StorageTimeoutInMinutes, int CleanupInMinutes) { string touch = Path.Combine(FileStoragePath, "FRS-touch"); int filesCount = 0; if (StorageTimeoutInMinutes > 0 && CleanupInMinutes > 0 && !String.IsNullOrEmpty(FileStoragePath) && Directory.Exists(FileStoragePath)) { if (File.Exists(touch)) { DateTime created = File.GetLastWriteTime(touch); if (DateTime.Now > created.AddMinutes(CleanupInMinutes)) { File.SetLastWriteTime(touch, DateTime.Now); string[] dir = Directory.GetFiles(FileStoragePath, maskStorage); foreach (string file in dir) { try { if (DateTime.Now > File.GetLastWriteTime(file).AddMinutes(StorageTimeoutInMinutes)) File.Delete(file); } catch { //nothing } } } } else using (FileStream file = File.Create(touch)) { }; filesCount = Directory.GetFiles(FileStoragePath, maskStorage).Length; } return filesCount; } private string GetPreparedFileName(string uuid) { if (!String.IsNullOrEmpty(uuid)) return String.Concat(uuid.Replace("-", ""), ".fpx"); else return String.Empty; } private bool PreparedPathExists() { string s = ConfigurationManager.AppSettings["FastReport.PreparedPath"]; return !string.IsNullOrEmpty(s); } private bool ReportsPathExists() { string s = ConfigurationManager.AppSettings["FastReport.ReportsPath"]; return !string.IsNullOrEmpty(s); } private string GetPreparedPath() { string s = ConfigurationManager.AppSettings["FastReport.PreparedPath"]; string result = HostingEnvironment.MapPath(s); if (String.IsNullOrEmpty(result)) result = s; return result; } private string GetReportsPath() { string s = ConfigurationManager.AppSettings["FastReport.ReportsPath"]; string result = HostingEnvironment.MapPath(s); if (String.IsNullOrEmpty(result)) result = s; return result; } public Stream GetPreparedByUUID(string uuid) { if (!PreparedPathExists()) throw new WebFaultException(new ErrorHandler { Cause = "Upload disabled", ErrorCode = 102 }, System.Net.HttpStatusCode.InternalServerError); string preparedPath = GetPreparedPath(); string preparedFile = GetPreparedFileName(uuid); string fullPath = Path.Combine(preparedPath, preparedFile); MemoryStream resultFile = new MemoryStream(); if (File.Exists(fullPath)) { File.SetLastWriteTime(fullPath, DateTime.Now); using (FileStream file = new FileStream(fullPath, FileMode.Open)) { file.CopyTo(resultFile); resultFile.Position = 0; } } else throw new WebFaultException(new ErrorHandler { Cause = "File not found", ErrorCode = 404 }, System.Net.HttpStatusCode.NotFound); return resultFile; } public Stream GetLogoByUUIDFixed(string uuid) { return GetLogoByUUID(uuid, "200", "200"); } public Stream GetLogoByUUID(string uuid, string width, string height) { int dx, dy; MemoryStream stream = new MemoryStream(); if (Int32.TryParse(width, out dx) && Int32.TryParse(height, out dy)) { Stream preparedStream = GetPreparedByUUID(uuid); using (Report r = new Report()) { Config.WebMode = true; try { r.LoadPrepared(preparedStream); MemoryStream pngStream = new MemoryStream(); ImageExport pngExport = new ImageExport(); pngExport.ImageFormat = ImageExportFormat.Png; pngExport.Resolution = 96; pngExport.PageRange = PageRange.PageNumbers; pngExport.PageNumbers = "1"; r.Export(pngExport, pngStream); pngStream.Position = 0; ResizePNG(pngStream, stream, dx, dy); } catch (Exception e) { throw new WebFaultException(new ErrorHandler { Cause = e.Message, ErrorCode = 103 }, System.Net.HttpStatusCode.InternalServerError); } stream.Position = 0; } } else throw new WebFaultException(new ErrorHandler { Cause = "Wrong width or height", ErrorCode = 106 }, System.Net.HttpStatusCode.BadRequest); return stream; } private void ResizePNG(Stream sourceStream, Stream targetStream, int maxWidth, int maxHeight) { Bitmap image = new Bitmap(sourceStream); float scaleX = (float)maxWidth / (float)image.Width; float scaleY = (float)maxHeight / (float)image.Height; float ratio = Math.Min(scaleX, scaleY); int newWidth = (int)Math.Round(image.Width * ratio); int newHeight = (int)Math.Round(image.Height * ratio); Bitmap newImage = new Bitmap(newWidth, newHeight, PixelFormat.Format24bppRgb); using (Graphics graphics = Graphics.FromImage(newImage)) { graphics.CompositingQuality = CompositingQuality.HighQuality; graphics.InterpolationMode = InterpolationMode.HighQualityBicubic; graphics.SmoothingMode = SmoothingMode.HighQuality; graphics.DrawImage(image, 0, 0, newWidth, newHeight); } newImage.Save(targetStream, System.Drawing.Imaging.ImageFormat.Png); } private void Write(Stream stream, string line) { byte[] b = Encoding.UTF8.GetBytes(line); stream.Write(b, 0, b.Length); } public Stream GetTest(Stream preparedReport) { return PreparePostStream(preparedReport); } private MemoryStream PreparePostStream(Stream preparedReport) { MemoryStream stream = new MemoryStream(); if (preparedReport != null) { preparedReport.CopyTo(stream); stream.Position = 0; MultipartParser parser = new MultipartParser(stream); if (parser.Success) stream = new MemoryStream(parser.FileContents); else stream.Position = 0; } return stream; } public Stream GetReportXml(ReportRequest request) { return GetReport(request); } public Stream GetReport(ReportRequest request) { ReportItem report = request.Report; GearItem gear = request.Gear; MemoryStream stream = new MemoryStream(); try { string reportsRoot = GetReportsPath(); string reportPath = Path.GetFullPath(Path.Combine(reportsRoot, report.Path)); if (report != null && gear != null && CheckReportAccess(reportPath, reportsRoot)) { using (Report r = new Report()) { Config.WebMode = true; r.Load(reportPath); if (report.Parameters != null) foreach (KeyValuePair param in report.Parameters) { r.SetParameterValue(param.Key, param.Value); } string connectionStringName = ConfigurationManager.AppSettings["FastReport.ConnectionStringName"]; string connectionString = null; if (!string.IsNullOrEmpty(connectionStringName)) connectionString = ConfigurationManager.ConnectionStrings[connectionStringName].ConnectionString; if (!string.IsNullOrEmpty(connectionString)) { // change first connection on default foreach (DataConnectionBase connection in r.Dictionary.Connections) { connection.ConnectionString = connectionString; break; } } // prepare without dialogs r.PreparePhase1(); r.PreparePhase2(); // export PrepareOutput(gear, r, stream); } } else throw new WebFaultException(new ErrorHandler { Cause = "Wrong report or gear", ErrorCode = 130 }, System.Net.HttpStatusCode.InternalServerError); } catch (Exception e) { throw new WebFaultException(new ErrorHandler { Cause = e.Message, ErrorCode = 131 }, System.Net.HttpStatusCode.InternalServerError); } stream.Position = 0; return stream; } public Stream GetPreparedReportByID(string id) { List list = GetReportsList(); ReportItem report = null; GearItem gear = new GearItem(); gear.Name = "FPX"; foreach (ReportItem item in list) if (item.ID == id) { report = item; break; } if (report != null) { ReportRequest request = new ReportRequest(); request.Gear = gear; request.Report = report; return GetReport(request); } else throw new WebFaultException(new ErrorHandler { Cause = "File not found", ErrorCode = 404 }, System.Net.HttpStatusCode.NotFound); } private void PrepareOutput(GearItem gear, Report r, MemoryStream stream) { switch (gear.Name) { case "FPX": { r.SavePrepared(stream); break; } case "PDF": { ExportPDF(r, stream, gear.Properties); break; } case "XLSX": { ExportXLSX(r, stream, gear.Properties); break; } case "DOCX": { ExportDOCX(r, stream, gear.Properties); break; } case "PPTX": { ExportPPTX(r, stream, gear.Properties); break; } case "ODS": { ExportODS(r, stream, gear.Properties); break; } case "ODT": { ExportODT(r, stream, gear.Properties); break; } case "MHT": { ExportMHT(r, stream, gear.Properties); break; } case "CSV": { ExportCSV(r, stream, gear.Properties); break; } case "DBF": { ExportDBF(r, stream, gear.Properties); break; } case "XML": { ExportXML(r, stream, gear.Properties); break; } case "TXT": { ExportTXT(r, stream, gear.Properties); break; } case "RTF": { ExportRTF(r, stream, gear.Properties); break; } case "HTML": { ExportHTML(r, stream, gear.Properties); break; } } } private void ExportRTF(Report r, MemoryStream stream, Dictionary parameters) { RTFExport rtf = new RTFExport(); if (parameters != null) { FillGeneralProperties(rtf, parameters); // add parameters } r.Export(rtf, stream); } private void ExportTXT(Report r, MemoryStream stream, Dictionary parameters) { TextExport txt = new TextExport(); if (parameters != null) { FillGeneralProperties(txt, parameters); // add parameters } r.Export(txt, stream); } private void ExportXML(Report r, MemoryStream stream, Dictionary parameters) { XMLExport xml = new XMLExport(); if (parameters != null) { FillGeneralProperties(xml, parameters); // add parameters } r.Export(xml, stream); } private void ExportDBF(Report r, MemoryStream stream, Dictionary parameters) { DBFExport dbf = new DBFExport(); if (parameters != null) { FillGeneralProperties(dbf, parameters); // add parameters } r.Export(dbf, stream); } private void ExportCSV(Report r, MemoryStream stream, Dictionary parameters) { CSVExport csv = new CSVExport(); if (parameters != null) { FillGeneralProperties(csv, parameters); // add parameters } r.Export(csv, stream); } private void ExportMHT(Report r, MemoryStream stream, Dictionary parameters) { MHTExport mht = new MHTExport(); if (parameters != null) { FillGeneralProperties(mht, parameters); // add parameters } r.Export(mht, stream); } private void ExportODT(Report r, MemoryStream stream, Dictionary parameters) { ODTExport odt = new ODTExport(); if (parameters != null) { FillGeneralProperties(odt, parameters); // add parameters } r.Export(odt, stream); } private void ExportODS(Report r, MemoryStream stream, Dictionary parameters) { ODSExport ods = new ODSExport(); if (parameters != null) { FillGeneralProperties(ods, parameters); // add parameters } r.Export(ods, stream); } private void ExportPPTX(Report r, MemoryStream stream, Dictionary parameters) { PowerPoint2007Export pptx = new PowerPoint2007Export(); if (parameters != null) { FillGeneralProperties(pptx, parameters); // add parameters } r.Export(pptx, stream); } private void ExportDOCX(Report r, MemoryStream stream, Dictionary parameters) { Word2007Export docx = new Word2007Export(); if (parameters != null) { FillGeneralProperties(docx, parameters); // add parameters } r.Export(docx, stream); } private void ExportXLSX(Report r, MemoryStream stream, Dictionary parameters) { Excel2007Export xlsx = new Excel2007Export(); if (parameters != null) { FillGeneralProperties(xlsx, parameters); // add parameters } r.Export(xlsx, stream); } private void ExportPDF(Report r, MemoryStream stream, Dictionary parameters) { PDFExport pdf = new PDFExport(); if (parameters != null) { FillGeneralProperties(pdf, parameters); bool value; if (parameters.ContainsKey("EmbeddingFonts") && bool.TryParse(parameters["EmbeddingFonts"], out value)) pdf.EmbeddingFonts = value; if (parameters.ContainsKey("PdfA") && bool.TryParse(parameters["PdfA"], out value)) pdf.PdfCompliance = value ? PDFExport.PdfStandard.PdfA_2a : PDFExport.PdfStandard.None; if (parameters.ContainsKey("Background") && bool.TryParse(parameters["Background"], out value)) pdf.Background = value; if (parameters.ContainsKey("PrintOptimized") && bool.TryParse(parameters["PrintOptimized"], out value)) pdf.PrintOptimized = value; if (parameters.ContainsKey("Title")) pdf.Title = parameters["Title"]; if (parameters.ContainsKey("Author")) pdf.Author = parameters["Author"]; if (parameters.ContainsKey("Subject")) pdf.Subject = parameters["Subject"]; if (parameters.ContainsKey("Keywords")) pdf.Keywords = parameters["Keywords"]; if (parameters.ContainsKey("Creator")) pdf.Creator = parameters["Creator"]; if (parameters.ContainsKey("Producer")) pdf.Producer = parameters["Producer"]; } r.Export(pdf, stream); } private void ExportHTML(Report r, MemoryStream stream, Dictionary parameters) { HTMLExport html = new HTMLExport(); if (parameters != null) { FillGeneralProperties(html, parameters); bool value; if (parameters.ContainsKey("Layers") && bool.TryParse(parameters["Layers"], out value)) html.Layers = value; else html.Layers = false; if (parameters.ContainsKey("SinglePage") && bool.TryParse(parameters["SinglePage"], out value)) html.SinglePage = value; else html.SinglePage = false; } html.Navigator = false; html.SubFolder = false; html.SaveStreams = true; r.Export(html, (Stream)null); ZipArchive zip = new ZipArchive(); for (int i = 0; i < html.GeneratedStreams.Count; i++) zip.AddStream(html.GeneratedFiles[i], html.GeneratedStreams[i]); zip.SaveToStream(stream); } private void FillGeneralProperties(ExportBase export, Dictionary parameters) { if (parameters.ContainsKey("PageRange")) { if (parameters["PageRange"] == "All") export.PageRange = PageRange.All; else export.PageRange = PageRange.PageNumbers; } if (parameters.ContainsKey("PageNumbers")) { export.PageNumbers = parameters["PageNumbers"]; } if (parameters.ContainsKey("Zoom")) { float zoom; if (float.TryParse(parameters["Zoom"], out zoom)) export.Zoom = zoom; } } private bool CheckReportAccess(string reportPath, string reportsRoot) { if (File.Exists(reportPath) && Path.GetExtension(reportPath) == ".frx") return reportPath.IndexOf(reportsRoot) != -1; else return false; } } }