@@ -12,6 +12,7 @@
using MongoDB.Driver;
using FastReport.Utils;
using FastReport.Data;
using MongoDB.Driver.Core.Configuration;

namespace FastReport.Data
{
@@ -30,23 +31,34 @@ private void btnAdvanced_Click(object sender, EventArgs e)
}
}

private void comboBoxScheme_SelectedValueChanged(object sender, EventArgs e)
{
if ((ConnectionStringScheme)comboBoxScheme.SelectedItem == ConnectionStringScheme.MongoDBPlusSrv)
tbPort.Enabled = false;
else tbPort.Enabled = true;
}

private void Localize()
{
MyRes res = new MyRes("ConnectionEditors,Common");

gbServer.Text = res.Get("ServerLogon");
//lblHost.Text = res.Get("Server");
lblHost.Text = Res.Get("ConnectionEditors,MongoDB,Host");
lblPort.Text = Res.Get("ConnectionEditors,MongoDB,Port");
lblUserName.Text = res.Get("UserName");
lblPassword.Text = res.Get("Password");
lblScheme.Text = Res.Get("ConnectionEditors,MongoDB,Scheme");

gbDatabase.Text = res.Get("Database");
lblDatabase.Text = res.Get("DatabaseName");
btnAdvanced.Text = Res.Get("Buttons,Advanced");
cbUseSsl.Text = Res.Get("ConnectionEditors,MongoDB,UseSsl");
}

protected override string GetConnectionString()
{
MongoUrlBuilder builder = new MongoUrlBuilder();
builder.Scheme = (ConnectionStringScheme)comboBoxScheme.SelectedItem;
if (!string.IsNullOrEmpty(FConnectionString))
builder = new MongoUrlBuilder(FConnectionString);
builder.Server = new MongoServerAddress(tbHost.Text, int.Parse(tbPort.Text));
@@ -57,7 +69,17 @@ protected override string GetConnectionString()
builder.UseSsl = cbUseSsl.Checked;
}
MongoDBDataConnection.dbName = builder.DatabaseName = tbDatabase.Text;
#if NET45
string url = builder.ToString();
if(builder.Scheme == ConnectionStringScheme.MongoDBPlusSrv && builder.Server.Port != 27017)
{
string portString = builder.Server.Port.ToString();
url = url.Remove(url.IndexOf(portString) - 1, 1).Replace(portString, "");
}
return url;
#else
return builder.ToMongoUrl().Url;
#endif
}

protected override void SetConnectionString(string value)
@@ -77,6 +99,7 @@ protected override void SetConnectionString(string value)
public MongoDBConnectionEditor()
{
InitializeComponent();
comboBoxScheme.DataSource = Enum.GetValues(typeof(ConnectionStringScheme));
Localize();
}
}
@@ -25,10 +25,10 @@
<PrivateAssets>all</PrivateAssets>
</ProjectReference>
</ItemGroup>
<ItemGroup >
<ItemGroup>
<PackageReference Include="MySql.Data" Version="[6.7.9,)" />
</ItemGroup>
<ItemGroup >
<ItemGroup>
<Reference Include="System" />
<Reference Include="System.Data" />
<Reference Include="System.Design" />
@@ -38,14 +38,12 @@
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
<Compile Update="MySqlConnectionEditor.cs">
<SubType>UserControl</SubType>
</Compile>
<Compile Update="MySqlConnectionEditor.cs" />
<Compile Update="MySqlConnectionEditor.Designer.cs">
<DependentUpon>MySqlConnectionEditor.cs</DependentUpon>
</Compile>
</ItemGroup>
<ItemGroup >
<ItemGroup>
<EmbeddedResource Update="MySqlConnectionEditor.resx">
<DependentUpon>MySqlConnectionEditor.cs</DependentUpon>
<SubType>Designer</SubType>
@@ -48,8 +48,6 @@
</EmbeddedResource>
</ItemGroup>
<ItemGroup>
<Compile Update="OracleConnectionEditor.cs">
<SubType>UserControl</SubType>
</Compile>
<Compile Update="OracleConnectionEditor.cs" />
</ItemGroup>
</Project>
@@ -1,7 +1,11 @@
<Project Sdk="Microsoft.NET.Sdk">
<Project Sdk="Microsoft.NET.Sdk">

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

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

<PropertyGroup>
@@ -23,8 +27,9 @@
<RepositoryUrl>https://github.com/FastReports/FastReport</RepositoryUrl>
</PropertyGroup>

<Import Project="..\..\..\..\UsedPackages.version" />
<ItemGroup>
<PackageReference Include="FastReport.OpenSource" Version="2020.1.0" />
<PackageReference Include="FastReport.OpenSource" Version="$(FROSVersion)" />
</ItemGroup>

</Project>
@@ -100,6 +100,7 @@ public AssemblyInitializer()
RegisteredObjects.Add(typeof(PolygonObject), "ReportPage,Shapes", 244, "Objects,Shapes,Heptagon", 0x70);
RegisteredObjects.Add(typeof(PolygonObject), "ReportPage,Shapes", 245, "Objects,Shapes,Octagon", 0x80);
RegisteredObjects.Add(typeof(SubreportObject), "ReportPage", 104, 5);
RegisteredObjects.Add(typeof(ContainerObject), "ReportPage", 144, 5);

RegisteredObjects.Add(typeof(TableObject), "ReportPage", 127, 6);
RegisteredObjects.Add(typeof(TableColumn), "", 215);
@@ -671,6 +671,10 @@ internal bool IsColumnDependentBand
#endregion

#region Report Engine
internal void SetUpdatingLayout(bool value)
{
updatingLayout = value;
}

/// <inheritdoc/>
public override string[] GetExpressions()
@@ -939,7 +943,10 @@ public override bool Break(BreakableComponent breakTo)
}
else
{
obj.Top -= breakLine;
// (case: object with Anchor = bottom on a breakable band)
// in case of bottom anchor, do not move the object. It will be moved automatically when we decrease the band height
if ((obj.Anchor & AnchorStyles.Bottom) == 0)
obj.Top -= breakLine;
obj.Parent = breakTo;
continue;
}
@@ -35,12 +35,15 @@ private void DrawBarcode(IGraphicsRenderer g, float width, float height)
if (showText)
{
string data = StripControlCodes(text);
// When we print, .Net automatically scales the font. However, we need to handle this process.
// Downscale the font to the screen resolution, then scale by required value (ky).
float fontZoom = 18f / (int)g.MeasureString(data, FFont).Height * ky;
using (Font drawFont = new Font(FFont.Name, FFont.Size * fontZoom, FFont.Style))
if (data.Length > 0)
{
g.DrawString(data, drawFont, Brushes.Black, new RectangleF(0, height - 18 * ky, width, 18 * ky));
// When we print, .Net automatically scales the font. However, we need to handle this process.
// Downscale the font to the screen resolution, then scale by required value (ky).
float fontZoom = 18f / (int)g.MeasureString(data, FFont).Height * ky;
using (Font drawFont = new Font(FFont.Name, FFont.Size * fontZoom, FFont.Style))
{
g.DrawString(data, drawFont, Brushes.Black, new RectangleF(0, height - 18 * ky, width, 18 * ky));
}
}
}
}

Large diffs are not rendered by default.

@@ -8,6 +8,7 @@
using FastReport.Code;
using System.Windows.Forms;
using System.Drawing.Design;
using FastReport.Barcode.QRCode;

namespace FastReport.Barcode
{
@@ -53,6 +54,28 @@ namespace FastReport.Barcode
/// </example>
public partial class BarcodeObject : ReportComponentBase
{
/// <summary>
/// Specifies the horizontal alignment of a Barcode object. Works only when autosize is on.
/// </summary>
public enum Alignment
{
/// <summary>
/// Specifies that the barcode is aligned to the left of the original layout.
/// </summary>
Left,

/// <summary>
/// Specifies that the barcode is aligned to the center of the original layout.
/// </summary>
Center,

/// <summary>
/// Specifies that the barcode is aligned to the right of the original layout.
/// </summary>
Right
}


#region Fields
private int angle;
private bool autoSize;
@@ -69,6 +92,8 @@ public partial class BarcodeObject : ReportComponentBase
private bool allowExpressions;
private string savedText;
private bool asBitmap;
private Alignment horzAlign;
private RectangleF origRect;
#endregion

#region Properties
@@ -88,6 +113,17 @@ public BarcodeBase Barcode
}
}

/// <summary>
/// Gets or sets the horizontal alignment of a Barcode object.
/// </summary>
[DefaultValue(Alignment.Left)]
[Category("Appearance")]
public Alignment HorzAlign
{
get { return horzAlign; }
set { horzAlign = value; }
}

/// <summary>
/// Gets or sets the symbology name.
/// </summary>
@@ -325,6 +361,19 @@ private void DrawBarcode(FRPaintEventArgs e)

#region Public Methods

/// <summary>
/// Initialize current BarcodeObject as Swiss QR.
/// </summary>
/// <param name="parameters">Parameters of swiss qr.</param>
public void CreateSwissQR(QRSwissParameters parameters)
{
QRSwiss swiss = new QRSwiss(parameters);
this.Barcode = new BarcodeQR();
Barcode.text = swiss.Pack();
this.Text = swiss.Pack();
this.ShowText = false;
}

public void UpdateAutoSize()
{
SetBarcodeProperties();
@@ -345,7 +394,31 @@ public void UpdateAutoSize()
if (size.Height > 0)
Width = size.Height + Padding.Horizontal;
}
RelocateAlign();
}
}

/// <summary>
/// Relocate BarcodeObject based on alignment
/// </summary>
public void RelocateAlign()
{
if (HorzAlign == Alignment.Left || origRect == RectangleF.Empty)
return;
switch( HorzAlign)
{
case Alignment.Center:
{
this.Left = origRect.Left + (origRect.Width / 2) - this.Width / 2;
break;
}
case Alignment.Right:
{
this.Left = origRect.Right - this.Width;
break;
}
}
origRect = RectangleF.Empty;
}

/// <inheritdoc/>
@@ -368,6 +441,7 @@ public override void Assign(Base source)
Brackets = src.Brackets;
AllowExpressions = src.AllowExpressions;
AsBitmap = src.AsBitmap;
HorzAlign = src.HorzAlign;
}

/// <inheritdoc/>
@@ -440,6 +514,8 @@ public override void Serialize(FRWriter writer)
writer.WriteStr("Brackets", Brackets);
if (AsBitmap != c.AsBitmap)
writer.WriteBool("AsBitmap", AsBitmap);
if (HorzAlign != c.HorzAlign)
writer.WriteValue("HorzAlign", HorzAlign);
Barcode.Serialize(writer, "Barcode.", c.Barcode);
}

@@ -529,6 +605,7 @@ public override void GetData()
{
try
{
origRect = this.Bounds;
UpdateAutoSize();
}
catch
@@ -579,6 +656,8 @@ public BarcodeItem(Type objType, string barcodeName)
new BarcodeItem(typeof(Barcode2of5Interleaved), "2/5 Interleaved"),
new BarcodeItem(typeof(Barcode2of5Industrial), "2/5 Industrial"),
new BarcodeItem(typeof(Barcode2of5Matrix), "2/5 Matrix"),
new BarcodeItem(typeof(BarcodeDeutscheIdentcode), "Deutsche Identcode"),
new BarcodeItem(typeof(BarcodeITF14), "ITF-14"),
new BarcodeItem(typeof(BarcodeCodabar), "Codabar"),
new BarcodeItem(typeof(Barcode128), "Code128"),
new BarcodeItem(typeof(Barcode39), "Code39"),

Large diffs are not rendered by default.

Large diffs are not rendered by default.

@@ -188,17 +188,6 @@ private void AddReferencedAssemblies(StringCollection assemblies, string default
string location;
foreach (string s in Report.ReferencedAssemblies)
{
//TODO thid core directive only for .net standard mode replace with checking the standard
#if NETSTANDARD2_0 || NETSTANDARD2_1

if (s == "System.Windows.Forms.dll")
{
location = GetFullAssemblyReference("FastReport.Compat", defaultPath);
if (location != "" && !ContansAssembly(assemblies, location))
assemblies.Add(location);
continue;
}
#endif
location = GetFullAssemblyReference(s, defaultPath);
if (location != "" && !ContansAssembly(assemblies, location))
assemblies.Add(location);
@@ -400,16 +389,18 @@ private void InternalCompile()
// configure compiler options
CompilerParameters cp = new CompilerParameters();
AddFastReportAssemblies(cp.ReferencedAssemblies);
#if NETSTANDARD || NETCOREAPP
cp.ReferencedAssemblies.Add("System.Drawing.Primitives");
#endif
AddReferencedAssemblies(cp.ReferencedAssemblies, currentFolder);
ReviewReferencedAssemblies(cp.ReferencedAssemblies);
cp.GenerateInMemory = true;
// sometimes the system temp folder is not accessible...
if (Config.TempFolder != null)
cp.TempFiles = new TempFileCollection(Config.TempFolder, false);

if (Config.WebMode &&
Config.EnableScriptSecurity &&
Config.ScriptSecurityProps.AddStubClasses)
AddStubClasses();

string errors = string.Empty;
CompilerResults cr;
bool exception = !InternalCompile(cp, out cr);
@@ -421,7 +412,7 @@ private void InternalCompile()
if (exception)
throw new CompilerException(errors);
}

private string GetAssemblyHash(CompilerParameters cp)
{
StringBuilder assemblyHashSB = new StringBuilder();
@@ -486,18 +477,73 @@ private bool HandleCompileErrors(CompilerParameters cp, CompilerResults cr, out
{
errors = string.Empty;
List<string> assemblyList = new List<string>(4);
Regex regex;

if (Config.WebMode && Config.EnableScriptSecurity)
{
for (int i=0; i < cr.Errors.Count; )
{
CompilerError ce = cr.Errors[i];
if (ce.ErrorNumber == "CS1685") // duplicate class
{
cr.Errors.Remove(ce);
continue;
}
else if (ce.ErrorNumber == "CS0436") // user using a forbidden type
{
const string pattern = "[\"'](\\S+)[\"']";
regex = new Regex(pattern, RegexOptions.Compiled);
string typeName = regex.Match(ce.ErrorText).Value;

const string res = "Web,ScriptSecurity,ForbiddenType";
string message = Res.TryGet(res);
if(string.Equals(res, message))
message = "Please, don't use the type " + typeName;
else
message = message.Replace("{typeName}", typeName); //$"Please, don't use the type {typeName}";

ce.ErrorText = message;

}
else if (ce.ErrorNumber == "CS0117") // user using a forbidden method
{
const string pattern = "[\"'](\\S+)[\"']";
regex = new Regex(pattern, RegexOptions.Compiled);
MatchCollection mathes = regex.Matches(ce.ErrorText);
if(mathes.Count > 1)
{
string methodName = mathes[1].Value;

const string res = "Web,ScriptSecurity,ForbiddenMethod";
string message = Res.TryGet(res);
if (string.Equals(res, message))
message = "Please, don't use the method " + methodName;
else
message = message.Replace("{methodName}", methodName); //$"Please, don't use the method {methodName}";

ce.ErrorText = message;
}
}

i++;
}
}

foreach (CompilerError ce in cr.Errors)
{
if (ce.ErrorNumber == "CS0012") // missing reference on assembly
{
// try to add reference
const string pattern = @"'(\S{1,}),";
Regex regex = new Regex(pattern);
string assemblyName = regex.Match(ce.ErrorText).Groups[1].Value; // Groups[1] include string without ' and , symbols
if (!assemblyList.Contains(assemblyName))
assemblyList.Add(assemblyName);
continue;
try
{
const string pattern = @"'(\S{1,}),";
regex = new Regex(pattern, RegexOptions.Compiled);
string assemblyName = regex.Match(ce.ErrorText).Groups[1].Value; // Groups[1] include string without ' and , symbols
if (!assemblyList.Contains(assemblyName))
assemblyList.Add(assemblyName);
continue;
}
catch { }
}

int line = GetScriptLine(ce.Line);

Large diffs are not rendered by default.

@@ -507,11 +507,26 @@ public override string[] GetExpressions()

if (!String.IsNullOrEmpty(VisibleExpression))
{
expressions.Add(VisibleExpression);
if (VisibleExpression.StartsWith("[") && VisibleExpression.EndsWith("]"))
{
expressions.Add(VisibleExpression.Substring(1, VisibleExpression.Length - 2));
}
else
{
expressions.Add(VisibleExpression);
}
}

if (!String.IsNullOrEmpty(PrintableExpression))
{
expressions.Add(PrintableExpression);
if (PrintableExpression.StartsWith("[") && PrintableExpression.EndsWith("]"))
{
expressions.Add(PrintableExpression.Substring(1, PrintableExpression.Length - 2));
}
else
{
expressions.Add(PrintableExpression);
}
}

return expressions.ToArray();
@@ -0,0 +1,391 @@
using FastReport.Utils;
using System;
using System.ComponentModel;
using System.Drawing;
using System.Windows.Forms;

namespace FastReport
{
/// <summary>
/// Container object that may contain child objects.
/// </summary>
public partial class ContainerObject : ReportComponentBase, IParent
{
#region Fields
private ReportComponentCollection objects;
private bool updatingLayout;
private string beforeLayoutEvent;
private string afterLayoutEvent;
#endregion

#region Properties
/// <summary>
/// Gets the collection of child objects.
/// </summary>
[Browsable(false)]
public ReportComponentCollection Objects
{
get { return objects; }
}

/// <summary>
/// This event occurs before the container layouts its child objects.
/// </summary>
public event EventHandler BeforeLayout;

/// <summary>
/// This event occurs after the child objects layout was finished.
/// </summary>
public event EventHandler AfterLayout;


/// <summary>
/// Gets or sets a script event name that will be fired before the container layouts its child objects.
/// </summary>
[Category("Build")]
public string BeforeLayoutEvent
{
get { return beforeLayoutEvent; }
set { beforeLayoutEvent = value; }
}

/// <summary>
/// Gets or sets a script event name that will be fired after the child objects layout was finished.
/// </summary>
[Category("Build")]
public string AfterLayoutEvent
{
get { return afterLayoutEvent; }
set { afterLayoutEvent = value; }
}

#endregion

#region IParent
/// <inheritdoc/>
public virtual void GetChildObjects(ObjectCollection list)
{
foreach (ReportComponentBase c in objects)
{
list.Add(c);
}
}

/// <inheritdoc/>
public virtual bool CanContain(Base child)
{
return (child is ReportComponentBase);
}

/// <inheritdoc/>
public virtual void AddChild(Base child)
{
if (child is ReportComponentBase)
objects.Add(child as ReportComponentBase);
}

/// <inheritdoc/>
public virtual void RemoveChild(Base child)
{
if (child is ReportComponentBase)
objects.Remove(child as ReportComponentBase);
}

/// <inheritdoc/>
public virtual int GetChildOrder(Base child)
{
return objects.IndexOf(child as ReportComponentBase);
}

/// <inheritdoc/>
public virtual void SetChildOrder(Base child, int order)
{
int oldOrder = child.ZOrder;
if (oldOrder != -1 && order != -1 && oldOrder != order)
{
if (order > objects.Count)
order = objects.Count;
if (oldOrder <= order)
order--;
objects.Remove(child as ReportComponentBase);
objects.Insert(order, child as ReportComponentBase);
}
}

/// <inheritdoc/>
public virtual void UpdateLayout(float dx, float dy)
{
if (updatingLayout)
return;
updatingLayout = true;
try
{
RectangleF remainingBounds = new RectangleF(0, 0, Width, Height);
remainingBounds.Width += dx;
remainingBounds.Height += dy;
foreach (ReportComponentBase c in Objects)
{
if ((c.Anchor & AnchorStyles.Right) != 0)
{
if ((c.Anchor & AnchorStyles.Left) != 0)
c.Width += dx;
else
c.Left += dx;
}
else if ((c.Anchor & AnchorStyles.Left) == 0)
{
c.Left += dx / 2;
}
if ((c.Anchor & AnchorStyles.Bottom) != 0)
{
if ((c.Anchor & AnchorStyles.Top) != 0)
c.Height += dy;
else
c.Top += dy;
}
else if ((c.Anchor & AnchorStyles.Top) == 0)
{
c.Top += dy / 2;
}
switch (c.Dock)
{
case DockStyle.Left:
c.Bounds = new RectangleF(remainingBounds.Left, remainingBounds.Top, c.Width, remainingBounds.Height);
remainingBounds.X += c.Width;
remainingBounds.Width -= c.Width;
break;

case DockStyle.Top:
c.Bounds = new RectangleF(remainingBounds.Left, remainingBounds.Top, remainingBounds.Width, c.Height);
remainingBounds.Y += c.Height;
remainingBounds.Height -= c.Height;
break;

case DockStyle.Right:
c.Bounds = new RectangleF(remainingBounds.Right - c.Width, remainingBounds.Top, c.Width, remainingBounds.Height);
remainingBounds.Width -= c.Width;
break;

case DockStyle.Bottom:
c.Bounds = new RectangleF(remainingBounds.Left, remainingBounds.Bottom - c.Height, remainingBounds.Width, c.Height);
remainingBounds.Height -= c.Height;
break;

case DockStyle.Fill:
c.Bounds = remainingBounds;
remainingBounds.Width = 0;
remainingBounds.Height = 0;
break;
}
}
}
finally
{
updatingLayout = false;
}
}
#endregion

#region Report engine
/// <inheritdoc/>
public override void SaveState()
{
base.SaveState();
SetRunning(true);
SetDesigning(false);
OnBeforePrint(EventArgs.Empty);

foreach (ReportComponentBase obj in Objects)
{
obj.SaveState();
obj.SetRunning(true);
obj.SetDesigning(false);
obj.OnBeforePrint(EventArgs.Empty);
}
}

/// <inheritdoc/>
public override void RestoreState()
{
OnAfterPrint(EventArgs.Empty);
base.RestoreState();
SetRunning(false);

foreach (ReportComponentBase obj in Objects)
{
obj.OnAfterPrint(EventArgs.Empty);
obj.RestoreState();
obj.SetRunning(false);
}
}

/// <inheritdoc/>
public override void GetData()
{
base.GetData();
foreach (ReportComponentBase obj in Objects)
{
obj.GetData();
obj.OnAfterData();

// break the component if it is of BreakableComponent an has non-empty BreakTo property
if (obj is BreakableComponent && (obj as BreakableComponent).BreakTo != null &&
(obj as BreakableComponent).BreakTo.GetType() == obj.GetType())
(obj as BreakableComponent).Break((obj as BreakableComponent).BreakTo);
}
OnAfterData();
}

/// <inheritdoc/>
public override float CalcHeight()
{
OnBeforeLayout(EventArgs.Empty);

// sort objects by Top
ReportComponentCollection sortedObjects = Objects.SortByTop();

// calc height of each object
float[] heights = new float[sortedObjects.Count];
for (int i = 0; i < sortedObjects.Count; i++)
{
ReportComponentBase obj = sortedObjects[i];
float height = obj.Height;
if (obj.Visible && (obj.CanGrow || obj.CanShrink))
{
float height1 = obj.CalcHeight();
if ((obj.CanGrow && height1 > height) || (obj.CanShrink && height1 < height))
height = height1;
}
heights[i] = height;
}

// calc shift amounts
float[] shifts = new float[sortedObjects.Count];
for (int i = 0; i < sortedObjects.Count; i++)
{
ReportComponentBase parent = sortedObjects[i];
float shift = heights[i] - parent.Height;
if (shift == 0)
continue;

for (int j = i + 1; j < sortedObjects.Count; j++)
{
ReportComponentBase child = sortedObjects[j];
if (child.ShiftMode == ShiftMode.Never)
continue;

if (child.Top >= parent.Bottom - 1e-4)
{
if (child.ShiftMode == ShiftMode.WhenOverlapped &&
(child.Left > parent.Right - 1e-4 || parent.Left > child.Right - 1e-4))
continue;

float parentShift = shifts[i];
float childShift = shifts[j];
if (shift > 0)
childShift = Math.Max(shift + parentShift, childShift);
else
childShift = Math.Min(shift + parentShift, childShift);
shifts[j] = childShift;
}
}
}

// update location and size of each component, calc max height
float maxHeight = 0;
for (int i = 0; i < sortedObjects.Count; i++)
{
ReportComponentBase obj = sortedObjects[i];
DockStyle saveDock = obj.Dock;
obj.Dock = DockStyle.None;
obj.Height = heights[i];
obj.Top += shifts[i];
if (obj.Visible && obj.Bottom > maxHeight)
maxHeight = obj.Bottom;
obj.Dock = saveDock;
}

if ((CanGrow && maxHeight > Height) || (CanShrink && maxHeight < Height))
Height = maxHeight;

// perform grow to bottom
foreach (ReportComponentBase obj in Objects)
{
if (obj.GrowToBottom)
obj.Height = Height - obj.Top;
}

OnAfterLayout(EventArgs.Empty);
return Height;
}

/// <summary>
/// This method fires the <b>BeforeLayout</b> event and the script code connected to the <b>BeforeLayoutEvent</b>.
/// </summary>
/// <param name="e">Event data.</param>
public void OnBeforeLayout(EventArgs e)
{
if (BeforeLayout != null)
BeforeLayout(this, e);
InvokeEvent(BeforeLayoutEvent, e);
}

/// <summary>
/// This method fires the <b>AfterLayout</b> event and the script code connected to the <b>AfterLayoutEvent</b>.
/// </summary>
/// <param name="e">Event data.</param>
public void OnAfterLayout(EventArgs e)
{
if (AfterLayout != null)
AfterLayout(this, e);
InvokeEvent(AfterLayoutEvent, e);
}
#endregion

#region Public methods
/// <inheritdoc/>
public override void Assign(Base source)
{
base.Assign(source);

ContainerObject src = source as ContainerObject;
BeforeLayoutEvent = src.BeforeLayoutEvent;
AfterLayoutEvent = src.AfterLayoutEvent;
}

/// <inheritdoc/>
public override void Serialize(FRWriter writer)
{
ContainerObject c = writer.DiffObject as ContainerObject;
base.Serialize(writer);

if (writer.SerializeTo == SerializeTo.Preview)
return;

if (BeforeLayoutEvent != c.BeforeLayoutEvent)
writer.WriteStr("BeforeLayoutEvent", BeforeLayoutEvent);
if (AfterLayoutEvent != c.AfterLayoutEvent)
writer.WriteStr("AfterLayoutEvent", AfterLayoutEvent);
}

/// <inheritdoc/>
public override void Draw(FRPaintEventArgs e)
{
DrawBackground(e);
DrawMarkers(e);
Border.Draw(e, new RectangleF(AbsLeft, AbsTop, Width, Height));
base.Draw(e);
}
#endregion

/// <summary>
/// Initializes a new instance of the <b>ContainerObject</b> class with default settings.
/// </summary>
public ContainerObject()
{
objects = new ReportComponentCollection(this);
beforeLayoutEvent = "";
afterLayoutEvent = "";
}
}
}
@@ -5,6 +5,7 @@
using System.Data;
using System.Data.Common;
using System.IO;
using System.Net;

namespace FastReport.Data
{
@@ -295,7 +296,39 @@ protected override DataSet CreateDataSet()
if (!String.IsNullOrEmpty(CsvFile) && !String.IsNullOrEmpty(Separator))
{
string allText = "";
using (StreamReader reader = new StreamReader(CsvFile, Encoding.GetEncoding(Codepage)))

WebRequest request;
WebResponse response = null;
try
{
Uri uri = new Uri(CsvFile);

if (uri.IsFile)
{
request = (FileWebRequest)WebRequest.Create(uri);
request.Timeout = 5000;
response = (FileWebResponse)request.GetResponse();
}
else if (uri.OriginalString.StartsWith("http"))
{
request = (HttpWebRequest)WebRequest.Create(uri);
request.Timeout = 5000;
response = (HttpWebResponse)request.GetResponse();
}
else if (uri.OriginalString.StartsWith("ftp"))
{
request = (FtpWebRequest)WebRequest.Create(uri);
request.Timeout = 5000;
response = (FtpWebResponse)request.GetResponse();
}
}
catch(Exception e)
{
throw e;
}
if (response == null) return dataset;

using (StreamReader reader = new StreamReader(response.GetResponseStream(), Encoding.GetEncoding(Codepage)))
{
allText = reader.ReadToEnd();
}
@@ -113,7 +113,10 @@ public string ConnectionString
[Editor("FastReport.TypeEditors.ExpressionEditor, FastReport", typeof(UITypeEditor))]
public string ConnectionStringExpression
{
get { return connectionStringExpression; }
get
{
return connectionStringExpression;
}
set { connectionStringExpression = value; }
}

@@ -495,7 +498,7 @@ public DbConnection GetConnection()
return null;
}



/// <summary>
/// Opens a specified connection object.
@@ -565,9 +568,9 @@ public void DisposeConnection(DbConnection connection)

if (ShouldNotDispose(connection))
return;
if (connection != null)
connection.Dispose();

if (connection != null)
connection.Dispose();
}

/// <summary>
@@ -2,8 +2,10 @@
using System;
using System.Data;
using System.Data.Common;
using System.Linq;
using System.Net;
using System.Text;
using System.Windows.Forms;

namespace FastReport.Data.JsonConnection
{
@@ -182,22 +184,39 @@ private void InitConnection(bool rebuildSchema)
JsonDataSourceConnectionStringBuilder builder = new JsonDataSourceConnectionStringBuilder(ConnectionString);
JsonBase obj = null;
string jsonText = builder.Json.Trim();
if(jsonText.Length >0)
if (jsonText.Length > 0)
{
if(!(jsonText[0] == '{' || jsonText[0] == '['))
if (!(jsonText[0] == '{' || jsonText[0] == '['))
{
using (WebClient client = new WebClient())
//using (WebClient client = new WebClient())
//{
// try
// {
// client.Encoding = Encoding.GetEncoding(builder.Encoding);
// }
// catch
// {
// client.Encoding = Encoding.UTF8;
// }
// jsonText = client.DownloadString(jsonText);
//}

HttpWebRequest req = (HttpWebRequest)WebRequest.Create(jsonText);

foreach (var header in builder.Headers)
{
try
{
client.Encoding = Encoding.GetEncoding(builder.Encoding);
}
catch
{
client.Encoding = Encoding.UTF8;
}
jsonText = client.DownloadString(jsonText);
req.Headers.Add(header.Key, header.Value);
}

using (var response = req.GetResponse() as HttpWebResponse)
{
var encoding = Encoding.GetEncoding(response.CharacterSet);

using (var responseStream = response.GetResponseStream())
using (var reader = new System.IO.StreamReader(responseStream, encoding))
jsonText = reader.ReadToEnd();
}

}
obj = JsonBase.FromString(jsonText) as JsonBase;
}
@@ -1,4 +1,9 @@
using System.Data.Common;
using System;
using System.Collections.Generic;
using System.Data.Common;
using System.Globalization;
using System.Text;
using System.Text.RegularExpressions;

namespace FastReport.Data.JsonConnection
{
@@ -21,7 +26,14 @@ public string Json
{
object result;
if (TryGetValue("Json", out result) && result != null)
{
if (Regex.IsMatch((string)result, @"^([A-Za-z0-9+\/]{4})*([A-Za-z0-9+\/]{3}=|[A-Za-z0-9+\/]{2}==)?$"))
{
var base64str = (Convert.FromBase64String(result.ToString()));
return System.Text.Encoding.UTF8.GetString(base64str);
}
return (string)result;
}
return "";
}
set
@@ -39,7 +51,14 @@ public string JsonSchema
{
object result;
if (TryGetValue("JsonSchema", out result) && result != null)
{
if (Regex.IsMatch((string)result, @"^([A-Za-z0-9+\/]{4})*([A-Za-z0-9+\/]{3}=|[A-Za-z0-9+\/]{2}==)?$"))
{
var base64str = (Convert.FromBase64String(result.ToString()));
return System.Text.Encoding.UTF8.GetString(base64str);
}
return (string)result;
}
return "";
}
set
@@ -66,7 +85,9 @@ public string Encoding
}
}


public Dictionary<string, string> Headers { get; set; }



#endregion Public Properties

@@ -78,6 +99,7 @@ public string Encoding
public JsonDataSourceConnectionStringBuilder()
{
ConnectionString = "";
Headers = new Dictionary<string, string>();
}

/// <summary>
@@ -89,8 +111,76 @@ public JsonDataSourceConnectionStringBuilder(string connectionString)
: base()
{
ConnectionString = connectionString;
Headers = new Dictionary<string, string>();
//while (ConnectionString.Contains("Header="))
//{
object result;
string header = string.Empty;
string[] splittedHeader;
int headerIteration = 0;
while (TryGetValue("Header" + headerIteration.ToString(CultureInfo.InvariantCulture.NumberFormat), out result) && result != null)
{
header = (string)result;

if (!string.IsNullOrWhiteSpace(header))
{
splittedHeader = header.Split(':');

string headerKey = splittedHeader[0], headerVal = splittedHeader[1];

if (Regex.IsMatch(headerKey, @"^([A-Za-z0-9+\/]{4})*([A-Za-z0-9+\/]{3}=|[A-Za-z0-9+\/]{2}==)?$"))
{
var base64str = Convert.FromBase64String(headerKey);
headerKey = System.Text.Encoding.UTF8.GetString(base64str);
}

if (Regex.IsMatch(headerVal, @"^([A-Za-z0-9+\/]{4})*([A-Za-z0-9+\/]{3}=|[A-Za-z0-9+\/]{2}==)?$"))
{
var base64str = Convert.FromBase64String(headerVal);
headerVal = System.Text.Encoding.UTF8.GetString(base64str);
}

Headers.Add(headerKey, headerVal);
//ConnectionString = ConnectionString.Replace(header, string.Empty);
}

headerIteration++;
}
//}
}

#endregion Public Constructors

// escape / ; " :
public override string ToString()
{
//TODO: do via stringbuilder
//string connString = $"Json={Json};JsonSchema={JsonSchema};Encoding={Encoding}";
StringBuilder builder = new StringBuilder();
builder.Append("Json=").Append(Convert.ToBase64String(System.Text.Encoding.UTF8.GetBytes(Json)))
.Append(";JsonSchema=").Append(Convert.ToBase64String(System.Text.Encoding.UTF8.GetBytes(JsonSchema)))
.Append(";Encoding=").Append(Encoding);
//string connString = "Json=" + Convert.ToBase64String(System.Text.Encoding.UTF8.GetBytes(Json))
// + ";JsonSchema=" + Convert.ToBase64String(System.Text.Encoding.UTF8.GetBytes(JsonSchema)) + ";Encoding=" + Encoding;
int headerIteration = 0;
foreach (var header in Headers)
{
var headerKey = header.Key;
var headerVal = header.Value;
if (headerKey.Contains(";") || headerKey.Contains(":") || headerKey.Contains("\"") || headerKey.Contains("\'"))
{
headerKey = Convert.ToBase64String(System.Text.Encoding.UTF8.GetBytes(headerKey));
}

if (headerVal.Contains(";") || headerVal.Contains(":") || headerVal.Contains("\"") || headerVal.Contains("\'"))
{
headerVal = Convert.ToBase64String(System.Text.Encoding.UTF8.GetBytes(headerVal));
}

builder.Append(";Header").Append(headerIteration.ToString(CultureInfo.InvariantCulture.NumberFormat)).Append("=").Append(headerKey).Append(":").Append(headerVal);
//connString += ";Header" + headerIteration + "=" + headerKey + ":" + headerVal;
}
return builder.ToString();
}
}
}
@@ -87,7 +87,7 @@ private void AddToOutputBand(BandBase band, bool getData)
private void ShowBandToPreparedPages(BandBase band, bool getData)
{
// handle "StartNewPage". Skip if it's the first row, avoid empty first page.
if (band.StartNewPage && band.FlagUseStartNewPage && (band.RowNo != 1 || band.FirstRowStartsNewPage) &&
if ((band.StartNewPage && !(band.Parent is PageHeaderBand)) && band.FlagUseStartNewPage && (band.RowNo != 1 || band.FirstRowStartsNewPage) &&
!band.Repeated)
{
EndColumn();
@@ -208,7 +208,15 @@ internal bool CanPrint(ReportComponentBase obj)
// Apply visible expression if needed.
if (!String.IsNullOrEmpty(obj.VisibleExpression))
{
object expression = Report.Calc(obj.VisibleExpression);
object expression = null;
if (obj.VisibleExpression.StartsWith("[") && obj.VisibleExpression.EndsWith("]"))
{
expression = Report.Calc(obj.VisibleExpression.Substring(1, obj.VisibleExpression.Length - 2));
}
else
{
expression = Report.Calc(obj.VisibleExpression);
}
if (expression is bool)
{
obj.Visible = (bool)expression;
@@ -218,7 +226,15 @@ internal bool CanPrint(ReportComponentBase obj)
// Apply exportable expression if needed.
if (!String.IsNullOrEmpty(obj.ExportableExpression))
{
object expression = Report.Calc(obj.ExportableExpression);
object expression = null;
if (obj.ExportableExpression.StartsWith("[") && obj.ExportableExpression.EndsWith("]"))
{
expression = Report.Calc(obj.ExportableExpression.Substring(1, obj.ExportableExpression.Length - 2));
}
else
{
expression = Report.Calc(obj.ExportableExpression);
}
if (expression is bool)
{
obj.Exportable = (bool)expression;
@@ -228,7 +244,15 @@ internal bool CanPrint(ReportComponentBase obj)
// Apply printable expression if needed.
if (!String.IsNullOrEmpty(obj.PrintableExpression))
{
object expression = Report.Calc(obj.PrintableExpression);
object expression = null;
if (obj.PrintableExpression.StartsWith("[") && obj.PrintableExpression.EndsWith("]"))
{
expression = Report.Calc(obj.PrintableExpression.Substring(1, obj.PrintableExpression.Length - 2));
}
else
{
expression = Report.Calc(obj.PrintableExpression);
}
if (expression is bool)
{
obj.Printable = (bool)expression;
@@ -75,7 +75,12 @@ private void BreakBand(BandBase band)

try
{
// (case: object with Anchor = bottom on a breakable band)
// disable re-layout
cloneBand.SetUpdatingLayout(true);
cloneBand.Height = FreeSpace;
cloneBand.SetUpdatingLayout(false);

if (cloneBand.Break(breakTo))
{
AddToPreparedPages(cloneBand);
@@ -384,7 +384,7 @@ private float GetBandHeightWithChildren(BandBase band)
while (band != null)
{
if (CanPrint(band))
result += band.Height;
result += (band.CanGrow || band.CanShrink) ? band.CalcHeight() : band.Height;
band = band.Child;
if (band != null && ((band as ChildBand).FillUnusedSpace || (band as ChildBand).CompleteToNRows != 0))
break;
@@ -30,6 +30,7 @@ public partial class ExportBase : Base
private bool shiftNonExportable;
private string saveInitialDirectory;
private List<Stream> generatedStreams;
protected bool webPreview;

#region Properties

@@ -479,7 +480,8 @@ internal void ExportPageNew(int pageNo)
{
(obj as BandBase).Top -= topShift;
}
if ((obj as BandBase).Exportable)
if ((obj as BandBase).Exportable
|| webPreview)
ExportBand(obj);
else if (obj != null)
{
@@ -512,6 +514,7 @@ public void Export(Report report, string fileName)
using (FileStream stream = new FileStream(fileName, FileMode.Create))
{
Export(report, stream);
stream.Close();
}
}

@@ -269,6 +269,23 @@ internal static FastString HtmlString(string text, TextRenderType textRenderType
Result.Append("<br />");
i++;
}
else if (text[i] == '\t' && crlf == CRLF.odt)
Result.Append("<text:tab/>");
else if (text[i] == ' ' && crlf == CRLF.odt)
{
int spaces = 1;
while (i < text.Length - 1)
{
if (text[i + 1] == ' ')
{
i++;
spaces++;
}
else
break;
}
Result.Append("<text:s text:c=\"" + spaces + "\"/>");
}
else if (text[i] == '\\')
Result.Append("&#92;");
else if (text[i] == '~' && !excel2007)
@@ -983,6 +983,16 @@ public HTMLExport()
res = new MyRes("Export,Html");
embeddedImages = new Dictionary<string, string>();
}

/// <summary>
/// Initializes a new instance of the <see cref="HTMLExport"/> class for WebPreview mode.
/// </summary>
public HTMLExport(bool webPreview) : this()
{
this.webPreview = webPreview;
if (webPreview)
exportMode = ExportType.WebPreview;
}
}

/// <summary>
@@ -610,7 +610,7 @@ private void LayerShape(FastString Page, ShapeObject obj, FastString text)

addstyle.Append(GetStyle());

addstyle.Append("background: url('" + GetLayerPicture(obj, out Width, out Height) + "');");
addstyle.Append("background: url('" + GetLayerPicture(obj, out Width, out Height) + "');no-repeat !important;-webkit-print-color-adjust:exact;");

float x = obj.Width > 0 ? obj.AbsLeft : (obj.AbsLeft + obj.Width);
float y = obj.Height > 0 ? hPos + obj.AbsTop : (hPos + obj.AbsTop + obj.Height);
@@ -56,7 +56,7 @@ public partial class PictureObject : PictureObjectBase
private bool shouldDisposeImage;
private Bitmap grayscaleBitmap;
private int grayscaleHash;

private ImageFormat imageFormat;
#endregion

#region Properties
@@ -84,10 +84,35 @@ public virtual Image Image
UpdateAutoSize();
UpdateTransparentImage();
ResetImageIndex();
imageFormat = CheckImageFormat();
ShouldDisposeImage = false;
}
}

/// <summary>
/// Gets or sets the expansion of image.
/// </summary>
[Category("Data")]
public virtual ImageFormat ImageFormat
{
get { return imageFormat; }
set
{
if (image == null)
return;
bool wasC = false;
using (MemoryStream stream = new MemoryStream())
{
wasC = ImageHelper.SaveAndConvert(Image, stream, value);
imageData = stream.ToArray();
}
if (!wasC)
return;
ForceLoadImage();
imageFormat = CheckImageFormat();
}
}

/// <summary>
/// Gets or sets a value indicating that the image should be displayed in grayscale mode.
/// </summary>
@@ -229,7 +254,47 @@ protected override float ImageHeight
#endregion

#region Private Methods

private ImageFormat CheckImageFormat()
{
if (Image == null || Image.RawFormat == null)
return null;
ImageFormat format = null;
if (ImageFormat.Jpeg.Equals(image.RawFormat))
{
format = ImageFormat.Jpeg;
}
else if (ImageFormat.Gif.Equals(image.RawFormat))
{
format = ImageFormat.Gif;
}
else if (ImageFormat.Png.Equals(image.RawFormat))
{
format = ImageFormat.Png;
}
else if (ImageFormat.Emf.Equals(image.RawFormat))
{
format = ImageFormat.Emf;
}
else if (ImageFormat.Icon.Equals(image.RawFormat))
{
format = ImageFormat.Icon;
}
else if (ImageFormat.Tiff.Equals(image.RawFormat))
{
format = ImageFormat.Tiff;
}
else if (ImageFormat.Bmp.Equals(image.RawFormat) || ImageFormat.MemoryBmp.Equals(image.RawFormat))
{
format = ImageFormat.Bmp;
}
else if (ImageFormat.Wmf.Equals(image.RawFormat))
{
format = ImageFormat.Wmf;
}
if (format != null)
return format;
return ImageFormat.Bmp;
}

private void UpdateTransparentImage()
{
@@ -277,6 +342,7 @@ public override void Assign(Base source)
if (src.Image == null && src.imageData != null)
imageData = src.imageData;
ShouldDisposeImage = true;
ImageFormat = src.ImageFormat;
}
}

@@ -399,6 +465,8 @@ public override void Serialize(FRWriter writer)
writer.WriteFloat("Transparency", Transparency);
if (Tile != c.Tile)
writer.WriteBool("Tile", Tile);
if (ImageFormat != c.ImageFormat)
writer.WriteValue("ImageFormat", ImageFormat);
// store image data
if (writer.SerializeTo != SerializeTo.SourcePages)
{
@@ -417,7 +485,7 @@ public override void Serialize(FRWriter writer)
{
using (MemoryStream stream = new MemoryStream())
{
ImageHelper.Save(Image, stream, ImageFormat.Png);
ImageHelper.Save(Image, stream, imageFormat);
bytes = stream.ToArray();
}
}
@@ -589,5 +657,6 @@ public PictureObject()
SetFlags(Flags.HasSmartTag, true);
ResetImageIndex();
}

}
}
@@ -84,6 +84,7 @@ public abstract partial class PictureObjectBase : ReportComponentBase
private string dataColumn;
private bool grayscale;
private string imageLocation;
private string imageSourceExpression;
private float maxHeight;
private float maxWidth;
private Padding padding;
@@ -165,6 +166,42 @@ public string ImageLocation
}
}

/// <summary>
/// Gets or sets the expression that determines the source for the image to display in the PictureObject.
/// </summary>
/// <remarks>
/// The result of the expression should be data column name or path to the image file.
/// The data column name will be saved to the <see cref="DataColumn"/> property.
/// The path will be savetd to the <see cref="ImageLocation"/> property.
/// </remarks>
[Category("Data")]
[Editor("FastReport.TypeEditors.ExpressionEditor, FastReport", typeof(UITypeEditor))]
public string ImageSourceExpression
{
get { return imageSourceExpression; }
set
{
imageSourceExpression = value;

if (!String.IsNullOrEmpty(ImageSourceExpression) && Report != null)
{
string expression = ImageSourceExpression;
if (ImageSourceExpression.StartsWith("[") && ImageSourceExpression.EndsWith("]"))
{
expression = ImageSourceExpression.Substring(1, ImageSourceExpression.Length - 2);
}
if (Data.DataHelper.IsValidColumn(Report.Dictionary, expression))
{
DataColumn = expression;
}
if (Data.DataHelper.IsValidParameter(Report.Dictionary, expression))
{
ImageLocation = Report.GetParameterValue(expression).ToString();
}
}
}
}

/// <summary>
/// Gets a value indicating that the image stored in the databases column
/// </summary>
@@ -324,6 +361,7 @@ public PictureObjectBase()
padding = new Padding();
imageLocation = "";
dataColumn = "";
imageSourceExpression = "";
}

#endregion Public Constructors
@@ -340,6 +378,7 @@ public override void Assign(Base source)
{
ImageLocation = src.ImageLocation;
DataColumn = src.DataColumn;
ImageSourceExpression = src.ImageSourceExpression;
Padding = src.Padding;
SizeMode = src.SizeMode;
MaxWidth = src.MaxWidth;
@@ -718,6 +757,9 @@ public override void Serialize(FRWriter writer)
if (DataColumn != c.DataColumn)
writer.WriteStr("DataColumn", DataColumn);

if (ImageSourceExpression != c.ImageSourceExpression)
writer.WriteStr("ImageSourceExpression", ImageSourceExpression);

if (Padding != c.Padding)
writer.WriteValue("Padding", Padding);
if (SizeMode != c.SizeMode)
@@ -917,6 +959,19 @@ public override string[] GetExpressions()
expressions.AddRange(base.GetExpressions());
if (!String.IsNullOrEmpty(DataColumn))
expressions.Add(DataColumn);

if (!String.IsNullOrEmpty(ImageSourceExpression))
{
if (ImageSourceExpression.StartsWith("[") && ImageSourceExpression.EndsWith("]"))
{
expressions.Add(ImageSourceExpression.Substring(1, ImageSourceExpression.Length - 2));
}
else
{
expressions.Add(ImageSourceExpression);
}
}

return expressions.ToArray();
}
}
@@ -214,6 +214,7 @@ public partial class Report : Base, IParent, ISupportInitialize
private ReportInfo reportInfo;
private string baseReport;
private Report baseReportObject;
private string baseReportAbsolutePath;
private string fileName;
private string scriptText;
private Language scriptLanguage;
@@ -373,6 +374,19 @@ public string BaseReport
set { SetBaseReport(value); }
}

/// <summary>
/// Gets or sets the absolute path to the parent report.
/// </summary>
/// <remarks>
/// This property contains the absolute path to the parent report.
/// </remarks>
[Browsable(true), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
public string BaseReportAbsolutePath
{
get { return baseReportAbsolutePath; }
set { baseReportAbsolutePath = value; }
}

/// <summary>
/// Gets or sets the name of a file the report was loaded from.
/// </summary>
@@ -606,7 +620,14 @@ public StyleCollection Styles
public string[] ReferencedAssemblies
{
get { return referencedAssemblies; }
set { referencedAssemblies = value; }
set {
// fix for old reports with "System.Windows.Forms.DataVisualization" in referenced assemblies
for (int i = 0; i < value.Length;i++)
{
value[i] = value[i].Replace("System.Windows.Forms.DataVisualization", "FastReport.DataVisualization");
}
referencedAssemblies = value;
}
}

/// <summary>
@@ -816,8 +837,29 @@ private string[] DefaultAssemblies
{
get
{
return new string[] { "System.dll", "System.Drawing.dll", "System.Windows.Forms.dll",
"System.Data.dll", "System.Xml.dll" };
return new string[] {
"System.dll",

"System.Drawing.dll",

"System.Data.dll",

"System.Xml.dll",

#if NETSTANDARD
"FastReport.Compat.dll",
#else
"System.Windows.Forms.dll",
#endif

#if NETSTANDARD || NETCOREAPP
"System.Drawing.Primitives",
#endif

#if MSCHART
"FastReport.DataVisualization.dll"
#endif
};
}
}

@@ -879,9 +921,9 @@ internal ObjectCollection AllNamedObjects
}
}

#endregion Properties
#endregion Properties

#region Private Methods
#region Private Methods

private bool ShouldSerializeReferencedAssemblies()
{
@@ -945,7 +987,13 @@ private void SetBaseReport(string value)
{
// convert the relative path to absolute path (based on the main report path).
if (!Path.IsPathRooted(value))
{
value = Path.GetFullPath(Path.GetDirectoryName(FileName) + Path.DirectorySeparatorChar + value);
}
if (!File.Exists(value) && File.Exists(BaseReportAbsolutePath))
{
value = BaseReportAbsolutePath;
}
Load(value);
}

@@ -999,6 +1047,7 @@ private void ClearReportProperties()
}
ScriptText = codeHelper.EmptyScript();
BaseReport = "";
BaseReportAbsolutePath = "";
DoublePass = false;
ConvertNulls = true;
Compressed = false;
@@ -1016,9 +1065,9 @@ private void ClearReportProperties()
needCompile = true;
}

#endregion Private Methods
#endregion Private Methods

#region Protected Methods
#region Protected Methods

/// <inheritdoc/>
protected override void Dispose(bool disposing)
@@ -1054,9 +1103,9 @@ protected override void DeserializeSubItems(FRReader reader)
base.DeserializeSubItems(reader);
}

#endregion Protected Methods
#endregion Protected Methods

#region IParent
#region IParent

/// <inheritdoc/>
public bool CanContain(Base child)
@@ -1123,9 +1172,9 @@ public virtual void UpdateLayout(float dx, float dy)
// do nothing
}

#endregion IParent
#endregion IParent

#region ISupportInitialize Members
#region ISupportInitialize Members

/// <inheritdoc/>
public void BeginInit()
@@ -1140,9 +1189,9 @@ public void EndInit()
Dictionary.RegisterData(initializeData, initializeDataName, false);
}

#endregion ISupportInitialize Members
#endregion ISupportInitialize Members

#region Script related
#region Script related

private void FillDataSourceCache()
{
@@ -1579,9 +1628,9 @@ public DataSourceBase GetDataSource(string alias)
return Dictionary.FindByAlias(alias) as DataSourceBase;
}

#endregion Script related
#endregion Script related

#region Public Methods
#region Public Methods

/// <inheritdoc/>
public override void Assign(Base source)
@@ -1687,6 +1736,34 @@ public void OnExportParameters(ExportParametersEventArgs e)
}
}

/// <summary>
/// Add the name of the assembly (in addition to the default) that will be used to compile the report script
/// </summary>
/// <param name="assembly_name">Assembly name</param>
/// <remarks>
/// For example: <code>report.AddReferencedAssembly("Newtonsoft.Json.dll")</code>
/// </remarks>
public void AddReferencedAssembly(string assembly_name)
{
string[] assemblies = ReferencedAssemblies;
Array.Resize(ref assemblies, assemblies.Length + 1);
assemblies[assemblies.Length - 1] = assembly_name;
}

/// <summary>
/// Add the names of the assembly (in addition to the default) that will be used to compile the report script
/// </summary>
/// <param name="assembly_names">Assembly's names</param>
public void AddReferencedAssembly(IList<string> assembly_names)
{
string[] assemblies = ReferencedAssemblies;
int oldLength = assemblies.Length;
Array.Resize(ref assemblies, oldLength + assembly_names.Count);
for (int i = 0; i < assembly_names.Count; i++)
{
assemblies[oldLength + i] = assembly_names[i];
}
}

/// <inheritdoc/>
public override void Serialize(FRWriter writer)
@@ -1699,6 +1776,9 @@ public override void Serialize(FRWriter writer)
// (based on the main report path). Do not convert when saving to the clipboard.
string value = writer.SerializeTo != SerializeTo.Undo ? GetRelativePathToBaseReport() : BaseReport;
writer.WriteStr("BaseReport", value);
// Fix bug with moving child report to another folder without parent report.
if (writer.SerializeTo == SerializeTo.Report)
writer.WriteStr("BaseReportAbsolutePath", BaseReport);
}
// always serialize ScriptLanguage because its default value depends on Config.ReportSettings.DefaultLanguage
writer.WriteValue("ScriptLanguage", ScriptLanguage);
@@ -1745,6 +1825,11 @@ public override void Serialize(FRWriter writer)
/// <inheritdoc/>
public override void Deserialize(FRReader reader)
{
if (reader.HasProperty("BaseReportAbsolutePath"))
{
BaseReportAbsolutePath = reader.ReadStr("BaseReportAbsolutePath");
}

base.Deserialize(reader);

// call OnAfterLoad method of each report object
@@ -2430,7 +2515,7 @@ public void LoadPrepared(Stream stream)
PreparedPages.Load(stream);
}

#endregion Public Methods
#endregion Public Methods

/// <summary>
/// Initializes a new instance of the <see cref="Report"/> class with default settings.
@@ -974,8 +974,19 @@ public override string[] GetExpressions()
expressions.Add(Hyperlink.Expression);
if (!String.IsNullOrEmpty(Bookmark))
expressions.Add(Bookmark);

if (!String.IsNullOrEmpty(ExportableExpression))
expressions.Add(ExportableExpression);
{
if (ExportableExpression.StartsWith("[") && ExportableExpression.EndsWith("]"))
{
expressions.Add(ExportableExpression.Substring(1, ExportableExpression.Length - 2));
}
else
{
expressions.Add(ExportableExpression);
}
}

return expressions.ToArray();
}

@@ -53,6 +53,7 @@ public partial class ReportPage : PageBase, IParent
#endregion // Constants

#region Fields
private string exportAlias;
private float paperWidth;
private float paperHeight;
private int rawPaperSize;
@@ -122,6 +123,16 @@ public float PaperWidth
set { paperWidth = value; }
}

/// <summary>
/// Gets or sets the page name on export
/// </summary>
[Category("Paper")]
public string ExportAlias
{
get { return exportAlias; }
set { exportAlias = value; }
}

/// <summary>
/// Gets or sets a height of the paper, in millimeters.
/// </summary>
@@ -835,6 +846,7 @@ public override void Assign(Base source)
base.Assign(source);

ReportPage src = source as ReportPage;
ExportAlias = src.ExportAlias;
Landscape = src.Landscape;
PaperWidth = src.PaperWidth;
PaperHeight = src.PaperHeight;
@@ -872,7 +884,8 @@ public override void Serialize(FRWriter writer)
{
ReportPage c = writer.DiffObject as ReportPage;
base.Serialize(writer);

if (ExportAlias != c.ExportAlias)
writer.WriteStr("ExportAlias", ExportAlias);
if (Landscape != c.Landscape)
writer.WriteBool("Landscape", Landscape);
if (FloatDiff(PaperWidth, c.PaperWidth))
@@ -1,4 +1,4 @@
using System;
using System;
using System.Drawing;
using System.Drawing.Text;
using System.Globalization;
@@ -39,6 +39,8 @@ public static partial class Config
private static bool preparedCompressed = true;
private static bool disableHotkeys = false;
private static bool disableBacklight = false;
private static bool enableScriptSecurity = false;
private static ScriptSecurityProperties scriptSecurityProps = null;

#endregion Private Fields

@@ -187,6 +189,37 @@ public static PrivateFontCollection PrivateFontCollection
{
get { return FastReport.TypeConverters.FontConverter.PrivateFontCollection; }
}

/// <summary>
/// Enable report script validation. For WebMode only
/// </summary>
public static bool EnableScriptSecurity
{
get
{
return enableScriptSecurity;
}
set
{
if (OnEnableScriptSecurityChanged != null)
OnEnableScriptSecurityChanged.Invoke(null, null);
enableScriptSecurity = value;
}
}

/// <summary>
/// Throws when property EnableScriptSecurity has been changed
/// </summary>
public static event EventHandler OnEnableScriptSecurityChanged;

/// <summary>
/// Properties of report script validation
/// </summary>
public static ScriptSecurityProperties ScriptSecurityProps
{
get { return scriptSecurityProps; }
}

#endregion Public Properties

#region Internal Methods
@@ -220,6 +253,8 @@ internal static void Init()
{
#if !COMMUNITY
RestoreExportOptions();
enableScriptSecurity = true; // don't throw event
scriptSecurityProps = new ScriptSecurityProperties();
#endif
}
LoadPlugins();
@@ -438,6 +473,69 @@ private static void RestoreRightToLeft()
}
}

/// <summary>
/// Properties of ScriptSecurity
/// </summary>
public class ScriptSecurityProperties
{
private readonly string[] defaultStopList = new[]
{
"GetType",
"typeof",
"TypeOf", // VB
"DllImport",
"LoadLibrary",
"GetProcAddress",
};

private string[] stopList;

/// <summary>
/// Add stubs for the most dangerous classes (in System.IO, System.Reflection etc)
/// </summary>
public bool AddStubClasses { get; set; } = true;

/// <summary>
/// List of keywords that shouldn't be declared in the report script
/// </summary>
public string[] StopList
{
get { return (string[])stopList.Clone(); }
set
{
if(value != null)
{
OnStopListChanged?.Invoke(this, null);
stopList = value;
}
}
}

/// <summary>
/// Throws when <see cref="StopList"/> has changed
/// </summary>
public event EventHandler OnStopListChanged;

internal ScriptSecurityProperties()
{
SetDefaultStopList();
}

internal ScriptSecurityProperties(string[] stopList)
{
this.stopList = stopList;
}

/// <summary>
/// Sets default value for <see cref="StopList"/>
/// </summary>
public void SetDefaultStopList()
{
StopList = defaultStopList;
}

}

private static void SaveUIOptions()
{
XmlItem xi = Root.FindItem("UIOptions");
@@ -27,7 +27,7 @@ public static Bitmap CloneBitmap(Image source)

public static void Save(Image image, Stream stream)
{
Save(image, stream, ImageFormat.Png);
Save(image, stream, image.GetImageFormat());
}

public static void Save(Image image, string fileName, ImageFormat format)
@@ -43,7 +43,12 @@ public static void Save(Image image, Stream stream, ImageFormat format)
if (image == null)
return;
if (image is Bitmap)
image.Save(stream, format);
{
if (format == ImageFormat.Icon)
SaveAsIcon(image, stream, true);
else
image.Save(stream, format);
}
else if (image is Metafile)
{
Metafile emf = null;
@@ -61,6 +66,65 @@ public static void Save(Image image, Stream stream, ImageFormat format)
}
}

public static bool SaveAndConvert(Image image, Stream stream, ImageFormat format)
{
if (image == null)
return false;
if(format == ImageFormat.Jpeg || format == ImageFormat.Gif
|| format == ImageFormat.Tiff || format == ImageFormat.Bmp
|| format == ImageFormat.Png
|| format == ImageFormat.MemoryBmp)
{
if(image is Bitmap)
{
if (format == ImageFormat.MemoryBmp)
throw new Exception(Res.Get("Export,Image,ImageParceFormatException"));
image.Save(stream, format);
return true;
}
//from mf to bitmap
using (Metafile metafile = image as Metafile)
using (Bitmap bitmap = new Bitmap(image.Width, image.Height))
{
bitmap.SetResolution(96F, 96F);
using (Graphics g = Graphics.FromImage(bitmap))
{
g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.AntiAlias;
g.DrawImage(metafile, 0, 0, (float)image.Width, (float)image.Height);
g.Dispose();
}
bitmap.Save(stream, format);
}
return true;

}
else if(format == ImageFormat.Icon)
{
return SaveAsIcon(image, stream, true);
}
else if(format == ImageFormat.Wmf || format == ImageFormat.Emf)
{
if (image is Metafile)
{
Metafile emf = null;
using (Bitmap bmp = new Bitmap(1, 1))
using (Graphics g = Graphics.FromImage(bmp))
{
IntPtr hdc = g.GetHdc();
emf = new Metafile(stream, hdc);
g.ReleaseHdc(hdc);
}
using (Graphics g = Graphics.FromImage(emf))
{
g.DrawImage(image, 0, 0);
}
return true;
}
}
//throw new Exception(Res.Get("Export,Image,ImageParceFormatException")); // we cant convert image to exif or from bitmap to mf
return false;
}

public static byte[] Load(string fileName)
{
if (!String.IsNullOrEmpty(fileName))
@@ -169,5 +233,131 @@ public static Bitmap GetGrayscaleBitmap(Image source)

return grayscaleBitmap;
}

/// <summary>
/// Converts a PNG image to a icon (ico)
/// </summary>
/// <param name="image">The input image</param>
/// <param name="output">The output stream</param>
/// <param name="preserveAspectRatio">Preserve the aspect ratio</param>
/// <returns>Wether or not the icon was succesfully generated</returns>
public static bool SaveAsIcon(Image image, Stream output, bool preserveAspectRatio = false)
{
int size = 256;
float width = size, height = size;
if (preserveAspectRatio)
{
if (image.Width > image.Height)
height = ((float)image.Height / image.Width) * size;
else
width = ((float)image.Width / image.Height) * size;
}

var newBitmap = new Bitmap(image, new Size((int)width, (int)height));
if (newBitmap == null)
return false;

// save the resized png into a memory stream for future use
using (MemoryStream memoryStream = new MemoryStream())
{
newBitmap.Save(memoryStream, ImageFormat.Png);

var iconWriter = new BinaryWriter(output);
if (output == null || iconWriter == null)
return false;

// 0-1 reserved, 0
iconWriter.Write((byte)0);
iconWriter.Write((byte)0);

// 2-3 image type, 1 = icon, 2 = cursor
iconWriter.Write((short)1);

// 4-5 number of images
iconWriter.Write((short)1);

// image entry 1
// 0 image width
iconWriter.Write((byte)width);
// 1 image height
iconWriter.Write((byte)height);

// 2 number of colors
iconWriter.Write((byte)0);

// 3 reserved
iconWriter.Write((byte)0);

// 4-5 color planes
iconWriter.Write((short)0);

// 6-7 bits per pixel
iconWriter.Write((short)32);

// 8-11 size of image data
iconWriter.Write((int)memoryStream.Length);

// 12-15 offset of image data
iconWriter.Write((int)(6 + 16));

// write image data
// png data must contain the whole png data file
iconWriter.Write(memoryStream.ToArray());

iconWriter.Flush();
}

return true;
}


}

public static class ImageExtension
{
/// <summary>
/// Returns an Image format.
/// </summary>
public static ImageFormat GetImageFormat(this Image bitmap)
{
if (bitmap == null || bitmap.RawFormat == null)
return null;
ImageFormat format = null;
if (ImageFormat.Jpeg.Equals(bitmap.RawFormat))
{
format = ImageFormat.Jpeg;
}
else if (ImageFormat.Gif.Equals(bitmap.RawFormat))
{
format = ImageFormat.Gif;
}
else if (ImageFormat.Png.Equals(bitmap.RawFormat))
{
format = ImageFormat.Png;
}
else if (ImageFormat.Emf.Equals(bitmap.RawFormat))
{
format = ImageFormat.Emf;
}
else if (ImageFormat.Icon.Equals(bitmap.RawFormat))
{
format = ImageFormat.Icon;
}
else if (ImageFormat.Tiff.Equals(bitmap.RawFormat))
{
format = ImageFormat.Tiff;
}
else if (ImageFormat.Bmp.Equals(bitmap.RawFormat) || ImageFormat.MemoryBmp.Equals(bitmap.RawFormat)) // MemoryBmp format raises a GDI exception
{
format = ImageFormat.Bmp;
}
else if (ImageFormat.Wmf.Equals(bitmap.RawFormat))
{
format = ImageFormat.Wmf;
}
if (format != null)
return format;
return ImageFormat.Bmp;
}
}
}
@@ -0,0 +1,27 @@

namespace FastReport.Web
{
internal static class Constants
{

internal const string DIALOG = "_dialog";

internal const string REALOAD = "_reload";

internal const string SILENT_RELOAD = "_silentReload";

}

#if DIALOGS
public partial class Dialog
{
internal const string ONCLICK = "onclick";

internal const string ONCHANGE = "onchange";


public const string DEFAULT_DATE_TIME_PICKER_FORMAT = "yyyy-MM-dd";

}
#endif
}
@@ -0,0 +1,47 @@
using FastReport.Dialog;
using System.Windows.Forms;
using static FastReport.Web.Constants;

namespace FastReport.Web
{
public partial class Dialog
{

private void ButtonClick(ButtonControl button)
{
if (button.DialogResult == DialogResult.OK)
{
FormClose(button, CloseReason.None);
CurrentForm++;
}
else if (button.DialogResult == DialogResult.Cancel)
{
FormClose(button, CloseReason.UserClosing);
WebReport.Canceled = true;
}
button.OnClick(null);
}

private void FormClose(ButtonControl button, CloseReason reason)
{
DialogPage dialog = button.Report.Pages[CurrentForm] as DialogPage;
dialog.Form.DialogResult = button.DialogResult;
FormClosingEventArgs closingArgs = new FormClosingEventArgs(reason, false);
dialog.OnFormClosing(closingArgs);
FormClosedEventArgs closedArgs = new FormClosedEventArgs(reason);
dialog.OnFormClosed(closedArgs);
dialog.ActiveInWeb = false;
}

private string GetButtonHtml(ButtonControl control)
{
return $"<input style=\"{GetButtonStyle(control)}\" type=\"button\" name=\"{control.Name}\" value=\"{control.Text}\" onclick=\"{GetEvent(ONCLICK, control, REALOAD)}\" title=\"{control.Text}\"/>";
}

private string GetButtonStyle(ButtonControl control)
{
return $"{GetControlPosition(control)} {GetControlFont(control.Font)} {GetControlAlign(control)} padding:0;margin:0;";
}

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

namespace FastReport.Web
{
public partial class Dialog
{
private void CheckBoxClick(CheckBoxControl cb, string data)
{
cb.Checked = data == "true";
cb.FilterData();
cb.OnClick(null);
}

private string GetCheckBoxHtml(CheckBoxControl control)
{
string id = GetControlID(control);
return string.Format("<span style=\"{0}\"><input style=\"vertical-align:middle;padding:0;margin:0 5px 0 0;\" type=\"checkbox\" name=\"{1}\" value=\"{2}\" onclick=\"{3}\" id=\"{4}\" {5}/><label style=\"{8}\" for=\"{6}\">{7}</label></span>",
// style
GetCheckBoxStyle(control),
// name
control.Name,
// value
control.Text,
// onclick
GetEvent(ONCLICK, control, DIALOG, $"document.getElementById('{id}').checked"),
// title
id,
control.Checked ? "checked" : "",
id,
control.Text,
GetControlFont(control.Font)
);
}

private string GetCheckBoxStyle(CheckBoxControl control)
{
return $"{GetControlPosition(control)} {GetControlFont(control.Font)}";
}
}
}
@@ -0,0 +1,73 @@
using FastReport.Dialog;
using System;
using System.Text;
using static FastReport.Web.Constants;

namespace FastReport.Web
{
public partial class Dialog
{
private void CheckedListBoxChange(CheckedListBoxControl cb, string index)
{
int i = index.IndexOf("_");
if (i != -1)
{
string item = index.Substring(0, i);
string state = index.Substring(i + 1);
int checkedIndex;
if (Int32.TryParse(item, out checkedIndex))
{
cb.CheckedListBox.SetItemChecked(checkedIndex, state == "true");
ControlFilterRefresh(cb);
cb.OnSelectedIndexChanged(null);
}
}
}

private string GetCheckedListBoxHtml(CheckedListBoxControl control)
{
if (control.Items.Count == 0)
{
control.FillData();
ControlFilterRefresh(control);
}
string id = GetControlID(control);
string html = string.Format("<span style=\"{0}\" name=\"{1}\" size=\"{2}\" id=\"{3}\">{4}</span>",
// style
GetCheckedListBoxStyle(control),
// name
control.Name,
// size
control.Items.Count.ToString(),
// title
id,
GetCheckedListBoxItems(control)
);
control.FilterData();
return html;
}

private string GetCheckedListBoxItems(CheckedListBoxControl control)
{
StringBuilder sb = new StringBuilder();
for (int i = 0; i < control.Items.Count; i++)
{
string id = GetControlID(control) + i.ToString();
sb.Append(string.Format("<input {0} type=\"checkbox\" onchange=\"{1}\" id=\"{2}\" /> {3}<br />",
control.CheckedIndices.Contains(i) ? "checked" : "",
// onchange
GetEvent(ONCHANGE, control, DIALOG, $"{i} + '_' + document.getElementById('{id}').checked"),
id,
control.Items[i]
));
}
return sb.ToString();
}

private string GetCheckedListBoxStyle(CheckedListBoxControl control)
{
return $"overflow-y:scroll;{GetControlPosition(control)}{GetControlFont(control.Font)}";
}

}
}