Config.cs 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726
  1. using System;
  2. using System.Drawing;
  3. using System.Drawing.Text;
  4. using System.Globalization;
  5. using System.IO;
  6. using System.Reflection;
  7. using System.Runtime.InteropServices;
  8. namespace FastReport.Utils
  9. {
  10. /// <summary>
  11. /// Contains some configuration properties and settings that will be applied to the FastReport.Net
  12. /// environment, including Report, Designer and Preview components.
  13. /// </summary>
  14. public static partial class Config
  15. {
  16. #if COMMUNITY
  17. const string CONFIG_NAME = "FastReport.Community.config";
  18. #elif MONO
  19. const string CONFIG_NAME = "FastReport.Mono.config";
  20. #else
  21. const string CONFIG_NAME = "FastReport.config";
  22. #endif
  23. #region Private Fields
  24. private static readonly CultureInfo engCultureInfo = new CultureInfo("en-US");
  25. private static readonly XmlDocument FDoc = new XmlDocument();
  26. private static readonly string version = typeof(Report).Assembly.GetName().Version.ToString(3);
  27. private static string FFolder = null;
  28. private static string FFontListFolder = null;
  29. private static string FLogs = "";
  30. private static bool FIsRunningOnMono;
  31. private static ReportSettings FReportSettings = new ReportSettings();
  32. private static bool FRightToLeft = false;
  33. private static string FTempFolder = null;
  34. private static string systemTempFolder = null;
  35. private static bool FStringOptimization = true;
  36. private static bool FWebMode;
  37. private static bool preparedCompressed = true;
  38. private static bool disableHotkeys = false;
  39. private static bool enableScriptSecurity = false;
  40. private static ScriptSecurityProperties scriptSecurityProps = null;
  41. private static bool forbidLocalData = false;
  42. private static bool userSetsScriptSecurity = false;
  43. private static readonly FRPrivateFontCollection privateFontCollection = new FRPrivateFontCollection();
  44. internal static bool CleanupOnExit;
  45. private static CompilerSettings compilerSettings = new CompilerSettings();
  46. private static string applicationFolder;
  47. private static readonly string baseDirectory = AppDomain.CurrentDomain.BaseDirectory;
  48. private static bool disableLastFormatting = false;
  49. #endregion Private Fields
  50. #region Public Properties
  51. /// <summary>
  52. /// Gets a value indicating that the Mono runtime is used.
  53. /// </summary>
  54. public static bool IsRunningOnMono
  55. {
  56. get { return FIsRunningOnMono; }
  57. }
  58. #if CROSSPLATFORM
  59. public static bool IsWindows { get; } = RuntimeInformation.IsOSPlatform(OSPlatform.Windows);
  60. #endif
  61. /// <summary>
  62. /// Gets or sets a value indicating is it impossible to specify a local data path in Xml and Csv.
  63. /// </summary>
  64. public static bool ForbidLocalData
  65. {
  66. get { return forbidLocalData; }
  67. set { forbidLocalData = value; }
  68. }
  69. /// <summary>
  70. /// Gets or sets the optimization of strings. Is experimental feature.
  71. /// </summary>
  72. public static bool IsStringOptimization
  73. {
  74. get { return FStringOptimization; }
  75. set { FStringOptimization = value; }
  76. }
  77. /// <summary>
  78. /// Enable or disable the compression in files with prepared reports (fpx).
  79. /// </summary>
  80. public static bool PreparedCompressed
  81. {
  82. get { return preparedCompressed; }
  83. set { preparedCompressed = value; }
  84. }
  85. /// <summary>
  86. /// Gets or sets the application folder.
  87. /// </summary>
  88. public static string ApplicationFolder
  89. {
  90. get
  91. {
  92. if(applicationFolder == null)
  93. return baseDirectory;
  94. return applicationFolder;
  95. }
  96. set
  97. {
  98. applicationFolder = value;
  99. }
  100. }
  101. /// <summary>
  102. /// Gets an english culture information for localization purposes
  103. /// </summary>
  104. public static CultureInfo EngCultureInfo
  105. {
  106. get { return engCultureInfo; }
  107. }
  108. /// <summary>
  109. /// Gets or sets the path used to load/save the configuration file.
  110. /// </summary>
  111. /// <remarks>
  112. /// By default, the configuration file is saved to the application local data folder
  113. /// (C:\Documents and Settings\User_Name\Local Settings\Application Data\FastReport\).
  114. /// Set this property to "" if you want to store the configuration file in the application folder.
  115. /// </remarks>
  116. public static string Folder
  117. {
  118. get { return FFolder; }
  119. set { FFolder = value; }
  120. }
  121. /// <summary>
  122. /// Gets or sets the path used to font.list file.
  123. /// </summary>
  124. /// <remarks>
  125. /// By default, the font.list file is saved to the FastReport.config folder
  126. /// If WebMode enabled (or config file path is null), then file is saved in the application folder.
  127. /// </remarks>
  128. public static string FontListFolder
  129. {
  130. get { return FFontListFolder; }
  131. set { FFontListFolder = value; }
  132. }
  133. /// <summary>
  134. /// Gets or sets the settings for the Report component.
  135. /// </summary>
  136. public static ReportSettings ReportSettings
  137. {
  138. get { return FReportSettings; }
  139. set { FReportSettings = value; }
  140. }
  141. /// <summary>
  142. /// Gets or sets a value indicating whether RTL layout should be used.
  143. /// </summary>
  144. public static bool RightToLeft
  145. {
  146. get { return FRightToLeft; }
  147. set { FRightToLeft = value; }
  148. }
  149. /// <summary>
  150. /// Gets or sets a value indicating whether hotkeys should be disabled.
  151. /// </summary>
  152. public static bool DisableHotkeys
  153. {
  154. get { return disableHotkeys; }
  155. set { disableHotkeys = value; }
  156. }
  157. /// <summary>
  158. /// Gets or sets a value indicating saving last formatting should be disabled.
  159. /// </summary>
  160. public static bool DisableLastFormatting
  161. {
  162. get { return disableLastFormatting; }
  163. set { disableLastFormatting = value; }
  164. }
  165. /// <summary>
  166. /// Gets the root item of config xml.
  167. /// </summary>
  168. public static XmlItem Root
  169. {
  170. get { return FDoc.Root; }
  171. }
  172. /// <summary>
  173. /// Gets or sets the path to the temporary folder used to store temporary files.
  174. /// </summary>
  175. /// <remarks>
  176. /// The default value is <b>null</b>, so the system temp folder will be used.
  177. /// </remarks>
  178. public static string TempFolder
  179. {
  180. get { return FTempFolder; }
  181. set { FTempFolder = value; }
  182. }
  183. /// <summary>
  184. /// Gets the path to the system temporary folder used to store temporary files.
  185. /// </summary>
  186. public static string SystemTempFolder
  187. {
  188. get { return systemTempFolder == null ? GetTempPath() : systemTempFolder; }
  189. }
  190. /// <summary>
  191. /// Gets FastReport version.
  192. /// </summary>
  193. public static string Version
  194. {
  195. get { return version; }
  196. }
  197. /// <summary>
  198. /// Called on script compile
  199. /// </summary>
  200. public static event EventHandler<ScriptSecurityEventArgs> ScriptCompile;
  201. /// <summary>
  202. /// Gets a PrivateFontCollection instance.
  203. /// </summary>
  204. public static FRPrivateFontCollection PrivateFontCollection
  205. {
  206. get { return privateFontCollection; }
  207. }
  208. /// <summary>
  209. /// Enable report script validation. For WebMode only
  210. /// </summary>
  211. public static bool EnableScriptSecurity
  212. {
  213. get
  214. {
  215. return enableScriptSecurity;
  216. }
  217. set
  218. {
  219. if (OnEnableScriptSecurityChanged != null)
  220. OnEnableScriptSecurityChanged.Invoke(null, null);
  221. enableScriptSecurity = value;
  222. //
  223. userSetsScriptSecurity = true;
  224. if (value)
  225. {
  226. if(scriptSecurityProps == null)
  227. scriptSecurityProps = new ScriptSecurityProperties();
  228. }
  229. }
  230. }
  231. /// <summary>
  232. /// Throws when property EnableScriptSecurity has been changed
  233. /// </summary>
  234. public static event EventHandler OnEnableScriptSecurityChanged;
  235. /// <summary>
  236. /// Properties of report script validation
  237. /// </summary>
  238. public static ScriptSecurityProperties ScriptSecurityProps
  239. {
  240. get { return scriptSecurityProps; }
  241. }
  242. /// <summary>
  243. /// Settings of report compiler.
  244. /// </summary>
  245. public static CompilerSettings CompilerSettings
  246. {
  247. get { return compilerSettings; }
  248. set { compilerSettings = value; }
  249. }
  250. #endregion Public Properties
  251. #region Internal Methods
  252. internal static string CreateTempFile(string dir)
  253. {
  254. if (String.IsNullOrEmpty(dir))
  255. return GetTempFileName();
  256. return Path.Combine(dir, Path.GetRandomFileName());
  257. }
  258. internal static string GetTempFolder()
  259. {
  260. return TempFolder == null ? GetTempPath() : TempFolder;
  261. }
  262. internal static void Init()
  263. {
  264. FIsRunningOnMono = Type.GetType("Mono.Runtime") != null;
  265. #if SKIA
  266. Topten.RichTextKit.FontFallback.CharacterMatcher = characterMatcher;
  267. #endif
  268. CheckWebMode();
  269. #if !CROSSPLATFORM
  270. if (!WebMode)
  271. LoadConfig();
  272. #endif
  273. if (!userSetsScriptSecurity && WebMode)
  274. {
  275. enableScriptSecurity = true; // don't throw event
  276. scriptSecurityProps = new ScriptSecurityProperties();
  277. }
  278. #if !COMMUNITY
  279. RestoreExportOptions();
  280. #endif
  281. LoadPlugins();
  282. // init TextRenderingHint.SystemDefault
  283. // bug in .Net: if you use any other hint before SystemDefault, the SystemDefault will
  284. // look like SingleBitPerPixel
  285. using (Bitmap bmp = new Bitmap(1, 1))
  286. using (Graphics g = Graphics.FromImage(bmp))
  287. {
  288. g.TextRenderingHint = System.Drawing.Text.TextRenderingHint.SystemDefault;
  289. g.DrawString(" ", SystemFonts.DefaultFont, Brushes.Black, 0, 0);
  290. }
  291. }
  292. private static void CheckWebMode()
  293. {
  294. // If we/user sets 'WebMode = true' before this check - Config shouln't change it (because check may be incorrect)
  295. if (!WebMode)
  296. {
  297. #if NETSTANDARD || NETCOREAPP
  298. var loadedAssemblies = AppDomain.CurrentDomain.GetAssemblies();
  299. foreach (var loadedAsmbly in loadedAssemblies)
  300. {
  301. bool isAspNetCore = loadedAsmbly.GetName().Name.StartsWith("Microsoft.AspNetCore");
  302. if (isAspNetCore)
  303. {
  304. WebMode = true;
  305. break;
  306. }
  307. }
  308. #else
  309. string processName = System.Diagnostics.Process.GetCurrentProcess().ProcessName;
  310. WebMode = String.Compare(processName, "iisexpress") == 0 ||
  311. String.Compare(processName, "w3wp") == 0;
  312. #endif
  313. }
  314. }
  315. internal static void WriteLogString(string s)
  316. {
  317. WriteLogString(s, false);
  318. }
  319. internal static void WriteLogString(string s, bool distinct)
  320. {
  321. if (distinct)
  322. {
  323. if (FLogs.IndexOf(s + "\r\n") != -1)
  324. return;
  325. }
  326. FLogs += s + "\r\n";
  327. }
  328. internal static void OnScriptCompile(ScriptSecurityEventArgs e)
  329. {
  330. if (ScriptCompile != null)
  331. {
  332. ScriptCompile.Invoke(null, e);
  333. }
  334. if (!e.IsValid)
  335. {
  336. throw new CompilerException(Res.Get("Messages,CompilerError"));
  337. }
  338. }
  339. #if NETSTANDARD || NETCOREAPP
  340. public static event EventHandler<Code.CodeDom.Compiler.CompilationEventArgs> BeforeEmitCompile;
  341. internal static void OnBeforeScriptCompilation(object sender, Code.CodeDom.Compiler.CompilationEventArgs e)
  342. {
  343. if (BeforeEmitCompile != null)
  344. {
  345. BeforeEmitCompile.Invoke(sender, e);
  346. }
  347. }
  348. #endif
  349. #endregion Internal Methods
  350. #region Private Methods
  351. private static string GetTempFileName()
  352. {
  353. return Path.Combine(GetTempFolder(), SystemFake.DateTime.Now.ToString("yyyy-dd-M--HH-mm-ss-") + Path.GetRandomFileName());
  354. }
  355. private static string GetTempPath()
  356. {
  357. if (!string.IsNullOrEmpty(systemTempFolder))
  358. return systemTempFolder;
  359. systemTempFolder = Environment.GetEnvironmentVariable("TMP");
  360. if (string.IsNullOrEmpty(systemTempFolder))
  361. systemTempFolder = Environment.GetEnvironmentVariable("TEMP");
  362. if (string.IsNullOrEmpty(systemTempFolder))
  363. systemTempFolder = Environment.GetEnvironmentVariable("TMPDIR");
  364. if (string.IsNullOrEmpty(systemTempFolder))
  365. systemTempFolder = Path.GetTempPath();
  366. return systemTempFolder;
  367. }
  368. private static void CurrentDomain_ProcessExit(object sender, EventArgs e)
  369. {
  370. FDoc.Root.Name = "Config";
  371. FDoc.AutoIndent = true;
  372. SaveUIStyle();
  373. SaveUIOptions();
  374. SavePreviewSettings();
  375. SaveCompilerSettings();
  376. SaveAuthServiceUser();
  377. #if !COMMUNITY
  378. SaveExportOptions();
  379. #endif
  380. if (!WebMode)
  381. {
  382. try
  383. {
  384. if (!Directory.Exists(Folder))
  385. Directory.CreateDirectory(Folder);
  386. string configFile = Path.Combine(Folder, CONFIG_NAME);
  387. if (CleanupOnExit)
  388. {
  389. File.Delete(configFile);
  390. }
  391. else
  392. {
  393. FDoc.Save(configFile);
  394. }
  395. if (FLogs != "")
  396. File.WriteAllText(Path.Combine(Folder, "FastReport.logs"), FLogs);
  397. }
  398. catch
  399. {
  400. }
  401. }
  402. }
  403. private static void LoadConfig()
  404. {
  405. bool configLoaded = false;
  406. if (!Config.WebMode)
  407. {
  408. try
  409. {
  410. if (Folder == null)
  411. {
  412. string baseFolder = Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData);
  413. Folder = Path.Combine(baseFolder, "FastReport");
  414. }
  415. else if (Folder == "")
  416. Folder = ApplicationFolder;
  417. }
  418. catch
  419. {
  420. }
  421. string fileName = Path.Combine(Folder, CONFIG_NAME);
  422. if (File.Exists(fileName))
  423. {
  424. try
  425. {
  426. FDoc.Load(fileName);
  427. configLoaded = true;
  428. }
  429. catch
  430. {
  431. }
  432. }
  433. RestoreUIStyle();
  434. RestoreDefaultLanguage();
  435. RestoreUIOptions();
  436. RestorePreviewSettings();
  437. RestoreAuthServiceUser();
  438. RestoreCompilerSettings();
  439. Res.LoadDefaultLocale();
  440. AppDomain.CurrentDomain.ProcessExit += new EventHandler(CurrentDomain_ProcessExit);
  441. }
  442. if (!configLoaded)
  443. {
  444. // load default config
  445. using (Stream stream = ResourceLoader.GetStream("FastReport.config"))
  446. {
  447. FDoc.Load(stream);
  448. }
  449. }
  450. }
  451. private static void LoadPlugins()
  452. {
  453. // main assembly initializer
  454. ProcessMainAssembly();
  455. XmlItem pluginsItem = Root.FindItem("Plugins");
  456. for (int i = 0; i < pluginsItem.Count; i++)
  457. {
  458. XmlItem item = pluginsItem[i];
  459. string pluginName = item.GetProp("Name");
  460. try
  461. {
  462. var assembly = Assembly.LoadFrom(pluginName);
  463. ProcessAssembly(assembly);
  464. }
  465. catch
  466. {
  467. }
  468. }
  469. // For CoreWin
  470. #if COREWIN
  471. LoadPluginsInCurrentFolder();
  472. #endif
  473. }
  474. private static void LoadPluginsInCurrentFolder()
  475. {
  476. var appFolder = ApplicationFolder;
  477. if(!string.IsNullOrEmpty(appFolder))
  478. {
  479. // find all plugin-connector in current directory
  480. var plugins = Directory.GetFiles(appFolder, "FastReport.Data.*.dll");
  481. // initialize
  482. foreach (var pluginName in plugins)
  483. {
  484. try
  485. {
  486. var assembly = Assembly.LoadFrom(pluginName);
  487. ProcessAssembly(assembly);
  488. }
  489. catch
  490. {
  491. }
  492. }
  493. }
  494. }
  495. private static void ProcessAssembly(Assembly a)
  496. {
  497. foreach (Type t in a.GetTypes())
  498. {
  499. if (t.IsSubclassOf(typeof(AssemblyInitializerBase)))
  500. Activator.CreateInstance(t);
  501. }
  502. }
  503. private static void RestoreDefaultLanguage()
  504. {
  505. XmlItem xi = Root.FindItem("Designer").FindItem("Code");
  506. string defaultLanguage = xi.GetProp("DefaultScriptLanguage");
  507. ReportSettings.DefaultLanguage = defaultLanguage == Language.Vb.ToString() ? Language.Vb : Language.CSharp;
  508. }
  509. private static void RestoreRightToLeft()
  510. {
  511. XmlItem xi = Root.FindItem("UIOptions");
  512. string rtl = xi.GetProp("RightToLeft");
  513. if (!String.IsNullOrEmpty(rtl))
  514. {
  515. switch (rtl)
  516. {
  517. case "Auto":
  518. RightToLeft = CultureInfo.CurrentCulture.TextInfo.IsRightToLeft;
  519. break;
  520. case "No":
  521. RightToLeft = false;
  522. break;
  523. case "Yes":
  524. RightToLeft = true;
  525. break;
  526. default:
  527. RightToLeft = false;
  528. break;
  529. }
  530. }
  531. }
  532. /// <summary>
  533. /// Properties of ScriptSecurity
  534. /// </summary>
  535. public class ScriptSecurityProperties
  536. {
  537. private static readonly string[] defaultStopList = new[]
  538. {
  539. "GetType",
  540. "typeof",
  541. "TypeOf", // VB
  542. "DllImport",
  543. "LoadLibrary",
  544. "GetProcAddress",
  545. };
  546. private string[] stopList;
  547. /// <summary>
  548. /// Add stubs for the most dangerous classes (in System.IO, System.Reflection etc)
  549. /// </summary>
  550. public bool AddStubClasses { get; set; } = true;
  551. /// <summary>
  552. /// List of keywords that shouldn't be declared in the report script
  553. /// </summary>
  554. public string[] StopList
  555. {
  556. get { return (string[])stopList.Clone(); }
  557. set
  558. {
  559. if(value != null)
  560. {
  561. OnStopListChanged?.Invoke(this, null);
  562. stopList = value;
  563. }
  564. }
  565. }
  566. /// <summary>
  567. /// Throws when <see cref="StopList"/> has changed
  568. /// </summary>
  569. public event EventHandler OnStopListChanged;
  570. internal ScriptSecurityProperties()
  571. {
  572. SetDefaultStopList();
  573. }
  574. internal ScriptSecurityProperties(string[] stopList)
  575. {
  576. this.stopList = stopList;
  577. }
  578. /// <summary>
  579. /// Sets default value for <see cref="StopList"/>
  580. /// </summary>
  581. public void SetDefaultStopList()
  582. {
  583. StopList = defaultStopList;
  584. }
  585. }
  586. private static void SaveUIOptions()
  587. {
  588. XmlItem xi = Root.FindItem("UIOptions");
  589. xi.SetProp("DisableHotkeys", Converter.ToString(DisableHotkeys));
  590. xi.SetProp("DisableLastFormatting", Converter.ToString(DisableLastFormatting));
  591. }
  592. private static void RestoreUIOptions()
  593. {
  594. RestoreRightToLeft();
  595. XmlItem xi = Root.FindItem("UIOptions");
  596. string disableHotkeysStringValue = xi.GetProp("DisableHotkeys");
  597. if (!String.IsNullOrEmpty(disableHotkeysStringValue))
  598. {
  599. disableHotkeys = disableHotkeysStringValue.ToLower() != "false";
  600. }
  601. string disableLastFormattingStringValue = xi.GetProp("DisableLastFormatting");
  602. if (!String.IsNullOrEmpty(disableLastFormattingStringValue))
  603. {
  604. disableLastFormatting = disableLastFormattingStringValue.ToLower() != "false";
  605. }
  606. }
  607. private static void SaveCompilerSettings()
  608. {
  609. XmlItem xi = Root.FindItem("CompilerSettings");
  610. xi.SetProp("Placeholder", CompilerSettings.Placeholder);
  611. xi.SetProp("ExceptionBehaviour", Converter.ToString(CompilerSettings.ExceptionBehaviour));
  612. }
  613. private static void RestoreCompilerSettings()
  614. {
  615. XmlItem xi = Root.FindItem("CompilerSettings");
  616. CompilerSettings.Placeholder = xi.GetProp("Placeholder");
  617. string exceptionBehaviour = xi.GetProp("ExceptionBehaviour");
  618. if (!String.IsNullOrEmpty(exceptionBehaviour))
  619. {
  620. try
  621. {
  622. CompilerSettings.ExceptionBehaviour =
  623. (CompilerExceptionBehaviour)Converter.FromString(typeof(CompilerExceptionBehaviour),
  624. exceptionBehaviour);
  625. }
  626. catch
  627. {
  628. CompilerSettings.ExceptionBehaviour = CompilerExceptionBehaviour.Default;
  629. }
  630. }
  631. }
  632. #endregion Private Methods
  633. }
  634. }