@@ -0,0 +1,64 @@
using FastReport.Dialog;
using System.Text;
using static FastReport.Web.Constants;

namespace FastReport.Web
{
public partial class Dialog
{
private void ComboBoxChange(ComboBoxControl cb, int index)
{
cb.SelectedIndex = index;
ControlFilterRefresh(cb);
cb.OnSelectedIndexChanged(null);
}

private string GetComboBoxHtml(ComboBoxControl control)
{
if (control.Items.Count == 0)
{
control.FillData();
ControlFilterRefresh(control);
}
else
{
control.SelectedItem = control.Items[control.SelectedIndex];
control.Text = control.SelectedItem.ToString();
}

string id = GetControlID(control);
string html = string.Format("<select style=\"{0}\" name=\"{1}\" onchange=\"{2}\" id=\"{3}\">{4}</select>",
// style
GetComboBoxStyle(control),
// name
control.Name,
// onclick
GetEvent(ONCHANGE, control, SILENT_RELOAD, $"document.getElementById('{id}').selectedIndex"),
// title
id,
GetComboBoxItems(control)//control.Text
);
control.FilterData();
return html;
}

private string GetComboBoxItems(ComboBoxControl control)
{
StringBuilder sb = new StringBuilder();
for (int i = 0; i < control.Items.Count; i++)
{
sb.Append(string.Format("<option {0} value=\"{1}\">{2}</option>",
i == control.SelectedIndex ? "selected" : "",
control.Items[i],
control.Items[i]));
}
return sb.ToString();
}

private string GetComboBoxStyle(ComboBoxControl control)
{
return $"{GetControlPosition(control)} {GetControlFont(control.Font)}";
}

}
}
@@ -0,0 +1,51 @@
using System;
using FastReport.Dialog;
using static FastReport.Web.Constants;

namespace FastReport.Web
{
public partial class Dialog
{

/// <summary>
/// Gets or sets date time format in javascript type="date"
/// </summary>
public string DateTimePickerFormat {
get;
set;
} = DEFAULT_DATE_TIME_PICKER_FORMAT;


private void DateTimePickerChange(DateTimePickerControl dp, string value)
{
dp.Value = DateTime.Parse(value);
dp.OnValueChanged(null);
}

private string GetDateTimePickerHtml(DateTimePickerControl control)
{
control.FillData();
ControlFilterRefresh(control);
string id = GetControlID(control);

return string.Format("<input style=\"{0}\" type=\"date\" name=\"{1}\" value=\"{2}\" onchange=\"{3}\" id=\"{4}\"/>",
// style
GetDateTimePickerStyle(control),
// name
control.Name,
// value
control.Value.ToString(DateTimePickerFormat),
// onclick
GetEvent(ONCHANGE, control, SILENT_RELOAD, $"document.getElementById('{id}').value"),
// title
id
);
}

private string GetDateTimePickerStyle(DateTimePickerControl control)
{
return $"{GetControlPosition(control)} {GetControlFont(control.Font)}";
}

}
}
@@ -0,0 +1,23 @@
using FastReport.Dialog;
using System.Text;

namespace FastReport.Web
{
public partial class Dialog
{
private string GetGroupBoxHtml(GroupBoxControl groupBox)
{
StringBuilder sb = new StringBuilder();

string s = $"<div style=\"{GetControlPosition(groupBox)}\">";
sb.Append(s);

sb.Append($"<div id=\"{groupBox.Name}\" style=\"position:relative;\">");

GetComponentHtml(sb, groupBox.Controls);
sb.Append("</div></div>");
return sb.ToString();
}

}
}
@@ -0,0 +1,18 @@
using FastReport.Dialog;

namespace FastReport.Web
{
public partial class Dialog
{
private string GetLabelHtml(LabelControl control)
{
return $"<div style=\"{GetLabelStyle(control)}\">{control.Text}</div>";
}

private string GetLabelStyle(LabelControl control)
{
return $"{GetControlPosition(control)} {GetControlFont(control.Font)} {GetControlAlign(control)}";
}

}
}
@@ -0,0 +1,59 @@
using FastReport.Dialog;
using System.Text;
using static FastReport.Web.Constants;

namespace FastReport.Web
{
public partial class Dialog
{
private void ListBoxChange(ListBoxControl cb, int index)
{
cb.SelectedIndex = index;
ControlFilterRefresh(cb);
cb.OnSelectedIndexChanged(null);
}

private string GetListBoxHtml(ListBoxControl control)
{
if (control.Items.Count == 0)
{
control.FillData();
ControlFilterRefresh(control);
}
string id = GetControlID(control);
string html = string.Format("<select style=\"{0}\" name=\"{1}\" size=\"{2}\" onchange=\"{3}\" id=\"{4}\">{5}</select>",
// style
GetListBoxStyle(control),
// name
control.Name,
// size
control.Items.Count.ToString(),
// onclick
GetEvent(ONCHANGE, control, DIALOG, $"document.getElementById('{id}').selectedIndex"),
// title
id,
GetListBoxItems(control)//control.Text
);
control.FilterData();
return html;
}

private string GetListBoxItems(ListBoxControl control)
{
StringBuilder sb = new StringBuilder();
for (int i = 0; i < control.Items.Count; i++)
{
sb.Append(string.Format("<option {0}>{1}</option>",
i == control.SelectedIndex ? "selected" : "",
control.Items[i]));
}
return sb.ToString();
}

private string GetListBoxStyle(ListBoxControl control)
{
return $"{GetControlPosition(control)} {GetControlFont(control.Font)}";
}

}
}
@@ -0,0 +1,49 @@
using FastReport.Dialog;
using System;
using System.Globalization;
using System.Text;
using static FastReport.Web.Constants;

namespace FastReport.Web
{
public partial class Dialog
{

private void MonthCalendarChange(MonthCalendarControl dp, string value)
{
dp.SelectionStart = DateTime.ParseExact(value, "d", CultureInfo.InvariantCulture);
}

private string GetMonthCalendarHtml(MonthCalendarControl control)
{
control.FillData();
ControlFilterRefresh(control);
string id = GetControlID(control);
StringBuilder html = new StringBuilder();
string selectedDate = control.SelectionStart.Month.ToString() + "/" + control.SelectionStart.Day.ToString() + "/" + control.SelectionStart.Year.ToString();
string ev = GetEvent(ONCHANGE, control, DIALOG, $"document.getElementById('{id}').value");
html.Append(String.Format("<div class=\"{0}\" style=\"{1}\" onchange=\"{2}\" id=\"{3}\"></div>",
"",
GetMonthCalendarStyle(control),
ev,
id
));
html.Append("<script>$(function() {$( \"#").Append(id).AppendLine("\" ).datepicker();");
html.Append("$( \"#").Append(id).Append("\" ).datepicker( \"option\", \"dateFormat\", \"").
Append(DEFAULT_DATE_TIME_PICKER_FORMAT).AppendLine("\" );");
html.Append("$( \"#").Append(id).Append(String.Format("\" ).datepicker( \"setDate\", \"{0}\", \"", selectedDate)).
Append(DEFAULT_DATE_TIME_PICKER_FORMAT).AppendLine("\" );");

html.Append("});</script>");

//control.FilterData();
return html.ToString();
}

private string GetMonthCalendarStyle(MonthCalendarControl control)
{
return $"{GetControlPosition(control)} {GetControlFont(control.Font)}";
}

}
}
@@ -0,0 +1,34 @@
using FastReport.Dialog;
using System.Drawing;
using System.IO;

namespace FastReport.Web
{
public partial class Dialog
{

private string GetPictureBoxHtml(PictureBoxControl control)
{
return $"<div style=\"{GetPictureBoxStyle(control)}\"></div>";
}

private string GetPictureBoxStyle(PictureBoxControl control)
{
return $"{GetControlPosition(control)} {GetControlAlign(control)} {GetPictureBoxURL(control.Image)} padding:0;margin:0;";
}

private string GetPictureBoxURL(Image image)
{
int hash = image.GetHashCode();
MemoryStream picStream = new MemoryStream();
image.Save(picStream, image.RawFormat);
byte[] imageArray = new byte[picStream.Length];
picStream.Position = 0;
picStream.Read(imageArray, 0, (int)picStream.Length);
WebReport.PictureCache.Add(hash.ToString(), imageArray);

string url = WebUtils.ToUrl(FastReportGlobal.FastReportOptions.RouteBasePath, $"preview.getPicture?");
return $" background: url('{url}reportId={WebReport.ID}&pictureId={hash}') no-repeat !important;-webkit-print-color-adjust:exact;";
}
}
}
@@ -0,0 +1,45 @@
using FastReport.Dialog;
using static FastReport.Web.Constants;

namespace FastReport.Web
{
public partial class Dialog
{

private void RadioButtonClick(RadioButtonControl rb, string data)
{
rb.Checked = data == "true";
rb.FilterData();
rb.OnClick(null);
}

private string GetRadioButtonHtml(RadioButtonControl control)
{
string id = GetControlID(control);
return string.Format("<span style=\"{0}\"><input style=\"vertical-align:middle;width:{1}px;border:none;padding:0;margin:0 5px 0 0;\" type=\"radio\" name=\"{2}\" value=\"{3}\" onclick=\"{4}\" id=\"{5}\" {6}/><label style=\"{9}\" for=\"{7}\">{8}</label></span>",
// style
GetRadioButtonStyle(control),
// width
Zoom(10),
// name
control.Name,
// value
control.Text,
// onclick
GetEvent(ONCLICK, control, SILENT_RELOAD, $"document.getElementById('{id}').checked"),
// title
id,
control.Checked ? "checked" : "",
id,
control.Text,
GetControlFont(control.Font)
);
}

private string GetRadioButtonStyle(RadioButtonControl control)
{
return $"{GetControlPosition(control)} {GetControlFont(control.Font)}";
}

}
}
@@ -0,0 +1,282 @@
using System;
using System.Drawing;
using System.Text;
using FastReport.Dialog;
using System.Windows.Forms;

namespace FastReport.Web
{
public partial class Dialog
{
private WebReport WebReport {
get;
}

private int CurrentForm {
get;
set;
}


public Dialog(WebReport webReport)
{
WebReport = webReport;
}


private void CheckDialogs()
{
Report report = this.WebReport.Report;
while (CurrentForm < report.Pages.Count && !(report.Pages[CurrentForm] is DialogPage && report.Pages[CurrentForm].Visible == true))
CurrentForm++;

if (CurrentForm < report.Pages.Count)
{
WebReport.Mode = WebReportMode.Dialog;
}
else
{
if(WebReport.Mode == WebReportMode.Dialog) //
{
report.PreparePhase2();
WebReport.ReportPrepared = true;
}
WebReport.Mode = WebReportMode.Preview;
}
}

internal void ProcessDialogs(StringBuilder sb)
{
Report report = this.WebReport.Report;

if (CurrentForm < report.Pages.Count)
{
DialogPage dialog = report.Pages[CurrentForm] as DialogPage;
if (!dialog.ActiveInWeb)
{
dialog.ActiveInWeb = true;
dialog.OnLoad(EventArgs.Empty);
dialog.OnShown(EventArgs.Empty);
}
GetDialogHtml(sb, dialog);
}
}

internal void SetDialogs(string dialogN, string controlName, string eventName, string data)
{
SetUpDialogs(dialogN, controlName, eventName, data);

CheckDialogs();
}


internal void SetUpDialogs(string dialogN, string controlName, string eventName, string data)
{
if (!string.IsNullOrEmpty(dialogN))
{
int dialogIndex = Convert.ToInt16(dialogN);
if (dialogIndex >= 0 && dialogIndex < WebReport.Report.Pages.Count)
{
DialogPage dialog = WebReport.Report.Pages[dialogIndex] as DialogPage;

DialogControl control = dialog.FindObject(controlName) as DialogControl;
if (control != null)
{
if (eventName == ONCHANGE)
{
if (!string.IsNullOrEmpty(data))
{
if (control is TextBoxControl)
TextBoxChange(control as TextBoxControl, data);
else if (control is ComboBoxControl)
ComboBoxChange(control as ComboBoxControl, Convert.ToInt16(data));
else if (control is ListBoxControl)
ListBoxChange(control as ListBoxControl, Convert.ToInt16(data));
else if (control is CheckedListBoxControl)
CheckedListBoxChange(control as CheckedListBoxControl, data);
else if (control is DateTimePickerControl)
DateTimePickerChange(control as DateTimePickerControl, data);
else if (control is MonthCalendarControl)
MonthCalendarChange(control as MonthCalendarControl, data);
}
}
else if (eventName == ONCLICK)
{
if (control is ButtonControl)
ButtonClick(control as ButtonControl);
else if (control is CheckBoxControl)
CheckBoxClick(control as CheckBoxControl, data);
else if (control is RadioButtonControl)
RadioButtonClick(control as RadioButtonControl, data);
}
}
}
}
}

private void ControlFilterRefresh(DataFilterBaseControl control)
{
control.FilterData();
if (control.DetailControl != null)
{
control.DetailControl.ResetFilter();
control.DetailControl.FillData(control);
}
}

private string GetDialogID()
{
return String.Concat(WebReport.ID, "Dialog");
}

private string GetControlID(DialogControl control)
{
return WebReport.ID + control.Name;
}


private void GetComponentHtml(StringBuilder sb, DialogComponentCollection collection)
{
foreach (DialogControl control in collection)
{
if (control.Visible)
{
// button
if (control is ButtonControl)
sb.Append(GetButtonHtml(control as ButtonControl));
// label
else if (control is LabelControl)
sb.Append(GetLabelHtml(control as LabelControl));
// textbox
else if (control is TextBoxControl)
sb.Append(GetTextBoxHtml(control as TextBoxControl));
// checkbox
else if (control is CheckBoxControl)
sb.Append(GetCheckBoxHtml(control as CheckBoxControl));
// radio button
else if (control is RadioButtonControl)
sb.Append(GetRadioButtonHtml(control as RadioButtonControl));
// combo box
else if (control is ComboBoxControl)
sb.Append(GetComboBoxHtml(control as ComboBoxControl));
// list box
else if (control is ListBoxControl)
sb.Append(GetListBoxHtml(control as ListBoxControl));
// checked list box
else if (control is CheckedListBoxControl)
sb.Append(GetCheckedListBoxHtml(control as CheckedListBoxControl));
// datetime
else if (control is DateTimePickerControl)
sb.Append(GetDateTimePickerHtml(control as DateTimePickerControl));
// monthcalendar
else if (control is MonthCalendarControl)
sb.Append(GetMonthCalendarHtml(control as MonthCalendarControl));
else if (control is GroupBoxControl)
sb.Append(GetGroupBoxHtml(control as GroupBoxControl));
else if (control is PictureBoxControl)
sb.Append(GetPictureBoxHtml(control as PictureBoxControl));
}
}
}

private string Zoom(float value)
{
return $"{value*WebReport.Zoom:0.##}";
}

private void GetDialogHtml(StringBuilder sb, DialogPage dialog)
{
string s = String.Format("<div style=\"min-width:{0}px! important;min-height:{1}px !important\">",
Zoom(dialog.Width),
Zoom(dialog.Height)
);
sb.Append(s);

sb.Append($"<div id=\"{GetDialogID()}\" style=\"position:relative;\" title=\"{dialog.Text}\">");

GetComponentHtml(sb, dialog.Controls);
sb.Append("</div></div>");
}


private string GetEvent(string eventName, DialogControl control, string func, string data = null)
{
data = string.IsNullOrEmpty(data) ? "'" : $"&data=' + {data}";

string HandlerURL = $"'&dialog={CurrentForm}&control={control.Name}&event={eventName}{data}";

return $"fr{WebReport.ID}.{func}({HandlerURL})";
}

private string GetControlFont(Font font)
{
string fontStyle = (((font.Style & FontStyle.Bold) > 0) ? "font-weight:bold;" : String.Empty) +
(((font.Style & FontStyle.Italic) > 0) ? "font-style:italic;" : "font-style:normal;");
if ((font.Style & FontStyle.Underline) > 0 && (font.Style & FontStyle.Strikeout) > 0)
fontStyle += "text-decoration:underline|line-through;";
else if ((font.Style & FontStyle.Underline) > 0)
fontStyle += "text-decoration:underline;";
else if ((font.Style & FontStyle.Strikeout) > 0)
fontStyle += "text-decoration:line-through;";

return $"font-size:{Zoom(font.Size)}pt;font-family:{font.FontFamily.Name};{fontStyle};display:inline-block;";
}

private string GetControlPosition(DialogControl control)
{
return string.Format("position:absolute;left:{0}px;top:{1}px;width:{2}px;height:{3}px;padding:0px;margin:0px;",
Zoom(control.Left),
Zoom(control.Top),
Zoom(control.Width),
Zoom(control.Height));
}

private string GetControlAlign(DialogControl control)
{
if (control is LabelControl)
return GetAlign((control as LabelControl).TextAlign);
else if (control is ButtonControl)
return GetAlign((control as ButtonControl).TextAlign);
else if (control is TextBoxControl)
return GetEditAlign((control as TextBoxControl).TextAlign);
else
return "";
}

private string GetEditAlign(HorizontalAlignment align)
{
if (align == HorizontalAlignment.Left)
return "text-align:left;";
else if (align == HorizontalAlignment.Center)
return "text-align:center;";
else if (align == HorizontalAlignment.Right)
return "text-align:right;";
else
return "";
}

private string GetAlign(ContentAlignment align)
{
if (align == ContentAlignment.TopLeft)
return "text-align:left;vertical-align:top;";
else if (align == ContentAlignment.TopCenter)
return "text-align:center;vertical-align:top;";
else if (align == ContentAlignment.TopRight)
return "text-align:right;vertical-align:top;";
else if (align == ContentAlignment.BottomLeft)
return "text-align:left;vertical-align:bottom;";
else if (align == ContentAlignment.BottomCenter)
return "text-align:center;vertical-align:bottom;";
else if (align == ContentAlignment.TopRight)
return "text-align:right;vertical-align:bottom;";
else if (align == ContentAlignment.MiddleLeft)
return "text-align:left;vertical-align:middle;";
else if (align == ContentAlignment.MiddleCenter)
return "text-align:center;vertical-align:middle;";
else if (align == ContentAlignment.MiddleRight)
return "text-align:right;vertical-align:middle;";
else
return "";
}
}
}
@@ -0,0 +1,66 @@
using FastReport.Dialog;
using static FastReport.Web.Constants;

namespace FastReport.Web
{
public partial class Dialog
{
private void TextBoxChange(TextBoxControl tb, string data)
{
tb.Text = data;
tb.FilterData();
tb.OnTextChanged(null);
}

private string GetValHook()
{
return
"<script>$.valHooks.textarea = {" +
"get: function(elem) {" +
"return elem.value.replace(/\\r?\\n/g, \'\\r\\n\');" +
"}};</script>";
}

private string GetTextBoxHtml(TextBoxControl control)
{
string id = GetControlID(control);
if (control.Multiline)
{
return
//GetValHook() +
string.Format("<textarea style=\"{0}\" type=\"text\" name=\"{1}\" onchange=\"{3}\" id=\"{4}\">{2}</textarea>",
// style
GetTextBoxStyle(control), //0
// name
control.Name, //1
// value
control.Text, //2
// onclick
GetEvent(ONCHANGE, control, DIALOG, $"document.getElementById('{id}').value.replace(/\\r?\\n/g, \'\\r\\n\')"), //3
// title
id //4
);
}
else
{
return string.Format("<input style=\"{0}\" type=\"text\" name=\"{1}\" value=\"{2}\" onchange=\"{3}\" id=\"{4}\"/>",
// style
GetTextBoxStyle(control),
// name
control.Name,
// value
control.Text,
// onclick
GetEvent(ONCHANGE, control, DIALOG, $"document.getElementById('{id}').value"),
// title
id
);
}
}

private string GetTextBoxStyle(TextBoxControl control)
{
return $"{GetControlPosition(control)} {GetControlFont(control.Font)} {GetControlAlign(control)}";
}
}
}
@@ -14,13 +14,20 @@ public enum WebReportMode
{
Preview,
Designer,
Dialog
}

public partial class WebReport
{
private string localizationFile;

#region Public Properties
#if DIALOGS
internal Dialog Dialog {
get;
}
#endif

#region Public Properties

/// <summary>
/// Unique ID of this instance.
@@ -112,7 +119,7 @@ public bool ReportPrepared
tab.ReportPrepared = value;
}
}

/// <summary>
/// Total prepared pages of current report
/// </summary>
@@ -143,16 +150,17 @@ public bool ReportPrepared
public bool ShowToolbar { get; set; } = true;
public float Zoom { get; set; } = 1.0f;
public bool Debug { get; set; } = false;
internal bool Canceled { get; set; } = false;

/// <summary>
/// Shows sidebar with outline.
/// Default value: true.
/// </summary>
public bool Outline { get; set; } = true;

#endregion
#endregion

#region Non-public
#region Non-public

// TODO
private string ReportFile { get; set; } = null;
@@ -167,15 +175,24 @@ public bool ReportPrepared
internal readonly Dictionary<string, byte[]> PictureCache = new Dictionary<string, byte[]>();
int currentTabIndex;

#endregion
#endregion

public WebReport()
{
string path = WebUtils.MapPath(LocalizationFile);
Res.LoadLocale(path);
WebReportCache.Instance.Add(this);
#if DIALOGS
Dialog = new Dialog(this);
#endif
}

static WebReport()
{
ScriptSecurity = new ScriptSecurity(new ScriptChecker());
}


public HtmlString RenderSync()
{
return Task.Run(() => Render()).Result;
@@ -194,6 +211,7 @@ internal HtmlString Render(bool renderBody)
switch (Mode)
{
case WebReportMode.Preview:
case WebReportMode.Dialog:
return new HtmlString(template_render(renderBody));
case WebReportMode.Designer:
return RenderDesigner();
@@ -214,7 +232,7 @@ public void RemoveFromCache()
// void ReportLoad()
// void RegisterData()

#region Navigation
#region Navigation

/// <summary>
/// Force go to next report page
@@ -259,6 +277,12 @@ public void GotoPage(int value)
CurrentPageIndex = value;
}

#endregion
#endregion

#region Script Security

private static ScriptSecurity ScriptSecurity = null;

#endregion
}
}
@@ -120,6 +120,35 @@ public IActionResult PrintHtml()
}
}

internal void Dialogs(HttpRequest request)
{
string dialogN = request.Query["dialog"];
string controlName = request.Query["control"];
string eventName = request.Query["event"];
string data = request.Query["data"];

#if DIALOGS
Dialog.SetDialogs(dialogN, controlName, eventName, data);
#endif
}


internal StringBuilder ReportBody()
{
#if DIALOGS
if (Mode == WebReportMode.Dialog)
{
StringBuilder sb = new StringBuilder();

Dialog.ProcessDialogs(sb);

return sb;
}
else
#endif
return ReportInHtml();
}

internal StringBuilder ReportInHtml()
{
PictureCache.Clear();
@@ -194,7 +223,7 @@ internal StringBuilder ReportInHtml()
// important container, it cuts off elements that are outside of the report page bounds
int pageWidth = (int)Math.Ceiling(GetReportPageWidthInPixels() * html.Zoom);
int pageHeight = (int)Math.Ceiling(GetReportPageHeightInPixels() * html.Zoom);
sb.Insert(0, $@"<div style=""width:{pageWidth}px;height:{(SinglePage ? pageHeight * html.Count : pageHeight)}px;overflow:hidden;display:inline-block;"">");
sb.Insert(0, $@"<div style=""width:{pageWidth}px;height:{pageHeight}px;overflow:hidden;display:inline-block;"">");
sb.Append("</div>");
}

@@ -679,16 +708,43 @@ void CacheHtmlPictures(HTMLExport html, int pageN)

float GetReportPageWidthInPixels()
{
ReportPage page = Report.PreparedPages.GetPage(0);
return page?.WidthInPixels ?? 0;
float _pageWidth = 0;

if (SinglePage)
{
foreach (ReportPage page in Report.Pages)
{
// find maxWidth
if (page.WidthInPixels > _pageWidth)
_pageWidth = page.WidthInPixels;
}
}
else
{
_pageWidth = Report.PreparedPages.GetPageSize(CurrentPageIndex).Width;
}

return _pageWidth;
}

float GetReportPageHeightInPixels()
{
ReportPage page = Report.PreparedPages.GetPage(0);
return page?.HeightInPixels ?? 0;
float _pageHeight = 0;
if (SinglePage)
{
for (int i = 0; i < Report.PreparedPages.Count; i++)
{
_pageHeight += Report.PreparedPages.GetPageSize(i).Height;
}
}
else
{
_pageHeight = Report.PreparedPages.GetPageSize(CurrentPageIndex).Height;
}

return _pageHeight;
}

#endregion
#endregion
}
}
@@ -35,8 +35,18 @@ public ReportController()
if (!FindWebReport(out WebReport webReport))
return new NotFoundResult();

if (!webReport.ReportPrepared && Request.Query["skipPrepare"].ToString() != "yes")
webReport.Report.Prepare();
webReport.Dialogs(Request);

if (webReport.Canceled)
return new OkResult();

if (webReport.Mode != WebReportMode.Dialog)
{
if (!webReport.ReportPrepared && Request.Query["skipPrepare"].ToString() != "yes")
webReport.Report.Prepare();
}
else
webReport.Report.PreparePhase1();

webReport.SetReportTab(Request);
webReport.SetReportPage(Request);
@@ -123,6 +133,16 @@ public ReportController()
}
});

RegisterHandler("/dialog", () =>
{
if (!FindWebReport(out WebReport webReport))
return new NotFoundResult();

webReport.Dialogs(Request);

return new OkResult();
});

RegisterHandler("/preview.textEditForm", () =>
{
if (!FindWebReport(out WebReport webReport))
@@ -32,6 +32,11 @@ Various report objects will allow your report to look exactly how you want it to
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="$(SolutionDir)FastReport.OpenSource\FastReport.OpenSource.csproj" />
</ItemGroup>
<ItemGroup>
<Compile Include="..\FastReport.Web.Base\*.cs">
<Link>Application\%(Filename)%(Extension)</Link>
</Compile>
</ItemGroup>
<ItemGroup>
<None Remove="Resources\angle-double-left.svg" />
@@ -71,4 +76,7 @@ Various report objects will allow your report to look exactly how you want it to
<PackageReference Include="Microsoft.AspNetCore.Html.Abstractions" Version="2.0.0" />
<PackageReference Include="Microsoft.AspNetCore.Mvc.Core" Version="2.0.2" />
</ItemGroup>
<ItemGroup>
<Compile Remove="Application\Dialog\*.*"/>
</ItemGroup>
</Project>
@@ -1,5 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<Dialogs>true</Dialogs>

<TargetFramework>netstandard2.0</TargetFramework>
<PackageRequireLicenseAcceptance>true</PackageRequireLicenseAcceptance>
<Version>1.0.0</Version>
@@ -32,6 +34,11 @@ $(DemoDescription)
<ItemGroup>
<ProjectReference Include="$(SolutionDir)FastReport.Core\FastReport.Core.csproj" />
</ItemGroup>
<ItemGroup>
<Compile Include="..\FastReport.Web.Base\*.cs">
<Link>Application\%(Filename)%(Extension)</Link>
</Compile>
</ItemGroup>
<ItemGroup>
<None Remove="Resources\angle-double-left.svg" />
<None Remove="Resources\angle-double-right.svg" />
@@ -70,4 +77,7 @@ $(DemoDescription)
<PackageReference Include="Microsoft.AspNetCore.Html.Abstractions" Version="2.0.0" />
<PackageReference Include="Microsoft.AspNetCore.Mvc.Core" Version="2.0.2" />
</ItemGroup>
<PropertyGroup Condition="$(Dialogs)">
<DefineConstants>$(DefineConstants);DIALOGS</DefineConstants>
</PropertyGroup>
</Project>
@@ -25,7 +25,7 @@ string template_body(bool renderBody)
{template_outline()}
<div class=""{template_FR}-report"">
{ReportInHtml().ToString()}
{ ReportBody()}
</div>
</div>
@@ -1,4 +1,6 @@
namespace FastReport.Web
using static FastReport.Web.Constants;

namespace FastReport.Web
{
partial class WebReport
{
@@ -165,6 +167,34 @@ partial class WebReport
}});
}},
{SILENT_RELOAD}: function (params, form) {{
var that = this;
var body = this._findBody();
var container = this._findContainer();
this._fetch({{
method: 'POST',
url: '{template_ROUTE_BASE_PATH}/preview.getReport?reportId={ID}&renderBody=yes' + (params || ''),
form: form,
onSuccess: function (xhr) {{
container.outerHTML = xhr.responseText;
that._execScripts();
}},
onError: function (xhr) {{
that._placeError(xhr, body);
}},
}});
}},
{DIALOG}: function (params, form) {{
this._fetch({{
method: 'POST',
url: '{template_ROUTE_BASE_PATH}/dialog?reportId={ID}' + (params || ''),
form: form
}});
}},
_execScripts: function () {{
var container = this._findContainer();
var scripts = container.getElementsByTagName('script');
@@ -1,13 +1,17 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFrameworks>netstandard2.0;netstandard2.1</TargetFrameworks>
<TargetFrameworks>netstandard2.0</TargetFrameworks>
</PropertyGroup>

<PropertyGroup Condition="'$(OS)' == 'Windows_NT'">
<TargetFrameworks>$(TargetFrameworks);net40</TargetFrameworks>
</PropertyGroup>

<PropertyGroup Condition="'$(VisualStudioVersion)' >= '16'">
<TargetFrameworks>$(TargetFrameworks);netstandard2.1</TargetFrameworks>
</PropertyGroup>

<PropertyGroup>
<SignAssembly>true</SignAssembly>
<AssemblyOriginatorKeyFile>../FastReport.OpenSource.snk</AssemblyOriginatorKeyFile>
@@ -0,0 +1,93 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using FastReport.Utils;
using System.Text.RegularExpressions;

namespace FastReport.Web
{
partial class WebReport
{
/// <summary>
/// Sets custom class for checking the report script.
/// </summary>
/// <param name="scriptChecker"></param>
public static void SetScriptSecurity(IScriptChecker scriptChecker)
{
ScriptSecurity.Dispose();
ScriptSecurity = new ScriptSecurity(scriptChecker);
}

}

internal class ScriptSecurity : IDisposable
{
private IScriptChecker ScriptChecker;

internal ScriptSecurity(IScriptChecker checker)
{
ScriptChecker = checker;
Config.ScriptCompile += Config_ScriptCompile;
}

internal void Config_ScriptCompile(object sender, ScriptSecurityEventArgs e)
{
if(Config.EnableScriptSecurity)
e.IsValid = ScriptChecker.IsValid(e.ReportLanguage, e.ReportScript, e.References, e.Report);
}

public void Dispose()
{
Config.ScriptCompile -= Config_ScriptCompile;
}
}

/// <summary>
/// Interface for overriding the standard check of the report script
/// <see cref="IsValid(Language, string, string[], Report)"/>
/// </summary>
public interface IScriptChecker
{
/// <summary>
/// Method for checking the report script
/// </summary>
/// <param name="lang">Report script language</param>
/// <param name="reportScript">Report script</param>
/// <param name="references">Referenced assemblies</param>
/// <param name="report">Report</param>
/// <returns>Returns true if the report passed the validation check</returns>
bool IsValid(Language lang, string reportScript, string[] references, Report report);
}

internal class ScriptChecker : IScriptChecker
{
public bool IsValid(Language lang, string reportScript, string[] references, Report report)
{
// LOGIC
foreach(string reference in references)
{
// in .Net Core need to add reference
if (reference.IndexOf("System.IO.FileSystem") != -1)
return false;

if (reference.IndexOf("Microsoft.AspNetCore") != -1)
return false;

if(reference.IndexOf("System.Net") != -1)
return false;
}

foreach (string pattern in Config.ScriptSecurityProps.StopList)
{
if (reportScript.IndexOf(pattern) != -1)
return false;

//regex = new Regex(pattern);
//if (regex.IsMatch(reportScript))
}

return true;
}
}
}
@@ -21,6 +21,7 @@
<Attention Text="Attention"/>
<BarcodeFewError Text="The number of digits is less than the permissible minimum."/>
<BarcodeManyError Text="The number of digits is greater than the allowable maximum."/>
<BarcodeLengthMismatch Text="Number of characters mismatch."/>
<CantFindObject Text="Can't find object"/>
<CantLoadReport Text="Can't load the report {0}"/>
<CantSaveReport Text="Can't save the report. The file may be write-protected."/>
@@ -123,11 +124,11 @@
<GoogleBigQueryDataConnection Text="Google Big Query connection"/>
<JsonDataConnection Text="JSON database"/>
<JsonDataSourceConnection Text="JSON (JavaScript Object Notation)" />
<CouchbaseDataConnection Text="Couchbase server"/>
<CouchbaseDataConnection Text="Couchbase server"/>
<MongoDBDataConnection Text="MongoDB connection"/>
<NosDbDataConnection Text="NosDb connection"/>
<RavenDBDataConnection Text="RavenDB connection"/>
<SqlAnywhereDataConnection Text="SqlAnywhere connection"/>
<SqlAnywhereDataConnection Text="SqlAnywhere connection"/>
<Bands Text="Bands">
<ReportTitle Text="Report Title"/>
<ReportSummary Text="Report Summary"/>
@@ -166,6 +167,7 @@
<TableObject Text="Table"/>
<MatrixObject Text="Matrix"/>
<SubreportObject Text="Subreport"/>
<ContainerObject Text="Container"/>
<BarcodeObject Text="Barcode"/>
<RichObject Text="Rich Text"/>
<MSChartObject Text="MS Chart"/>
@@ -642,11 +644,13 @@
<Design Text="Design Report"/>
<PrintText Text="Print"/>
<Print Text="Print (Ctrl+P)"/>
<OpenText Text="Open"/>
<Open Text="Open File"/>
<Save Text="Save File"/>
<SaveText Text="Save"/>
<SaveToCloud Text="Save to Cloud"/>
<SaveToCloudText Text="Save to Cloud"/>
<Search Text="Search"/>
<Email Text="Send by E-mail"/>
<Find Text="Find Text"/>
<Outline Text="Outline"/>
@@ -1985,7 +1989,7 @@
</Xml>
<Csv>
<ConfigureDatabase Text="Configure database"/>
<SelectFile Text="Select .csv file:"/>
<SelectFile Text="Select .csv file (path or url):"/>
<Codepage Text="Codepage:"/>
<Separator Text="Separator:"/>
<FieldNames Text="Field names in first string"/>
@@ -2016,8 +2020,17 @@
<Encoding Text="Encoding"/>
<Input Text="Json or URL"/>
<Schema Text="Json Schema"/>
<RequestHeaders Text="Request Headers"/>
<HeaderKey Text="Header"/>
<HeaderVal Text="Value"/>
<ConfirmChanges Text="Json has been modified. Generate a new schema?" />
</Json>
<MongoDB>
<Scheme Text="Scheme:"/>
<Host Text="Host:"/>
<Port Text="Port:"/>
<UseSsl Text="Use SSL"/>
</MongoDB>
</ConnectionEditors>
<ComponentMenu>
<Component>
@@ -2118,30 +2131,32 @@
<Barcode0 Text="2/5 Interleaved"/>
<Barcode1 Text="2/5 Industrial"/>
<Barcode2 Text="2/5 Matrix"/>
<Barcode3 Text="Codabar"/>
<Barcode4 Text="Code128"/>
<Barcode5 Text="Code39"/>
<Barcode6 Text="Code39 Extended"/>
<Barcode7 Text="Code93"/>
<Barcode8 Text="Code93 Extended"/>
<Barcode9 Text="EAN8"/>
<Barcode10 Text="EAN13"/>
<Barcode11 Text="MSI"/>
<Barcode12 Text="PostNet"/>
<Barcode13 Text="UPC-A"/>
<Barcode14 Text="UPC-E0"/>
<Barcode15 Text="UPC-E1"/>
<Barcode16 Text="Supplement 2"/>
<Barcode17 Text="Supplement 5"/>
<Barcode18 Text="PDF417"/>
<Barcode19 Text="Datamatrix"/>
<Barcode20 Text="QR Code"/>
<Barcode21 Text="Aztec"/>
<Barcode22 Text="Plessey"/>
<Barcode23 Text="GS1-128 (UCC/EAN-128)"/>
<Barcode24 Text="Pharmacode"/>
<Barcode25 Text="Intelligent Mail (USPS)"/>
<Barcode26 Text="MaxiCode"/>
<Barcode3 Text="Deutsche Identcode"/>
<Barcode4 Text="ITF-14"/>
<Barcode5 Text="Codabar"/>
<Barcode6 Text="Code128"/>
<Barcode7 Text="Code39"/>
<Barcode8 Text="Code39 Extended"/>
<Barcode9 Text="Code93"/>
<Barcode10 Text="Code93 Extended"/>
<Barcode11 Text="EAN8"/>
<Barcode12 Text="EAN13"/>
<Barcode13 Text="MSI"/>
<Barcode14 Text="PostNet"/>
<Barcode15 Text="UPC-A"/>
<Barcode16 Text="UPC-E0"/>
<Barcode17 Text="UPC-E1"/>
<Barcode18 Text="Supplement 2"/>
<Barcode19 Text="Supplement 5"/>
<Barcode20 Text="PDF417"/>
<Barcode21 Text="Datamatrix"/>
<Barcode22 Text="QR Code"/>
<Barcode23 Text="Aztec"/>
<Barcode24 Text="Plessey"/>
<Barcode25 Text="GS1-128 (UCC/EAN-128)"/>
<Barcode26 Text="Pharmacode"/>
<Barcode27 Text="Intelligent Mail (USPS)"/>
<Barcode28 Text="MaxiCode"/>
</Barcodes>
</Barcode>
<ZipCodeObject>
@@ -2237,6 +2252,7 @@
<Image Text="Export to Image">
<File Text="Image file"/>
<ImageFormat Text="Format:"/>
<ImageParceFormatException Text="The bitmap cannot be converted to the selected format."/>
<Resolution Text="Resolution:"/>
<Quality Text="Jpeg quality:"/>
<SeparateFiles Text="Separate file for each page"/>
@@ -2608,6 +2624,10 @@
<EnterPage Text="Enter the page number to jump"/>
<TotalPages Text="Total pages (read only)"/>
<Back Text="Back"/>
<ScriptSecurity>
<ForbiddenType Text="Please, don't use the type {typeName}"/>
<ForbiddenMethod Text="Please, don't use the method {methodName}"/>
</ScriptSecurity>
</Web>
<Properties>
<Categories>
@@ -1,4 +1,4 @@
Copyright (c) 2018 Fast Reports Inc
Copyright (c) 2020 Fast Reports Inc

Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

@@ -4,7 +4,7 @@

## What is FastReport?

FastReport provides open source report generator for .NET Core 2.x/.NET Framework 4.x. You can use the FastReport in MVC, Web API applications.
FastReport provides free open source report generator for .NET Core/.NET Framework. You can use the FastReport Open Source in MVC, Web API applications.

[![Image of FastReport](https://raw.githubusercontent.com/FastReports/FastReport.Documentation/master/images/FastReport-screenshot2-small.png)](https://raw.githubusercontent.com/FastReports/FastReport.Documentation/master/images/FastReport-screenshot2.png)

@@ -117,9 +117,9 @@ Licensed under the MIT license. See [LICENSE.md](LICENSE.md) for details.

[FastReport Open Source Documentation](https://fastreports.github.io/FastReport.Documentation/)

[FastReport Open Source Articles and How-Tos](https://fropensource.blogspot.com/)
[FastReport Open Source Blog with Articles and How-Tos](https://opensource.fast-report.com/)

[The Feature Comparison Table for FastReport Open Source, FastReport Core, FastReport .NET](https://fastreports.github.io/FastReport.Documentation/COMPARISON.html "FastReport Open Source vs FastReport Core vs FastReport .NET")
[The Feature Comparison Table for FastReport Open Source, FastReport Core, FastReport .NET](https://opensource.fast-report.com/p/the-feature-comparison-table-for.html "FastReport Open Source vs FastReport Core vs FastReport .NET")

[FastReport Core Online Demo](https://www.fast-report.com:2018 "Click to view FastReport Online Demo")

@@ -1,11 +1,25 @@
<?xml version="1.0" encoding="utf-8"?>
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<!-- This file sets version used packages in FastReport.Core, FastReport.OpenSource & FastReport.Core3 -->
<!-- This group sets version used packages in FastReport.Core, FastReport.OpenSource & FastReport.Core3 -->
<PropertyGroup>

<FRCompatVersion>2020.3.2</FRCompatVersion>
<FRCompatVersion>2020.3.8</FRCompatVersion>

<FRDataVisualizationVersion>2020.3.1</FRDataVisualizationVersion>
<FRDataVisualizationVersion>2020.3.8</FRDataVisualizationVersion>

</PropertyGroup>

<!-- This group sets version used packages in Demos -->
<PropertyGroup>

<FRCoreVersion>2020.3.17</FRCoreVersion>

<FRCoreWebVersion>2020.3.17</FRCoreWebVersion>

<FROSVersion>2020.3.17</FROSVersion>

<FROSWebVersion>2020.3.17</FROSWebVersion>

</PropertyGroup>

</Project>
@@ -1,3 +1,3 @@
theme: jekyll-theme-cayman
title: FastReport Open Source
description: FastReport provides open source report generator for .NET Core 2.x/.Net Framework 4.x.
description: FastReport provides open source report generator for .NET Core/.NET Framework.
@@ -4,11 +4,11 @@

publiccodeYmlVersion: '0.2'
name: FastReport
releaseDate: '2019-12-02'
releaseDate: '2020-05-20'
url: 'https://github.com/FastReports/FastReport.git'
applicationSuite: Report generator
landingURL: 'https://github.com/FastReports/FastReport'
softwareVersion: 2020.1.0
softwareVersion: 2020.3.0
roadmap: 'https://github.com/FastReports/FastReport/issues/79'
developmentStatus: stable
softwareType: library
@@ -95,12 +95,13 @@ description:
- finance
- library
- printing
- pdf
- viewer
- word-processor
featureList:
- generate report
- 'export to PDF, html, image, etc.'
longDescription: FastReport fornisce un generatore di report open source per .NET Core 2.x / .NET Framework 4.x. È possibile utilizzare FastReport in MVC, applicazioni API Web. FastReport è scritto in C# ed è compatibile con .NET Standard 2.0 e versioni successive. L'architettura FastReport estendibile consente di creare oggetti, filtri di esportazione, procedure guidate e motori DB personalizzati. È possibile ottenere dati da XML, CSV, Json, MS SQL, MySql, Oracle, Postgres, MongoDB, Couchbase, RavenDB, SQLite. FastReport ha un motore di script integrato che supporta due lingue .NET, C# e VB.NET. È possibile utilizzare tutta la potenza di .NET nei report per eseguire complesse operazioni di gestione dei dati e molto altro. È possibile creare un modello di report in diversi modi:creazione di report da codice, sviluppo di template di report come file XML, utilizzando FastReport Online Designer, utilizzando FastReport Designer Community Edition (freeware). FastReport Open Source può salvare documenti in HTML, BMP, PNG, JPEG, GIF, TIFF, EMF. L'esportazione PDF è disponibile come plug-in. FASTREPORT Open Source è un programma per la creazione di report con specifica gestione di sezioni visualmente distinte. Queste comprendono:titolo del report, riassunto, titolo principale, sottotitolo, testata della colonna, nota in calce della colonna, testata dei dati, dati, nota in calce dei dati, testata di gruppo, nota in calce del gruppo, figli, overlay. Inoltre è possibile l’uso di sottoreport, che sono totalmente gestiti dal programma. L’ampia gamma di campi permette la creazione di qualsiasi tipo di report:liste, master-detail, gruppi, colonne multiple, master-detail-detail e molti altri.
longDescription: FastReport fornisce un generatore di report open source per .NET Core/.NET Framework. È possibile utilizzare FastReport in MVC, applicazioni API Web. FastReport è scritto in C# ed è compatibile con .NET Standard 2.0 e versioni successive. L'architettura FastReport estendibile consente di creare oggetti, filtri di esportazione, procedure guidate e motori DB personalizzati. È possibile ottenere dati da XML, CSV, Json, MS SQL, MySql, Oracle, Postgres, MongoDB, Couchbase, RavenDB, SQLite. FastReport ha un motore di script integrato che supporta due lingue .NET, C# e VB.NET. È possibile utilizzare tutta la potenza di .NET nei report per eseguire complesse operazioni di gestione dei dati e molto altro. È possibile creare un modello di report in diversi modi:creazione di report da codice, sviluppo di template di report come file XML, utilizzando FastReport Online Designer, utilizzando FastReport Designer Community Edition (freeware). FastReport Open Source può salvare documenti in HTML, BMP, PNG, JPEG, GIF, TIFF, EMF. L'esportazione PDF è disponibile come plug-in. FASTREPORT Open Source è un programma per la creazione di report con specifica gestione di sezioni visualmente distinte. Queste comprendono:titolo del report, riassunto, titolo principale, sottotitolo, testata della colonna, nota in calce della colonna, testata dei dati, dati, nota in calce dei dati, testata di gruppo, nota in calce del gruppo, figli, overlay. Inoltre è possibile l’uso di sottoreport, che sono totalmente gestiti dal programma. L’ampia gamma di campi permette la creazione di qualsiasi tipo di report:liste, master-detail, gruppi, colonne multiple, master-detail-detail e molti altri.
screenshots:
- assets/images/FastReport-screenshot2.png
- assets/images/FastReport-screenshot1.png
@@ -126,7 +127,7 @@ description:
genericName: Generatore di report

en:
shortDescription: FastReport provides open source report generator for .NET Core 2.x/.NET Framework 4.x. You can use the FastReport in MVC, Web API applications.
shortDescription: FastReport provides open source report generator for .NET Core/.NET Framework. You can use the FastReport in MVC, Web API applications.
documentation: 'https://github.com/FastReports/FastReport.Documentation'
freeTags:
- fastreport
@@ -140,12 +141,13 @@ description:
- finance
- library
- printing
- pdf
- viewer
- word-processor
featureList:
- generate report
- 'export to PDF, html, image, etc.'
longDescription: FastReport provides open source report generator for .NET Core 2.x/.NET Framework 4.x. You can use the FastReport in MVC, Web API applications. FastReport is written in C# and it is compatible with .NET Standard 2.0 and higher. Extendable FastReport architecture allows creating your own objects, export filters, wizards and DB engines. You can get data from XML, CSV, Json, MS SQL, MySql, Oracle, Postgres, MongoDB, Couchbase, RavenDB, SQLite. FastReport has a built-in script engine that supports two .NET languages, C# and VB.NET. You can use all of the .NET power in your reports to perform complex data handling and much more. You can make a report template in several ways:creating report from code, developing report template as XML file, using the FastReport Online Designer, using the FastReport Designer Community Edition (freeware). FastReport Open Source can save documents in HTML, BMP, PNG, JPEG, GIF, TIFF, EMF. PDF Export is available as a plugin.
longDescription: FastReport provides open source report generator for .NET Core/.NET Framework. You can use the FastReport in MVC, Web API applications. FastReport is written in C# and it is compatible with .NET Standard 2.0 and higher. Extendable FastReport architecture allows creating your own objects, export filters, wizards and DB engines. You can get data from XML, CSV, Json, MS SQL, MySql, Oracle, Postgres, MongoDB, Couchbase, RavenDB, SQLite. FastReport has a built-in script engine that supports two .NET languages, C# and VB.NET. You can use all of the .NET power in your reports to perform complex data handling and much more. You can make a report template in several ways:creating report from code, developing report template as XML file, using the FastReport Online Designer, using the FastReport Designer Community Edition (freeware). FastReport Open Source can save documents in HTML, BMP, PNG, JPEG, GIF, TIFF, EMF. PDF Export is available as a plugin.

screenshots:
- assets/images/FastReport-screenshot2.png