Compare commits
13 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 26c148dccc | |||
| 8497056185 | |||
| 5498e2c2bb | |||
| 602a8ce08c | |||
| 7e82524c4e | |||
| 783973b9da | |||
| 096cd1ef73 | |||
| 07b01fa318 | |||
| 0ba253c61d | |||
| 5da7f034e9 | |||
| 8eebd4ccae | |||
| c47e254efe | |||
| 3f35749619 |
@@ -27,10 +27,4 @@ dotnet_naming_symbols.private_fields.applicable_kinds = field
|
||||
dotnet_naming_symbols.private_fields.applicable_accessibilities = private
|
||||
|
||||
dotnet_naming_style.prefix_underscore.capitalization = camel_case
|
||||
dotnet_naming_style.prefix_underscore.required_prefix = _
|
||||
|
||||
# https://github.com/MicrosoftDocs/visualstudio-docs/blob/master/docs/ide/editorconfig-code-style-settings-reference.md
|
||||
[*.cs]
|
||||
csharp_style_var_for_built_in_types = true:suggestion
|
||||
csharp_style_var_when_type_is_apparent = true:suggestion
|
||||
csharp_style_var_elsewhere = true:suggestion
|
||||
dotnet_naming_style.prefix_underscore.required_prefix = _
|
||||
@@ -1,66 +0,0 @@
|
||||
---
|
||||
name: 🐛 Bug Report
|
||||
about: File a bug report, if you've discovered a problem in Umbraco.
|
||||
---
|
||||
|
||||
A brief description of the issue goes here.
|
||||
|
||||
<!--
|
||||
|
||||
If you haven't yet done so, please read the "contributing guidelines"
|
||||
thoroughly. Then, proceed by filling out the rest of the details in the issue
|
||||
template below. The more details you can give us, the easier it will be for us
|
||||
to determine the cause of a problem.
|
||||
|
||||
See: https://github.com/umbraco/Umbraco-CMS/blob/dev-v7/.github/CONTRIBUTING.md
|
||||
|
||||
-->
|
||||
|
||||
|
||||
|
||||
Reproduction
|
||||
------------
|
||||
|
||||
If you're filing a bug, please describe how to reproduce it. Include as much
|
||||
relevant information as possible, such as:
|
||||
|
||||
### Bug summary
|
||||
|
||||
<!--
|
||||
* Write a short summary of the bug
|
||||
* Try to pinpoint it as much as possible
|
||||
* Try to state the _actual problem_, and not just what you _think_ the
|
||||
solution might be.
|
||||
-->
|
||||
|
||||
### Specifics
|
||||
|
||||
<!--
|
||||
* Mention the URL where this bug occurs, if applicable
|
||||
* What version of Umbraco are you using (down to the very last digit!)
|
||||
* What browser and version you are using
|
||||
* Please mention if you've checked it in other browsers as well
|
||||
* Please include *full error messages* and *screenshots* if possible
|
||||
-->
|
||||
|
||||
### Steps to reproduce
|
||||
|
||||
<!--
|
||||
* Clearly mention the steps to reproduce the bug
|
||||
-->
|
||||
|
||||
### Expected result
|
||||
|
||||
<!--
|
||||
* What did you _expect_ that would happen on your Umbraco site?
|
||||
* Describe the intended/desired outcome after you did the steps mentioned.
|
||||
-->
|
||||
|
||||
### Actual result
|
||||
|
||||
<!--
|
||||
* What is the actual result of the above steps?
|
||||
* Describe the behaviour of the bug
|
||||
* Please, please include **error messages** and screenshots. They might mean
|
||||
nothing to you, but they are _very_ helpful to us.
|
||||
-->
|
||||
@@ -1,31 +0,0 @@
|
||||
---
|
||||
name: 📮 Feature Request
|
||||
about: Open a feature request, if you want to propose a new feature.
|
||||
---
|
||||
|
||||
A brief description of your feature request goes here.
|
||||
|
||||
|
||||
<!--
|
||||
If you want to discuss the feature you're imagining, please make sure to keep
|
||||
those discussions on the forum at https://our.umbraco.com/ (choose the
|
||||
category "Contributing to Umbraco", Umbraco HQ follows all new topics there).
|
||||
|
||||
Once you've come to a conclusion in the discussion, feel free to propose the
|
||||
new feature here.
|
||||
-->
|
||||
|
||||
How can you help?
|
||||
-------------------------------
|
||||
|
||||
<!--
|
||||
The resources (read: available time and effort) of Umbraco's core team are
|
||||
limited.
|
||||
|
||||
If we can not work on your suggestion, please don't take it personally. Most
|
||||
likely, it's either:
|
||||
|
||||
- We think your idea is valid, but we can't find the time to work on it.
|
||||
- Your idea might be better suited as a package, if it's not suitable for
|
||||
the majority of users.
|
||||
-->
|
||||
@@ -1,9 +0,0 @@
|
||||
---
|
||||
name: ⁉️ Support Question
|
||||
about: Having trouble with Umbraco? -> https://our.umbraco.com
|
||||
---
|
||||
|
||||
This issue tracker is NOT meant for support questions. If you have a question,
|
||||
please join us on the forum at https://our.umbraco.com.
|
||||
|
||||
Thanks!
|
||||
@@ -1,9 +0,0 @@
|
||||
---
|
||||
name: 📖 Documentation Issue
|
||||
about: See https://github.com/umbraco/UmbracoDocs/issues for documentation issues
|
||||
---
|
||||
|
||||
The Umbraco documentation has its own dedicated repository. Please open your
|
||||
documentation-related issue at https://github.com/umbraco/UmbracoDocs/issues
|
||||
|
||||
Thanks!
|
||||
@@ -1,31 +0,0 @@
|
||||
---
|
||||
name: 🔐 Security Issue
|
||||
about: Discovered a Security Issue in Umbraco?
|
||||
---
|
||||
|
||||
⚠️ PLEASE DON'T DISCLOSE SECURITY-RELATED ISSUES PUBLICLY, SEE BELOW.
|
||||
|
||||
If you have found a security issue in Umbraco, please send the details to
|
||||
security@umbraco.com and don't disclose it publicly until we can provide a fix for
|
||||
it. If you wish, we'll credit you for finding verified issues, when we release
|
||||
the patched version.
|
||||
|
||||
❗ Please read more about how to report security issues on https://umbraco.com/security
|
||||
|
||||
A note on "Self XSS"
|
||||
--------------------
|
||||
|
||||
Umbraco is a CMS, that allows users to edit content on a website. As such,
|
||||
all _authenticated users_ can:
|
||||
|
||||
- Edit content, and (depending on the field types) insert HTML and CSS in that
|
||||
content, with a variety of allowed attributes.
|
||||
- Depending on the user level: Edit template files, and insert C#, HTML, CSS and
|
||||
javascript in so on.
|
||||
- Upload files to the site, which will become publicly available.
|
||||
|
||||
We see these functionalities as _features_, and not as security issues. Please
|
||||
report the mentioned items only if they can be performed by non-authorized
|
||||
users, or other exploitable vulnerabilities.
|
||||
|
||||
Thanks!
|
||||
@@ -1,11 +0,0 @@
|
||||
### Prerequisites
|
||||
|
||||
- [ ] I have [created an issue](https://github.com/umbraco/Umbraco-CMS/issues) for the proposed changes in this PR, the link is:
|
||||
- [ ] I have added steps to test this contribution in the description below
|
||||
|
||||
### Description
|
||||
<!-- A description of the changes proposed in the pull-request -->
|
||||
<!-- Make sure to link to the related issue number so we can easily find it in the issue tracker -->
|
||||
|
||||
|
||||
<!-- Thanks for contributing to Umbraco CMS! -->
|
||||
@@ -1,6 +1,6 @@
|
||||
# The MIT License (MIT) #
|
||||
|
||||
Copyright (c) 2013-present Umbraco
|
||||
Copyright (c) 2013 Umbraco
|
||||
|
||||
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:
|
||||
|
||||
|
||||
@@ -1,56 +1,87 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<package xmlns="http://schemas.microsoft.com/packaging/2010/07/nuspec.xsd">
|
||||
<metadata minClientVersion="3.4.4">
|
||||
<id>UmbracoCms.Core</id>
|
||||
<version>8.0.0</version>
|
||||
<title>Umbraco Cms Core Binaries</title>
|
||||
<authors>Umbraco HQ</authors>
|
||||
<owners>Umbraco HQ</owners>
|
||||
<licenseUrl>http://opensource.org/licenses/MIT</licenseUrl>
|
||||
<projectUrl>http://umbraco.com/</projectUrl>
|
||||
<iconUrl>http://umbraco.com/media/357769/100px_transparent.png</iconUrl>
|
||||
<requireLicenseAcceptance>false</requireLicenseAcceptance>
|
||||
<description>Contains the core assemblies needed to run Umbraco Cms. This package only contains assemblies and can be used for package development. Use the UmbracoCms package to setup Umbraco in Visual Studio as an ASP.NET project.</description>
|
||||
<summary>Contains the core assemblies needed to run Umbraco Cms</summary>
|
||||
<language>en-US</language>
|
||||
<tags>umbraco</tags>
|
||||
<dependencies>
|
||||
<!--
|
||||
note: dependencies are specified as [x.y.z,x.999999) eg [2.1.0,2.999999) and NOT [2.1.0,3.0.0) because
|
||||
the latter would pick anything below 3.0.0 and that includes prereleases such as 3.0.0-alpha, and we do
|
||||
not want this to happen as the alpha of the next major is, really, the next major already.
|
||||
-->
|
||||
<dependency id="AutoMapper" version="[7.0.1,7.999999)" />
|
||||
<dependency id="LightInject" version="[5.1.2,5.999999)" />
|
||||
<dependency id="LightInject.Annotation" version="[1.1.0,1.999999)" />
|
||||
<dependency id="LightInject.Web" version="[2.0.0,2.999999)" />
|
||||
<dependency id="Microsoft.AspNet.Identity.Core" version="[2.2.2,2.999999)" />
|
||||
<dependency id="Microsoft.AspNet.WebApi.Client" version="[5.2.6,5.999999)" />
|
||||
<dependency id="Microsoft.Owin" version="[4.0.0,4.999999)" />
|
||||
<dependency id="MiniProfiler" version="[3.2.0.157,3.999999)" />
|
||||
<dependency id="MySql.Data" version="[6.10.7,6.999999)" />
|
||||
<dependency id="Newtonsoft.Json" version="[11.0.2,11.999999)" />
|
||||
<dependency id="Semver" version="[2.0.4,2.999999)" />
|
||||
<dependency id="Serilog" version="[2.7.1,2.999999)" />
|
||||
<dependency id="Serilog.Enrichers.Process" version="[2.0.1,2.999999)" />
|
||||
<dependency id="Serilog.Enrichers.Thread" version="[3.0.0,3.999999)" />
|
||||
<dependency id="Serilog.Filters.Expressions" version="[2.0.0,2.999999)" />
|
||||
<dependency id="Serilog.Formatting.Compact" version="[1.0.0,1.999999)" />
|
||||
<dependency id="Serilog.Settings.AppSettings" version="[2.1.2,2.999999)" />
|
||||
<dependency id="Serilog.Sinks.File" version="[4.0.0,4.999999)" />
|
||||
<dependency id="Umbraco.SqlServerCE" version="[4.0.0.1,4.999999)" />
|
||||
<dependency id="NPoco" version="[3.9.4,3.999999)" />
|
||||
</dependencies>
|
||||
</metadata>
|
||||
<files>
|
||||
<!-- libs -->
|
||||
<file src="$BuildTmp$\WebApp\bin\Umbraco.Core.dll" target="lib\net472\Umbraco.Core.dll" />
|
||||
<metadata minClientVersion="3.4.4">
|
||||
<id>UmbracoCms.Core</id>
|
||||
<version>8.0.0</version>
|
||||
<title>Umbraco Cms Core Binaries</title>
|
||||
<authors>Umbraco HQ</authors>
|
||||
<owners>Umbraco HQ</owners>
|
||||
<licenseUrl>http://opensource.org/licenses/MIT</licenseUrl>
|
||||
<projectUrl>http://umbraco.com/</projectUrl>
|
||||
<iconUrl>http://umbraco.com/media/357769/100px_transparent.png</iconUrl>
|
||||
<requireLicenseAcceptance>false</requireLicenseAcceptance>
|
||||
<description>Contains the core assemblies needed to run Umbraco Cms. This package only contains assemblies and can be used for package development. Use the UmbracoCms-package to setup Umbraco in Visual Studio as an ASP.NET project.</description>
|
||||
<summary>Contains the core assemblies needed to run Umbraco Cms</summary>
|
||||
<language>en-US</language>
|
||||
<tags>umbraco</tags>
|
||||
<dependencies>
|
||||
<!--
|
||||
note: dependencies are specified as [x.y.z,x.999999) eg [2.1.0,2.999999) and NOT [2.1.0,3.0.0) because
|
||||
the latter would pick anything below 3.0.0 and that includes prereleases such as 3.0.0-alpha, and we do
|
||||
not want this to happen as the alpha of the next major is, really, the next major already.
|
||||
-->
|
||||
<dependency id="AutoMapper" version="[7.0.1,7.999999)" />
|
||||
<dependency id="ClientDependency" version="[1.9.6,1.999999)" />
|
||||
<dependency id="ClientDependency-Mvc5" version="[1.8.0,1.999999)" />
|
||||
<dependency id="CSharpTest.Net.Collections" version="[14.906.1403.1082,14.999999)" />
|
||||
<dependency id="Examine" version="[1.0.0-beta025,1.999999)" />
|
||||
<dependency id="HtmlAgilityPack" version="[1.7.2,1.999999)" />
|
||||
<dependency id="ImageProcessor" version="[2.6.1.19,2.999999)" />
|
||||
<dependency id="ImageProcessor.Web" version="[4.9.2.19,4.999999)" />
|
||||
<dependency id="ImageProcessor.Web.Config" version="[2.4.1.19,2.999999)" />
|
||||
<dependency id="LightInject" version="[5.1.2,5.999999)" />
|
||||
<dependency id="LightInject.Annotation" version="[1.1.0,1.999999)" />
|
||||
<dependency id="LightInject.Mvc" version="[2.0.0,2.999999)" />
|
||||
<dependency id="LightInject.WebApi" version="[2.0.0,2.999999)" />
|
||||
<dependency id="log4net" version="[2.0.8,2.999999)" />
|
||||
<dependency id="Log4Net.Async" version="[2.0.4,2.999999)" />
|
||||
<dependency id="Lucene.Net.Contrib" version="[3.0.3,3.999999)" />
|
||||
<dependency id="Markdown" version="[2.2.1,2.999999)" />
|
||||
<dependency id="Microsoft.AspNet.Identity.Owin" version="[2.2.1,2.999999)" />
|
||||
<dependency id="Microsoft.AspNet.Mvc" version="[5.2.6,5.999999)" />
|
||||
<dependency id="Microsoft.AspNet.SignalR.Core" version="[2.2.3,2.999999)" />
|
||||
<dependency id="Microsoft.AspNet.WebApi" version="[5.2.6,5.999999)" />
|
||||
<dependency id="Microsoft.CodeAnalysis.CSharp" version="[2.8.0,2.999999)" />
|
||||
<dependency id="Microsoft.CodeDom.Providers.DotNetCompilerPlatform" version="[1.0.8,1.999999)" />
|
||||
<dependency id="Microsoft.Net.Compilers" version="[2.8.0,2.999999)" />
|
||||
<dependency id="Microsoft.Owin.Host.SystemWeb" version="[4.0.0,4.999999)" />
|
||||
<dependency id="Microsoft.Owin.Security.Cookies" version="[4.0.0,4.999999)" />
|
||||
<dependency id="Microsoft.Owin.Security.OAuth" version="[4.0.0,4.999999)" />
|
||||
<dependency id="Microsoft.Web.Xdt" version="[2.1.2,2.999999)" />
|
||||
<dependency id="MiniProfiler" version="[3.2.0.157,3.999999)" />
|
||||
<dependency id="MySql.Data" version="[6.10.7,6.999999)" />
|
||||
<dependency id="Newtonsoft.Json" version="[11.0.2,11.999999)" />
|
||||
<dependency id="NPoco" version="[3.9.3,3.999999)" />
|
||||
<dependency id="Semver" version="[2.0.4,2.999999)" />
|
||||
<dependency id="System.Reflection.Primitives" version="[4.3.0,4.999999)" />
|
||||
<dependency id="System.Runtime.Handles" version="[4.3.0,4.999999)" />
|
||||
<dependency id="System.Security.Cryptography.X509Certificates" version="[4.3.2,4.999999)" />
|
||||
<dependency id="System.Threading.Tasks.Dataflow" version="[4.8.0,4.999999)" />
|
||||
<dependency id="Umbraco.SqlServerCE" version="[4.0.0.1,4.999999)" />
|
||||
</dependencies>
|
||||
</metadata>
|
||||
<files>
|
||||
<file src="$BuildTmp$\WebApp\bin\Umbraco.Core.dll" target="lib\net472\Umbraco.Core.dll" />
|
||||
<file src="$BuildTmp$\WebApp\bin\Umbraco.Web.dll" target="lib\net472\Umbraco.Web.dll" />
|
||||
<file src="$BuildTmp$\WebApp\bin\Umbraco.Web.UI.dll" target="lib\net472\Umbraco.Web.UI.dll" />
|
||||
<file src="$BuildTmp$\WebApp\bin\Umbraco.Examine.dll" target="lib\net472\Umbraco.Examine.dll" />
|
||||
|
||||
<!-- docs -->
|
||||
<file src="$BuildTmp$\WebApp\bin\Umbraco.Core.xml" target="lib\Umbraco.Core.xml" />
|
||||
<!-- docs -->
|
||||
<file src="$BuildTmp$\WebApp\bin\Umbraco.Core.xml" target="lib\Umbraco.Core.xml" />
|
||||
<file src="$BuildTmp$\WebApp\bin\Umbraco.Web.xml" target="lib\Umbraco.Web.xml" />
|
||||
<file src="$BuildTmp$\WebApp\bin\Umbraco.Web.UI.xml" target="lib\Umbraco.Web.UI.xml" />
|
||||
<file src="$BuildTmp$\WebApp\bin\Umbraco.Examine.xml" target="lib\Umbraco.Examine.xml" />
|
||||
|
||||
<!-- symbols -->
|
||||
<file src="$BuildTmp$\bin\Umbraco.Core.pdb" target="lib" />
|
||||
<file src="$BuildTmp$\..\src\Umbraco.Core\**\*.cs" exclude="$BuildTmp$\..\src\**\TemporaryGeneratedFile*.cs" target="src\Umbraco.Core" />
|
||||
</files>
|
||||
<file src="tools\install.core.ps1" target="tools\install.ps1" />
|
||||
|
||||
<!-- symbols -->
|
||||
<file src="$BuildTmp$\bin\Umbraco.Core.pdb" target="lib" />
|
||||
<file src="$BuildTmp$\..\src\Umbraco.Core\**\*.cs" exclude="$BuildTmp$\..\src\**\TemporaryGeneratedFile*.cs" target="src\Umbraco.Core" />
|
||||
<file src="$BuildTmp$\bin\Umbraco.Web.pdb" target="lib" />
|
||||
<file src="$BuildTmp$\..\src\Umbraco.Web\**\*.cs" exclude="$BuildTmp$\..\src\**\TemporaryGeneratedFile*.cs" target="src\Umbraco.Web" />
|
||||
<file src="$BuildTmp$\bin\Umbraco.Web.UI.pdb" target="lib" />
|
||||
<file src="$BuildTmp$\..\src\Umbraco.Web.UI\**\*.cs" exclude="$BuildTmp$\..\src\**\TemporaryGeneratedFile*.cs" target="src\Umbraco.Web.UI" />
|
||||
<file src="$BuildTmp$\bin\Umbraco.Examine.pdb" target="lib" />
|
||||
<file src="$BuildTmp$\..\src\Umbraco.Examine\**\*.cs" exclude="$BuildTmp$\..\src\**\TemporaryGeneratedFile*.cs" target="src\Umbraco.Examine" />
|
||||
</files>
|
||||
</package>
|
||||
|
||||
@@ -1,62 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<package xmlns="http://schemas.microsoft.com/packaging/2010/07/nuspec.xsd">
|
||||
<metadata minClientVersion="3.4.4">
|
||||
<id>UmbracoCms.Web</id>
|
||||
<version>8.0.0</version>
|
||||
<title>Umbraco Cms Core Binaries</title>
|
||||
<authors>Umbraco HQ</authors>
|
||||
<owners>Umbraco HQ</owners>
|
||||
<licenseUrl>http://opensource.org/licenses/MIT</licenseUrl>
|
||||
<projectUrl>http://umbraco.com/</projectUrl>
|
||||
<iconUrl>http://umbraco.com/media/357769/100px_transparent.png</iconUrl>
|
||||
<requireLicenseAcceptance>false</requireLicenseAcceptance>
|
||||
<description>Contains the web assemblies needed to run Umbraco Cms. This package only contains assemblies and can be used for package development. Use the UmbracoCms package to setup Umbraco in Visual Studio as an ASP.NET project.</description>
|
||||
<summary>Contains the core assemblies needed to run Umbraco Cms</summary>
|
||||
<language>en-US</language>
|
||||
<tags>umbraco</tags>
|
||||
<dependencies>
|
||||
<!--
|
||||
note: dependencies are specified as [x.y.z,x.999999) eg [2.1.0,2.999999) and NOT [2.1.0,3.0.0) because
|
||||
the latter would pick anything below 3.0.0 and that includes prereleases such as 3.0.0-alpha, and we do
|
||||
not want this to happen as the alpha of the next major is, really, the next major already.
|
||||
-->
|
||||
<dependency id="UmbracoCms.Core" version="[$version$]" />
|
||||
<dependency id="AutoMapper" version="[7.0.1,7.999999)" />
|
||||
<dependency id="ClientDependency" version="[1.9.7,1.999999)" />
|
||||
<dependency id="ClientDependency-Mvc5" version="[1.8.0,1.999999)" />
|
||||
<dependency id="CSharpTest.Net.Collections" version="[14.906.1403.1082,14.999999)" />
|
||||
<dependency id="Examine" version="[1.0.0-beta025,1.999999)" />
|
||||
<dependency id="Lucene.Net.Contrib" version="[3.0.3,3.999999)" />
|
||||
<dependency id="HtmlAgilityPack" version="[1.8.9,1.999999)" />
|
||||
<dependency id="ImageProcessor" version="[2.6.2.25,2.999999)" />
|
||||
<dependency id="LightInject.Mvc" version="[2.0.0,2.999999)" />
|
||||
<dependency id="LightInject.WebApi" version="[2.0.0,2.999999)" />
|
||||
<dependency id="Markdown" version="[2.2.1,2.999999)" />
|
||||
<dependency id="Microsoft.AspNet.Identity.Owin" version="[2.2.2,2.999999)" />
|
||||
<dependency id="Microsoft.AspNet.Mvc" version="[5.2.6,5.999999)" />
|
||||
<dependency id="Microsoft.AspNet.SignalR.Core" version="[2.2.3,2.999999)" />
|
||||
<dependency id="Microsoft.AspNet.WebApi" version="[5.2.6,5.999999)" />
|
||||
<dependency id="Microsoft.Owin.Host.SystemWeb" version="[4.0.0,4.999999)" />
|
||||
<dependency id="Microsoft.Owin.Security.Cookies" version="[4.0.0,4.999999)" />
|
||||
<dependency id="Microsoft.Owin.Security.OAuth" version="[4.0.0,4.999999)" />
|
||||
<dependency id="System.Threading.Tasks.Dataflow" version="[4.8.0,4.999999)" />
|
||||
</dependencies>
|
||||
</metadata>
|
||||
<files>
|
||||
<!-- libs -->
|
||||
<file src="$BuildTmp$\WebApp\bin\Umbraco.Web.dll" target="lib\net472\Umbraco.Web.dll" />
|
||||
<file src="$BuildTmp$\WebApp\bin\Umbraco.Web.UI.dll" target="lib\net472\Umbraco.Web.UI.dll" />
|
||||
<file src="$BuildTmp$\WebApp\bin\Umbraco.Examine.dll" target="lib\net472\Umbraco.Examine.dll" />
|
||||
|
||||
<!-- docs -->
|
||||
<file src="$BuildTmp$\WebApp\bin\Umbraco.Web.xml" target="lib\Umbraco.Web.xml" />
|
||||
<file src="$BuildTmp$\WebApp\bin\Umbraco.Web.UI.xml" target="lib\Umbraco.Web.UI.xml" />
|
||||
<file src="$BuildTmp$\WebApp\bin\Umbraco.Examine.xml" target="lib\Umbraco.Examine.xml" />
|
||||
|
||||
<!-- symbols -->
|
||||
<file src="$BuildTmp$\bin\Umbraco.Web.pdb" target="lib" />
|
||||
<file src="$BuildTmp$\..\src\Umbraco.Web\**\*.cs" exclude="$BuildTmp$\..\src\**\TemporaryGeneratedFile*.cs" target="src\Umbraco.Web" />
|
||||
<file src="$BuildTmp$\bin\Umbraco.Examine.pdb" target="lib" />
|
||||
<file src="$BuildTmp$\..\src\Umbraco.Examine\**\*.cs" exclude="$BuildTmp$\..\src\**\TemporaryGeneratedFile*.cs" target="src\Umbraco.Examine" />
|
||||
</files>
|
||||
</package>
|
||||
@@ -1,65 +1,59 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<package xmlns="http://schemas.microsoft.com/packaging/2010/07/nuspec.xsd">
|
||||
<metadata minClientVersion="3.4.4">
|
||||
<id>UmbracoCms</id>
|
||||
<version>8.0.0</version>
|
||||
<title>Umbraco Cms</title>
|
||||
<authors>Umbraco HQ</authors>
|
||||
<owners>Umbraco HQ</owners>
|
||||
<licenseUrl>http://opensource.org/licenses/MIT</licenseUrl>
|
||||
<projectUrl>http://umbraco.com/</projectUrl>
|
||||
<iconUrl>http://umbraco.com/media/357769/100px_transparent.png</iconUrl>
|
||||
<requireLicenseAcceptance>false</requireLicenseAcceptance>
|
||||
<description>Installs Umbraco Cms in your Visual Studio ASP.NET project</description>
|
||||
<summary>Installs Umbraco Cms in your Visual Studio ASP.NET project</summary>
|
||||
<language>en-US</language>
|
||||
<tags>umbraco</tags>
|
||||
<dependencies>
|
||||
<dependency id="UmbracoCms.Web" version="[$version$]" />
|
||||
<!--
|
||||
note: dependencies are specified as [x.y.z,x.999999) eg [2.1.0,2.999999) and NOT [2.1.0,3.0.0) because
|
||||
the latter would pick anything below 3.0.0 and that includes prereleases such as 3.0.0-alpha, and we do
|
||||
not want this to happen as the alpha of the next major is, really, the next major already.
|
||||
-->
|
||||
<dependency id="Microsoft.AspNet.SignalR.Core" version="[2.2.3, 2.999999)" />
|
||||
<dependency id="Umbraco.ModelsBuilder.Ui" version="[8.0.0-alpha.24]" />
|
||||
<dependency id="ImageProcessor.Web" version="[4.9.3.25,4.999999)" />
|
||||
<dependency id="ImageProcessor.Web.Config" version="[2.4.1.19,2.999999)" />
|
||||
<dependency id="Microsoft.CodeDom.Providers.DotNetCompilerPlatform" version="[2.0.0,2.999999)" />
|
||||
<dependency id="Microsoft.Net.Compilers" version="[2.9.0,2.999999)" />
|
||||
</dependencies>
|
||||
</metadata>
|
||||
<files>
|
||||
<!-- files -->
|
||||
<file src="$BuildTmp$\Configs\**" target="Content\Config" exclude="$BuildTmp$\Configs\Web.config.transform" />
|
||||
<file src="$BuildTmp$\WebApp\Views\**" target="Content\Views" exclude="$BuildTmp$\WebApp\Views\Web.config" />
|
||||
<file src="$BuildTmp$\WebApp\default.aspx" target="Content\default.aspx" />
|
||||
<file src="$BuildTmp$\WebApp\Global.asax" target="Content\Global.asax" />
|
||||
<file src="$BuildTmp$\WebApp\config\BackOfficeTours\**" target="Content\Config\BackOfficeTours" />
|
||||
<file src="$BuildTmp$\WebApp\Media\Web.config" target="Content\Media\Web.config" />
|
||||
<metadata minClientVersion="3.4.4">
|
||||
<id>UmbracoCms</id>
|
||||
<version>8.0.0</version>
|
||||
<title>Umbraco Cms</title>
|
||||
<authors>Umbraco HQ</authors>
|
||||
<owners>Umbraco HQ</owners>
|
||||
<licenseUrl>http://opensource.org/licenses/MIT</licenseUrl>
|
||||
<projectUrl>http://umbraco.com/</projectUrl>
|
||||
<iconUrl>http://umbraco.com/media/357769/100px_transparent.png</iconUrl>
|
||||
<requireLicenseAcceptance>false</requireLicenseAcceptance>
|
||||
<description>Installs Umbraco Cms in your Visual Studio ASP.NET project</description>
|
||||
<summary>Installs Umbraco Cms in your Visual Studio ASP.NET project</summary>
|
||||
<language>en-US</language>
|
||||
<tags>umbraco</tags>
|
||||
<dependencies>
|
||||
<dependency id="UmbracoCms.Core" version="[$version$]" />
|
||||
<!--
|
||||
note: dependencies are specified as [x.y.z,x.999999) eg [2.1.0,2.999999) and NOT [2.1.0,3.0.0) because
|
||||
the latter would pick anything below 3.0.0 and that includes prereleases such as 3.0.0-alpha, and we do
|
||||
not want this to happen as the alpha of the next major is, really, the next major already.
|
||||
-->
|
||||
<dependency id="Microsoft.AspNet.SignalR.Core" version="[2.2.3, 2.999999)" />
|
||||
<dependency id="Umbraco.ModelsBuilder.Ui" version="[8.0.0-alpha.20]" />
|
||||
</dependencies>
|
||||
</metadata>
|
||||
<files>
|
||||
<file src="$BuildTmp$\Configs\**" target="Content\Config" exclude="$BuildTmp$\Configs\Web.config.transform" />
|
||||
<file src="$BuildTmp$\WebApp\Views\**" target="Content\Views" exclude="$BuildTmp$\WebApp\Views\Web.config" />
|
||||
<file src="$BuildTmp$\WebApp\default.aspx" target="Content\default.aspx" />
|
||||
<file src="$BuildTmp$\WebApp\Global.asax" target="Content\Global.asax" />
|
||||
<file src="$BuildTmp$\WebApp\Web.config" target="UmbracoFiles\Web.config" />
|
||||
<file src="$BuildTmp$\WebApp\App_Browsers\**" target="UmbracoFiles\App_Browsers" />
|
||||
<file src="$BuildTmp$\WebApp\config\splashes\**" target="UmbracoFiles\Config\splashes" />
|
||||
<file src="$BuildTmp$\WebApp\config\BackOfficeTours\**" target="Content\Config\BackOfficeTours" />
|
||||
<file src="$BuildTmp$\WebApp\umbraco\**" target="UmbracoFiles\umbraco" />
|
||||
<file src="$BuildTmp$\WebApp\umbraco_client\**" target="UmbracoFiles\umbraco_client" />
|
||||
<file src="$BuildTmp$\WebApp\Media\Web.config" target="Content\Media\Web.config" />
|
||||
|
||||
<!-- these files are copied by install.ps1 -->
|
||||
<file src="$BuildTmp$\WebApp\Web.config" target="UmbracoFiles\Web.config" />
|
||||
<file src="$BuildTmp$\WebApp\umbraco\**" target="UmbracoFiles\umbraco" />
|
||||
<file src="$BuildTmp$\WebApp\config\splashes\**" target="UmbracoFiles\Config\splashes" />
|
||||
<file src="$BuildTmp$\WebApp\App_Plugins\ModelsBuilder\modelsbuilder.htm" target="Content\App_Plugins\ModelsBuilder\modelsbuilder.htm" />
|
||||
<file src="$BuildTmp$\WebApp\App_Plugins\ModelsBuilder\modelsbuilder.controller.js" target="Content\App_Plugins\ModelsBuilder\modelsbuilder.controller.js" />
|
||||
<file src="$BuildTmp$\WebApp\App_Plugins\ModelsBuilder\modelsbuilder.resource.js" target="Content\App_Plugins\ModelsBuilder\modelsbuilder.resource.js" />
|
||||
<file src="$BuildTmp$\WebApp\App_Plugins\ModelsBuilder\package.manifest" target="Content\App_Plugins\ModelsBuilder\package.manifest" />
|
||||
|
||||
<!-- tools -->
|
||||
<!-- beware! install.ps1 not supported by PackageReference -->
|
||||
<file src="tools\install.ps1" target="tools\install.ps1" />
|
||||
<file src="tools\Readme.txt" target="tools\Readme.txt" />
|
||||
<file src="tools\ReadmeUpgrade.txt" target="tools\ReadmeUpgrade.txt" />
|
||||
<file src="tools\install.ps1" target="tools\install.ps1" />
|
||||
<file src="tools\Readme.txt" target="tools\Readme.txt" />
|
||||
<file src="tools\ReadmeUpgrade.txt" target="tools\ReadmeUpgrade.txt" />
|
||||
<file src="tools\Web.config.install.xdt" target="Content\Web.config.install.xdt" />
|
||||
<file src="tools\applications.config.install.xdt" target="Content\config\applications.config.install.xdt" />
|
||||
<file src="tools\ClientDependency.config.install.xdt" target="Content\config\ClientDependency.config.install.xdt" />
|
||||
<file src="tools\Dashboard.config.install.xdt" target="Content\config\Dashboard.config.install.xdt" />
|
||||
<file src="tools\trees.config.install.xdt" target="Content\config\trees.config.install.xdt" />
|
||||
<file src="tools\umbracoSettings.config.install.xdt" target="Content\config\umbracoSettings.config.install.xdt" />
|
||||
<file src="tools\Views.Web.config.install.xdt" target="Views\Web.config.install.xdt" />
|
||||
|
||||
<!-- config transforms -->
|
||||
<!-- beware! config transforms not supported by PackageReference -->
|
||||
<file src="tools\Web.config.install.xdt" target="Content\Web.config.install.xdt" />
|
||||
<file src="tools\applications.config.install.xdt" target="Content\config\applications.config.install.xdt" />
|
||||
<file src="tools\ClientDependency.config.install.xdt" target="Content\config\ClientDependency.config.install.xdt" />
|
||||
<file src="tools\Dashboard.config.install.xdt" target="Content\config\Dashboard.config.install.xdt" />
|
||||
<file src="tools\trees.config.install.xdt" target="Content\config\trees.config.install.xdt" />
|
||||
<file src="tools\umbracoSettings.config.install.xdt" target="Content\config\umbracoSettings.config.install.xdt" />
|
||||
<file src="tools\Views.Web.config.install.xdt" target="Views\Web.config.install.xdt" /> <!-- FIXME Content\ !! and then... transform?! -->
|
||||
|
||||
<!-- UmbracoCms props and targets -->
|
||||
<file src="build\**" target="build" />
|
||||
</files>
|
||||
<file src="build\**" target="build" />
|
||||
</files>
|
||||
</package>
|
||||
|
||||
@@ -47,6 +47,9 @@
|
||||
<CustomFilesToInclude Include=".\umbraco\**\*">
|
||||
<Dir>umbraco</Dir>
|
||||
</CustomFilesToInclude>
|
||||
<CustomFilesToInclude Include=".\umbraco_client\**\*">
|
||||
<Dir>umbraco_client</Dir>
|
||||
</CustomFilesToInclude>
|
||||
<CustomFilesToInclude Include=".\Global.asax">
|
||||
<Dir>.</Dir>
|
||||
</CustomFilesToInclude>
|
||||
|
||||
@@ -1,26 +1,26 @@
|
||||
|
||||
_ _ __ __ ____ _____ _____ ____
|
||||
| | | | \/ | _ \| __ \ /\ / ____/ __ \
|
||||
_ _ __ __ ____ _____ _____ ____
|
||||
| | | | \/ | _ \| __ \ /\ / ____/ __ \
|
||||
| | | | \ / | |_) | |__) | / \ | | | | | |
|
||||
| | | | |\/| | _ <| _ / / /\ \| | | | | |
|
||||
| |__| | | | | |_) | | \ \ / ____ | |___| |__| |
|
||||
\____/|_| |_|____/|_| \_/_/ \_\_____\____/
|
||||
|
||||
\____/|_| |_|____/|_| \_/_/ \_\_____\____/
|
||||
|
||||
----------------------------------------------------
|
||||
|
||||
Don't forget to build!
|
||||
|
||||
|
||||
When upgrading your website using NuGet you should answer "No" to the questions to overwrite the Web.config
|
||||
file (and config files in the config folder).
|
||||
When upgrading your website using NuGet you should answer "No" to the questions to overwrite the Web.config
|
||||
file (and config files in the config folder).
|
||||
|
||||
This NuGet package includes build targets that extend the creation of a deploy package, which is generated by
|
||||
This NuGet package includes build targets that extend the creation of a deploy package, which is generated by
|
||||
Publishing from Visual Studio. The targets will only work once Publishing is configured, so if you don't use
|
||||
Publish this won't affect you.
|
||||
The following items will now be automatically included when creating a deploy package or publishing to the file
|
||||
system: umbraco, config\splashes and global.asax.
|
||||
The following items will now be automatically included when creating a deploy package or publishing to the file
|
||||
system: umbraco, umbraco_client, config\splashes and global.asax.
|
||||
|
||||
Please read the release notes on our.umbraco.com:
|
||||
https://our.umbraco.com/download/releases
|
||||
http://our.umbraco.com/contribute/releases
|
||||
|
||||
- Umbraco
|
||||
- Umbraco
|
||||
@@ -1,30 +1,39 @@
|
||||
|
||||
_ _ __ __ ____ _____ _____ ____
|
||||
| | | | \/ | _ \| __ \ /\ / ____/ __ \
|
||||
_ _ __ __ ____ _____ _____ ____
|
||||
| | | | \/ | _ \| __ \ /\ / ____/ __ \
|
||||
| | | | \ / | |_) | |__) | / \ | | | | | |
|
||||
| | | | |\/| | _ <| _ / / /\ \| | | | | |
|
||||
| |__| | | | | |_) | | \ \ / ____ | |___| |__| |
|
||||
\____/|_| |_|____/|_| \_/_/ \_\_____\____/
|
||||
|
||||
\____/|_| |_|____/|_| \_/_/ \_\_____\____/
|
||||
|
||||
----------------------------------------------------
|
||||
|
||||
*** IMPORTANT NOTICE FOR UPGRADES FROM VERSIONS BELOW 7.7.0 ***
|
||||
|
||||
Be sure to read the version specific upgrade information before proceeding:
|
||||
https://our.umbraco.com/documentation/Getting-Started/Setup/Upgrading/version-specific#version-7-7-0
|
||||
|
||||
Depending on the version you are upgrading from, you may need to make some changes to your web.config
|
||||
and you will need to be aware of the breaking changes listed there to see if these affect your installation.
|
||||
|
||||
|
||||
Don't forget to build!
|
||||
|
||||
We've done our best to transform your configuration files but in case something is not quite right: remember we
|
||||
backed up your files in App_Data\NuGetBackup so you can find the original files before they were transformed.
|
||||
|
||||
We've overwritten all the files in the Umbraco folder, these have been backed up in
|
||||
App_Data\NuGetBackup. We didn't overwrite the UI.xml file nor did we remove any files or folders that you or
|
||||
a package might have added. Only the existing files were overwritten. If you customized anything then make
|
||||
We've overwritten all the files in the Umbraco and Umbraco_Client folder, these have been backed up in
|
||||
App_Data\NuGetBackup. We didn't overwrite the UI.xml file nor did we remove any files or folders that you or
|
||||
a package might have added. Only the existing files were overwritten. If you customized anything then make
|
||||
sure to do a compare and merge with the NuGetBackup folder.
|
||||
|
||||
This NuGet package includes build targets that extend the creation of a deploy package, which is generated by
|
||||
This NuGet package includes build targets that extend the creation of a deploy package, which is generated by
|
||||
Publishing from Visual Studio. The targets will only work once Publishing is configured, so if you don't use
|
||||
Publish this won't affect you.
|
||||
The following items will now be automatically included when creating a deploy package or publishing to the file
|
||||
system: umbraco, config\splashes and global.asax.
|
||||
The following items will now be automatically included when creating a deploy package or publishing to the file
|
||||
system: umbraco, umbraco_client, config\splashes and global.asax.
|
||||
|
||||
Please read the release notes on our.umbraco.com:
|
||||
http://our.umbraco.com/contribute/releases
|
||||
|
||||
- Umbraco
|
||||
- Umbraco
|
||||
@@ -150,6 +150,10 @@
|
||||
|
||||
<runtime>
|
||||
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
|
||||
<dependentAssembly xdt:Transform="Insert">
|
||||
<assemblyIdentity name="log4net" publicKeyToken="669e0ddf0bb1aa2a" culture="neutral" />
|
||||
<bindingRedirect oldVersion="0.0.0.0-2.0.8.0" newVersion="2.0.8.0" />
|
||||
</dependentAssembly>
|
||||
<dependentAssembly xdt:Transform="Insert">
|
||||
<assemblyIdentity name="Microsoft.Owin" publicKeyToken="31bf3856ad364e35" culture="neutral" />
|
||||
<bindingRedirect oldVersion="0.0.0.0-4.0.0.0" newVersion="4.0.0.0" />
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
<?xml version="1.0"?>
|
||||
<applications xmlns:xdt="http://schemas.microsoft.com/XML-Document-Transform">
|
||||
<add alias="content" xdt:Locator="Match(alias)" xdt:Transform="SetAttributes(icon)" />
|
||||
<add alias="media" xdt:Locator="Match(alias)" xdt:Transform="SetAttributes(icon)" />
|
||||
<add alias="settings" xdt:Locator="Match(alias)" xdt:Transform="SetAttributes(icon)" />
|
||||
<add alias="developer" xdt:Locator="Match(alias)" xdt:Transform="SetAttributes(icon)" />
|
||||
<add alias="users" xdt:Locator="Match(alias)" xdt:Transform="SetAttributes(icon)" />
|
||||
<add alias="member" xdt:Locator="Match(alias)" xdt:Transform="SetAttributes(icon)" />
|
||||
<add alias="forms" name="Forms" sortOrder="6" xdt:Locator="Match(alias)" xdt:Transform="InsertIfMissing" />
|
||||
<add alias="translation" sortOrder="7" xdt:Locator="Match(alias)" xdt:Transform="SetAttributes(icon,sortOrder)" />
|
||||
</applications>
|
||||
<add alias="content" icon="traycontent" xdt:Locator="Match(alias)" xdt:Transform="SetAttributes(icon)" />
|
||||
<add alias="media" icon="traymedia" xdt:Locator="Match(alias)" xdt:Transform="SetAttributes(icon)" />
|
||||
<add alias="settings" icon="traysettings" xdt:Locator="Match(alias)" xdt:Transform="SetAttributes(icon)" />
|
||||
<add alias="developer" icon="traydeveloper" xdt:Locator="Match(alias)" xdt:Transform="SetAttributes(icon)" />
|
||||
<add alias="users" icon="trayusers" xdt:Locator="Match(alias)" xdt:Transform="SetAttributes(icon)" />
|
||||
<add alias="member" icon="traymember" xdt:Locator="Match(alias)" xdt:Transform="SetAttributes(icon)" />
|
||||
<add alias="forms" name="Forms" icon="icon-umb-contour" sortOrder="6" xdt:Locator="Match(alias)" xdt:Transform="InsertIfMissing" />
|
||||
<add alias="translation" icon="traytranslation" sortOrder="7" xdt:Locator="Match(alias)" xdt:Transform="SetAttributes(icon,sortOrder)" />
|
||||
</applications>
|
||||
@@ -33,6 +33,7 @@ if ($project) {
|
||||
robocopy $umbracoBinFolder $umbracoBinBackupPath /e /LOG:$copyLogsPath\UmbracoBinBackup.log
|
||||
|
||||
# Delete files Umbraco ships with
|
||||
if(Test-Path $umbracoBinFolder\log4net.dll) { Remove-Item $umbracoBinFolder\log4net.dll -Force -Confirm:$false }
|
||||
if(Test-Path $umbracoBinFolder\Microsoft.ApplicationBlocks.Data.dll) { Remove-Item $umbracoBinFolder\Microsoft.ApplicationBlocks.Data.dll -Force -Confirm:$false }
|
||||
if(Test-Path $umbracoBinFolder\System.Data.SqlServerCe.dll) { Remove-Item $umbracoBinFolder\System.Data.SqlServerCe.dll -Force -Confirm:$false }
|
||||
if(Test-Path $umbracoBinFolder\System.Data.SqlServerCe.Entity.dll) { Remove-Item $umbracoBinFolder\System.Data.SqlServerCe.Entity.dll -Force -Confirm:$false }
|
||||
|
||||
@@ -44,6 +44,14 @@ if ($project) {
|
||||
robocopy $umbracoFolder $umbracoBackupPath /e /LOG:$copyLogsPath\UmbracoBackup.log
|
||||
robocopy $umbracoFolderSource $umbracoFolder /is /it /e /xf UI.xml /LOG:$copyLogsPath\UmbracoCopy.log
|
||||
|
||||
$umbracoClientFolder = Join-Path $projectPath "Umbraco_Client"
|
||||
New-Item -ItemType Directory -Force -Path $umbracoClientFolder
|
||||
$umbracoClientFolderSource = Join-Path $installPath "UmbracoFiles\Umbraco_Client"
|
||||
$umbracoClientBackupPath = Join-Path $backupPath "Umbraco_Client"
|
||||
New-Item -ItemType Directory -Force -Path $umbracoClientBackupPath
|
||||
robocopy $umbracoClientFolder $umbracoClientBackupPath /e /LOG:$copyLogsPath\UmbracoClientBackup.log
|
||||
robocopy $umbracoClientFolderSource $umbracoClientFolder /is /it /e /LOG:$copyLogsPath\UmbracoClientCopy.log
|
||||
|
||||
$copyWebconfig = $true
|
||||
$destinationWebConfig = Join-Path $projectPath "Web.config"
|
||||
|
||||
@@ -77,7 +85,15 @@ if ($project) {
|
||||
$splashesDestination = Join-Path $projectPath "Config\splashes\"
|
||||
New-Item $splashesDestination -Type directory
|
||||
Copy-Item $splashesSource $splashesDestination -Force
|
||||
|
||||
|
||||
$sqlCe64Source = Join-Path $installPath "UmbracoFiles\bin\amd64\*"
|
||||
$sqlCe64Destination = Join-Path $projectPath "bin\amd64\"
|
||||
Copy-Item $sqlCe64Source $sqlCe64Destination -Force
|
||||
|
||||
$sqlCex86Source = Join-Path $installPath "UmbracoFiles\bin\x86\*"
|
||||
$sqlCex86Destination = Join-Path $projectPath "bin\x86\"
|
||||
Copy-Item $sqlCex86source $sqlCex86Destination -Force
|
||||
|
||||
$umbracoUIXMLSource = Join-Path $installPath "UmbracoFiles\Umbraco\Config\Create\UI.xml"
|
||||
$umbracoUIXMLDestination = Join-Path $projectPath "Umbraco\Config\Create\UI.xml"
|
||||
Copy-Item $umbracoUIXMLSource $umbracoUIXMLDestination -Force
|
||||
@@ -143,4 +159,4 @@ if ($project) {
|
||||
{
|
||||
$DTE.ItemOperations.OpenFile($toolsPath + '\ReadmeUpgrade.txt')
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -69,9 +69,6 @@
|
||||
$global:node_nodepath = $this.ClearEnvVar("NODEPATH")
|
||||
$global:node_npmcache = $this.ClearEnvVar("NPM_CONFIG_CACHE")
|
||||
$global:node_npmprefix = $this.ClearEnvVar("NPM_CONFIG_PREFIX")
|
||||
|
||||
# https://github.com/gruntjs/grunt-contrib-connect/issues/235
|
||||
$this.SetEnvVar("NODE_NO_HTTP2", "1")
|
||||
})
|
||||
|
||||
$ubuild.DefineMethod("RestoreNode",
|
||||
@@ -81,8 +78,6 @@
|
||||
$this.SetEnvVar("NODEPATH", $node_nodepath)
|
||||
$this.SetEnvVar("NPM_CONFIG_CACHE", $node_npmcache)
|
||||
$this.SetEnvVar("NPM_CONFIG_PREFIX", $node_npmprefix)
|
||||
|
||||
$ignore = $this.ClearEnvVar("NODE_NO_HTTP2")
|
||||
})
|
||||
|
||||
$ubuild.DefineMethod("CompileBelle",
|
||||
@@ -119,13 +114,17 @@
|
||||
&npm install >> $log 2>&1
|
||||
Write-Output ">> $? $($error.Count)" >> $log 2>&1
|
||||
|
||||
Write-Output "### install bower" >> $log 2>&1
|
||||
&npm install -g bower >> $log 2>&1
|
||||
$error.Clear() # that one fails 'cos bower is deprecated - ignore
|
||||
|
||||
Write-Output "### install gulp" >> $log 2>&1
|
||||
&npm install -g gulp >> $log 2>&1
|
||||
$error.Clear() # that one fails 'cos deprecated stuff - ignore
|
||||
|
||||
Write-Output "### install gulp-cli" >> $log 2>&1
|
||||
&npm install -g gulp-cli --quiet >> $log 2>&1
|
||||
$error.Clear() # that one fails 'cos some files not being removed - ignore
|
||||
if (-not $?) { throw "Failed to install gulp-cli" } # that one is expected to work
|
||||
|
||||
Write-Output "### gulp build for version $($this.Version.Release)" >> $log 2>&1
|
||||
&gulp build --buildversion=$this.Version.Release >> $log 2>&1
|
||||
@@ -400,15 +399,9 @@
|
||||
-Symbols -Verbosity detailed -outputDirectory "$($this.BuildOutput)" > "$($this.BuildTemp)\nupack.cmscore.log"
|
||||
if (-not $?) { throw "Failed to pack NuGet UmbracoCms.Core." }
|
||||
|
||||
&$this.BuildEnv.NuGet Pack "$nuspecs\UmbracoCms.Web.nuspec" `
|
||||
-Properties BuildTmp="$($this.BuildTemp)" `
|
||||
-Version "$($this.Version.Semver.ToString())" `
|
||||
-Symbols -Verbosity detailed -outputDirectory "$($this.BuildOutput)" > "$($this.BuildTemp)\nupack.cmsweb.log"
|
||||
if (-not $?) { throw "Failed to pack NuGet UmbracoCms.Web." }
|
||||
|
||||
&$this.BuildEnv.NuGet Pack "$nuspecs\UmbracoCms.nuspec" `
|
||||
-Properties BuildTmp="$($this.BuildTemp)" `
|
||||
-Version "$($this.Version.Semver.ToString())" `
|
||||
-Version $this.Version.Semver.ToString() `
|
||||
-Verbosity detailed -outputDirectory "$($this.BuildOutput)" > "$($this.BuildTemp)\nupack.cms.log"
|
||||
if (-not $?) { throw "Failed to pack NuGet UmbracoCms." }
|
||||
|
||||
@@ -424,7 +417,7 @@
|
||||
$ubuild.DefineMethod("VerifyNuGet",
|
||||
{
|
||||
$this.VerifyNuGetConsistency(
|
||||
("UmbracoCms", "UmbracoCms.Core", "UmbracoCms.Web"),
|
||||
("UmbracoCms", "UmbracoCms.Core"),
|
||||
("Umbraco.Core", "Umbraco.Web", "Umbraco.Web.UI", "Umbraco.Examine"))
|
||||
if ($this.OnError()) { return }
|
||||
})
|
||||
@@ -434,7 +427,7 @@
|
||||
Write-Host "Prepare Azure Gallery"
|
||||
$this.CopyFile("$($this.SolutionRoot)\build\Azure\azuregalleryrelease.ps1", $this.BuildOutput)
|
||||
})
|
||||
|
||||
|
||||
$ubuild.DefineMethod("Build",
|
||||
{
|
||||
$error.Clear()
|
||||
@@ -464,7 +457,6 @@
|
||||
if ($this.OnError()) { return }
|
||||
$this.PrepareAzureGallery()
|
||||
if ($this.OnError()) { return }
|
||||
Write-Host "Done"
|
||||
})
|
||||
|
||||
# ################################################################
|
||||
@@ -480,4 +472,5 @@
|
||||
$ubuild.Build()
|
||||
if ($ubuild.OnError()) { return }
|
||||
}
|
||||
Write-Host "Done"
|
||||
if ($get) { return $ubuild }
|
||||
|
||||
@@ -17,7 +17,7 @@ Assume positive intent and try to understand before being understood.
|
||||
|
||||
Treat others as you would like to be treated.
|
||||
|
||||
This also goes for treating the HQ with respect. For example: don’t promote products on [our.umbraco.com](https://our.umbraco.com) that directly compete with our commercial offerings which enables us to work for a sustainable Umbraco.
|
||||
This also goes for treating the HQ with respect. For example: don’t promote products on [our.umbraco.org](https://our.umbraco.org) that directly compete with our commercial offerings which enables us to work for a sustainable Umbraco.
|
||||
|
||||
## Open
|
||||
|
||||
@@ -82,7 +82,7 @@ These wonderful volunteers will provide you with a first reply to your PR, revie
|
||||
You can get in touch with [the PR team](#the-pr-team) in multiple ways, we love open conversations and we are a friendly bunch. No question you have is stupid. Any questions you have usually helps out multiple people with the same question. Ask away:
|
||||
|
||||
- If there's an existing issue on the issue tracker then that's a good place to leave questions and discuss how to start or move forward
|
||||
- Unsure where to start? Did something not work as expected? Try leaving a note in the ["Contributing to Umbraco"](https://our.umbraco.com/forum/contributing-to-umbraco-cms/) forum, the team monitors that one closely
|
||||
- Unsure where to start? Did something not work as expected? Try leaving a note in the ["Contributing to Umbraco"](https://our.umbraco.org/forum/contributing-to-umbraco-cms/) forum, the team monitors that one closely
|
||||
- We're also [active in the Gitter chatroom](https://gitter.im/umbraco/Umbraco-CMS)
|
||||
|
||||
## Code of Conduct
|
||||
@@ -31,7 +31,7 @@ Before creating bug reports, please check [this list](#before-submitting-a-bug-r
|
||||
|
||||
##### Before Submitting A Bug Report
|
||||
|
||||
* Most importantly, check **if you can reproduce the problem** in the [latest version of Umbraco](https://our.umbraco.com/download/). We might have already fixed your particular problem.
|
||||
* Most importantly, check **if you can reproduce the problem** in the [latest version of Umbraco](https://our.umbraco.org/download/). We might have already fixed your particular problem.
|
||||
* It also helps tremendously to check if the issue you're experiencing is present in **a clean install** of the Umbraco version you're currently using. Custom code can have side-effects that don't occur in a clean install.
|
||||
* **Use the Google**. Whatever you're experiencing, Google it plus "Umbraco" - usually you can get some pretty good hints from the search results, including open issues and further troubleshooting hints.
|
||||
* If you do find and existing issue has **and the issue is still open**, add a comment to the existing issue if you have additional information. If you have the same problem and no new info to add, just "star" the issue.
|
||||
@@ -65,11 +65,13 @@ Most of the suggestions in the [reporting bugs](#reporting-bugs) section also co
|
||||
Some additional hints that may be helpful:
|
||||
|
||||
* **Include screenshots and animated GIFs** which help you demonstrate the steps or point out the part of Umbraco which the suggestion is related to.
|
||||
* **Explain why this enhancement would be useful to most Umbraco users** and isn't something that can or should be implemented as a [community package](https://our.umbraco.com/projects/).
|
||||
* **Explain why this enhancement would be useful to most Umbraco users** and isn't something that can or should be implemented as a [community package](https://our.umbraco.org/projects/).
|
||||
|
||||
### Your First Code Contribution
|
||||
|
||||
Unsure where to begin contributing to Umbraco? You can start by looking through [these `Up for grabs` and issues](https://issues.umbraco.org/issues?q=&project=U4&tagValue=upforgrabs&release=&issueType=&search=search) or on the [new issue tracker](https://github.com/umbraco/Umbraco-CMS/issues?q=is%3Aopen+is%3Aissue+label%3Acommunity%2Fup-for-grabs).
|
||||
Unsure where to begin contributing to Umbraco? You can start by looking through [these `Up for grabs` and issues](http://issues.umbraco.org/issues/U4?q=%28project%3A+%7BU4%7D+Difficulty%3A+%7BVery+Easy%7D+%23Easy+%23Unresolved+Priority%3A+Normal+%23Major+%23Show-stopper+State%3A+-%7BIn+Progress%7D+sort+by%3A+votes+Affected+versions%3A+-6.*+Affected+versions%3A+-4.*%29+OR+%28tag%3A+%7BUp+For+Grabs%7D+%23Unresolved+%29).
|
||||
|
||||
The issue list is sorted by total number of upvotes. While not perfect, number of upvotes is a reasonable proxy for impact a given change will have.
|
||||
|
||||
### Pull Requests
|
||||
|
||||
@@ -78,7 +80,7 @@ The most successful pull requests usually look a like this:
|
||||
* Fill in the required template
|
||||
* Include screenshots and animated GIFs in your pull request whenever possible.
|
||||
* Unit tests, while optional are awesome, thank you!
|
||||
* New code is commented with documentation from which [the reference documentation](https://our.umbraco.com/documentation/Reference/) is generated
|
||||
* New code is commented with documentation from which [the reference documentation](https://our.umbraco.org/documentation/Reference/) is generated
|
||||
|
||||
Again, these are guidelines, not strict requirements.
|
||||
|
||||
@@ -114,8 +116,8 @@ There's two big areas that you should know about:
|
||||
|
||||
To find the general areas of something you're looking to fix or improve, have a look at the following two parts of the API documentation.
|
||||
|
||||
* [The AngularJS based backoffice files](https://our.umbraco.com/apidocs/ui/#/api) (to be found in `src\Umbraco.Web.UI.Client\src`)
|
||||
* [The rest](https://our.umbraco.com/apidocs/csharp/)
|
||||
* [The AngularJS based backoffice files](https://our.umbraco.org/apidocs/ui/#/api) (to be found in `src\Umbraco.Web.UI.Client\src`)
|
||||
* [The rest](https://our.umbraco.org/apidocs/csharp/)
|
||||
|
||||
### What branch should I target for my contributions?
|
||||
|
||||
@@ -127,7 +129,7 @@ We like to use [Gitflow as much as possible](https://jeffkreeftmeijer.com/git-fl
|
||||
|
||||
The easiest way to get started is to run `build.bat` which will build both the backoffice (also known as "Belle") and the Umbraco core. You can then easily start debugging from Visual Studio, or if you need to debug Belle you can run `gulp dev` in `src\Umbraco.Web.UI.Client`. See [this page](BUILD.md) for more details.
|
||||
|
||||
Alternatively, you can open `src\umbraco.sln` in Visual Studio 2017 (version 15.3 or higher, [the community edition is free](https://www.visualstudio.com/thank-you-downloading-visual-studio/?sku=Community&rel=15) for you to use to contribute to Open Source projects). In Visual Studio, find the Task Runner Explorer (in the View menu under Other Windows) and run the build task under the gulpfile.
|
||||
Alternatively, you can open `src\umbraco.sln` in Visual Studio 2017 ([the community edition is free](https://www.visualstudio.com/thank-you-downloading-visual-studio/?sku=Community&rel=15) for you to use to contribute to Open Source projects). In Visual Studio, find the Task Runner Explorer (in the View menu under Other Windows) and run the build task under the gulpfile.
|
||||
|
||||

|
||||
|
||||
@@ -154,4 +156,4 @@ git rebase upstream/dev-v7
|
||||
|
||||
In this command we're syncing with the `dev-v7` branch, but you can of course choose another one if needed.
|
||||
|
||||
(More info on how this works: [http://robots.thoughtbot.com/post/5133345960/keeping-a-git-fork-updated](http://robots.thoughtbot.com/post/5133345960/keeping-a-git-fork-updated))
|
||||
(More info on how this works: [http://robots.thoughtbot.com/post/5133345960/keeping-a-git-fork-updated](http://robots.thoughtbot.com/post/5133345960/keeping-a-git-fork-updated))
|
||||
@@ -0,0 +1,11 @@
|
||||
### Prerequisites
|
||||
|
||||
- [ ] I have written a descriptive pull-request title
|
||||
- [ ] I have linked this PR to an issue on the tracker at http://issues.umbraco.org
|
||||
|
||||
### Description
|
||||
<!-- A description of the changes proposed in the pull-request -->
|
||||
|
||||
|
||||
|
||||
<!-- Thanks for contributing to Umbraco CMS! -->
|
||||
@@ -1,18 +1,9 @@
|
||||
_You are browsing the Umbraco v8 branch. Umbraco 8 is currently under development._
|
||||
_You are browsing the Umbraco v8 branch._
|
||||
|
||||
_Looking for Umbraco version 7? [Click here](https://github.com/umbraco/Umbraco-CMS) to go to the v7 branch._
|
||||
|
||||
_Ready to try out Version 8? [See the quick start guide](V8_GETTING_STARTED.md)._
|
||||
|
||||
When is Umbraco 8 coming?
|
||||
=========================
|
||||
When it's ready. We're done with the major parts of the architecture work and are focusing on three seperate tracks to prepare Umbraco 8 for release:
|
||||
1) Editor Track (_currently in progress_). Without editors, there's no market for Umbraco. So we want to make sure that Umbraco 8 is full of love for editors.
|
||||
2) Partner Track. Without anyone implementing Umbraco, there's nothing for editors to update. So we want to make sure that Umbraco 8 is a joy to implement
|
||||
3) Contributor Track. Without our fabulous ecosystem of both individual Umbracians and 3rd party ISVs, Umbraco wouldn't be as rich a platform as it is today. We want to make sure that it's easy, straight forward and as backwards-compatible as possible to create packages for Umbraco
|
||||
|
||||
Once a track is done, we start releasing previews where we ask people to test the features we believe are ready. While the testing is going on and we gather feedback, we move on to the next track. This doesn't mean that there hasn't already been work done in the area, but that a track focuses on finalizing, polishing and preparing the features for release.
|
||||
|
||||
Umbraco CMS
|
||||
===========
|
||||
The friendliest, most flexible and fastest growing ASP.NET CMS used by more than 443,000 websites worldwide: [https://umbraco.com](https://umbraco.com)
|
||||
@@ -57,5 +48,4 @@ Umbraco is contribution focused and community driven. If you want to contribute
|
||||
|
||||
Another way you can contribute to Umbraco is by providing issue reports. For information on how to submit an issue report refer to our [online guide for reporting issues](CONTRIBUTING_DETAILED.md#reporting-bugs).
|
||||
|
||||
You can comment and report issues on the [github issue tracker](https://github.com/umbraco/Umbraco-CMS/issues).
|
||||
Since [September 2018](https://umbraco.com/blog/a-second-take-on-umbraco-issue-tracker-hello-github-issues/) the old issue tracker is in read only mode, but can still be found at [http://issues.umbraco.org](http://issues.umbraco.org).
|
||||
To view existing issues, please visit [http://issues.umbraco.org](http://issues.umbraco.org).
|
||||
@@ -23,7 +23,7 @@ We recommend running the site with the Visual Studio since you'll be able to rem
|
||||
|
||||
### Making code changes
|
||||
|
||||
* _[The process for making code changes in v8 is the same as v7](https://github.com/umbraco/Umbraco-CMS/blob/dev-v7/.github/CONTRIBUTING.md)_
|
||||
* _[The process for making code changes in v8 is the same as v7](https://github.com/umbraco/Umbraco-CMS/blob/dev-v7/docs/CONTRIBUTING.md)_
|
||||
* Any .NET changes you make you just need to compile
|
||||
* Any Angular/JS changes you make you will need to make sure you are running the Gulp build. Easiest way to do this is from within Visual Studio in the `Task Runner Explorer`. You can find this window by pressing `ctrl + q` and typing in `Task Runner Explorer`. In this window you'll see all Gulp tasks, double click on the `dev` task, this will compile the angular solution and start a file watcher, then any html/js changes you make are automatically built.
|
||||
* When making js changes, you should have the chrome developer tools open to ensure that cache is disabled
|
||||
@@ -33,5 +33,5 @@ We recommend running the site with the Visual Studio since you'll be able to rem
|
||||
|
||||
We are keeping track of [known issues and limitations here](http://issues.umbraco.org/issue/U4-11279). These line items will eventually be turned into actual tasks to be worked on. Feel free to help us keep this list updated if you find issues and even help fix some of these items. If there is a particular item you'd like to help fix please mention this on the task and we'll create a sub task for the item to continue discussion there.
|
||||
|
||||
There's [a list of tasks for v8 that haven't been completed](https://issues.umbraco.org/issues?q=&project=U4&tagValue=&release=8.0.0&issueType=&resolvedState=open&search=search). If you are interested in helping out with any of these please mention this on the task. This list will be constantly updated as we begin to document and design some of the other tasks that still need to get done.
|
||||
There's [a list of tasks for v8 that haven't been completed](http://issues.umbraco.org/issues/U4?q=Due+in+version%3A+8.0.0+%23Unresolved+). If you are interested in helping out with any of these please mention this on the task. This list will be constantly updated as we begin to document and design some of the other tasks that still need to get done.
|
||||
|
||||
|
Before Width: | Height: | Size: 12 KiB After Width: | Height: | Size: 12 KiB |
|
Before Width: | Height: | Size: 26 KiB After Width: | Height: | Size: 26 KiB |
|
Before Width: | Height: | Size: 18 KiB After Width: | Height: | Size: 18 KiB |
|
Before Width: | Height: | Size: 12 KiB After Width: | Height: | Size: 12 KiB |
|
Before Width: | Height: | Size: 20 KiB After Width: | Height: | Size: 20 KiB |
|
Before Width: | Height: | Size: 27 KiB After Width: | Height: | Size: 27 KiB |
@@ -8,7 +8,7 @@
|
||||
<meta name="title" content="{{#title}}{{title}}{{/title}}{{^title}}{{>partials/title}}{{/title}} {{#_appTitle}}| {{_appTitle}} {{/_appTitle}}">
|
||||
<meta name="generator" content="docfx {{_docfxVersion}}">
|
||||
{{#_description}}<meta name="description" content="{{_description}}">{{/_description}}
|
||||
<link rel="icon" type="image/png" href="https://our.umbraco.com/assets/images/app-icons/favicon.png">
|
||||
<link rel="icon" type="image/png" href="https://our.umbraco.org/assets/images/app-icons/favicon.png">
|
||||
<link rel="stylesheet" href="{{_rel}}styles/docfx.vendor.css">
|
||||
<link rel="stylesheet" href="{{_rel}}styles/docfx.css">
|
||||
<link rel="stylesheet" href="{{_rel}}styles/main.css">
|
||||
|
||||
@@ -63,7 +63,7 @@ a:focus {
|
||||
}
|
||||
|
||||
.navbar-header .navbar-brand {
|
||||
background: url(https://our.umbraco.com/assets/images/logo.svg) left center no-repeat;
|
||||
background: url(https://our.umbraco.org/assets/images/logo.svg) left center no-repeat;
|
||||
background-size: 40px auto;
|
||||
width:50px;
|
||||
}
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
using System.Resources;
|
||||
|
||||
[assembly: AssemblyCompany("Umbraco")]
|
||||
[assembly: AssemblyCopyright("Copyright © Umbraco 2018")]
|
||||
[assembly: AssemblyCopyright("Copyright © Umbraco 2017")]
|
||||
[assembly: AssemblyTrademark("")]
|
||||
[assembly: AssemblyCulture("")]
|
||||
|
||||
@@ -19,4 +19,4 @@ using System.Resources;
|
||||
|
||||
// these are FYI and changed automatically
|
||||
[assembly: AssemblyFileVersion("8.0.0")]
|
||||
[assembly: AssemblyInformationalVersion("8.0.0-alpha.52")]
|
||||
[assembly: AssemblyInformationalVersion("8.0.0-alpha.44")]
|
||||
|
||||
@@ -3,6 +3,7 @@ using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using System.Web;
|
||||
using Umbraco.Core.Components;
|
||||
using Umbraco.Core.Events;
|
||||
using Umbraco.Core.Models;
|
||||
using Umbraco.Core.Models.Membership;
|
||||
@@ -10,7 +11,7 @@ using Umbraco.Core.Security;
|
||||
using Umbraco.Core.Services;
|
||||
using Umbraco.Core.Services.Implement;
|
||||
|
||||
namespace Umbraco.Core.Components
|
||||
namespace Umbraco.Core.Auditing
|
||||
{
|
||||
public sealed class AuditEventsComponent : UmbracoComponentBase, IUmbracoCoreComponent
|
||||
{
|
||||
@@ -52,6 +53,18 @@ namespace Umbraco.Core.Components
|
||||
_userService = userService;
|
||||
_entityService = entityService;
|
||||
|
||||
//BackOfficeUserManager.AccountLocked += ;
|
||||
//BackOfficeUserManager.AccountUnlocked += ;
|
||||
BackOfficeUserManager.ForgotPasswordRequested += OnForgotPasswordRequest;
|
||||
BackOfficeUserManager.ForgotPasswordChangedSuccess += OnForgotPasswordChange;
|
||||
BackOfficeUserManager.LoginFailed += OnLoginFailed;
|
||||
//BackOfficeUserManager.LoginRequiresVerification += ;
|
||||
BackOfficeUserManager.LoginSuccess += OnLoginSuccess;
|
||||
BackOfficeUserManager.LogoutSuccess += OnLogoutSuccess;
|
||||
BackOfficeUserManager.PasswordChanged += OnPasswordChanged;
|
||||
BackOfficeUserManager.PasswordReset += OnPasswordReset;
|
||||
//BackOfficeUserManager.ResetAccessFailedCount += ;
|
||||
|
||||
UserService.SavedUserGroup += OnSavedUserGroupWithUsers;
|
||||
|
||||
UserService.SavedUser += OnSavedUser;
|
||||
@@ -242,6 +255,64 @@ namespace Umbraco.Core.Components
|
||||
"umbraco/user/delete", "delete user");
|
||||
}
|
||||
|
||||
private void OnLoginSuccess(object sender, EventArgs args)
|
||||
{
|
||||
if (args is IdentityAuditEventArgs identityArgs)
|
||||
{
|
||||
var performingUser = GetPerformingUser(identityArgs.PerformingUser);
|
||||
WriteAudit(performingUser, identityArgs.AffectedUser, identityArgs.IpAddress, "umbraco/user/sign-in/login", "login success");
|
||||
}
|
||||
}
|
||||
|
||||
private void OnLogoutSuccess(object sender, EventArgs args)
|
||||
{
|
||||
if (args is IdentityAuditEventArgs identityArgs)
|
||||
{
|
||||
var performingUser = GetPerformingUser(identityArgs.PerformingUser);
|
||||
WriteAudit(performingUser, identityArgs.AffectedUser, identityArgs.IpAddress, "umbraco/user/sign-in/logout", "logout success");
|
||||
}
|
||||
}
|
||||
|
||||
private void OnPasswordReset(object sender, EventArgs args)
|
||||
{
|
||||
if (args is IdentityAuditEventArgs identityArgs && identityArgs.PerformingUser >= 0)
|
||||
{
|
||||
WriteAudit(identityArgs.PerformingUser, identityArgs.AffectedUser, identityArgs.IpAddress, "umbraco/user/password/reset", "password reset");
|
||||
}
|
||||
}
|
||||
|
||||
private void OnPasswordChanged(object sender, EventArgs args)
|
||||
{
|
||||
if (args is IdentityAuditEventArgs identityArgs && identityArgs.PerformingUser >= 0)
|
||||
{
|
||||
WriteAudit(identityArgs.PerformingUser, identityArgs.AffectedUser, identityArgs.IpAddress, "umbraco/user/password/change", "password change");
|
||||
}
|
||||
}
|
||||
|
||||
private void OnLoginFailed(object sender, EventArgs args)
|
||||
{
|
||||
if (args is IdentityAuditEventArgs identityArgs && identityArgs.PerformingUser >= 0)
|
||||
{
|
||||
WriteAudit(identityArgs.PerformingUser, 0, identityArgs.IpAddress, "umbraco/user/sign-in/failed", "login failed", affectedDetails: "");
|
||||
}
|
||||
}
|
||||
|
||||
private void OnForgotPasswordChange(object sender, EventArgs args)
|
||||
{
|
||||
if (args is IdentityAuditEventArgs identityArgs && identityArgs.PerformingUser >= 0)
|
||||
{
|
||||
WriteAudit(identityArgs.PerformingUser, identityArgs.AffectedUser, identityArgs.IpAddress, "umbraco/user/password/forgot/change", "password forgot/change");
|
||||
}
|
||||
}
|
||||
|
||||
private void OnForgotPasswordRequest(object sender, EventArgs args)
|
||||
{
|
||||
if (args is IdentityAuditEventArgs identityArgs && identityArgs.PerformingUser >= 0)
|
||||
{
|
||||
WriteAudit(identityArgs.PerformingUser, identityArgs.AffectedUser, identityArgs.IpAddress, "umbraco/user/password/forgot/request", "password forgot/request");
|
||||
}
|
||||
}
|
||||
|
||||
private void WriteAudit(int performingId, int affectedId, string ipAddress, string eventType, string eventDetails, string affectedDetails = null)
|
||||
{
|
||||
var performingUser = _userService.GetUserById(performingId);
|
||||
@@ -1,8 +1,10 @@
|
||||
using System;
|
||||
using System.ComponentModel;
|
||||
using System.Threading;
|
||||
using System.Web;
|
||||
using Umbraco.Core.Security;
|
||||
|
||||
namespace Umbraco.Web.Security
|
||||
namespace Umbraco.Core.Auditing
|
||||
{
|
||||
/// <summary>
|
||||
/// This class is used by events raised from hthe BackofficeUserManager
|
||||
@@ -18,7 +18,10 @@ namespace Umbraco.Core
|
||||
// this only gets called when an assembly can't be resolved
|
||||
AppDomain.CurrentDomain.AssemblyResolve += CurrentDomain_AssemblyResolve;
|
||||
}
|
||||
|
||||
|
||||
private static readonly Regex Log4NetAssemblyPattern = new Regex("log4net, Version=([\\d\\.]+?), Culture=neutral, PublicKeyToken=\\w+$", RegexOptions.Compiled);
|
||||
private const string Log4NetReplacement = "log4net, Version=2.0.8.0, Culture=neutral, PublicKeyToken=669e0ddf0bb1aa2a";
|
||||
|
||||
/// <summary>
|
||||
/// This is used to do an assembly binding redirect via code - normally required due to signature changes in assemblies
|
||||
/// </summary>
|
||||
@@ -27,6 +30,12 @@ namespace Umbraco.Core
|
||||
/// <returns></returns>
|
||||
private static Assembly CurrentDomain_AssemblyResolve(object sender, ResolveEventArgs args)
|
||||
{
|
||||
//log4net:
|
||||
if (Log4NetAssemblyPattern.IsMatch(args.Name) && args.Name != Log4NetReplacement)
|
||||
{
|
||||
return Assembly.Load(Log4NetAssemblyPattern.Replace(args.Name, Log4NetReplacement));
|
||||
}
|
||||
|
||||
//AutoMapper:
|
||||
// ensure the assembly is indeed AutoMapper and that the PublicKeyToken is null before trying to Load again
|
||||
// do NOT just replace this with 'return Assembly', as it will cause an infinite loop -> stackoverflow
|
||||
|
||||
@@ -40,4 +40,4 @@ namespace Umbraco.Core.Collections
|
||||
public static bool operator !=(CompositeIntStringKey key1, CompositeIntStringKey key2)
|
||||
=> key1._key2 != key2._key2 || key1._key1 != key2._key1;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -14,31 +14,30 @@ namespace Umbraco.Core.Collections
|
||||
/// </remarks>
|
||||
/// <typeparam name="TValue">The type of elements contained in the BindableCollection</typeparam>
|
||||
/// <typeparam name="TKey">The type of the indexing key</typeparam>
|
||||
public class ObservableDictionary<TKey, TValue> : ObservableCollection<TValue>, IReadOnlyDictionary<TKey, TValue>, IDictionary<TKey, TValue>
|
||||
public class ObservableDictionary<TKey, TValue> : ObservableCollection<TValue>
|
||||
{
|
||||
protected Dictionary<TKey, int> Indecies { get; }
|
||||
protected Func<TValue, TKey> KeySelector { get; }
|
||||
protected Dictionary<TKey, int> Indecies = new Dictionary<TKey, int>();
|
||||
protected Func<TValue, TKey> KeySelector;
|
||||
|
||||
/// <summary>
|
||||
/// Create new ObservableDictionary
|
||||
/// </summary>
|
||||
/// <param name="keySelector">Selector function to create key from value</param>
|
||||
/// <param name="equalityComparer">The equality comparer to use when comparing keys, or null to use the default comparer.</param>
|
||||
public ObservableDictionary(Func<TValue, TKey> keySelector, IEqualityComparer<TKey> equalityComparer = null)
|
||||
public ObservableDictionary(Func<TValue, TKey> keySelector)
|
||||
: base()
|
||||
{
|
||||
KeySelector = keySelector ?? throw new ArgumentException("keySelector");
|
||||
Indecies = new Dictionary<TKey, int>(equalityComparer);
|
||||
if (keySelector == null) throw new ArgumentException("keySelector");
|
||||
KeySelector = keySelector;
|
||||
}
|
||||
|
||||
#region Protected Methods
|
||||
|
||||
protected override void InsertItem(int index, TValue item)
|
||||
{
|
||||
var key = KeySelector(item);
|
||||
if (Indecies.ContainsKey(key))
|
||||
throw new DuplicateKeyException(key.ToString());
|
||||
|
||||
if (index != Count)
|
||||
if (index != this.Count)
|
||||
{
|
||||
foreach (var k in Indecies.Keys.Where(k => Indecies[k] >= index).ToList())
|
||||
{
|
||||
@@ -48,6 +47,7 @@ namespace Umbraco.Core.Collections
|
||||
|
||||
base.InsertItem(index, item);
|
||||
Indecies[key] = index;
|
||||
|
||||
}
|
||||
|
||||
protected override void ClearItems()
|
||||
@@ -56,6 +56,7 @@ namespace Umbraco.Core.Collections
|
||||
Indecies.Clear();
|
||||
}
|
||||
|
||||
|
||||
protected override void RemoveItem(int index)
|
||||
{
|
||||
var item = this[index];
|
||||
@@ -70,10 +71,9 @@ namespace Umbraco.Core.Collections
|
||||
Indecies[k]--;
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
public bool ContainsKey(TKey key)
|
||||
public virtual bool ContainsKey(TKey key)
|
||||
{
|
||||
return Indecies.ContainsKey(key);
|
||||
}
|
||||
@@ -83,10 +83,10 @@ namespace Umbraco.Core.Collections
|
||||
/// </summary>
|
||||
/// <param name="key">Key of element to replace</param>
|
||||
/// <returns></returns>
|
||||
public TValue this[TKey key]
|
||||
public virtual TValue this[TKey key]
|
||||
{
|
||||
|
||||
get => this[Indecies[key]];
|
||||
get { return this[Indecies[key]]; }
|
||||
set
|
||||
{
|
||||
//confirm key matches
|
||||
@@ -95,7 +95,7 @@ namespace Umbraco.Core.Collections
|
||||
|
||||
if (!Indecies.ContainsKey(key))
|
||||
{
|
||||
Add(value);
|
||||
this.Add(value);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -112,10 +112,9 @@ namespace Umbraco.Core.Collections
|
||||
///
|
||||
/// <exception cref="InvalidOperationException"></exception>
|
||||
/// <returns>False if key not found</returns>
|
||||
public bool Replace(TKey key, TValue value)
|
||||
public virtual bool Replace(TKey key, TValue value)
|
||||
{
|
||||
if (!Indecies.ContainsKey(key)) return false;
|
||||
|
||||
//confirm key matches
|
||||
if (!KeySelector(value).Equals(key))
|
||||
throw new InvalidOperationException("Key of new value does not match");
|
||||
@@ -125,11 +124,11 @@ namespace Umbraco.Core.Collections
|
||||
|
||||
}
|
||||
|
||||
public bool Remove(TKey key)
|
||||
public virtual bool Remove(TKey key)
|
||||
{
|
||||
if (!Indecies.ContainsKey(key)) return false;
|
||||
|
||||
RemoveAt(Indecies[key]);
|
||||
this.RemoveAt(Indecies[key]);
|
||||
return true;
|
||||
|
||||
}
|
||||
@@ -139,13 +138,12 @@ namespace Umbraco.Core.Collections
|
||||
/// </summary>
|
||||
/// <param name="currentKey"></param>
|
||||
/// <param name="newKey"></param>
|
||||
public void ChangeKey(TKey currentKey, TKey newKey)
|
||||
public virtual void ChangeKey(TKey currentKey, TKey newKey)
|
||||
{
|
||||
if (!Indecies.ContainsKey(currentKey))
|
||||
{
|
||||
throw new InvalidOperationException("No item with the key " + currentKey + "was found in the collection");
|
||||
}
|
||||
|
||||
if (ContainsKey(newKey))
|
||||
{
|
||||
throw new DuplicateKeyException(newKey.ToString());
|
||||
@@ -157,81 +155,16 @@ namespace Umbraco.Core.Collections
|
||||
Indecies.Add(newKey, currentIndex);
|
||||
}
|
||||
|
||||
#region IDictionary and IReadOnlyDictionary implementation
|
||||
|
||||
public bool TryGetValue(TKey key, out TValue val)
|
||||
{
|
||||
if (Indecies.TryGetValue(key, out var index))
|
||||
{
|
||||
val = this[index];
|
||||
return true;
|
||||
}
|
||||
val = default;
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns all keys
|
||||
/// </summary>
|
||||
public IEnumerable<TKey> Keys => Indecies.Keys;
|
||||
|
||||
/// <summary>
|
||||
/// Returns all values
|
||||
/// </summary>
|
||||
public IEnumerable<TValue> Values => base.Items;
|
||||
|
||||
ICollection<TKey> IDictionary<TKey, TValue>.Keys => Indecies.Keys;
|
||||
|
||||
//this will never be used
|
||||
ICollection<TValue> IDictionary<TKey, TValue>.Values => Values.ToList();
|
||||
|
||||
bool ICollection<KeyValuePair<TKey, TValue>>.IsReadOnly => false;
|
||||
|
||||
IEnumerator<KeyValuePair<TKey, TValue>> IEnumerable<KeyValuePair<TKey, TValue>>.GetEnumerator()
|
||||
{
|
||||
foreach (var i in Values)
|
||||
{
|
||||
var key = KeySelector(i);
|
||||
yield return new KeyValuePair<TKey, TValue>(key, i);
|
||||
}
|
||||
}
|
||||
|
||||
void IDictionary<TKey, TValue>.Add(TKey key, TValue value)
|
||||
{
|
||||
Add(value);
|
||||
}
|
||||
|
||||
void ICollection<KeyValuePair<TKey, TValue>>.Add(KeyValuePair<TKey, TValue> item)
|
||||
{
|
||||
Add(item.Value);
|
||||
}
|
||||
|
||||
bool ICollection<KeyValuePair<TKey, TValue>>.Contains(KeyValuePair<TKey, TValue> item)
|
||||
{
|
||||
return ContainsKey(item.Key);
|
||||
}
|
||||
|
||||
void ICollection<KeyValuePair<TKey, TValue>>.CopyTo(KeyValuePair<TKey, TValue>[] array, int arrayIndex)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
bool ICollection<KeyValuePair<TKey, TValue>>.Remove(KeyValuePair<TKey, TValue> item)
|
||||
{
|
||||
return Remove(item.Key);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
internal class DuplicateKeyException : Exception
|
||||
{
|
||||
|
||||
public string Key { get; private set; }
|
||||
public DuplicateKeyException(string key)
|
||||
: base("Attempted to insert duplicate key \"" + key + "\" in collection.")
|
||||
: base("Attempted to insert duplicate key " + key + " in collection")
|
||||
{
|
||||
Key = key;
|
||||
}
|
||||
|
||||
public string Key { get; }
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -111,15 +111,15 @@ namespace Umbraco.Core.Components
|
||||
catch (Exception e)
|
||||
{
|
||||
// in case of an error, force-dump everything to log
|
||||
_logger.Info<BootLoader>("Component Report:\r\n{ComponentReport}", GetComponentsReport(requirements));
|
||||
_logger.Error<BootLoader>(e, "Failed to sort compontents.");
|
||||
_logger.Info<BootLoader>(() => GetComponentsReport(requirements));
|
||||
_logger.Error<BootLoader>("Failed to sort components.", e);
|
||||
throw;
|
||||
}
|
||||
|
||||
// bit verbose but should help for troubleshooting
|
||||
var text = "Ordered Components: " + Environment.NewLine + string.Join(Environment.NewLine, sortedComponentTypes) + Environment.NewLine;
|
||||
Console.WriteLine(text);
|
||||
_logger.Debug<BootLoader>("Ordered Components: {SortedComponentTypes}", sortedComponentTypes);
|
||||
_logger.Debug<BootLoader>(text);
|
||||
|
||||
return sortedComponentTypes;
|
||||
}
|
||||
|
||||
@@ -63,6 +63,8 @@ namespace Umbraco.Core.Composing.CompositionRoots
|
||||
container.RegisterSingleton<IRelationTypeRepository, RelationTypeRepository>();
|
||||
container.RegisterSingleton<IServerRegistrationRepository, ServerRegistrationRepository>();
|
||||
container.RegisterSingleton<ITagRepository, TagRepository>();
|
||||
container.RegisterSingleton<ITaskRepository, TaskRepository>();
|
||||
container.RegisterSingleton<ITaskTypeRepository, TaskTypeRepository>();
|
||||
container.RegisterSingleton<ITemplateRepository, TemplateRepository>();
|
||||
container.RegisterSingleton<IUserGroupRepository, UserGroupRepository>();
|
||||
container.RegisterSingleton<IUserRepository, UserRepository>();
|
||||
|
||||
@@ -28,6 +28,7 @@ namespace Umbraco.Core.Composing.CompositionRoots
|
||||
// register the services
|
||||
container.RegisterSingleton<IKeyValueService, KeyValueService>();
|
||||
container.RegisterSingleton<IPublicAccessService, PublicAccessService>();
|
||||
container.RegisterSingleton<ITaskService, TaskService>();
|
||||
container.RegisterSingleton<IDomainService, DomainService>();
|
||||
container.RegisterSingleton<IAuditService, AuditService>();
|
||||
container.RegisterSingleton<ITagService, TagService>();
|
||||
|
||||
@@ -58,7 +58,6 @@ namespace Umbraco.Core.Composing
|
||||
// resets *everything* that is 'current'
|
||||
internal static void Reset()
|
||||
{
|
||||
_container?.Dispose();
|
||||
_container = null;
|
||||
|
||||
_shortStringHelper = null;
|
||||
@@ -159,9 +158,6 @@ namespace Umbraco.Core.Composing
|
||||
public static IPublishedValueFallback PublishedValueFallback
|
||||
=> _publishedValueFallback ?? Container.GetInstance<IPublishedValueFallback>() ?? new NoopPublishedValueFallback();
|
||||
|
||||
public static IVariationContextAccessor VariationContextAccessor
|
||||
=> Container.GetInstance<IVariationContextAccessor>();
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
||||
@@ -148,7 +148,7 @@ namespace Umbraco.Core.Composing
|
||||
catch (FileNotFoundException ex)
|
||||
{
|
||||
//this will occur if it cannot load the assembly
|
||||
Current.Logger.Error(typeof(TypeFinder), ex, "Could not load assembly App_Code");
|
||||
Current.Logger.Error(typeof(TypeFinder), "Could not load assembly App_Code", ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -224,6 +224,7 @@ namespace Umbraco.Core.Composing
|
||||
"Dynamic,",
|
||||
"HtmlDiff,",
|
||||
"Iesi.Collections,",
|
||||
"log4net,",
|
||||
"Microsoft.",
|
||||
"Newtonsoft.",
|
||||
"NHibernate.",
|
||||
@@ -439,7 +440,7 @@ namespace Umbraco.Core.Composing
|
||||
}
|
||||
catch (TypeLoadException ex)
|
||||
{
|
||||
Current.Logger.Error(typeof(TypeFinder), ex, "Could not query types on {Assembly} assembly, this is most likely due to this assembly not being compatible with the current Umbraco version", assembly);
|
||||
Current.Logger.Error(typeof(TypeFinder), $"Could not query types on {assembly} assembly, this is most likely due to this assembly not being compatible with the current Umbraco version", ex);
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -505,7 +506,7 @@ namespace Umbraco.Core.Composing
|
||||
}
|
||||
catch (TypeLoadException ex)
|
||||
{
|
||||
Current.Logger.Error(typeof(TypeFinder), ex, "Could not query types on {Assembly} assembly, this is most likely due to this assembly not being compatible with the current Umbraco version", assembly);
|
||||
Current.Logger.Error(typeof(TypeFinder), $"Could not query types on {assembly} assembly, this is most likely due to this assembly not being compatible with the current Umbraco version", ex);
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -572,7 +573,7 @@ namespace Umbraco.Core.Composing
|
||||
if (NotifiedLoadExceptionAssemblies.Contains(a.FullName) == false)
|
||||
{
|
||||
NotifiedLoadExceptionAssemblies.Add(a.FullName);
|
||||
Current.Logger.Warn(typeof (TypeFinder), ex, "Could not load all types from {TypeName}.", a.GetName().Name);
|
||||
Current.Logger.Warn(typeof (TypeFinder), ex, $"Could not load all types from {a.GetName().Name}.");
|
||||
}
|
||||
}
|
||||
return rex.Types.WhereNotNull().ToArray();
|
||||
|
||||
@@ -494,7 +494,7 @@ namespace Umbraco.Core.Composing
|
||||
if (--attempts == 0)
|
||||
throw;
|
||||
|
||||
_logger.Logger.Debug<TypeLoader>("Attempted to get filestream for file {Path} failed, {NumberOfAttempts} attempts left, pausing for {PauseMilliseconds} milliseconds", path, attempts, pauseMilliseconds);
|
||||
_logger.Logger.Debug<TypeLoader>(() => $"Attempted to get filestream for file {path} failed, {attempts} attempts left, pausing for {pauseMilliseconds} milliseconds");
|
||||
Thread.Sleep(pauseMilliseconds);
|
||||
}
|
||||
}
|
||||
@@ -645,7 +645,7 @@ namespace Umbraco.Core.Composing
|
||||
if (typeList != null)
|
||||
{
|
||||
// need to put some logging here to try to figure out why this is happening: http://issues.umbraco.org/issue/U4-3505
|
||||
_logger.Logger.Debug<TypeLoader>("Getting {TypeName}: found a cached type list.", GetName(baseType, attributeType));
|
||||
_logger.Logger.Debug<TypeLoader>(() => $"Getting {GetName(baseType, attributeType)}: found a cached type list.");
|
||||
return typeList.Types;
|
||||
}
|
||||
|
||||
@@ -676,7 +676,7 @@ namespace Umbraco.Core.Composing
|
||||
// so in this instance there will never be a result.
|
||||
if (cacheResult.Exception is CachedTypeNotFoundInFileException || cacheResult.Success == false)
|
||||
{
|
||||
_logger.Logger.Debug<TypeLoader>("Getting {TypeName}: failed to load from cache file, must scan assemblies.", GetName(baseType, attributeType));
|
||||
_logger.Logger.Debug<TypeLoader>(() => $"Getting {GetName(baseType, attributeType)}: failed to load from cache file, must scan assemblies.");
|
||||
scan = true;
|
||||
}
|
||||
else
|
||||
@@ -695,7 +695,7 @@ namespace Umbraco.Core.Composing
|
||||
catch (Exception ex)
|
||||
{
|
||||
// in case of any exception, we have to exit, and revert to scanning
|
||||
_logger.Logger.Error<TypeLoader>(ex, "Getting {TypeName}: failed to load cache file type {CacheType}, reverting to scanning assemblies.", GetName(baseType, attributeType), type);
|
||||
_logger.Logger.Error<TypeLoader>("Getting " + GetName(baseType, attributeType) + ": failed to load cache file type " + type + ", reverting to scanning assemblies.", ex);
|
||||
scan = true;
|
||||
break;
|
||||
}
|
||||
@@ -703,7 +703,7 @@ namespace Umbraco.Core.Composing
|
||||
|
||||
if (scan == false)
|
||||
{
|
||||
_logger.Logger.Debug<TypeLoader>("Getting {TypeName}: loaded types from cache file.", GetName(baseType, attributeType));
|
||||
_logger.Logger.Debug<TypeLoader>(() => $"Getting {GetName(baseType, attributeType)}: loaded types from cache file.");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -711,7 +711,7 @@ namespace Umbraco.Core.Composing
|
||||
if (scan)
|
||||
{
|
||||
// either we had to scan, or we could not get the types from the cache file - scan now
|
||||
_logger.Logger.Debug<TypeLoader>("Getting {TypeName}: scanning assemblies.", GetName(baseType, attributeType));
|
||||
_logger.Logger.Debug<TypeLoader>(() => $"Getting {GetName(baseType, attributeType)}: scanning assemblies.");
|
||||
|
||||
foreach (var t in finder())
|
||||
typeList.Add(t);
|
||||
@@ -729,11 +729,11 @@ namespace Umbraco.Core.Composing
|
||||
UpdateCache();
|
||||
}
|
||||
|
||||
_logger.Logger.Debug<TypeLoader>("Got {TypeName}, caching ({CacheType}).", GetName(baseType, attributeType), added.ToString().ToLowerInvariant());
|
||||
_logger.Logger.Debug<TypeLoader>(() => $"Got {GetName(baseType, attributeType)}, caching ({added.ToString().ToLowerInvariant()}).");
|
||||
}
|
||||
else
|
||||
{
|
||||
_logger.Logger.Debug<TypeLoader>("Got {TypeName}.", GetName(baseType, attributeType));
|
||||
_logger.Logger.Debug<TypeLoader>(() => $"Got {GetName(baseType, attributeType)}.");
|
||||
}
|
||||
|
||||
return typeList.Types;
|
||||
|
||||
@@ -12,7 +12,7 @@ using Semver;
|
||||
using Umbraco.Core.IO;
|
||||
using Umbraco.Core.Logging;
|
||||
|
||||
namespace Umbraco.Web.UI.JavaScript
|
||||
namespace Umbraco.Core.Configuration
|
||||
{
|
||||
/// <summary>
|
||||
/// A utility class for working with CDF config and cache files - use sparingly!
|
||||
@@ -79,13 +79,47 @@ namespace Umbraco.Web.UI.JavaScript
|
||||
versionAttribute.SetValue(newVersion);
|
||||
clientDependencyConfigXml.Save(_fileName, SaveOptions.DisableFormatting);
|
||||
|
||||
_logger.Info<ClientDependencyConfiguration>("Updated version number from {OldVersion} to {NewVersion}", oldVersion, newVersion);
|
||||
_logger.Info<ClientDependencyConfiguration>(() => $"Updated version number from {oldVersion} to {newVersion}");
|
||||
return true;
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.Error<ClientDependencyConfiguration>(ex, "Couldn't update ClientDependency version number");
|
||||
_logger.Error<ClientDependencyConfiguration>("Couldn't update ClientDependency version number", ex);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Changes the version number in ClientDependency.config to a random value to avoid stale caches
|
||||
/// </summary>
|
||||
/// <seealso cref="UpdateVersionNumber(SemVersion, DateTime, string)" />
|
||||
[Obsolete("Use the UpdateVersionNumber method specifying the version, date and dateFormat instead")]
|
||||
public bool IncreaseVersionNumber()
|
||||
{
|
||||
try
|
||||
{
|
||||
var clientDependencyConfigXml = XDocument.Load(_fileName, LoadOptions.PreserveWhitespace);
|
||||
if (clientDependencyConfigXml.Root != null)
|
||||
{
|
||||
|
||||
var versionAttribute = clientDependencyConfigXml.Root.Attribute("version");
|
||||
|
||||
//Set the new version to the hashcode of now
|
||||
var oldVersion = versionAttribute.Value;
|
||||
var newVersion = Math.Abs(DateTime.UtcNow.GetHashCode());
|
||||
|
||||
versionAttribute.SetValue(newVersion);
|
||||
clientDependencyConfigXml.Save(_fileName, SaveOptions.DisableFormatting);
|
||||
|
||||
_logger.Info<ClientDependencyConfiguration>(() => $"Updated version number from {oldVersion} to {newVersion}");
|
||||
return true;
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.Error<ClientDependencyConfiguration>("Couldn't update ClientDependency version number", ex);
|
||||
}
|
||||
|
||||
return false;
|
||||
@@ -107,7 +141,7 @@ namespace Umbraco.Web.UI.JavaScript
|
||||
|
||||
try
|
||||
{
|
||||
var fullPath = currentHttpContext.Server.MapPath(XmlFileMapper.FileMapDefaultFolder);
|
||||
var fullPath = currentHttpContext.Server.MapPath(XmlFileMapper.FileMapVirtualFolder);
|
||||
if (fullPath != null)
|
||||
{
|
||||
cdfTempDirectories.Add(fullPath);
|
||||
@@ -116,7 +150,7 @@ namespace Umbraco.Web.UI.JavaScript
|
||||
catch (Exception ex)
|
||||
{
|
||||
//invalid path format or something... try/catch to be safe
|
||||
_logger.Error<ClientDependencyConfiguration>(ex, "Could not get path from ClientDependency.config");
|
||||
_logger.Error<ClientDependencyConfiguration>("Could not get path from ClientDependency.config", ex);
|
||||
}
|
||||
|
||||
var success = true;
|
||||
@@ -133,7 +167,7 @@ namespace Umbraco.Web.UI.JavaScript
|
||||
catch (Exception ex)
|
||||
{
|
||||
// Something could be locking the directory or the was another error, making sure we don't break the upgrade installer
|
||||
_logger.Error<ClientDependencyConfiguration>(ex, "Could not clear temp files");
|
||||
_logger.Error<ClientDependencyConfiguration>("Could not clear temp files", ex);
|
||||
success = false;
|
||||
}
|
||||
}
|
||||
@@ -61,8 +61,7 @@ namespace Umbraco.Core.Configuration
|
||||
|
||||
var config = WebConfigurationManager.OpenWebConfiguration(appPath);
|
||||
var settings = (MailSettingsSectionGroup)config.GetSectionGroup("system.net/mailSettings");
|
||||
// note: "noreply@example.com" is/was the sample SMTP from email - we'll regard that as "not configured"
|
||||
if (settings == null || settings.Smtp == null || "noreply@example.com".Equals(settings.Smtp.From, StringComparison.OrdinalIgnoreCase)) return false;
|
||||
if (settings == null || settings.Smtp == null) return false;
|
||||
if (settings.Smtp.SpecifiedPickupDirectory != null && string.IsNullOrEmpty(settings.Smtp.SpecifiedPickupDirectory.PickupDirectoryLocation) == false)
|
||||
return true;
|
||||
if (settings.Smtp.Network != null && string.IsNullOrEmpty(settings.Smtp.Network.Host) == false)
|
||||
|
||||
@@ -40,15 +40,13 @@ namespace Umbraco.Core.Configuration.Grid
|
||||
var gridConfig = Path.Combine(_configFolder.FullName, "grid.editors.config.js");
|
||||
if (File.Exists(gridConfig))
|
||||
{
|
||||
var sourceString = File.ReadAllText(gridConfig);
|
||||
|
||||
try
|
||||
{
|
||||
editors.AddRange(parser.ParseGridEditors(sourceString));
|
||||
editors.AddRange(parser.ParseGridEditors(File.ReadAllText(gridConfig)));
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.Error<GridEditorsConfig>(ex, "Could not parse the contents of grid.editors.config.js into a JSON array '{Json}", sourceString);
|
||||
_logger.Error<GridEditorsConfig>("Could not parse the contents of grid.editors.config.js into a JSON array", ex);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -88,7 +88,7 @@ namespace Umbraco.Core.Configuration
|
||||
if (_healthChecks == null)
|
||||
{
|
||||
var ex = new ConfigurationErrorsException("Could not load the " + typeof(IHealthChecks) + " from config file, ensure the web.config and healthchecks.config files are formatted correctly");
|
||||
Current.Logger.Error<UmbracoConfig>(ex, "Config error");
|
||||
Current.Logger.Error<UmbracoConfig>("Config error", ex);
|
||||
throw ex;
|
||||
}
|
||||
|
||||
@@ -103,7 +103,7 @@ namespace Umbraco.Core.Configuration
|
||||
if (_dashboardSection == null)
|
||||
{
|
||||
var ex = new ConfigurationErrorsException("Could not load the " + typeof(IDashboardSection) + " from config file, ensure the web.config and Dashboard.config files are formatted correctly");
|
||||
Current.Logger.Error<UmbracoConfig>(ex, "Config error");
|
||||
Current.Logger.Error<UmbracoConfig>("Config error", ex);
|
||||
throw ex;
|
||||
}
|
||||
|
||||
@@ -162,7 +162,7 @@ namespace Umbraco.Core.Configuration
|
||||
if (_umbracoSettings == null)
|
||||
{
|
||||
var ex = new ConfigurationErrorsException("Could not load the " + typeof (IUmbracoSettingsSection) + " from config file, ensure the web.config and umbracoSettings.config files are formatted correctly");
|
||||
Current.Logger.Error<UmbracoConfig>(ex, "Config error");
|
||||
Current.Logger.Error<UmbracoConfig>("Config error", ex);
|
||||
throw ex;
|
||||
}
|
||||
|
||||
@@ -193,4 +193,4 @@ namespace Umbraco.Core.Configuration
|
||||
|
||||
//TODO: Add other configurations here !
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -136,7 +136,6 @@ namespace Umbraco.Core.Configuration.UmbracoSettings
|
||||
|
||||
bool IContentSection.EnableInheritedMediaTypes => EnableInheritedMediaTypes;
|
||||
|
||||
|
||||
string IContentSection.LoginBackgroundImage => LoginBackgroundImage;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,24 +1,9 @@
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Linq;
|
||||
|
||||
namespace Umbraco.Core.Configuration.UmbracoSettings
|
||||
{
|
||||
public static class ContentSectionExtensions
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets a value indicating whether the file extension corresponds to an image.
|
||||
/// </summary>
|
||||
/// <param name="extension">The file extension.</param>
|
||||
/// <param name="contentConfig"></param>
|
||||
/// <returns>A value indicating whether the file extension corresponds to an image.</returns>
|
||||
public static bool IsImageFile(this IContentSection contentConfig, string extension)
|
||||
{
|
||||
if (contentConfig == null) throw new ArgumentNullException(nameof(contentConfig));
|
||||
if (extension == null) return false;
|
||||
extension = extension.TrimStart('.');
|
||||
return contentConfig.ImageFileTypes.InvariantContains(extension);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Determines if file extension is allowed for upload based on (optional) white list and black list
|
||||
/// held in settings.
|
||||
@@ -30,17 +15,5 @@ namespace Umbraco.Core.Configuration.UmbracoSettings
|
||||
(contentSection.AllowedUploadFiles.Any() == false &&
|
||||
contentSection.DisallowedUploadFiles.Any(x => x.InvariantEquals(extension)) == false);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the auto-fill configuration for a specified property alias.
|
||||
/// </summary>
|
||||
/// <param name="contentSection"></param>
|
||||
/// <param name="propertyTypeAlias">The property type alias.</param>
|
||||
/// <returns>The auto-fill configuration for the specified property alias, or null.</returns>
|
||||
public static IImagingAutoFillUploadField GetConfig(this IContentSection contentSection, string propertyTypeAlias)
|
||||
{
|
||||
var autoFillConfigs = contentSection.ImageAutoFillProperties;
|
||||
return autoFillConfigs?.FirstOrDefault(x => x.Alias == propertyTypeAlias);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,7 +14,7 @@ namespace Umbraco.Core.Configuration.UmbracoSettings
|
||||
IEnumerable<string> ImageTagAllowedAttributes { get; }
|
||||
|
||||
IEnumerable<IImagingAutoFillUploadField> ImageAutoFillProperties { get; }
|
||||
|
||||
|
||||
string ScriptFolderPath { get; }
|
||||
|
||||
IEnumerable<string> ScriptFileTypes { get; }
|
||||
@@ -67,4 +67,4 @@ namespace Umbraco.Core.Configuration.UmbracoSettings
|
||||
|
||||
string LoginBackgroundImage { get; }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,8 +8,6 @@
|
||||
|
||||
bool DisableAlternativeTemplates { get; }
|
||||
|
||||
bool ValidateAlternativeTemplates { get; }
|
||||
|
||||
bool DisableFindContentByIdPath { get; }
|
||||
|
||||
bool DisableRedirectUrlTracking { get; }
|
||||
@@ -18,4 +16,5 @@
|
||||
|
||||
string UmbracoApplicationUrl { get; }
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -5,27 +5,44 @@ namespace Umbraco.Core.Configuration.UmbracoSettings
|
||||
internal class WebRoutingElement : ConfigurationElement, IWebRoutingSection
|
||||
{
|
||||
[ConfigurationProperty("trySkipIisCustomErrors", DefaultValue = "false")]
|
||||
public bool TrySkipIisCustomErrors => (bool) base["trySkipIisCustomErrors"];
|
||||
public bool TrySkipIisCustomErrors
|
||||
{
|
||||
get { return (bool) base["trySkipIisCustomErrors"]; }
|
||||
}
|
||||
|
||||
[ConfigurationProperty("internalRedirectPreservesTemplate", DefaultValue = "false")]
|
||||
public bool InternalRedirectPreservesTemplate => (bool) base["internalRedirectPreservesTemplate"];
|
||||
public bool InternalRedirectPreservesTemplate
|
||||
{
|
||||
get { return (bool) base["internalRedirectPreservesTemplate"]; }
|
||||
}
|
||||
|
||||
[ConfigurationProperty("disableAlternativeTemplates", DefaultValue = "false")]
|
||||
public bool DisableAlternativeTemplates => (bool) base["disableAlternativeTemplates"];
|
||||
|
||||
[ConfigurationProperty("validateAlternativeTemplates", DefaultValue = "false")]
|
||||
public bool ValidateAlternativeTemplates => (bool) base["validateAlternativeTemplates"];
|
||||
|
||||
public bool DisableAlternativeTemplates
|
||||
{
|
||||
get { return (bool) base["disableAlternativeTemplates"]; }
|
||||
}
|
||||
[ConfigurationProperty("disableFindContentByIdPath", DefaultValue = "false")]
|
||||
public bool DisableFindContentByIdPath => (bool) base["disableFindContentByIdPath"];
|
||||
public bool DisableFindContentByIdPath
|
||||
{
|
||||
get { return (bool) base["disableFindContentByIdPath"]; }
|
||||
}
|
||||
|
||||
[ConfigurationProperty("disableRedirectUrlTracking", DefaultValue = "false")]
|
||||
public bool DisableRedirectUrlTracking => (bool) base["disableRedirectUrlTracking"];
|
||||
public bool DisableRedirectUrlTracking
|
||||
{
|
||||
get { return (bool) base["disableRedirectUrlTracking"]; }
|
||||
}
|
||||
|
||||
[ConfigurationProperty("urlProviderMode", DefaultValue = "AutoLegacy")]
|
||||
public string UrlProviderMode => (string) base["urlProviderMode"];
|
||||
public string UrlProviderMode
|
||||
{
|
||||
get { return (string) base["urlProviderMode"]; }
|
||||
}
|
||||
|
||||
[ConfigurationProperty("umbracoApplicationUrl", DefaultValue = null)]
|
||||
public string UmbracoApplicationUrl => (string)base["umbracoApplicationUrl"];
|
||||
public string UmbracoApplicationUrl
|
||||
{
|
||||
get { return (string)base["umbracoApplicationUrl"]; }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -22,7 +22,7 @@ namespace Umbraco.Core.Configuration
|
||||
/// <summary>
|
||||
/// Gets the version comment of the executing code (eg "beta").
|
||||
/// </summary>
|
||||
public static string CurrentComment => "alpha.52";
|
||||
public static string CurrentComment => "alpha.44";
|
||||
|
||||
/// <summary>
|
||||
/// Gets the assembly version of Umbraco.Code.dll.
|
||||
|
||||
@@ -13,9 +13,9 @@
|
||||
public const string Content = "content";
|
||||
|
||||
/// <summary>
|
||||
/// Application alias for the packages section.
|
||||
/// Application alias for the developer section.
|
||||
/// </summary>
|
||||
public const string Packages = "packages";
|
||||
public const string Developer = "developer";
|
||||
|
||||
/// <summary>
|
||||
/// Application alias for the media section.
|
||||
@@ -145,15 +145,6 @@
|
||||
|
||||
public const string PartialViewMacros = "partialViewMacros";
|
||||
|
||||
public static class Groups
|
||||
{
|
||||
public const string Settings = "settingsGroup";
|
||||
|
||||
public const string Templating = "templatingGroup";
|
||||
|
||||
public const string ThirdParty = "thirdPartyGroup";
|
||||
}
|
||||
|
||||
//TODO: Fill in the rest!
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,6 +23,9 @@ namespace Umbraco.Core
|
||||
{
|
||||
public const string MemberUsernameRuleType = "MemberUsername";
|
||||
public const string MemberRoleRuleType = "MemberRole";
|
||||
|
||||
[Obsolete("No longer supported, this is here for backwards compatibility only")]
|
||||
public const string MemberIdRuleType = "MemberId";
|
||||
}
|
||||
|
||||
|
||||
@@ -91,11 +94,6 @@ namespace Umbraco.Core
|
||||
/// Property alias for the Media's file extension.
|
||||
/// </summary>
|
||||
public const string Extension = "umbracoExtension";
|
||||
|
||||
/// <summary>
|
||||
/// The default height/width of an image file if the size can't be determined from the metadata
|
||||
/// </summary>
|
||||
public const int DefaultSize = 200;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -13,9 +13,7 @@
|
||||
|
||||
public const int Textbox = -88;
|
||||
public const int Boolean = -49;
|
||||
public const int DateTime = -36;
|
||||
public const int DropDownSingle = -39;
|
||||
public const int DropDownMultiple = -42;
|
||||
public const int Datetime = -36;
|
||||
|
||||
public const int DefaultContentListView = -95;
|
||||
public const int DefaultMediaListView = -96;
|
||||
|
||||
@@ -71,6 +71,9 @@ namespace Umbraco.Core
|
||||
[Obsolete("This no longer exists in the database")]
|
||||
internal const string Stylesheet = "9F68DA4F-A3A8-44C2-8226-DCBD125E4840";
|
||||
|
||||
[Obsolete("This no longer exists in the database")]
|
||||
internal const string StylesheetProperty = "5555da4f-a123-42b2-4488-dcdfb25e4111";
|
||||
|
||||
// ReSharper restore MemberHidesStaticFromOuterClass
|
||||
}
|
||||
|
||||
|
||||
@@ -58,7 +58,6 @@
|
||||
/// </remarks>
|
||||
public const string RecycleBinMediaPathPrefix = "-1,-21,";
|
||||
|
||||
public const int DefaultLabelDataTypeId = -92;
|
||||
public const string UmbracoConnectionName = "umbracoDbDSN";
|
||||
public const string UmbracoUpgradePlanName = "Umbraco.Core";
|
||||
}
|
||||
|
||||
@@ -115,7 +115,7 @@ namespace Umbraco.Core
|
||||
/// <summary>
|
||||
/// Determines whether a variation varies by culture and segment.
|
||||
/// </summary>
|
||||
public static bool VariesByCultureAndSegment(this ContentVariation variation) => (variation & ContentVariation.CultureAndSegment) == ContentVariation.CultureAndSegment;
|
||||
public static bool VariesByCultureAndSegment(this ContentVariation variation) => (variation & ContentVariation.CultureAndSegment) > 0;
|
||||
|
||||
/// <summary>
|
||||
/// Validates that a combination of culture and segment is valid for the variation.
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using Umbraco.Core.Logging;
|
||||
|
||||
namespace Umbraco.Core.Logging
|
||||
namespace Umbraco.Core
|
||||
{
|
||||
/// <summary>
|
||||
/// Starts the timer and invokes a callback upon disposal. Provides a simple way of timing an operation by wrapping it in a <code>using</code> (C#) statement.
|
||||
@@ -9,7 +10,7 @@ namespace Umbraco.Core.Logging
|
||||
public class DisposableTimer : DisposableObjectSlim
|
||||
{
|
||||
private readonly ILogger _logger;
|
||||
private readonly LogLevel _level;
|
||||
private readonly LogType? _logType;
|
||||
private readonly Type _loggerType;
|
||||
private readonly int _thresholdMilliseconds;
|
||||
private readonly IDisposable _profilerStep;
|
||||
@@ -17,33 +18,39 @@ namespace Umbraco.Core.Logging
|
||||
private string _failMessage;
|
||||
private Exception _failException;
|
||||
private bool _failed;
|
||||
private readonly string _timingId;
|
||||
|
||||
internal enum LogType
|
||||
{
|
||||
Debug, Info
|
||||
}
|
||||
|
||||
// internal - created by profiling logger
|
||||
internal DisposableTimer(ILogger logger, LogLevel level, IProfiler profiler, Type loggerType,
|
||||
internal DisposableTimer(ILogger logger, LogType logType, IProfiler profiler, Type loggerType,
|
||||
string startMessage, string endMessage, string failMessage = null,
|
||||
int thresholdMilliseconds = 0)
|
||||
{
|
||||
_logger = logger ?? throw new ArgumentNullException(nameof(logger));
|
||||
_level = level;
|
||||
_loggerType = loggerType ?? throw new ArgumentNullException(nameof(loggerType));
|
||||
if (logger == null) throw new ArgumentNullException(nameof(logger));
|
||||
if (loggerType == null) throw new ArgumentNullException(nameof(loggerType));
|
||||
|
||||
_logger = logger;
|
||||
_logType = logType;
|
||||
_loggerType = loggerType;
|
||||
_endMessage = endMessage;
|
||||
_failMessage = failMessage;
|
||||
_thresholdMilliseconds = thresholdMilliseconds < 0 ? 0 : thresholdMilliseconds;
|
||||
_timingId = Guid.NewGuid().ToString("N").Substring(0, 7); // keep it short-ish
|
||||
|
||||
if (thresholdMilliseconds == 0)
|
||||
{
|
||||
switch (_level)
|
||||
switch (logType)
|
||||
{
|
||||
case LogLevel.Debug:
|
||||
logger.Debug(loggerType, "{StartMessage} [Timing {TimingId}]", startMessage, _timingId);
|
||||
case LogType.Debug:
|
||||
logger.Debug(loggerType, startMessage);
|
||||
break;
|
||||
case LogLevel.Information:
|
||||
logger.Info(loggerType, "{StartMessage} [Timing {TimingId}]", startMessage, _timingId);
|
||||
case LogType.Info:
|
||||
logger.Info(loggerType, startMessage);
|
||||
break;
|
||||
default:
|
||||
throw new ArgumentOutOfRangeException(nameof(level));
|
||||
throw new ArgumentOutOfRangeException(nameof(logType));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -79,20 +86,20 @@ namespace Umbraco.Core.Logging
|
||||
_profilerStep?.Dispose();
|
||||
|
||||
if ((Stopwatch.ElapsedMilliseconds >= _thresholdMilliseconds || _failed)
|
||||
&& _loggerType != null && _logger != null
|
||||
&& _logType.HasValue && _loggerType != null && _logger != null
|
||||
&& (_endMessage.IsNullOrWhiteSpace() == false || _failed))
|
||||
{
|
||||
if (_failed)
|
||||
{
|
||||
_logger.Error(_loggerType, _failException, "{FailMessage} ({Duration}ms) [Timing {TimingId}]", _failMessage, Stopwatch.ElapsedMilliseconds, _timingId);
|
||||
_logger.Error(_loggerType, $"{_failMessage} ({Stopwatch.ElapsedMilliseconds}ms)", _failException);
|
||||
}
|
||||
else switch (_level)
|
||||
else switch (_logType)
|
||||
{
|
||||
case LogLevel.Debug:
|
||||
_logger.Debug(_loggerType, "{EndMessage} ({Duration}ms) [Timing {TimingId}]", _endMessage, Stopwatch.ElapsedMilliseconds, _timingId);
|
||||
case LogType.Debug:
|
||||
_logger.Debug(_loggerType, () => $"{_endMessage} ({Stopwatch.ElapsedMilliseconds}ms)");
|
||||
break;
|
||||
case LogLevel.Information:
|
||||
_logger.Info(_loggerType, "{EndMessage} ({Duration}ms) [Timing {TimingId}]", _endMessage, Stopwatch.ElapsedMilliseconds, _timingId);
|
||||
case LogType.Info:
|
||||
_logger.Info(_loggerType, () => $"{_endMessage} ({Stopwatch.ElapsedMilliseconds}ms)");
|
||||
break;
|
||||
// filtered in the ctor
|
||||
//default:
|
||||
@@ -92,7 +92,18 @@ namespace Umbraco.Core
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// <summary>The flatten list.</summary>
|
||||
/// <param name="e">The items.</param>
|
||||
/// <param name="f">The select child.</param>
|
||||
/// <typeparam name="T">Item type</typeparam>
|
||||
/// <returns>list of TItem</returns>
|
||||
[EditorBrowsable(EditorBrowsableState.Never)]
|
||||
[Obsolete("Do not use, use SelectRecursive instead which has far less potential of re-iterating an iterator which may cause significantly more SQL queries")]
|
||||
public static IEnumerable<T> FlattenList<T>(this IEnumerable<T> e, Func<T, IEnumerable<T>> f)
|
||||
{
|
||||
return e.SelectMany(c => f(c).FlattenList(f)).Concat(e);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns true if all items in the other collection exist in this collection
|
||||
/// </summary>
|
||||
|
||||
@@ -14,7 +14,10 @@ namespace Umbraco.Core.Events
|
||||
_msgs.Add(msg);
|
||||
}
|
||||
|
||||
public int Count => _msgs.Count;
|
||||
public int Count
|
||||
{
|
||||
get { return _msgs.Count; }
|
||||
}
|
||||
|
||||
public IEnumerable<EventMessage> GetAll()
|
||||
{
|
||||
|
||||
@@ -307,7 +307,7 @@ namespace Umbraco.Core.Events
|
||||
|
||||
// fixme see notes above
|
||||
// delete event args does NOT superceedes 'unpublished' event
|
||||
if (argType.IsGenericType && argType.GetGenericTypeDefinition() == typeof(PublishEventArgs<>) && infos.EventDefinition.EventName == "Unpublished")
|
||||
if (argType.IsGenericType && argType.GetGenericTypeDefinition() == typeof(PublishEventArgs<>) && infos.EventDefinition.EventName == "UnPublished")
|
||||
return false;
|
||||
|
||||
// found occurences, need to determine if this event args is superceded
|
||||
|
||||
@@ -24,19 +24,11 @@ namespace Umbraco.Core
|
||||
{
|
||||
return "Unknown, httpContext is null";
|
||||
}
|
||||
|
||||
HttpRequestBase request;
|
||||
try
|
||||
{
|
||||
// is not null - throws
|
||||
request = httpContext.Request;
|
||||
}
|
||||
catch
|
||||
if (httpContext.Request == null)
|
||||
{
|
||||
return "Unknown, httpContext.Request is null";
|
||||
}
|
||||
|
||||
if (request.ServerVariables == null)
|
||||
if (httpContext.Request.ServerVariables == null)
|
||||
{
|
||||
return "Unknown, httpContext.Request.ServerVariables is null";
|
||||
}
|
||||
@@ -45,16 +37,16 @@ namespace Umbraco.Core
|
||||
|
||||
try
|
||||
{
|
||||
var ipAddress = request.ServerVariables["HTTP_X_FORWARDED_FOR"];
|
||||
var ipAddress = httpContext.Request.ServerVariables["HTTP_X_FORWARDED_FOR"];
|
||||
|
||||
if (string.IsNullOrEmpty(ipAddress))
|
||||
return request.UserHostAddress;
|
||||
return httpContext.Request.UserHostAddress;
|
||||
|
||||
var addresses = ipAddress.Split(',');
|
||||
if (addresses.Length != 0)
|
||||
return addresses[0];
|
||||
|
||||
return request.UserHostAddress;
|
||||
return httpContext.Request.UserHostAddress;
|
||||
}
|
||||
catch (System.Exception ex)
|
||||
{
|
||||
|
||||
@@ -1,15 +1,20 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Drawing;
|
||||
using System.Globalization;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using LightInject;
|
||||
using Umbraco.Core.Configuration;
|
||||
using Umbraco.Core.Configuration.UmbracoSettings;
|
||||
using Umbraco.Core.Composing;
|
||||
using Umbraco.Core.Exceptions;
|
||||
using Umbraco.Core.IO.MediaPathSchemes;
|
||||
using Umbraco.Core.Logging;
|
||||
using Umbraco.Core.Media;
|
||||
|
||||
using Umbraco.Core.Media.Exif;
|
||||
using Umbraco.Core.Models;
|
||||
|
||||
namespace Umbraco.Core.IO
|
||||
@@ -27,6 +32,8 @@ namespace Umbraco.Core.IO
|
||||
// dependencies, so we have to rely on property injection for anything we might need
|
||||
Current.Container.InjectProperties(this);
|
||||
MediaPathScheme.Initialize(this);
|
||||
|
||||
UploadAutoFillProperties = new UploadAutoFillProperties(this, Logger, ContentConfig);
|
||||
}
|
||||
|
||||
[Inject]
|
||||
@@ -37,7 +44,9 @@ namespace Umbraco.Core.IO
|
||||
|
||||
[Inject]
|
||||
internal ILogger Logger { get; set; }
|
||||
|
||||
|
||||
internal UploadAutoFillProperties UploadAutoFillProperties { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Deletes all files passed in.
|
||||
/// </summary>
|
||||
@@ -102,7 +111,7 @@ namespace Umbraco.Core.IO
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Logger.Error<MediaFileSystem>(e, "Failed to delete attached file '{File}'", file);
|
||||
Logger.Error<MediaFileSystem>("Failed to delete attached file \"" + file + "\".", e);
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -204,9 +213,113 @@ namespace Umbraco.Core.IO
|
||||
return filepath;
|
||||
}
|
||||
|
||||
|
||||
// gets or creates a property for a content item.
|
||||
private static Property GetProperty(IContentBase content, string propertyTypeAlias)
|
||||
{
|
||||
var property = content.Properties.FirstOrDefault(x => x.Alias.InvariantEquals(propertyTypeAlias));
|
||||
if (property != null) return property;
|
||||
|
||||
var propertyType = content.GetContentType().CompositionPropertyTypes
|
||||
.FirstOrDefault(x => x.Alias.InvariantEquals(propertyTypeAlias));
|
||||
if (propertyType == null)
|
||||
throw new Exception("No property type exists with alias " + propertyTypeAlias + ".");
|
||||
|
||||
property = new Property(propertyType);
|
||||
content.Properties.Add(property);
|
||||
return property;
|
||||
}
|
||||
|
||||
// fixme - what's below belongs to the upload property editor, not the media filesystem!
|
||||
|
||||
public void SetUploadFile(IContentBase content, string propertyTypeAlias, string filename, Stream filestream, string culture = null, string segment = null)
|
||||
{
|
||||
var property = GetProperty(content, propertyTypeAlias);
|
||||
var oldpath = property.GetValue(culture, segment) is string svalue ? GetRelativePath(svalue) : null;
|
||||
var filepath = StoreFile(content, property.PropertyType, filename, filestream, oldpath);
|
||||
property.SetValue(GetUrl(filepath), culture, segment);
|
||||
SetUploadFile(content, property, filepath, filestream, culture, segment);
|
||||
}
|
||||
|
||||
public void SetUploadFile(IContentBase content, string propertyTypeAlias, string filepath, string culture = null, string segment = null)
|
||||
{
|
||||
var property = GetProperty(content, propertyTypeAlias);
|
||||
// fixme delete?
|
||||
var oldpath = property.GetValue(culture, segment) is string svalue ? GetRelativePath(svalue) : null;
|
||||
if (string.IsNullOrWhiteSpace(oldpath) == false && oldpath != filepath)
|
||||
DeleteFile(oldpath);
|
||||
property.SetValue(GetUrl(filepath), culture, segment);
|
||||
using (var filestream = OpenFile(filepath))
|
||||
{
|
||||
SetUploadFile(content, property, filepath, filestream, culture, segment);
|
||||
}
|
||||
}
|
||||
|
||||
// sets a file for the FileUpload property editor
|
||||
// ie generates thumbnails and populates autofill properties
|
||||
private void SetUploadFile(IContentBase content, Property property, string filepath, Stream filestream, string culture = null, string segment = null)
|
||||
{
|
||||
// will use filepath for extension, and filestream for length
|
||||
UploadAutoFillProperties.Populate(content, property.Alias, filepath, filestream, culture, segment);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Image
|
||||
|
||||
/// <summary>
|
||||
/// Gets a value indicating whether the file extension corresponds to an image.
|
||||
/// </summary>
|
||||
/// <param name="extension">The file extension.</param>
|
||||
/// <returns>A value indicating whether the file extension corresponds to an image.</returns>
|
||||
public bool IsImageFile(string extension)
|
||||
{
|
||||
if (extension == null) return false;
|
||||
extension = extension.TrimStart('.');
|
||||
return ContentConfig.ImageFileTypes.InvariantContains(extension);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the dimensions of an image.
|
||||
/// </summary>
|
||||
/// <param name="stream">A stream containing the image bytes.</param>
|
||||
/// <returns>The dimension of the image.</returns>
|
||||
/// <remarks>First try with EXIF as it is faster and does not load the entire image
|
||||
/// in memory. Fallback to GDI which means loading the image in memory and thus
|
||||
/// use potentially large amounts of memory.</remarks>
|
||||
public Size GetDimensions(Stream stream)
|
||||
{
|
||||
//Try to load with exif
|
||||
try
|
||||
{
|
||||
var jpgInfo = ImageFile.FromStream(stream);
|
||||
|
||||
if (jpgInfo.Format != ImageFileFormat.Unknown
|
||||
&& jpgInfo.Properties.ContainsKey(ExifTag.PixelYDimension)
|
||||
&& jpgInfo.Properties.ContainsKey(ExifTag.PixelXDimension))
|
||||
{
|
||||
var height = Convert.ToInt32(jpgInfo.Properties[ExifTag.PixelYDimension].Value);
|
||||
var width = Convert.ToInt32(jpgInfo.Properties[ExifTag.PixelXDimension].Value);
|
||||
if (height > 0 && width > 0)
|
||||
{
|
||||
return new Size(width, height);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
//We will just swallow, just means we can't read exif data, we don't want to log an error either
|
||||
}
|
||||
|
||||
//we have no choice but to try to read in via GDI
|
||||
using (var image = Image.FromStream(stream))
|
||||
{
|
||||
|
||||
var fileWidth = image.Width;
|
||||
var fileHeight = image.Height;
|
||||
return new Size(fileWidth, fileHeight);
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -73,11 +73,11 @@ namespace Umbraco.Core.IO
|
||||
}
|
||||
catch (UnauthorizedAccessException ex)
|
||||
{
|
||||
Current.Logger.Error<PhysicalFileSystem>(ex, "Not authorized to get directories for '{Path}'", fullPath);
|
||||
Current.Logger.Error<PhysicalFileSystem>("Not authorized to get directories", ex);
|
||||
}
|
||||
catch (DirectoryNotFoundException ex)
|
||||
{
|
||||
Current.Logger.Error<PhysicalFileSystem>(ex, "Directory not found for '{Path}'", fullPath);
|
||||
Current.Logger.Error<PhysicalFileSystem>("Directory not found", ex);
|
||||
}
|
||||
|
||||
return Enumerable.Empty<string>();
|
||||
@@ -109,7 +109,7 @@ namespace Umbraco.Core.IO
|
||||
}
|
||||
catch (DirectoryNotFoundException ex)
|
||||
{
|
||||
Current.Logger.Error<PhysicalFileSystem>(ex, "Directory not found for '{Path}'", fullPath);
|
||||
Current.Logger.Error<PhysicalFileSystem>("Directory not found", ex);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -189,11 +189,11 @@ namespace Umbraco.Core.IO
|
||||
}
|
||||
catch (UnauthorizedAccessException ex)
|
||||
{
|
||||
Current.Logger.Error<PhysicalFileSystem>(ex, "Not authorized to get directories for '{Path}'", fullPath);
|
||||
Current.Logger.Error<PhysicalFileSystem>("Not authorized to get directories", ex);
|
||||
}
|
||||
catch (DirectoryNotFoundException ex)
|
||||
{
|
||||
Current.Logger.Error<PhysicalFileSystem>(ex, "Directory not found for '{FullPath}'", fullPath);
|
||||
Current.Logger.Error<PhysicalFileSystem>("Directory not found", ex);
|
||||
}
|
||||
|
||||
return Enumerable.Empty<string>();
|
||||
@@ -226,7 +226,7 @@ namespace Umbraco.Core.IO
|
||||
}
|
||||
catch (FileNotFoundException ex)
|
||||
{
|
||||
Current.Logger.Error<PhysicalFileSystem>(ex.InnerException, "DeleteFile failed with FileNotFoundException for '{Path}'", fullPath);
|
||||
Current.Logger.Info<PhysicalFileSystem>(() => $"DeleteFile failed with FileNotFoundException: {ex.InnerException}");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -54,7 +54,7 @@ namespace Umbraco.Core.IO
|
||||
}
|
||||
|
||||
_logger = logger;
|
||||
_logger.Debug<ShadowFileSystems>("Shadow '{ShadowId}'", id);
|
||||
_logger.Debug<ShadowFileSystems>(() => "Shadow " + id + ".");
|
||||
_id = id;
|
||||
|
||||
_wrappers = wrappers;
|
||||
@@ -112,7 +112,7 @@ namespace Umbraco.Core.IO
|
||||
{
|
||||
lock (Locker)
|
||||
{
|
||||
_logger.Debug<ShadowFileSystems>("UnShadow '{ShadowId}' {Status}", _id, _completed ? "complete" : "abort");
|
||||
_logger.Debug<ShadowFileSystems>(() => "UnShadow " + _id + " (" + (_completed ? "complete" : "abort") + ").");
|
||||
|
||||
var exceptions = new List<Exception>();
|
||||
foreach (var wrapper in _wrappers)
|
||||
|
||||
@@ -6,7 +6,10 @@ namespace Umbraco.Core.IO
|
||||
//all paths has a starting but no trailing /
|
||||
public class SystemDirectories
|
||||
{
|
||||
public static string Bin => "~/bin";
|
||||
//TODO: Why on earth is this even configurable? You cannot change the /Bin folder in ASP.Net
|
||||
public static string Bin => IOHelper.ReturnPath("umbracoBinDirectory", "~/bin");
|
||||
|
||||
public static string Base => IOHelper.ReturnPath("umbracoBaseDirectory", "~/base");
|
||||
|
||||
public static string Config => IOHelper.ReturnPath("umbracoConfigDirectory", "~/config");
|
||||
|
||||
@@ -16,7 +19,6 @@ namespace Umbraco.Core.IO
|
||||
|
||||
public static string Install => IOHelper.ReturnPath("umbracoInstallPath", "~/install");
|
||||
|
||||
//TODO: Consider removing this
|
||||
public static string Masterpages => IOHelper.ReturnPath("umbracoMasterPagesPath", "~/masterpages");
|
||||
|
||||
//NOTE: this is not configurable and shouldn't need to be
|
||||
@@ -38,7 +40,8 @@ namespace Umbraco.Core.IO
|
||||
|
||||
public static string Umbraco => IOHelper.ReturnPath("umbracoPath", "~/umbraco");
|
||||
|
||||
//TODO: Consider removing this
|
||||
public static string UmbracoClient => IOHelper.ReturnPath("umbracoClientPath", "~/umbraco_client");
|
||||
|
||||
public static string UserControls => IOHelper.ReturnPath("umbracoUsercontrolsPath", "~/usercontrols");
|
||||
|
||||
public static string WebServices => IOHelper.ReturnPath("umbracoWebservicesPath", Umbraco.EnsureEndsWith("/") + "webservices");
|
||||
|
||||
@@ -0,0 +1,21 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Web;
|
||||
|
||||
namespace Umbraco.Core.Logging
|
||||
{
|
||||
/// <summary>
|
||||
/// Allows for outputting a normalized appdomainappid token in a log format
|
||||
/// </summary>
|
||||
public sealed class AppDomainTokenConverter : log4net.Util.PatternConverter
|
||||
{
|
||||
protected override void Convert(TextWriter writer, object state)
|
||||
{
|
||||
writer.Write(HttpRuntime.AppDomainAppId.ReplaceNonAlphanumericChars(string.Empty));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,121 @@
|
||||
using log4net.Appender;
|
||||
using log4net.Core;
|
||||
using log4net.Util;
|
||||
using System;
|
||||
using System.Runtime.Remoting.Messaging;
|
||||
|
||||
namespace Umbraco.Core.Logging
|
||||
{
|
||||
/// <summary>
|
||||
/// Borrowed from https://github.com/cjbhaines/Log4Net.Async - will reference Nuget packages directly in v8
|
||||
/// </summary>
|
||||
public abstract class AsyncForwardingAppenderBase : ForwardingAppender
|
||||
{
|
||||
#region Private Members
|
||||
|
||||
private const FixFlags DefaultFixFlags = FixFlags.Partial;
|
||||
private FixFlags fixFlags = DefaultFixFlags;
|
||||
private LoggingEventHelper loggingEventHelper;
|
||||
|
||||
#endregion Private Members
|
||||
|
||||
#region Properties
|
||||
|
||||
public FixFlags Fix
|
||||
{
|
||||
get { return fixFlags; }
|
||||
set { SetFixFlags(value); }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns HttpContext.Current
|
||||
/// </summary>
|
||||
protected internal object HttpContext
|
||||
{
|
||||
get
|
||||
{
|
||||
return CallContext.HostContext;
|
||||
}
|
||||
set
|
||||
{
|
||||
CallContext.HostContext = value;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The logger name that will be used for logging internal errors.
|
||||
/// </summary>
|
||||
protected abstract string InternalLoggerName { get; }
|
||||
|
||||
public abstract int? BufferSize { get; set; }
|
||||
|
||||
#endregion Properties
|
||||
|
||||
public override void ActivateOptions()
|
||||
{
|
||||
base.ActivateOptions();
|
||||
loggingEventHelper = new LoggingEventHelper(InternalLoggerName, DefaultFixFlags);
|
||||
InitializeAppenders();
|
||||
}
|
||||
|
||||
#region Appender Management
|
||||
|
||||
public override void AddAppender(IAppender newAppender)
|
||||
{
|
||||
base.AddAppender(newAppender);
|
||||
SetAppenderFixFlags(newAppender);
|
||||
}
|
||||
|
||||
private void SetFixFlags(FixFlags newFixFlags)
|
||||
{
|
||||
if (newFixFlags != fixFlags)
|
||||
{
|
||||
loggingEventHelper.Fix = newFixFlags;
|
||||
fixFlags = newFixFlags;
|
||||
InitializeAppenders();
|
||||
}
|
||||
}
|
||||
|
||||
private void InitializeAppenders()
|
||||
{
|
||||
foreach (var appender in Appenders)
|
||||
{
|
||||
SetAppenderFixFlags(appender);
|
||||
}
|
||||
}
|
||||
|
||||
private void SetAppenderFixFlags(IAppender appender)
|
||||
{
|
||||
var bufferingAppender = appender as BufferingAppenderSkeleton;
|
||||
if (bufferingAppender != null)
|
||||
{
|
||||
bufferingAppender.Fix = Fix;
|
||||
}
|
||||
}
|
||||
|
||||
#endregion Appender Management
|
||||
|
||||
#region Forwarding
|
||||
|
||||
protected void ForwardInternalError(string message, Exception exception, Type thisType)
|
||||
{
|
||||
LogLog.Error(thisType, message, exception);
|
||||
var loggingEvent = loggingEventHelper.CreateLoggingEvent(Level.Error, message, exception);
|
||||
ForwardLoggingEvent(loggingEvent, thisType);
|
||||
}
|
||||
|
||||
protected void ForwardLoggingEvent(LoggingEvent loggingEvent, Type thisType)
|
||||
{
|
||||
try
|
||||
{
|
||||
base.Append(loggingEvent);
|
||||
}
|
||||
catch (Exception exception)
|
||||
{
|
||||
LogLog.Error(thisType, "Unable to forward logging event", exception);
|
||||
}
|
||||
}
|
||||
|
||||
#endregion Forwarding
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,5 @@
|
||||
using System;
|
||||
using System.Linq;
|
||||
|
||||
namespace Umbraco.Core.Logging
|
||||
{
|
||||
@@ -7,79 +8,34 @@ namespace Umbraco.Core.Logging
|
||||
/// </summary>
|
||||
public class DebugDiagnosticsLogger : ILogger
|
||||
{
|
||||
public bool IsEnabled(Type reporting, LogLevel level)
|
||||
=> true;
|
||||
|
||||
/// <inheritdoc/>
|
||||
public void Fatal(Type reporting, Exception exception, string message)
|
||||
public void Error(Type reporting, string message, Exception exception = null)
|
||||
{
|
||||
System.Diagnostics.Debug.WriteLine(message + Environment.NewLine + exception, reporting.FullName);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public void Fatal(Type reporting, Exception exception)
|
||||
public void Warn(Type reporting, string format)
|
||||
{
|
||||
System.Diagnostics.Debug.WriteLine(Environment.NewLine + exception, reporting.FullName);
|
||||
System.Diagnostics.Debug.WriteLine(format, reporting.FullName);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public void Fatal(Type reporting, string message)
|
||||
public void Warn(Type reporting, Func<string> messageBuilder)
|
||||
{
|
||||
System.Diagnostics.Debug.WriteLine(message);
|
||||
System.Diagnostics.Debug.WriteLine(messageBuilder(), reporting.FullName);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public void Fatal(Type reporting, Exception exception, string messageTemplate, params object[] propertyValues)
|
||||
public void Warn(Type reporting, string format, params object[] args)
|
||||
{
|
||||
System.Diagnostics.Debug.WriteLine(MessageTemplates.Render(messageTemplate, propertyValues) + Environment.NewLine + exception, reporting.FullName);
|
||||
System.Diagnostics.Debug.WriteLine(string.Format(format, args), reporting.FullName);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public void Fatal(Type reporting, string messageTemplate, params object[] propertyValues)
|
||||
public void Warn(Type reporting, string format, params Func<object>[] args)
|
||||
{
|
||||
System.Diagnostics.Debug.WriteLine(messageTemplate, propertyValues);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public void Error(Type reporting, Exception exception, string message)
|
||||
{
|
||||
System.Diagnostics.Debug.WriteLine(message + Environment.NewLine + exception, reporting.FullName);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public void Error(Type reporting, Exception exception)
|
||||
{
|
||||
System.Diagnostics.Debug.WriteLine(Environment.NewLine + exception, reporting.FullName);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public void Error(Type reporting, string message)
|
||||
{
|
||||
System.Diagnostics.Debug.WriteLine(message);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public void Error(Type reporting, Exception exception, string messageTemplate, params object[] propertyValues)
|
||||
{
|
||||
System.Diagnostics.Debug.WriteLine(MessageTemplates.Render(messageTemplate, propertyValues) + Environment.NewLine + exception, reporting.FullName);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public void Error(Type reporting, string messageTemplate, params object[] propertyValues)
|
||||
{
|
||||
System.Diagnostics.Debug.WriteLine(messageTemplate, propertyValues);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public void Warn(Type reporting, string message)
|
||||
{
|
||||
System.Diagnostics.Debug.WriteLine(message, reporting.FullName);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public void Warn(Type reporting, string message, params object[] propertyValues)
|
||||
{
|
||||
System.Diagnostics.Debug.WriteLine(MessageTemplates.Render(message, propertyValues), reporting.FullName);
|
||||
System.Diagnostics.Debug.WriteLine(string.Format(format, args.Select(x => x()).ToArray()), reporting.FullName);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
@@ -89,9 +45,21 @@ namespace Umbraco.Core.Logging
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public void Warn(Type reporting, Exception exception, string message, params object[] propertyValues)
|
||||
public void Warn(Type reporting, Exception exception, Func<string> messageBuilder)
|
||||
{
|
||||
System.Diagnostics.Debug.WriteLine(MessageTemplates.Render(message + Environment.NewLine + exception, propertyValues), reporting.FullName);
|
||||
System.Diagnostics.Debug.WriteLine(messageBuilder() + Environment.NewLine + exception, reporting.FullName);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public void Warn(Type reporting, Exception exception, string format, params object[] args)
|
||||
{
|
||||
System.Diagnostics.Debug.WriteLine(string.Format(format + Environment.NewLine + exception, args), reporting.FullName);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public void Warn(Type reporting, Exception exception, string format, params Func<object>[] args)
|
||||
{
|
||||
System.Diagnostics.Debug.WriteLine(string.Format(format + Environment.NewLine + exception, args.Select(x => x()).ToArray()), reporting.FullName);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
@@ -101,9 +69,21 @@ namespace Umbraco.Core.Logging
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public void Info(Type reporting, string messageTemplate, params object[] propertyValues)
|
||||
public void Info(Type reporting, Func<string> messageBuilder)
|
||||
{
|
||||
System.Diagnostics.Debug.WriteLine(MessageTemplates.Render(messageTemplate, propertyValues), reporting.FullName);
|
||||
System.Diagnostics.Debug.WriteLine(messageBuilder(), reporting.FullName);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public void Info(Type reporting, string format, params object[] args)
|
||||
{
|
||||
System.Diagnostics.Debug.WriteLine(string.Format(format, args), reporting.FullName);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public void Info(Type reporting, string format, params Func<object>[] args)
|
||||
{
|
||||
System.Diagnostics.Debug.WriteLine(string.Format(format, args.Select(x => x()).ToArray()), reporting.FullName);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
@@ -113,21 +93,21 @@ namespace Umbraco.Core.Logging
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public void Debug(Type reporting, string messageTemplate, params object[] propertyValues)
|
||||
public void Debug(Type reporting, Func<string> messageBuilder)
|
||||
{
|
||||
System.Diagnostics.Debug.WriteLine(MessageTemplates.Render(messageTemplate, propertyValues), reporting.FullName);
|
||||
System.Diagnostics.Debug.WriteLine(messageBuilder(), reporting.FullName);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public void Verbose(Type reporting, string message)
|
||||
public void Debug(Type reporting, string format, params object[] args)
|
||||
{
|
||||
System.Diagnostics.Debug.WriteLine(message, reporting.FullName);
|
||||
System.Diagnostics.Debug.WriteLine(string.Format(format, args), reporting.FullName);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public void Verbose(Type reporting, string messageTemplate, params object[] propertyValues)
|
||||
public void Debug(Type reporting, string format, params Func<object>[] args)
|
||||
{
|
||||
System.Diagnostics.Debug.WriteLine(MessageTemplates.Render(messageTemplate, propertyValues), reporting.FullName);
|
||||
System.Diagnostics.Debug.WriteLine(string.Format(format, args.Select(x => x()).ToArray()), reporting.FullName);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,105 +1,22 @@
|
||||
using System;
|
||||
using System.ComponentModel;
|
||||
|
||||
namespace Umbraco.Core.Logging
|
||||
{
|
||||
/// <summary>
|
||||
/// Defines the logging service.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// <para>Message templates in logging methods follow the Message Templates specification
|
||||
/// available at https://messagetemplates.org/ in order to support structured logging.</para>
|
||||
/// <para>Implementations must ensure that they support these templates. Note that the
|
||||
/// specification includes support for traditional C# numeric placeholders.</para>
|
||||
/// <para>For instance, "Processed {Input} in {Time}ms."</para>
|
||||
/// </remarks>
|
||||
public interface ILogger
|
||||
{
|
||||
/// <summary>
|
||||
/// Determines if logging is enabled at a specified level, for a reporting type.
|
||||
/// </summary>
|
||||
/// <param name="reporting">The reporting type.</param>
|
||||
/// <param name="level">The level.</param>
|
||||
bool IsEnabled(Type reporting, LogLevel level);
|
||||
|
||||
/// <summary>
|
||||
/// Logs a fatal message with an exception.
|
||||
/// </summary>
|
||||
/// <param name="reporting">The reporting type.</param>
|
||||
/// <param name="exception">An exception.</param>
|
||||
/// <param name="message">A message.</param>
|
||||
void Fatal(Type reporting, Exception exception, string message);
|
||||
|
||||
/// <summary>
|
||||
/// Logs a fatal exception.
|
||||
/// </summary>
|
||||
/// <param name="reporting">The reporting type.</param>
|
||||
/// <param name="exception">An exception.</param>
|
||||
/// <remarks>The message string is unspecified and is implementation-specific.</remarks>
|
||||
void Fatal(Type reporting, Exception exception);
|
||||
|
||||
/// <summary>
|
||||
/// Logs a fatal message.
|
||||
/// </summary>
|
||||
/// <param name="reporting">The reporting type.</param>
|
||||
/// <param name="message">A message.</param>
|
||||
void Fatal(Type reporting, string message);
|
||||
|
||||
/// <summary>
|
||||
/// Logs a fatal message with an exception.
|
||||
/// </summary>
|
||||
/// <param name="reporting">The reporting type.</param>
|
||||
/// <param name="exception">An exception.</param>
|
||||
/// <param name="messageTemplate">A message template.</param>
|
||||
/// <param name="propertyValues">Property values.</param>
|
||||
void Fatal(Type reporting, Exception exception, string messageTemplate, params object[] propertyValues);
|
||||
|
||||
/// <summary>
|
||||
/// Logs a fatal message.
|
||||
/// </summary>
|
||||
/// <param name="reporting">The reporting type.</param>
|
||||
/// <param name="messageTemplate">A message template.</param>
|
||||
/// <param name="propertyValues">Property values.</param>
|
||||
void Fatal(Type reporting, string messageTemplate, params object[] propertyValues);
|
||||
|
||||
/// <summary>
|
||||
/// Logs an error message with an exception.
|
||||
/// </summary>
|
||||
/// <param name="reporting">The reporting type.</param>
|
||||
/// <param name="exception">An exception.</param>
|
||||
/// <param name="message">A message.</param>
|
||||
void Error(Type reporting, Exception exception, string message);
|
||||
|
||||
/// <summary>
|
||||
/// Logs an error exception.
|
||||
/// </summary>
|
||||
/// <param name="reporting">The reporting type.</param>
|
||||
/// <param name="exception">An exception.</param>
|
||||
/// <remarks>The message string is unspecified and is implementation-specific.</remarks>
|
||||
void Error(Type reporting, Exception exception);
|
||||
|
||||
/// <summary>
|
||||
/// Logs an error message.
|
||||
/// </summary>
|
||||
/// <param name="reporting">The reporting type.</param>
|
||||
/// <param name="message">A message.</param>
|
||||
void Error(Type reporting, string message);
|
||||
|
||||
/// <summary>
|
||||
/// Logs an error message with an exception.
|
||||
/// </summary>
|
||||
/// <param name="reporting">The reporting type.</param>
|
||||
/// <param name="exception">An exception.</param>
|
||||
/// <param name="messageTemplate">A message template.</param>
|
||||
/// <param name="propertyValues">Property values.</param>
|
||||
void Error(Type reporting, Exception exception, string messageTemplate, params object[] propertyValues);
|
||||
void Error(Type reporting, string message, Exception exception = null);
|
||||
|
||||
/// <summary>
|
||||
/// Logs an error message.
|
||||
/// </summary>
|
||||
/// <param name="reporting">The reporting type.</param>
|
||||
/// <param name="messageTemplate">A message template.</param>
|
||||
/// <param name="propertyValues">Property values.</param>
|
||||
void Error(Type reporting, string messageTemplate, params object[] propertyValues);
|
||||
// note: should we have more overloads for Error too?
|
||||
|
||||
/// <summary>
|
||||
/// Logs a warning message.
|
||||
@@ -112,9 +29,8 @@ namespace Umbraco.Core.Logging
|
||||
/// Logs a warning message.
|
||||
/// </summary>
|
||||
/// <param name="reporting">The reporting type.</param>
|
||||
/// <param name="messageTemplate">A message template.</param>
|
||||
/// <param name="propertyValues">Property values.</param>
|
||||
void Warn(Type reporting, string messageTemplate, params object[] propertyValues);
|
||||
/// <param name="messageBuilder">A message builder.</param>
|
||||
void Warn(Type reporting, Func<string> messageBuilder);
|
||||
|
||||
/// <summary>
|
||||
/// Logs a warning message with an exception.
|
||||
@@ -129,9 +45,8 @@ namespace Umbraco.Core.Logging
|
||||
/// </summary>
|
||||
/// <param name="reporting">The reporting type.</param>
|
||||
/// <param name="exception">An exception.</param>
|
||||
/// <param name="messageTemplate">A message template.</param>
|
||||
/// <param name="propertyValues">Property values.</param>
|
||||
void Warn(Type reporting, Exception exception, string messageTemplate, params object[] propertyValues);
|
||||
/// <param name="messageBuilder">A message builder.</param>
|
||||
void Warn(Type reporting, Exception exception, Func<string> messageBuilder);
|
||||
|
||||
/// <summary>
|
||||
/// Logs an information message.
|
||||
@@ -141,12 +56,11 @@ namespace Umbraco.Core.Logging
|
||||
void Info(Type reporting, string message);
|
||||
|
||||
/// <summary>
|
||||
/// Logs a info message.
|
||||
/// Logs an information message.
|
||||
/// </summary>
|
||||
/// <param name="reporting">The reporting type.</param>
|
||||
/// <param name="messageTemplate">A message template.</param>
|
||||
/// <param name="propertyValues">Property values.</param>
|
||||
void Info(Type reporting, string messageTemplate, params object[] propertyValues);
|
||||
/// <param name="messageBuilder">A message builder.</param>
|
||||
void Info(Type reporting, Func<string> messageBuilder);
|
||||
|
||||
/// <summary>
|
||||
/// Logs a debugging message.
|
||||
@@ -156,26 +70,10 @@ namespace Umbraco.Core.Logging
|
||||
void Debug(Type reporting, string message);
|
||||
|
||||
/// <summary>
|
||||
/// Logs a debug message.
|
||||
/// Logs a debugging message.
|
||||
/// </summary>
|
||||
/// <param name="reporting">The reporting type.</param>
|
||||
/// <param name="messageTemplate">A message template.</param>
|
||||
/// <param name="propertyValues">Property values.</param>
|
||||
void Debug(Type reporting, string messageTemplate, params object[] propertyValues);
|
||||
|
||||
/// <summary>
|
||||
/// Logs a verbose message.
|
||||
/// </summary>
|
||||
/// <param name="reporting">The reporting type.</param>
|
||||
/// <param name="message">A message.</param>
|
||||
void Verbose(Type reporting, string message);
|
||||
|
||||
/// <summary>
|
||||
/// Logs a verbose message.
|
||||
/// </summary>
|
||||
/// <param name="reporting">The reporting type.</param>
|
||||
/// <param name="messageTemplate">A message template.</param>
|
||||
/// <param name="propertyValues">Property values.</param>
|
||||
void Verbose(Type reporting, string messageTemplate, params object[] propertyValues);
|
||||
/// <param name="messageBuilder">A message builder.</param>
|
||||
void Debug(Type reporting, Func<string> messageBuilder);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
namespace Umbraco.Core.Logging
|
||||
{
|
||||
/// <summary>
|
||||
/// Borrowed from https://github.com/cjbhaines/Log4Net.Async - will reference Nuget packages directly in v8
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
internal interface IQueue<T>
|
||||
{
|
||||
void Enqueue(T item);
|
||||
bool TryDequeue(out T ret);
|
||||
}
|
||||
}
|
||||
@@ -2,9 +2,8 @@
|
||||
using System.Runtime.CompilerServices;
|
||||
using ImageProcessor.Common.Exceptions;
|
||||
using Umbraco.Core.Composing;
|
||||
using Umbraco.Core.Logging;
|
||||
|
||||
namespace Umbraco.Web
|
||||
namespace Umbraco.Core.Logging
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
@@ -28,7 +27,7 @@ namespace Umbraco.Web
|
||||
{
|
||||
// Using LogHelper since the ImageProcessor logger expects a parameterless constructor.
|
||||
var message = $"{callerName} {lineNumber} : {text}";
|
||||
Current.Logger.Error<T>(new ImageProcessingException(message));
|
||||
Current.Logger.Error<T>(string.Empty, new ImageProcessingException(message));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -42,7 +41,7 @@ namespace Umbraco.Web
|
||||
{
|
||||
// Using LogHelper since the ImageProcessor logger expects a parameterless constructor.
|
||||
var message = $"{callerName} {lineNumber} : {text}";
|
||||
Current.Logger.Error(type, new ImageProcessingException(message));
|
||||
Current.Logger.Error(type, string.Empty, new ImageProcessingException(message));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,32 +0,0 @@
|
||||
using System;
|
||||
using System.Web;
|
||||
|
||||
namespace Umbraco.Core.Logging
|
||||
{
|
||||
public static class LogHttpRequest
|
||||
{
|
||||
static readonly string RequestIdItemName = typeof(LogHttpRequest).Name + "+RequestId";
|
||||
|
||||
/// <summary>
|
||||
/// Retrieve the id assigned to the currently-executing HTTP request, if any.
|
||||
/// </summary>
|
||||
/// <param name="requestId">The request id.</param>
|
||||
/// <returns><c>true</c> if there is a request in progress; <c>false</c> otherwise.</returns>
|
||||
public static bool TryGetCurrentHttpRequestId(out Guid requestId)
|
||||
{
|
||||
if (HttpContext.Current == null)
|
||||
{
|
||||
requestId = default(Guid);
|
||||
return false;
|
||||
}
|
||||
|
||||
var requestIdItem = HttpContext.Current.Items[RequestIdItemName];
|
||||
if (requestIdItem == null)
|
||||
HttpContext.Current.Items[RequestIdItemName] = requestId = Guid.NewGuid();
|
||||
else
|
||||
requestId = (Guid)requestIdItem;
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,15 +0,0 @@
|
||||
namespace Umbraco.Core.Logging
|
||||
{
|
||||
/// <summary>
|
||||
/// Specifies the level of a log event.
|
||||
/// </summary>
|
||||
public enum LogLevel
|
||||
{
|
||||
Verbose,
|
||||
Debug,
|
||||
Information,
|
||||
Warning,
|
||||
Error,
|
||||
Fatal
|
||||
}
|
||||
}
|
||||
@@ -24,8 +24,8 @@ namespace Umbraco.Core.Logging
|
||||
/// <inheritdoc/>
|
||||
public IDisposable Step(string name)
|
||||
{
|
||||
_logger.Debug<LogProfiler>("Begin: {ProfileName}", name);
|
||||
return new LightDisposableTimer(duration => _logger.Info<LogProfiler>("End {ProfileName} ({ProfileDuration}ms)", name, duration));
|
||||
_logger.Debug<LogProfiler>(() => $"Begin: {name}.");
|
||||
return new LightDisposableTimer(duration => _logger.Info<LogProfiler>(() => $"End {name}. ({duration}ms)"));
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
|
||||
@@ -0,0 +1,244 @@
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.Globalization;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Threading;
|
||||
using log4net;
|
||||
using log4net.Config;
|
||||
using Umbraco.Core.Configuration;
|
||||
using Umbraco.Core.Diagnostics;
|
||||
using log4net.Util;
|
||||
|
||||
namespace Umbraco.Core.Logging
|
||||
{
|
||||
///<summary>
|
||||
/// Implements <see cref="ILogger"/> on top of log4net.
|
||||
///</summary>
|
||||
public class Logger : ILogger
|
||||
{
|
||||
/// <summary>
|
||||
/// Initialize a new instance of the <see cref="Logger"/> class with a log4net configuration file.
|
||||
/// </summary>
|
||||
/// <param name="log4NetConfigFile"></param>
|
||||
public Logger(FileInfo log4NetConfigFile)
|
||||
: this()
|
||||
{
|
||||
XmlConfigurator.Configure(log4NetConfigFile);
|
||||
}
|
||||
|
||||
// private for CreateWithDefaultLog4NetConfiguration
|
||||
private Logger()
|
||||
{
|
||||
// add custom global properties to the log4net context that we can use in our logging output
|
||||
GlobalContext.Properties["processId"] = Process.GetCurrentProcess().Id;
|
||||
GlobalContext.Properties["appDomainId"] = AppDomain.CurrentDomain.Id;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a logger with the default log4net configuration discovered (i.e. from the web.config).
|
||||
/// </summary>
|
||||
/// <remarks>Used by UmbracoApplicationBase to get its logger.</remarks>
|
||||
public static Logger CreateWithDefaultLog4NetConfiguration()
|
||||
{
|
||||
return new Logger();
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public void Error(Type reporting, string message, Exception exception = null)
|
||||
{
|
||||
var logger = LogManager.GetLogger(reporting);
|
||||
if (logger == null) return;
|
||||
|
||||
var dump = false;
|
||||
|
||||
if (IsTimeoutThreadAbortException(exception))
|
||||
{
|
||||
message += "\r\nThe thread has been aborted, because the request has timed out.";
|
||||
|
||||
// dump if configured, or if stacktrace contains Monitor.ReliableEnter
|
||||
dump = UmbracoConfig.For.CoreDebug().DumpOnTimeoutThreadAbort || IsMonitorEnterThreadAbortException(exception);
|
||||
|
||||
// dump if it is ok to dump (might have a cap on number of dump...)
|
||||
dump &= MiniDump.OkToDump();
|
||||
}
|
||||
|
||||
if (dump)
|
||||
{
|
||||
try
|
||||
{
|
||||
var dumped = MiniDump.Dump(withException: true);
|
||||
message += dumped
|
||||
? "\r\nA minidump was created in App_Data/MiniDump"
|
||||
: "\r\nFailed to create a minidump";
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
message += string.Format("\r\nFailed to create a minidump ({0}: {1})", e.GetType().FullName, e.Message);
|
||||
}
|
||||
}
|
||||
|
||||
logger.Error(message, exception);
|
||||
}
|
||||
|
||||
private static bool IsMonitorEnterThreadAbortException(Exception exception)
|
||||
{
|
||||
var abort = exception as ThreadAbortException;
|
||||
if (abort == null) return false;
|
||||
|
||||
var stacktrace = abort.StackTrace;
|
||||
return stacktrace.Contains("System.Threading.Monitor.ReliableEnter");
|
||||
}
|
||||
|
||||
private static bool IsTimeoutThreadAbortException(Exception exception)
|
||||
{
|
||||
var abort = exception as ThreadAbortException;
|
||||
if (abort == null) return false;
|
||||
|
||||
if (abort.ExceptionState == null) return false;
|
||||
|
||||
var stateType = abort.ExceptionState.GetType();
|
||||
if (stateType.FullName != "System.Web.HttpApplication+CancelModuleException") return false;
|
||||
|
||||
var timeoutField = stateType.GetField("_timeout", BindingFlags.Instance | BindingFlags.NonPublic);
|
||||
if (timeoutField == null) return false;
|
||||
|
||||
return (bool) timeoutField.GetValue(abort.ExceptionState);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public void Warn(Type reporting, string format)
|
||||
{
|
||||
var logger = LogManager.GetLogger(reporting);
|
||||
if (logger == null || logger.IsWarnEnabled == false) return;
|
||||
logger.Warn(format);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public void Warn(Type reporting, Func<string> messageBuilder)
|
||||
{
|
||||
var logger = LogManager.GetLogger(reporting);
|
||||
if (logger == null || logger.IsWarnEnabled == false) return;
|
||||
logger.Warn(messageBuilder());
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public void Warn(Type reporting, string format, params object[] args)
|
||||
{
|
||||
var logger = LogManager.GetLogger(reporting);
|
||||
if (logger == null || logger.IsWarnEnabled == false) return;
|
||||
logger.WarnFormat(format, args);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public void Warn(Type reporting, string format, params Func<object>[] args)
|
||||
{
|
||||
var logger = LogManager.GetLogger(reporting);
|
||||
if (logger == null || logger.IsWarnEnabled == false) return;
|
||||
logger.WarnFormat(format, args.Select(x => x.Invoke()).ToArray());
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public void Warn(Type reporting, Exception exception, string message)
|
||||
{
|
||||
var logger = LogManager.GetLogger(reporting);
|
||||
if (logger == null || logger.IsWarnEnabled == false) return;
|
||||
logger.Warn(message, exception);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public void Warn(Type reporting, Exception exception, Func<string> messageBuilder)
|
||||
{
|
||||
var logger = LogManager.GetLogger(reporting);
|
||||
if (logger == null || logger.IsWarnEnabled == false) return;
|
||||
logger.Warn(messageBuilder(), exception);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public void Warn(Type reporting, Exception exception, string format, params object[] args)
|
||||
{
|
||||
var logger = LogManager.GetLogger(reporting);
|
||||
if (logger == null || logger.IsWarnEnabled == false) return;
|
||||
// there is no WarnFormat overload that accepts an exception
|
||||
// format the message the way log4net would do it (see source code LogImpl.cs)
|
||||
var message = new SystemStringFormat(CultureInfo.InvariantCulture, format, args);
|
||||
logger.Warn(message, exception);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public void Warn(Type reporting, Exception exception, string format, params Func<object>[] args)
|
||||
{
|
||||
var logger = LogManager.GetLogger(reporting);
|
||||
if (logger == null || logger.IsWarnEnabled == false) return;
|
||||
// there is no WarnFormat overload that accepts an exception
|
||||
// format the message the way log4net would do it (see source code LogImpl.cs)
|
||||
var message = new SystemStringFormat(CultureInfo.InvariantCulture, format, args.Select(x => x.Invoke()).ToArray());
|
||||
logger.Warn(message, exception);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public void Info(Type reporting, string message)
|
||||
{
|
||||
var logger = LogManager.GetLogger(reporting);
|
||||
if (logger == null || logger.IsInfoEnabled == false) return;
|
||||
logger.Info(message);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public void Info(Type reporting, Func<string> generateMessage)
|
||||
{
|
||||
var logger = LogManager.GetLogger(reporting);
|
||||
if (logger == null || logger.IsInfoEnabled == false) return;
|
||||
logger.Info(generateMessage());
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public void Info(Type reporting, string format, params object[] args)
|
||||
{
|
||||
var logger = LogManager.GetLogger(reporting);
|
||||
if (logger == null || logger.IsInfoEnabled == false) return;
|
||||
logger.InfoFormat(format, args);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public void Info(Type reporting, string format, params Func<object>[] args)
|
||||
{
|
||||
var logger = LogManager.GetLogger(reporting);
|
||||
if (logger == null || logger.IsInfoEnabled == false) return;
|
||||
logger.InfoFormat(format, args.Select(x => x.Invoke()).ToArray());
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public void Debug(Type reporting, string message)
|
||||
{
|
||||
var logger = LogManager.GetLogger(reporting);
|
||||
if (logger == null || logger.IsDebugEnabled == false) return;
|
||||
logger.Debug(message);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public void Debug(Type reporting, Func<string> messageBuilder)
|
||||
{
|
||||
var logger = LogManager.GetLogger(reporting);
|
||||
if (logger == null || logger.IsDebugEnabled == false) return;
|
||||
logger.Debug(messageBuilder());
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public void Debug(Type reporting, string format, params object[] args)
|
||||
{
|
||||
var logger = LogManager.GetLogger(reporting);
|
||||
if (logger == null || logger.IsDebugEnabled == false) return;
|
||||
logger.DebugFormat(format, args);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public void Debug(Type reporting, string format, params Func<object>[] args)
|
||||
{
|
||||
var logger = LogManager.GetLogger(reporting);
|
||||
if (logger == null || logger.IsDebugEnabled == false) return;
|
||||
logger.DebugFormat(format, args.Select(x => x.Invoke()).ToArray());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,5 @@
|
||||
using System;
|
||||
using System.Linq;
|
||||
|
||||
namespace Umbraco.Core.Logging
|
||||
{
|
||||
@@ -7,63 +8,17 @@ namespace Umbraco.Core.Logging
|
||||
/// </summary>
|
||||
public static class LoggerExtensions
|
||||
{
|
||||
/// <summary>
|
||||
/// Determines if logging is enabled at a specified level, for a reporting type.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The reporting type.</typeparam>
|
||||
/// <param name="logger">The logger.</param>
|
||||
/// <param name="level">The level.</param>
|
||||
public static bool IsEnabled<T>(this ILogger logger, LogLevel level)
|
||||
=> logger.IsEnabled(typeof(T), level);
|
||||
|
||||
/// <summary>
|
||||
/// Logs an error message with an exception.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The reporting type.</typeparam>
|
||||
/// <param name="logger">The logger.</param>
|
||||
/// <param name="message">A message.</param>
|
||||
/// <param name="exception">An exception.</param>
|
||||
public static void Error<T>(this ILogger logger, Exception exception, string message)
|
||||
=> logger.Error(typeof(T), exception, message);
|
||||
|
||||
/// <summary>
|
||||
/// Logs an error message with an exception.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The reporting type.</typeparam>
|
||||
/// <param name="logger">The logger.</param>
|
||||
/// <param name="exception">An exception.</param>
|
||||
/// <param name="messageTemplate">A message template.</param>
|
||||
/// <param name="propertyValues">Property values.</param>
|
||||
public static void Error<T>(this ILogger logger, Exception exception, string messageTemplate, params object[] propertyValues)
|
||||
=> logger.Error(typeof(T), exception, messageTemplate, propertyValues);
|
||||
|
||||
/// <summary>
|
||||
/// Logs an error exception.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The reporting type.</typeparam>
|
||||
/// <param name="logger">The logger.</param>
|
||||
/// <param name="exception">An exception.</param>
|
||||
public static void Error<T>(this ILogger logger, Exception exception)
|
||||
=> logger.Error(typeof(T), exception);
|
||||
|
||||
/// <summary>
|
||||
/// Logs an error message.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The reporting type.</typeparam>
|
||||
/// <param name="logger">The logger.</param>
|
||||
/// <param name="message">A message.</param>
|
||||
public static void Error<T>(this ILogger logger, string message)
|
||||
=> logger.Error(typeof(T), message);
|
||||
|
||||
/// <summary>
|
||||
/// Logs an error message.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The reporting type.</typeparam>
|
||||
/// <param name="logger">The logger.</param>
|
||||
/// <param name="messageTemplate">A message template.</param>
|
||||
/// <param name="propertyValues">Property values.</param>
|
||||
public static void Error<T>(this ILogger logger, string messageTemplate, params object[] propertyValues)
|
||||
=> logger.Error(typeof(T), messageTemplate, propertyValues);
|
||||
/// <param name="exception">An exception.</param>
|
||||
public static void Error<T>(this ILogger logger, string message, Exception exception = null)
|
||||
{
|
||||
logger.Error(typeof(T), message, exception);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Logs a warning message.
|
||||
@@ -72,38 +27,44 @@ namespace Umbraco.Core.Logging
|
||||
/// <param name="logger">The logger.</param>
|
||||
/// <param name="message">A message.</param>
|
||||
public static void Warn<T>(this ILogger logger, string message)
|
||||
=> logger.Warn(typeof(T), message);
|
||||
{
|
||||
logger.Warn(typeof(T), message);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Logs a warning message.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The reporting type.</typeparam>
|
||||
/// <param name="logger">The logger.</param>
|
||||
/// <param name="messageTemplate">A message template.</param>
|
||||
/// <param name="propertyValues">Property values.</param>
|
||||
public static void Warn<T>(this ILogger logger, string messageTemplate, params object[] propertyValues)
|
||||
=> logger.Warn(typeof(T), messageTemplate, propertyValues);
|
||||
/// <param name="messageBuilder">A message builder.</param>
|
||||
public static void Warn<T>(this ILogger logger, Func<string> messageBuilder)
|
||||
{
|
||||
logger.Warn(typeof(T), messageBuilder);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Logs a warning message with an exception.
|
||||
/// Logs a formatted warning message with an exception.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The reporting type.</typeparam>
|
||||
/// <param name="logger">The logger.</param>
|
||||
/// <param name="exception">An exception.</param>
|
||||
/// <param name="messageBuilder">A message builder.</param>
|
||||
public static void Warn<T>(this ILogger logger, Exception exception, Func<string> messageBuilder)
|
||||
{
|
||||
logger.Warn(typeof(T), exception, messageBuilder);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Logs a formatted warning message with an exception.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The reporting type.</typeparam>
|
||||
/// <param name="logger">The logger.</param>
|
||||
/// <param name="exception">An exception.</param>
|
||||
/// <param name="message">A message.</param>
|
||||
public static void Warn<T>(this ILogger logger, Exception exception, string message)
|
||||
=> logger.Warn(typeof(T), exception, message);
|
||||
|
||||
/// <summary>
|
||||
/// Logs a warning message with an exception.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The reporting type.</typeparam>
|
||||
/// <param name="logger">The logger.</param>
|
||||
/// <param name="exception">An exception.</param>
|
||||
/// <param name="messageTemplate">A message template.</param>
|
||||
/// <param name="propertyValues">Property values.</param>
|
||||
public static void Warn<T>(this ILogger logger, Exception exception, string messageTemplate, params object[] propertyValues)
|
||||
=> logger.Warn(typeof(T), exception, messageTemplate, propertyValues);
|
||||
{
|
||||
logger.Warn(typeof(T), exception, message);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Logs an information message.
|
||||
@@ -112,17 +73,20 @@ namespace Umbraco.Core.Logging
|
||||
/// <param name="logger">The logger.</param>
|
||||
/// <param name="message">A message.</param>
|
||||
public static void Info<T>(this ILogger logger, string message)
|
||||
=> logger.Info(typeof(T), message);
|
||||
{
|
||||
logger.Info(typeof(T), message);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Logs a information message.
|
||||
/// Logs an information message.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The reporting type</typeparam>
|
||||
/// <typeparam name="T">The reporting type.</typeparam>
|
||||
/// <param name="logger">The logger.</param>
|
||||
/// <param name="messageTemplate">A message template.</param>
|
||||
/// <param name="propertyValues">Property values.</param>
|
||||
public static void Info<T>(this ILogger logger, string messageTemplate, params object[] propertyValues)
|
||||
=> logger.Info(typeof(T), messageTemplate, propertyValues);
|
||||
/// <param name="messageBuilder">A message builder.</param>
|
||||
public static void Info<T>(this ILogger logger, Func<string> messageBuilder)
|
||||
{
|
||||
logger.Info(typeof(T), messageBuilder);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Logs a debugging message.
|
||||
@@ -131,56 +95,19 @@ namespace Umbraco.Core.Logging
|
||||
/// <param name="logger">The logger.</param>
|
||||
/// <param name="message">A message.</param>
|
||||
public static void Debug<T>(this ILogger logger, string message)
|
||||
=> logger.Debug(typeof(T), message);
|
||||
{
|
||||
logger.Debug(typeof(T), message);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Logs a debugging message.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The reporting type</typeparam>
|
||||
/// <param name="logger">The logger.</param>
|
||||
/// <param name="messageTemplate">A message template.</param>
|
||||
/// <param name="propertyValues">Property values.</param>
|
||||
public static void Debug<T>(this ILogger logger, string messageTemplate, params object[] propertyValues)
|
||||
=> logger.Debug(typeof(T), messageTemplate, propertyValues);
|
||||
|
||||
/// <summary>
|
||||
/// Logs a verbose message.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The reporting type.</typeparam>
|
||||
/// <param name="logger">The logger.</param>
|
||||
/// <param name="message">A message.</param>
|
||||
public static void Verbose<T>(this ILogger logger, string message)
|
||||
=> logger.Verbose(typeof(T), message);
|
||||
|
||||
/// <summary>
|
||||
/// Logs a verbose message.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The reporting type.</typeparam>
|
||||
/// <param name="logger">The logger.</param>
|
||||
/// <param name="messageTemplate">A message template.</param>
|
||||
/// <param name="propertyValues">Property values.</param>
|
||||
public static void Verbose<T>(this ILogger logger, string messageTemplate, params object[] propertyValues)
|
||||
=> logger.Verbose(typeof(T), messageTemplate, propertyValues);
|
||||
|
||||
/// <summary>
|
||||
/// Logs a fatal message.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The reporting type.</typeparam>
|
||||
/// <param name="logger">The logger.</param>
|
||||
/// <param name="exception">An exception.</param>
|
||||
/// <param name="message">A message.</param>
|
||||
public static void Fatal<T>(this ILogger logger, Exception exception, string message)
|
||||
=> logger.Fatal(typeof(T), exception, message);
|
||||
|
||||
/// <summary>
|
||||
/// Logs a fatal message.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The reporting type.</typeparam>
|
||||
/// <param name="logger">The logger.</param>
|
||||
/// <param name="exception">An exception.</param>
|
||||
/// <param name="messageTemplate">A message template.</param>
|
||||
/// <param name="propertyValues">Property values.</param>
|
||||
public static void Fatal<T>(this ILogger logger, Exception exception, string messageTemplate, params object[] propertyValues)
|
||||
=> logger.Fatal(typeof(T), exception, messageTemplate, propertyValues);
|
||||
/// <param name="messageBuilder">A message builder.</param>
|
||||
public static void Debug<T>(this ILogger logger, Func<string> messageBuilder)
|
||||
{
|
||||
logger.Debug(typeof(T), messageBuilder);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
using log4net.Core;
|
||||
|
||||
namespace Umbraco.Core.Logging
|
||||
{
|
||||
/// <remarks>
|
||||
/// Borrowed from https://github.com/cjbhaines/Log4Net.Async - will reference Nuget packages directly in v8
|
||||
/// </remarks>
|
||||
internal sealed class LoggingEventContext
|
||||
{
|
||||
public LoggingEventContext(LoggingEvent loggingEvent, object httpContext)
|
||||
{
|
||||
LoggingEvent = loggingEvent;
|
||||
HttpContext = httpContext;
|
||||
}
|
||||
|
||||
public LoggingEvent LoggingEvent { get; set; }
|
||||
|
||||
public object HttpContext { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
using System;
|
||||
using log4net.Core;
|
||||
|
||||
namespace Umbraco.Core.Logging
|
||||
{
|
||||
/// <remarks>
|
||||
/// Borrowed from https://github.com/cjbhaines/Log4Net.Async - will reference Nuget packages directly in v8
|
||||
/// </remarks>
|
||||
internal sealed class LoggingEventHelper
|
||||
{
|
||||
// needs to be a seperate class so that location is determined correctly by log4net when required
|
||||
|
||||
private static readonly Type HelperType = typeof(LoggingEventHelper);
|
||||
private readonly string loggerName;
|
||||
|
||||
public FixFlags Fix { get; set; }
|
||||
|
||||
public LoggingEventHelper(string loggerName, FixFlags fix)
|
||||
{
|
||||
this.loggerName = loggerName;
|
||||
Fix = fix;
|
||||
}
|
||||
|
||||
public LoggingEvent CreateLoggingEvent(Level level, string message, Exception exception)
|
||||
{
|
||||
var loggingEvent = new LoggingEvent(HelperType, null, loggerName, level, message, exception)
|
||||
{
|
||||
Fix = Fix
|
||||
};
|
||||
return loggingEvent;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,35 +0,0 @@
|
||||
using System;
|
||||
using System.Linq;
|
||||
using Serilog;
|
||||
|
||||
namespace Umbraco.Core.Logging
|
||||
{
|
||||
/// <summary>
|
||||
/// Provides tools to support message templates.
|
||||
/// </summary>
|
||||
public static class MessageTemplates
|
||||
{
|
||||
// Umbraco now uses Message Templates (https://messagetemplates.org/) for logging, which means
|
||||
// we cannot plainly use string.Format() to format them. There is a work-in-progress C# lib,
|
||||
// derived from Serilog, which should help (https://github.com/messagetemplates/messagetemplates-csharp)
|
||||
// but it only has a pre-release NuGet package. So, we've got to use Serilog's code, which
|
||||
// means we cannot get rid of Serilog entirely. We may want to revisit this at some point.
|
||||
|
||||
private static readonly Lazy<global::Serilog.ILogger> MinimalLogger = new Lazy<global::Serilog.ILogger>(() => new LoggerConfiguration().CreateLogger());
|
||||
|
||||
public static string Render(string messageTemplate, params object[] args)
|
||||
{
|
||||
// by default, unless initialized otherwise, Log.Logger is SilentLogger which cannot bind message
|
||||
// templates. Log.Logger is set to a true Logger when initializing Umbraco's logger, but in case
|
||||
// that has not been done already - use a temp minimal logger (eg for tests).
|
||||
var logger = Log.Logger as global::Serilog.Core.Logger ?? MinimalLogger.Value;
|
||||
|
||||
var bound = logger.BindMessageTemplate(messageTemplate, args, out var parsedTemplate, out var boundProperties);
|
||||
|
||||
if (!bound)
|
||||
throw new FormatException($"Could not format message \"{messageTemplate}\" with {args.Length} args.");
|
||||
|
||||
return parsedTemplate.Render(boundProperties.ToDictionary(x => x.Name, x => x.Value));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -26,34 +26,34 @@ namespace Umbraco.Core.Logging
|
||||
switch (eventType)
|
||||
{
|
||||
case TraceEventType.Critical:
|
||||
_logger.Fatal(_type.Value, exception, "[{EventType}] Event Id: {EventId}, State: {State}", eventType, eventId, state);
|
||||
_logger.Error(_type.Value, string.Format("Event Id: {0}, state: {1}", eventId, state), exception ?? new Exception("Critical error"));
|
||||
return true;
|
||||
case TraceEventType.Error:
|
||||
_logger.Error(_type.Value, exception, "[{EventType}] Event Id: {EventId}, State: {State}", eventType, eventId, state);
|
||||
_logger.Error(_type.Value, string.Format("Event Id: {0}, state: {1}", eventId, state), exception ?? new Exception("Error"));
|
||||
return true;
|
||||
case TraceEventType.Warning:
|
||||
_logger.Warn(_type.Value, "[{EventType}] Event Id: {EventId}, State: {State}", eventType, eventId, state);
|
||||
_logger.Warn(_type.Value, string.Format("Event Id: {0}, state: {1}", eventId, state));
|
||||
return true;
|
||||
case TraceEventType.Information:
|
||||
_logger.Info(_type.Value, "[{EventType}] Event Id: {EventId}, State: {State}", eventType, eventId, state);
|
||||
_logger.Info(_type.Value, string.Format("Event Id: {0}, state: {1}", eventId, state));
|
||||
return true;
|
||||
case TraceEventType.Verbose:
|
||||
_logger.Debug(_type.Value, "[{EventType}] Event Id: {EventId}, State: {State}", eventType, eventId, state);
|
||||
_logger.Debug(_type.Value, string.Format("Event Id: {0}, state: {1}", eventId, state));
|
||||
return true;
|
||||
case TraceEventType.Start:
|
||||
_logger.Debug(_type.Value, "[{EventType}] Event Id: {EventId}, State: {State}", eventType, eventId, state);
|
||||
_logger.Debug(_type.Value, string.Format("Event Id: {0}, state: {1}", eventId, state));
|
||||
return true;
|
||||
case TraceEventType.Stop:
|
||||
_logger.Debug(_type.Value, "[{EventType}] Event Id: {EventId}, State: {State}", eventType, eventId, state);
|
||||
_logger.Debug(_type.Value, string.Format("Event Id: {0}, state: {1}", eventId, state));
|
||||
return true;
|
||||
case TraceEventType.Suspend:
|
||||
_logger.Debug(_type.Value, "[{EventType}] Event Id: {EventId}, State: {State}", eventType, eventId, state);
|
||||
_logger.Debug(_type.Value, string.Format("Event Id: {0}, state: {1}", eventId, state));
|
||||
return true;
|
||||
case TraceEventType.Resume:
|
||||
_logger.Debug(_type.Value, "[{EventType}] Event Id: {EventId}, State: {State}", eventType, eventId, state);
|
||||
_logger.Debug(_type.Value, string.Format("Event Id: {0}, state: {1}", eventId, state));
|
||||
return true;
|
||||
case TraceEventType.Transfer:
|
||||
_logger.Debug(_type.Value, "[{EventType}] Event Id: {EventId}, State: {State}", eventType, eventId, state);
|
||||
_logger.Debug(_type.Value, string.Format("Event Id: {0}, state: {1}", eventId, state));
|
||||
return true;
|
||||
default:
|
||||
throw new ArgumentOutOfRangeException("eventType");
|
||||
|
||||
@@ -13,8 +13,10 @@ namespace Umbraco.Core.Logging
|
||||
|
||||
public ProfilingLogger(ILogger logger, IProfiler profiler)
|
||||
{
|
||||
Logger = logger ?? throw new ArgumentNullException(nameof(logger));
|
||||
Profiler = profiler ?? throw new ArgumentNullException(nameof(profiler));
|
||||
if (logger == null) throw new ArgumentNullException(nameof(logger));
|
||||
if (profiler == null) throw new ArgumentNullException(nameof(profiler));
|
||||
Logger = logger;
|
||||
Profiler = profiler;
|
||||
}
|
||||
|
||||
public DisposableTimer TraceDuration<T>(string startMessage)
|
||||
@@ -24,33 +26,27 @@ namespace Umbraco.Core.Logging
|
||||
|
||||
public DisposableTimer TraceDuration<T>(string startMessage, string completeMessage, string failMessage = null)
|
||||
{
|
||||
return new DisposableTimer(Logger, LogLevel.Information, Profiler, typeof(T), startMessage, completeMessage, failMessage);
|
||||
return new DisposableTimer(Logger, DisposableTimer.LogType.Info, Profiler, typeof(T), startMessage, completeMessage, failMessage);
|
||||
}
|
||||
|
||||
public DisposableTimer TraceDuration(Type loggerType, string startMessage, string completeMessage, string failMessage = null)
|
||||
{
|
||||
return new DisposableTimer(Logger, LogLevel.Information, Profiler, loggerType, startMessage, completeMessage, failMessage);
|
||||
return new DisposableTimer(Logger, DisposableTimer.LogType.Info, Profiler, loggerType, startMessage, completeMessage, failMessage);
|
||||
}
|
||||
|
||||
public DisposableTimer DebugDuration<T>(string startMessage)
|
||||
{
|
||||
return Logger.IsEnabled<T>(LogLevel.Debug)
|
||||
? DebugDuration<T>(startMessage, "Completed.")
|
||||
: null;
|
||||
return DebugDuration<T>(startMessage, "Completed.");
|
||||
}
|
||||
|
||||
public DisposableTimer DebugDuration<T>(string startMessage, string completeMessage, string failMessage = null, int thresholdMilliseconds = 0)
|
||||
{
|
||||
return Logger.IsEnabled<T>(LogLevel.Debug)
|
||||
? new DisposableTimer(Logger, LogLevel.Debug, Profiler, typeof(T), startMessage, completeMessage, failMessage, thresholdMilliseconds)
|
||||
: null;
|
||||
return new DisposableTimer(Logger, DisposableTimer.LogType.Debug, Profiler, typeof(T), startMessage, completeMessage, failMessage, thresholdMilliseconds);
|
||||
}
|
||||
|
||||
public DisposableTimer DebugDuration(Type loggerType, string startMessage, string completeMessage, string failMessage = null, int thresholdMilliseconds = 0)
|
||||
{
|
||||
return Logger.IsEnabled(loggerType, LogLevel.Debug)
|
||||
? new DisposableTimer(Logger, LogLevel.Debug, Profiler, loggerType, startMessage, completeMessage, failMessage, thresholdMilliseconds)
|
||||
: null;
|
||||
return new DisposableTimer(Logger, DisposableTimer.LogType.Debug, Profiler, loggerType, startMessage, completeMessage, failMessage, thresholdMilliseconds);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,78 @@
|
||||
using System;
|
||||
|
||||
namespace Umbraco.Core.Logging
|
||||
{
|
||||
/// <summary>
|
||||
/// Borrowed from https://github.com/cjbhaines/Log4Net.Async - will reference Nuget packages directly in v8
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
internal sealed class RingBuffer<T> : IQueue<T>
|
||||
{
|
||||
private readonly object lockObject = new object();
|
||||
private readonly T[] buffer;
|
||||
private readonly int size;
|
||||
private int readIndex = 0;
|
||||
private int writeIndex = 0;
|
||||
private bool bufferFull = false;
|
||||
|
||||
public int Size { get { return size; } }
|
||||
|
||||
public event Action<object, EventArgs> BufferOverflow;
|
||||
|
||||
public RingBuffer(int size)
|
||||
{
|
||||
this.size = size;
|
||||
buffer = new T[size];
|
||||
}
|
||||
|
||||
public void Enqueue(T item)
|
||||
{
|
||||
var bufferWasFull = false;
|
||||
lock (lockObject)
|
||||
{
|
||||
buffer[writeIndex] = item;
|
||||
writeIndex = (++writeIndex) % size;
|
||||
if (bufferFull)
|
||||
{
|
||||
bufferWasFull = true;
|
||||
readIndex = writeIndex;
|
||||
}
|
||||
else if (writeIndex == readIndex)
|
||||
{
|
||||
bufferFull = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (bufferWasFull)
|
||||
{
|
||||
if (BufferOverflow != null)
|
||||
{
|
||||
BufferOverflow(this, EventArgs.Empty);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public bool TryDequeue(out T ret)
|
||||
{
|
||||
if (readIndex == writeIndex && !bufferFull)
|
||||
{
|
||||
ret = default(T);
|
||||
return false;
|
||||
}
|
||||
lock (lockObject)
|
||||
{
|
||||
if (readIndex == writeIndex && !bufferFull)
|
||||
{
|
||||
ret = default(T);
|
||||
return false;
|
||||
}
|
||||
|
||||
ret = buffer[readIndex];
|
||||
buffer[readIndex] = default(T);
|
||||
readIndex = (++readIndex) % size;
|
||||
bufferFull = false;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,95 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using log4net.Appender;
|
||||
using log4net.Util;
|
||||
|
||||
namespace Umbraco.Core.Logging
|
||||
{
|
||||
/// <summary>
|
||||
/// This class will do the exact same thing as the RollingFileAppender that comes from log4net
|
||||
/// With the extension, that it is able to do automatic cleanup of the logfiles in the directory where logging happens
|
||||
///
|
||||
/// By specifying the properties MaxLogFileDays and BaseFilePattern, the files will automaticly get deleted when
|
||||
/// the logger is configured(typically when the app starts). To utilize this appender swap out the type of the rollingFile appender
|
||||
/// that ships with Umbraco, to be Umbraco.Core.Logging.RollingFileCleanupAppender, and add the maxLogFileDays and baseFilePattern elements
|
||||
/// to the configuration i.e.:
|
||||
///
|
||||
/// <example>
|
||||
/// <appender name="rollingFile" type="Log4netAwesomeness.CustomRollingFileAppender, Log4netAwesomeness">
|
||||
/// <file type="log4net.Util.PatternString" value="App_Data\Logs\UmbracoTraceLog.%property{log4net:HostName}.txt" />
|
||||
/// <lockingModel type="log4net.Appender.FileAppender+MinimalLock" />
|
||||
/// <appendToFile value="true" />
|
||||
/// <rollingStyle value="Date" />
|
||||
/// <maximumFileSize value="5MB" />
|
||||
/// <maxLogFileDays value="5"/>
|
||||
/// <basefilePattern value="UmbracoTraceLog.*.txt.*"/>
|
||||
/// <layout type="log4net.Layout.PatternLayout">
|
||||
/// <conversionPattern value=" %date [P%property{processId}/D%property{appDomainId}/T%thread] %-5level %logger - %message%newline" />
|
||||
/// </layout>
|
||||
/// <layout type="log4net.Layout.PatternLayout">
|
||||
/// <conversionPattern value=" %date [P%property{processId}/D%property{appDomainId}/T%thread] %-5level %logger - %message%newline" />
|
||||
/// </layout>
|
||||
/// <encoding value="utf-8" />
|
||||
/// </appender>
|
||||
/// </example>
|
||||
/// </summary>
|
||||
public class RollingFileCleanupAppender : RollingFileAppender
|
||||
{
|
||||
public int MaxLogFileDays { get; set; }
|
||||
public string BaseFilePattern { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// This override will delete logs older than the specified amount of days
|
||||
/// </summary>
|
||||
/// <param name="fileName"></param>
|
||||
/// <param name="append"></param>
|
||||
protected override void OpenFile(string fileName, bool append)
|
||||
{
|
||||
bool cleanup = true;
|
||||
// Validate settings and input
|
||||
if (MaxLogFileDays <= 0)
|
||||
{
|
||||
LogLog.Warn(typeof(RollingFileCleanupAppender), "Parameter 'MaxLogFileDays' needs to be a positive integer, aborting cleanup");
|
||||
cleanup = false;
|
||||
}
|
||||
|
||||
if (string.IsNullOrWhiteSpace(BaseFilePattern))
|
||||
{
|
||||
LogLog.Warn(typeof(RollingFileCleanupAppender), "Parameter 'BaseFilePattern' is empty, aborting cleanup");
|
||||
cleanup = false;
|
||||
}
|
||||
// grab the directory we are logging to, as this is were we will search for older logfiles
|
||||
var logFolder = Path.GetDirectoryName(fileName);
|
||||
if (Directory.Exists(logFolder) == false)
|
||||
{
|
||||
LogLog.Warn(typeof(RollingFileCleanupAppender), string.Format("Directory '{0}' for logfiles does not exist, aborting cleanup", logFolder));
|
||||
cleanup = false;
|
||||
}
|
||||
// If everything is validated, we can do the actual cleanup
|
||||
if (cleanup)
|
||||
{
|
||||
Cleanup(logFolder);
|
||||
}
|
||||
|
||||
base.OpenFile(fileName, append);
|
||||
}
|
||||
|
||||
private void Cleanup(string directoryPath)
|
||||
{
|
||||
// only take files that matches the pattern we are using i.e. UmbracoTraceLog.*.txt.*
|
||||
string[] logFiles = Directory.GetFiles(directoryPath, BaseFilePattern);
|
||||
LogLog.Debug(typeof(RollingFileCleanupAppender), string.Format("Found {0} files that matches the baseFilePattern: '{1}'", logFiles.Length, BaseFilePattern));
|
||||
|
||||
foreach (var logFile in logFiles)
|
||||
{
|
||||
DateTime lastAccessTime = System.IO.File.GetLastWriteTimeUtc(logFile);
|
||||
// take the value from the config file
|
||||
if (lastAccessTime < DateTime.Now.AddDays(-MaxLogFileDays))
|
||||
{
|
||||
LogLog.Debug(typeof(RollingFileCleanupAppender), string.Format("Deleting file {0} as its lastAccessTime is older than {1} days speficied by MaxLogFileDays", logFile, MaxLogFileDays));
|
||||
base.DeleteFile(logFile);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,36 +0,0 @@
|
||||
using System;
|
||||
using Serilog.Core;
|
||||
using Serilog.Events;
|
||||
|
||||
namespace Umbraco.Core.Logging.Serilog.Enrichers
|
||||
{
|
||||
/// <summary>
|
||||
/// Enrich log events with a HttpRequestId GUID.
|
||||
/// Original source - https://github.com/serilog-web/classic/blob/master/src/SerilogWeb.Classic/Classic/Enrichers/HttpRequestIdEnricher.cs
|
||||
/// Nupkg: 'Serilog.Web.Classic' contains handlers & extra bits we do not want
|
||||
/// </summary>
|
||||
internal class HttpRequestIdEnricher : ILogEventEnricher
|
||||
{
|
||||
/// <summary>
|
||||
/// The property name added to enriched log events.
|
||||
/// </summary>
|
||||
public const string HttpRequestIdPropertyName = "HttpRequestId";
|
||||
|
||||
/// <summary>
|
||||
/// Enrich the log event with an id assigned to the currently-executing HTTP request, if any.
|
||||
/// </summary>
|
||||
/// <param name="logEvent">The log event to enrich.</param>
|
||||
/// <param name="propertyFactory">Factory for creating new properties to add to the event.</param>
|
||||
public void Enrich(LogEvent logEvent, ILogEventPropertyFactory propertyFactory)
|
||||
{
|
||||
if (logEvent == null) throw new ArgumentNullException("logEvent");
|
||||
|
||||
Guid requestId;
|
||||
if (!LogHttpRequest.TryGetCurrentHttpRequestId(out requestId))
|
||||
return;
|
||||
|
||||
var requestIdProperty = new LogEventProperty(HttpRequestIdPropertyName, new ScalarValue(requestId));
|
||||
logEvent.AddPropertyIfAbsent(requestIdProperty);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,48 +0,0 @@
|
||||
using System;
|
||||
using System.Threading;
|
||||
using System.Web;
|
||||
using Serilog.Core;
|
||||
using Serilog.Events;
|
||||
|
||||
namespace Umbraco.Core.Logging.Serilog.Enrichers
|
||||
{
|
||||
/// <summary>
|
||||
/// Enrich log events with a HttpRequestNumber unique within the current
|
||||
/// logging session.
|
||||
/// Original source - https://github.com/serilog-web/classic/blob/master/src/SerilogWeb.Classic/Classic/Enrichers/HttpRequestNumberEnricher.cs
|
||||
/// Nupkg: 'Serilog.Web.Classic' contains handlers & extra bits we do not want
|
||||
/// </summary>
|
||||
internal class HttpRequestNumberEnricher : ILogEventEnricher
|
||||
{
|
||||
/// <summary>
|
||||
/// The property name added to enriched log events.
|
||||
/// </summary>
|
||||
public const string HttpRequestNumberPropertyName = "HttpRequestNumber";
|
||||
|
||||
static int _lastRequestNumber;
|
||||
static readonly string RequestNumberItemName = typeof(HttpRequestNumberEnricher).Name + "+RequestNumber";
|
||||
|
||||
/// <summary>
|
||||
/// Enrich the log event with the number assigned to the currently-executing HTTP request, if any.
|
||||
/// </summary>
|
||||
/// <param name="logEvent">The log event to enrich.</param>
|
||||
/// <param name="propertyFactory">Factory for creating new properties to add to the event.</param>
|
||||
public void Enrich(LogEvent logEvent, ILogEventPropertyFactory propertyFactory)
|
||||
{
|
||||
if (logEvent == null) throw new ArgumentNullException("logEvent");
|
||||
|
||||
if (HttpContext.Current == null)
|
||||
return;
|
||||
|
||||
int requestNumber;
|
||||
var requestNumberItem = HttpContext.Current.Items[RequestNumberItemName];
|
||||
if (requestNumberItem == null)
|
||||
HttpContext.Current.Items[RequestNumberItemName] = requestNumber = Interlocked.Increment(ref _lastRequestNumber);
|
||||
else
|
||||
requestNumber = (int)requestNumberItem;
|
||||
|
||||
var requestNumberProperty = new LogEventProperty(HttpRequestNumberPropertyName, new ScalarValue(requestNumber));
|
||||
logEvent.AddPropertyIfAbsent(requestNumberProperty);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,39 +0,0 @@
|
||||
using Serilog.Core;
|
||||
using Serilog.Events;
|
||||
using System;
|
||||
using System.Web;
|
||||
|
||||
namespace Umbraco.Core.Logging.Serilog.Enrichers
|
||||
{
|
||||
/// <summary>
|
||||
/// Enrich log events with the HttpSessionId property.
|
||||
/// Original source - https://github.com/serilog-web/classic/blob/master/src/SerilogWeb.Classic/Classic/Enrichers/HttpSessionIdEnricher.cs
|
||||
/// Nupkg: 'Serilog.Web.Classic' contains handlers & extra bits we do not want
|
||||
/// </summary>
|
||||
internal class HttpSessionIdEnricher : ILogEventEnricher
|
||||
{
|
||||
/// <summary>
|
||||
/// The property name added to enriched log events.
|
||||
/// </summary>
|
||||
public const string HttpSessionIdPropertyName = "HttpSessionId";
|
||||
|
||||
/// <summary>
|
||||
/// Enrich the log event with the current ASP.NET session id, if sessions are enabled.</summary>
|
||||
/// <param name="logEvent">The log event to enrich.</param>
|
||||
/// <param name="propertyFactory">Factory for creating new properties to add to the event.</param>
|
||||
public void Enrich(LogEvent logEvent, ILogEventPropertyFactory propertyFactory)
|
||||
{
|
||||
if (logEvent == null) throw new ArgumentNullException("logEvent");
|
||||
|
||||
if (HttpContext.Current == null)
|
||||
return;
|
||||
|
||||
if (HttpContext.Current.Session == null)
|
||||
return;
|
||||
|
||||
var sessionId = HttpContext.Current.Session.SessionID;
|
||||
var sessionIdProperty = new LogEventProperty(HttpSessionIdPropertyName, new ScalarValue(sessionId));
|
||||
logEvent.AddPropertyIfAbsent(sessionIdProperty);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,49 +0,0 @@
|
||||
using Serilog.Core;
|
||||
using Serilog.Events;
|
||||
|
||||
namespace Umbraco.Core.Logging.Serilog.Enrichers
|
||||
{
|
||||
/// <summary>
|
||||
/// This is used to create a new property in Logs called 'Log4NetLevel'
|
||||
/// So that we can map Serilog levels to Log4Net levels - so log files stay consistent
|
||||
/// </summary>
|
||||
internal class Log4NetLevelMapperEnricher : ILogEventEnricher
|
||||
{
|
||||
public void Enrich(LogEvent logEvent, ILogEventPropertyFactory propertyFactory)
|
||||
{
|
||||
var log4NetLevel = string.Empty;
|
||||
|
||||
switch (logEvent.Level)
|
||||
{
|
||||
case LogEventLevel.Debug:
|
||||
log4NetLevel = "DEBUG";
|
||||
break;
|
||||
|
||||
case LogEventLevel.Error:
|
||||
log4NetLevel = "ERROR";
|
||||
break;
|
||||
|
||||
case LogEventLevel.Fatal:
|
||||
log4NetLevel = "FATAL";
|
||||
break;
|
||||
|
||||
case LogEventLevel.Information:
|
||||
log4NetLevel = "INFO";
|
||||
break;
|
||||
|
||||
case LogEventLevel.Verbose:
|
||||
log4NetLevel = "ALL";
|
||||
break;
|
||||
|
||||
case LogEventLevel.Warning:
|
||||
log4NetLevel = "WARN";
|
||||
break;
|
||||
}
|
||||
|
||||
//Pad string so that all log levels are 5 chars long (needed to keep the txt log file lined up nicely)
|
||||
log4NetLevel = log4NetLevel.PadRight(5);
|
||||
|
||||
logEvent.AddPropertyIfAbsent(propertyFactory.CreateProperty("Log4NetLevel", log4NetLevel));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,107 +0,0 @@
|
||||
using System;
|
||||
using System.Web;
|
||||
using Serilog;
|
||||
using Serilog.Events;
|
||||
using Serilog.Formatting.Compact;
|
||||
using Umbraco.Core.Logging.Serilog.Enrichers;
|
||||
|
||||
namespace Umbraco.Core.Logging.Serilog
|
||||
{
|
||||
public static class LoggerConfigExtensions
|
||||
{
|
||||
/// <summary>
|
||||
/// This configures Serilog with some defaults
|
||||
/// Such as adding ProcessID, Thread, AppDomain etc
|
||||
/// It is highly recommended that you keep/use this default in your own logging config customizations
|
||||
/// </summary>
|
||||
/// <param name="logConfig">A Serilog LoggerConfiguration</param>
|
||||
public static LoggerConfiguration MinimalConfiguration(this LoggerConfiguration logConfig)
|
||||
{
|
||||
global::Serilog.Debugging.SelfLog.Enable(msg => System.Diagnostics.Debug.WriteLine(msg));
|
||||
|
||||
//Set this environment variable - so that it can be used in external config file
|
||||
//add key="serilog:write-to:RollingFile.pathFormat" value="%BASEDIR%\logs\log.txt" />
|
||||
Environment.SetEnvironmentVariable("BASEDIR", AppDomain.CurrentDomain.BaseDirectory, EnvironmentVariableTarget.Process);
|
||||
|
||||
logConfig.MinimumLevel.Verbose() //Set to highest level of logging (as any sinks may want to restrict it to Errors only)
|
||||
.Enrich.WithProcessId()
|
||||
.Enrich.WithProcessName()
|
||||
.Enrich.WithThreadId()
|
||||
.Enrich.WithProperty("AppDomainId", AppDomain.CurrentDomain.Id)
|
||||
.Enrich.WithProperty("AppDomainAppId", HttpRuntime.AppDomainAppId.ReplaceNonAlphanumericChars(string.Empty))
|
||||
.Enrich.WithProperty("MachineName", Environment.MachineName)
|
||||
.Enrich.With<Log4NetLevelMapperEnricher>()
|
||||
.Enrich.With<HttpSessionIdEnricher>()
|
||||
.Enrich.With<HttpRequestNumberEnricher>()
|
||||
.Enrich.With<HttpRequestIdEnricher>();
|
||||
|
||||
return logConfig;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Outputs a .txt format log at /App_Data/Logs/
|
||||
/// </summary>
|
||||
/// <param name="logConfig">A Serilog LoggerConfiguration</param>
|
||||
/// <param name="minimumLevel">The log level you wish the JSON file to collect - default is Verbose (highest)</param>
|
||||
/// <param name="retainedFileCount">The number of days to keep log files. Default is set to null which means all logs are kept</param>
|
||||
public static LoggerConfiguration OutputDefaultTextFile(this LoggerConfiguration logConfig, LogEventLevel minimumLevel = LogEventLevel.Verbose, int? retainedFileCount = null)
|
||||
{
|
||||
//Main .txt logfile - in similar format to older Log4Net output
|
||||
//Ends with ..txt as Date is inserted before file extension substring
|
||||
logConfig.WriteTo.File($@"{AppDomain.CurrentDomain.BaseDirectory}\App_Data\Logs\UmbracoTraceLog.{Environment.MachineName}..txt",
|
||||
shared: true,
|
||||
rollingInterval: RollingInterval.Day,
|
||||
restrictedToMinimumLevel: minimumLevel,
|
||||
retainedFileCountLimit: null, //Setting to null means we keep all files - default is 31 days
|
||||
outputTemplate: "{Timestamp:yyyy-MM-dd HH:mm:ss,fff} [P{ProcessId}/D{AppDomainId}/T{ThreadId}] {Log4NetLevel} {SourceContext} - {Message:lj}{NewLine}{Exception}");
|
||||
|
||||
return logConfig;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Outputs a CLEF format JSON log at /App_Data/Logs/
|
||||
/// </summary>
|
||||
/// <param name="logConfig">A Serilog LoggerConfiguration</param>
|
||||
/// <param name="minimumLevel">The log level you wish the JSON file to collect - default is Verbose (highest)</param>
|
||||
/// <param name="retainedFileCount">The number of days to keep log files. Default is set to null which means all logs are kept</param>
|
||||
public static LoggerConfiguration OutputDefaultJsonFile(this LoggerConfiguration logConfig, LogEventLevel minimumLevel = LogEventLevel.Verbose, int? retainedFileCount = null)
|
||||
{
|
||||
//.clef format (Compact log event format, that can be imported into local SEQ & will make searching/filtering logs easier)
|
||||
//Ends with ..txt as Date is inserted before file extension substring
|
||||
logConfig.WriteTo.File(new CompactJsonFormatter(), $@"{AppDomain.CurrentDomain.BaseDirectory}\App_Data\Logs\UmbracoTraceLog.{Environment.MachineName}..json",
|
||||
shared: true,
|
||||
rollingInterval: RollingInterval.Day, //Create a new JSON file every day
|
||||
retainedFileCountLimit: retainedFileCount, //Setting to null means we keep all files - default is 31 days
|
||||
restrictedToMinimumLevel: minimumLevel);
|
||||
|
||||
return logConfig;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Reads settings from /config/serilog.config
|
||||
/// That allows the main logging pipeline to be configured
|
||||
/// </summary>
|
||||
/// <param name="logConfig">A Serilog LoggerConfiguration</param>
|
||||
public static LoggerConfiguration ReadFromConfigFile(this LoggerConfiguration logConfig)
|
||||
{
|
||||
//Read from main serilog.config file
|
||||
logConfig.ReadFrom.AppSettings(filePath: AppDomain.CurrentDomain.BaseDirectory + @"\config\serilog.config");
|
||||
|
||||
return logConfig;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Reads settings from /config/serilog.user.config
|
||||
/// That allows a seperate logging pipeline to be configured that wil not affect the main Umbraco log
|
||||
/// </summary>
|
||||
/// <param name="logConfig">A Serilog LoggerConfiguration</param>
|
||||
public static LoggerConfiguration ReadFromUserConfigFile(this LoggerConfiguration logConfig)
|
||||
{
|
||||
//A nested logger - where any user configured sinks via config can not effect the main 'umbraco' logger above
|
||||
logConfig.WriteTo.Logger(cfg =>
|
||||
cfg.ReadFrom.AppSettings(filePath: AppDomain.CurrentDomain.BaseDirectory + @"\config\serilog.user.config"));
|
||||
|
||||
return logConfig;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,277 +0,0 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Reflection;
|
||||
using System.Threading;
|
||||
using Serilog;
|
||||
using Serilog.Events;
|
||||
using Umbraco.Core.Configuration;
|
||||
using Umbraco.Core.Diagnostics;
|
||||
|
||||
namespace Umbraco.Core.Logging.Serilog
|
||||
{
|
||||
///<summary>
|
||||
/// Implements <see cref="ILogger"/> on top of Serilog.
|
||||
///</summary>
|
||||
public class SerilogLogger : ILogger
|
||||
{
|
||||
/// <summary>
|
||||
/// Initialize a new instance of the <see cref="SerilogLogger"/> class with a configuration file.
|
||||
/// </summary>
|
||||
/// <param name="logConfigFile"></param>
|
||||
public SerilogLogger(FileInfo logConfigFile)
|
||||
{
|
||||
Log.Logger = new LoggerConfiguration()
|
||||
.ReadFrom.AppSettings(filePath: AppDomain.CurrentDomain.BaseDirectory + logConfigFile)
|
||||
.CreateLogger();
|
||||
}
|
||||
|
||||
public SerilogLogger(LoggerConfiguration logConfig)
|
||||
{
|
||||
//Configure Serilog static global logger with config passed in
|
||||
Log.Logger = logConfig.CreateLogger();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a logger with some pre-defined configuration and remainder from config file
|
||||
/// </summary>
|
||||
/// <remarks>Used by UmbracoApplicationBase to get its logger.</remarks>
|
||||
public static SerilogLogger CreateWithDefaultConfiguration()
|
||||
{
|
||||
var loggerConfig = new LoggerConfiguration();
|
||||
loggerConfig
|
||||
.MinimalConfiguration()
|
||||
.OutputDefaultTextFile(LogEventLevel.Debug)
|
||||
.OutputDefaultJsonFile()
|
||||
.ReadFromConfigFile()
|
||||
.ReadFromUserConfigFile();
|
||||
|
||||
return new SerilogLogger(loggerConfig);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets a contextualized logger.
|
||||
/// </summary>
|
||||
private global::Serilog.ILogger LoggerFor(Type reporting)
|
||||
=> Log.Logger.ForContext(reporting);
|
||||
|
||||
/// <summary>
|
||||
/// Maps Umbraco's log level to Serilog's.
|
||||
/// </summary>
|
||||
private LogEventLevel MapLevel(LogLevel level)
|
||||
{
|
||||
switch (level)
|
||||
{
|
||||
case LogLevel.Debug:
|
||||
return LogEventLevel.Debug;
|
||||
case LogLevel.Error:
|
||||
return LogEventLevel.Error;
|
||||
case LogLevel.Fatal:
|
||||
return LogEventLevel.Fatal;
|
||||
case LogLevel.Information:
|
||||
return LogEventLevel.Information;
|
||||
case LogLevel.Verbose:
|
||||
return LogEventLevel.Verbose;
|
||||
case LogLevel.Warning:
|
||||
return LogEventLevel.Warning;
|
||||
}
|
||||
|
||||
throw new NotSupportedException($"LogLevel \"{level}\" is not supported.");
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public bool IsEnabled(Type reporting, LogLevel level)
|
||||
=> LoggerFor(reporting).IsEnabled(MapLevel(level));
|
||||
|
||||
/// <inheritdoc/>
|
||||
public void Fatal(Type reporting, Exception exception, string message)
|
||||
{
|
||||
var logger = LoggerFor(reporting);
|
||||
DumpThreadAborts(logger, LogEventLevel.Fatal, exception, ref message);
|
||||
logger.Fatal(exception, message);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public void Fatal(Type reporting, Exception exception)
|
||||
{
|
||||
var logger = LoggerFor(reporting);
|
||||
var message = "Exception.";
|
||||
DumpThreadAborts(logger, LogEventLevel.Fatal, exception, ref message);
|
||||
logger.Fatal(exception, message);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public void Fatal(Type reporting, string message)
|
||||
{
|
||||
LoggerFor(reporting).Fatal(message);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public void Fatal(Type reporting, string messageTemplate, params object[] propertyValues)
|
||||
{
|
||||
LoggerFor(reporting).Fatal(messageTemplate, propertyValues);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public void Fatal(Type reporting, Exception exception, string messageTemplate, params object[] propertyValues)
|
||||
{
|
||||
var logger = LoggerFor(reporting);
|
||||
DumpThreadAborts(logger, LogEventLevel.Fatal, exception, ref messageTemplate);
|
||||
logger.Fatal(exception, messageTemplate, propertyValues);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public void Error(Type reporting, Exception exception, string message)
|
||||
{
|
||||
var logger = LoggerFor(reporting);
|
||||
DumpThreadAborts(logger, LogEventLevel.Error, exception, ref message);
|
||||
logger.Error(exception, message);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public void Error(Type reporting, Exception exception)
|
||||
{
|
||||
var logger = LoggerFor(reporting);
|
||||
var message = "Exception";
|
||||
DumpThreadAborts(logger, LogEventLevel.Error, exception, ref message);
|
||||
logger.Error(exception, message);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public void Error(Type reporting, string message)
|
||||
{
|
||||
LoggerFor(reporting).Error(message);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public void Error(Type reporting, string messageTemplate, params object[] propertyValues)
|
||||
{
|
||||
LoggerFor(reporting).Error(messageTemplate, propertyValues);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public void Error(Type reporting, Exception exception, string messageTemplate, params object[] propertyValues)
|
||||
{
|
||||
var logger = LoggerFor(reporting);
|
||||
DumpThreadAborts(logger, LogEventLevel.Error, exception, ref messageTemplate);
|
||||
logger.Error(exception, messageTemplate, propertyValues);
|
||||
}
|
||||
|
||||
private static void DumpThreadAborts(global::Serilog.ILogger logger, LogEventLevel level, Exception exception, ref string messageTemplate)
|
||||
{
|
||||
var dump = false;
|
||||
|
||||
if (IsTimeoutThreadAbortException(exception))
|
||||
{
|
||||
messageTemplate += "\r\nThe thread has been aborted, because the request has timed out.";
|
||||
|
||||
// dump if configured, or if stacktrace contains Monitor.ReliableEnter
|
||||
dump = UmbracoConfig.For.CoreDebug().DumpOnTimeoutThreadAbort || IsMonitorEnterThreadAbortException(exception);
|
||||
|
||||
// dump if it is ok to dump (might have a cap on number of dump...)
|
||||
dump &= MiniDump.OkToDump();
|
||||
}
|
||||
|
||||
if (dump)
|
||||
{
|
||||
try
|
||||
{
|
||||
var dumped = MiniDump.Dump(withException: true);
|
||||
messageTemplate += dumped
|
||||
? "\r\nA minidump was created in App_Data/MiniDump"
|
||||
: "\r\nFailed to create a minidump";
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
messageTemplate += "\r\nFailed to create a minidump";
|
||||
|
||||
//Log a new entry (as opposed to appending to same log entry)
|
||||
logger.Write(level, ex, "Failed to create a minidump ({ExType}: {ExMessage})",
|
||||
new object[]{ ex.GetType().FullName, ex.Message });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static bool IsMonitorEnterThreadAbortException(Exception exception)
|
||||
{
|
||||
if (!(exception is ThreadAbortException abort)) return false;
|
||||
|
||||
var stacktrace = abort.StackTrace;
|
||||
return stacktrace.Contains("System.Threading.Monitor.ReliableEnter");
|
||||
}
|
||||
|
||||
private static bool IsTimeoutThreadAbortException(Exception exception)
|
||||
{
|
||||
if (!(exception is ThreadAbortException abort)) return false;
|
||||
|
||||
if (abort.ExceptionState == null) return false;
|
||||
|
||||
var stateType = abort.ExceptionState.GetType();
|
||||
if (stateType.FullName != "System.Web.HttpApplication+CancelModuleException") return false;
|
||||
|
||||
var timeoutField = stateType.GetField("_timeout", BindingFlags.Instance | BindingFlags.NonPublic);
|
||||
if (timeoutField == null) return false;
|
||||
|
||||
return (bool) timeoutField.GetValue(abort.ExceptionState);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public void Warn(Type reporting, string message)
|
||||
{
|
||||
LoggerFor(reporting).Warning(message);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public void Warn(Type reporting, string message, params object[] propertyValues)
|
||||
{
|
||||
LoggerFor(reporting).Warning(message, propertyValues);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public void Warn(Type reporting, Exception exception, string message)
|
||||
{
|
||||
LoggerFor(reporting).Warning(exception, message);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public void Warn(Type reporting, Exception exception, string messageTemplate, params object[] propertyValues)
|
||||
{
|
||||
LoggerFor(reporting).Warning(exception, messageTemplate, propertyValues);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public void Info(Type reporting, string message)
|
||||
{
|
||||
LoggerFor(reporting).Information(message);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public void Info(Type reporting, string messageTemplate, params object[] propertyValues)
|
||||
{
|
||||
LoggerFor(reporting).Information(messageTemplate, propertyValues);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public void Debug(Type reporting, string message)
|
||||
{
|
||||
LoggerFor(reporting).Debug(message);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public void Debug(Type reporting, string messageTemplate, params object[] propertyValues)
|
||||
{
|
||||
LoggerFor(reporting).Debug(messageTemplate, propertyValues);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public void Verbose(Type reporting, string message)
|
||||
{
|
||||
LoggerFor(reporting).Verbose(message);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public void Verbose(Type reporting, string messageTemplate, params object[] propertyValues)
|
||||
{
|
||||
LoggerFor(reporting).Verbose(messageTemplate, propertyValues);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -5,7 +5,7 @@ using System.Text.RegularExpressions;
|
||||
using HtmlAgilityPack;
|
||||
using Umbraco.Core.Xml;
|
||||
|
||||
namespace Umbraco.Web.Macros
|
||||
namespace Umbraco.Core.Macros
|
||||
{
|
||||
/// <summary>
|
||||
/// Parses the macro syntax in a string and renders out it's contents
|
||||
@@ -117,7 +117,7 @@ namespace Umbraco.Core
|
||||
|
||||
lock (_locko)
|
||||
{
|
||||
_logger.Debug<MainDom>("Signaled {Signaled} ({SignalSource})", _signaled ? "(again)" : string.Empty, source);
|
||||
_logger.Debug<MainDom>(() => "Signaled" + (_signaled ? " (again)" : "") + " (" + source + ").");
|
||||
if (_signaled) return;
|
||||
if (_isMainDom == false) return; // probably not needed
|
||||
_signaled = true;
|
||||
@@ -125,7 +125,7 @@ namespace Umbraco.Core
|
||||
|
||||
try
|
||||
{
|
||||
_logger.Info<MainDom>("Stopping ({SignalSource})", source);
|
||||
_logger.Info<MainDom>("Stopping.");
|
||||
foreach (var callback in _callbacks.OrderBy(x => x.Key).Select(x => x.Value))
|
||||
{
|
||||
try
|
||||
@@ -134,19 +134,19 @@ namespace Umbraco.Core
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
_logger.Error<MainDom>(e, "Error while running callback, remaining callbacks will not run.");
|
||||
_logger.Error<MainDom>("Error while running callback, remaining callbacks will not run.", e);
|
||||
throw;
|
||||
}
|
||||
|
||||
}
|
||||
_logger.Debug<MainDom>("Stopped ({SignalSource})", source);
|
||||
_logger.Debug<MainDom>("Stopped.");
|
||||
}
|
||||
finally
|
||||
{
|
||||
// in any case...
|
||||
_isMainDom = false;
|
||||
_asyncLocker.Dispose();
|
||||
_logger.Info<MainDom>("Released ({SignalSource})", source);
|
||||
_logger.Info<MainDom>("Released.");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||