Compare commits

...

14 Commits

Author SHA1 Message Date
Benedek Farkas
8f76bbd91d Fixing that upgrading Newtonsoft.Json to 13.x broke the SpecFlow test execution app 2024-12-07 20:14:58 +01:00
Benedek Farkas
cf01021e83 Fixing typo 2024-12-07 20:14:01 +01:00
Benedek Farkas
2d35e087c4 Adding step to run the Setup with SpecFlow 2024-12-07 20:11:47 +01:00
Benedek Farkas
c4c0af7a66 Using Title Casing in the Compile workflow's step names 2024-12-07 20:11:07 +01:00
Benedek Farkas
ebae790f15 #8276: Updating Npgsql to 4.0.17 and fixing setup with PostgreSQL (#8810)
* Updating Npgsql to version 4.0.17 (the latest minor version of the closest major version that isn't vulnerable)

https://github.com/OrchardCMS/Orchard/security/dependabot/54

* Fixing that Projection Migrations created indexes with the same name in different tables, which is not supported by PostgreSQL
2024-12-06 14:14:57 +01:00
Benedek Farkas
79f66cebf6 #8752: Publish/unpublish Menu Items in the Menu editor (#8807)
* Cleaning up Core/Navigation/Controllers/AdminController

* Extending Core/Navigation/Controllers/AdminController to be able to publish/unpublish menuitems

* Redirecting to menu when saving a menu item and using the menu item text in the notification

* Fixing that saving a menu item shouldn't publish it if it's unpublished

* Using the menu item text in the notification when publishing and unpublishing too
2024-12-06 10:09:52 +01:00
Benedek Farkas
0d93cb1d8d #8816: Compilation workflow should test the setup and code generation (#8817)
* Updating Compile workflow with setup and code generation steps

* Updating NHibernate reference and OrchardBasicCorrectness.ruleset path in ModuleTestsCsProj code generation template

* Ignoring CS2008 warning when recompiling with generated modules, because the theme and test projects don't have .cs files

* Generating a test project should also include packages.config

* Fixing the relative path of Orchard.Core and Orchard.Framework in the generated test project

* A bit of code styling in the Compile workflow

* Updating Readme

* Revert "A bit of code styling in the Compile workflow"

This reverts commit 7b01ebbad0.
2024-12-06 09:59:15 +01:00
Benedek Farkas
8425b4ad76 #8811: Update vulnerable NuGet packages and consolidate them (#8812)
* Updating System.IdentityModel.Tokens.Jwt and its dependencies in Orchard.Azure.MediaServices

* Using System.IO.Compression instead of DotNetZip

* Upgrading Newtonsoft.Json from 12.0.3 (vulnerable) to 13.0.3

* Updating ModuleRootWebConfig.txt codegen template according to the new Newtonsoft.Json version
2024-12-06 09:49:45 +01:00
Andrea Piovanelli
81570fab35 Internal page links validation for LinkField (#8805)
Some checks failed
Compile / Compile .NET solution (push) Has been cancelled
Compile / Compile client-side assets (push) Has been cancelled
* Added page internal references management in LinkField valid urls (e.g. field.Value = "#someId")

* Code refactoring to check LinkField value.
2024-10-29 09:14:13 +01:00
Benedek Farkas
0d9fccb624 Fixing WebDownloaderTests 2024-05-03 15:33:07 +02:00
Benedek Farkas
fdbb06ba8d #8640: Fixing consistency between different Enumeration Field flavors' data storage (#8789)
* Reworking EnumerationField's logic to store/retrieve its (selected) values

* Fixing exception when creating new item with CheckboxList flavor, adding more nullchecks and compactness

* Code styling in EnumerationFieldDriver

* Code styling in EnumerationField editor template

* Fixing that EnumerationFieldDriver and the EnumerationField editor template should read SelectedValues instead of Values directly

---------

Co-authored-by: Matteo Piovanelli <MatteoPiovanelli-Laser@users.noreply.github.com>
2024-04-19 11:11:47 +02:00
Benedek Farkas
15cad85d1e #6793: Adding a content-independent culture selector shape for the front-end (#8784)
* Adds a new CultureSelector shape for front-end

* fixed query string culture change

* Moving NameValueCollectionExtensions from Orchard.DynamicForms and Orchard.Localization to Orchard.Framework

* Code styling

* Simplifying UserCultureSelectorController and removing the addition of the culture to the query string

* EOF empty lines and code styling

* Fixing that the main Orchard.Localization should depend on Orchard.Autoroute

* Code styling in LocalizationService

* Updating LocalizationService to not have to use IEnumerable.Single

* Matching culture name matching in LocalizationService culture- and casing-invariant

---------

Co-authored-by: Sergio Navarro <jersio@hotmail.com>
Co-authored-by: psp589 <pablosanchez589@gmail.com>
2024-04-18 23:35:48 +02:00
Benedek Farkas
0b86413e60 6748: Stricter file and folder name validation (#6792)
* Media Library: More strict file and folder name validation, fixes #6748

* Resetting MediaLibraryService changes to 1.10.x

* Code styling in FileSystemStorageProvider

* Adding string file and folder name validation to FileSystemStorageProvider, so that MediaLibrary components don't need to do it separately

* Applying the same file and folder name validation to AzureFileSystem too

* Code styling and fixes in AzureFileSystem, MediaLibrary and IStorageProvider

* Simplifying invalid character detection

* Code styling

* Adding InvalidNameCharacterException to be able to handle invalid characters precisely at various user-facing components

* Updating MediaLibrary not to log an error when a file can't be uploaded due to invalid characters

---------

Co-authored-by: Lombiq <github@lombiq.com>
2024-04-18 21:37:48 +02:00
Benedek Farkas
3a6810ec67 8225: Adding a checkbox to StringFilterForm to control whether an empty value should cause the filter to be skipped (#8781)
* Adding a checkbox to StringFilterForm to control whether an empty value should cause the filter to be skipped

* Removing StringOperator.ContainsAnyIfProvided as its now obsolete due to the IgnoreFilterIfValueIsEmpty checkbox setting

* Code styling in StringFilterForm

* Adding missing T-string

* Adding migration step to upgrade from using the ContainsAnyIfProvided operator in StringFilterForm
2024-04-17 11:52:51 +02:00
162 changed files with 1008 additions and 618 deletions

View File

@@ -16,29 +16,56 @@ jobs:
shell: pwsh
runs-on: windows-latest
steps:
- name: Clone repository
- name: Clone Repository
uses: actions/checkout@v4.1.1
- name: Restore NuGet packages
- name: Restore NuGet Packages
run: nuget restore src/Orchard.sln
- name: Add msbuild to PATH
- name: Add MSBuild to PATH
uses: microsoft/setup-msbuild@v2
- name: Compile
run: msbuild Orchard.proj /m /v:minimal /t:Compile /p:MvcBuildViews=true /p:TreatWarningsAsErrors=true -WarnAsError
run: msbuild Orchard.proj /m /v:minimal /t:Compile /p:TreatWarningsAsErrors=true -WarnAsError /p:MvcBuildViews=true
- name: Test
run: msbuild Orchard.proj /m /v:minimal /t:Test
- name: Test Setup with SpecFlow
run: |
$nunitConsole = (Get-ChildItem -Path 'src/packages' -Recurse -Filter 'nunit-console.exe' | Select-Object -Last 1).FullName
& $nunitConsole 'build/Compile/Orchard.Specs.dll' /xml='build/Orchard.Specs.xml' /run=Orchard.Specs.SetupFeature.RootAndSetupFolderShowsSetupScreenAndFormValuesAreValidated
- name: Run Orchard Setup with Orchard.exe
run: |
$commandFile = 'src/Orchard.Web/bin/setup-commands.txt'
New-Item -Path $commandFile -ItemType File -Force
Set-Content -Path $commandFile -Value 'setup /SiteName:Orchard /AdminUsername:admin /AdminPassword:Password1! /DatabaseProvider:SqlCe /Recipe:Default'
& 'src/Orchard.Web/bin/Orchard.exe' @$commandFile
- name: Run Code Generation
run: |
$commandFile = 'src/Orchard.Web/bin/codegen-commands.txt'
New-Item -Path $commandFile -ItemType File -Force
Set-Content -Path $commandFile -Value @'
feature enable Orchard.CodeGeneration
codegen module Orchard.CodeGeneration.TestModule
codegen theme Orchard.CodeGeneration.TestTheme /CreateProject:true
codegen moduletests Orchard.CodeGeneration.TestModule
'@
& 'src/Orchard.Web/bin/Orchard.exe' @$commandFile
- name: Compile Again with Generated Projects
run: msbuild Orchard.proj /m /v:minimal /t:Compile /p:TreatWarningsAsErrors=true -WarnAsError /NoWarn:CS2008
compile-node:
name: Compile client-side assets
name: Compile Client-side Assets
defaults:
run:
shell: pwsh
runs-on: windows-latest
steps:
- name: Clone repository
- name: Clone Repository
uses: actions/checkout@v4.1.1
- name: Setup NodeJS
@@ -46,7 +73,7 @@ jobs:
with:
node-version: '7'
- name: Setup NPM packages
- name: Setup NPM Packages
working-directory: ./src
run: |
npm install --loglevel warn
@@ -55,7 +82,7 @@ jobs:
$gulpVersion = (Get-Content Package.json -Raw | ConvertFrom-Json).devDependencies.gulp
Start-Process npm -NoNewWindow -Wait -ArgumentList "install gulp@$gulpVersion -g --loglevel warn"
- name: Rebuild client-side assets
- name: Rebuild Client-side Assets
working-directory: ./src
run: |
gulp rebuild

View File

@@ -52,12 +52,6 @@ Website: http://dlr.codeplex.com
Copyright: Copyright (c) Microsoft Corporation
License: Apache Software Foundation License 2.0
DotNetZip
-----
Website: http://dotnetzip.codeplex.com/
Copyright:
License: MS-PL
Eric Meyer's Reset CSS
-----
Website: http://meyerweb.com/eric/tools/css/reset/

View File

@@ -1,16 +1,14 @@
# Orchard
Orchard is a free, open source, community-focused Content Management System built on the ASP.NET MVC platform.
Orchard is a free, open source, community-focused Content Management System built on the ASP.NET MVC platform. You are looking at Orchard 1, the older, .NET Framework-based version that has been in development since 2009.
[![Join the chat at https://gitter.im/OrchardCMS/Orchard](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/OrchardCMS/Orchard?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
If you're starting a new project (or maintaining a project built on Orchard 1), you should check out [Orchard Core](https://github.com/OrchardCMS/OrchardCore), the new generation of Orchard built on ASP.NET Core. You can also try it for free on [DotNest.com](https://dotnest.com)!
You can try it for free on [DotNest.com](https://dotnest.com) or on Microsoft Azure by clicking on this button.
[![Deploy to Azure](https://azuredeploy.net/deploybutton.png)](https://portal.azure.com/#create/OutercurveFoundation.OrchardCMS)
Join the community discussion on [Discord](https://orchardcore.net/discord), where we also have a [channel dedicated to Orchard 1](https://discord.com/channels/551136772243980291/551137194689953848).
## About The Orchard Project
#### Please visit our website at https://orchardproject.net for the most current information about this project.
#### Please visit our website at https://orchardcore.net for the most current information about this project.
Orchard is a free, open source, community-focused **Content Management System** built on the ASP.NET MVC platform.
@@ -24,12 +22,12 @@ Our mission is to empower our users and foster a dedicated and diverse community
Orchard is currently in version **[1.10.3](https://github.com/OrchardCMS/Orchard/releases/tag/1.10.3)**: It contains bugfixes and the more impactful changes and new features added in the latest major version (*1.10*).
We invite participation by the developer community in shaping the projects direction, so that we can publicly validate our designs and development approach.
We invite participation by the developer community in shaping the project's direction, so that we can publicly validate our designs and development approach.
All our releases are available on our [Releases](https://github.com/OrchardCMS/Orchard/releases) page, and we encourage interested developers to check out the source code on the Orchard GitHub site and get involved with the project.
* [Download the latest release](https://github.com/OrchardCMS/Orchard/releases)
* [Feature roadmap](https://docs.orchardproject.net/en/latest/Documentation/Feature-roadmap/)
* [Docs and designs/specs](https://docs.orchardproject.net)
* [Feature roadmap](https://docs.orchardcore.net/projects/O1/en/latest/Documentation/Feature-roadmap/)
* [Docs and designs/specs](https://docs.orchardcore.net/projects/O1/en/latest/)
## How To Get Involved
@@ -42,11 +40,7 @@ There are many ways you can contribute to Orchard:
* [Find and file a bug](https://github.com/OrchardCMS/Orchard/issues)
* [Propose a feature idea](https://github.com/OrchardCMS/Orchard/issues/new)
* [Ask and answer questions on Stack Overflow](https://stackoverflow.com/questions/tagged/orchardcms)
* [Participate in our gitter.im chatroom](https://gitter.im/OrchardCMS/Orchard)
* [Submit a pull request](https://docs.orchardproject.net/en/latest/Documentation/Contributing-patches/)
* [Join us on Discord](https://orchardcore.net/discord)
* [Submit a pull request](https://docs.orchardcore.net/projects/O1/en/latest/Documentation/Contributing-patches/)
* [Translate Orchard](https://crowdin.com/project/orchard-cms)
* [Contribute modules and themes to our gallery](https://gallery.orchardproject.net/)
## The Future Of Orchard CMS: Orchard Core
As the underlying frameworks (.NET, ASP.NET and ASP.NET MVC) are constantly evolving, Orchard of course keeps track of the changes and improvements of these: Orchard Core is the next generation of Orchard releases that is based on [ASP.NET Core](https://www.asp.net/core). Just like the current Orchard project, it's fully [open-source and is publicly available on GitHub](https://github.com/OrchardCMS/OrchardCore). Orchard Core (as a framework) is being built from scratch: it's still in development and does not share any of its code base (at least directly) with the current versions (1.x) of Orchard.
* [Contribute modules and themes to our gallery](https://gallery.orchardproject.net)

View File

@@ -16,7 +16,7 @@
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="Newtonsoft.Json" publicKeyToken="30ad4fe6b2a6aeed" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-12.0.0.0" newVersion="12.0.0.0" />
<bindingRedirect oldVersion="0.0.0.0-13.0.0.0" newVersion="13.0.0.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Web.Http" publicKeyToken="31bf3856ad364e35" culture="neutral" />

View File

@@ -24,7 +24,7 @@
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="Newtonsoft.Json" publicKeyToken="30ad4fe6b2a6aeed" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-12.0.0.0" newVersion="12.0.0.0" />
<bindingRedirect oldVersion="0.0.0.0-13.0.0.0" newVersion="13.0.0.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Web.Http" publicKeyToken="31bf3856ad364e35" culture="neutral" />

View File

@@ -151,7 +151,7 @@
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="Newtonsoft.Json" publicKeyToken="30ad4fe6b2a6aeed" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-12.0.0.0" newVersion="12.0.0.0" />
<bindingRedirect oldVersion="0.0.0.0-13.0.0.0" newVersion="13.0.0.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="NHibernate" publicKeyToken="aa95f207798dfdb4" culture="neutral" />

View File

@@ -24,7 +24,7 @@
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="Newtonsoft.Json" publicKeyToken="30ad4fe6b2a6aeed" />
<bindingRedirect oldVersion="0.0.0.0-12.0.0.0" newVersion="12.0.0.0" />
<bindingRedirect oldVersion="0.0.0.0-13.0.0.0" newVersion="13.0.0.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="Autofac" publicKeyToken="17863af14b0044da" />

View File

@@ -1,8 +1,8 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.IO.Compression;
using System.Linq;
using Ionic.Zip;
using NUnit.Framework;
using Orchard.Environment.Configuration;
using Orchard.FileSystems.Media;
@@ -53,10 +53,10 @@ namespace Orchard.Tests.Modules.Media.Services {
[Test]
public void GetMediaFoldersTest() {
StorageProvider.ListFoldersPredicate = path => {
return string.IsNullOrEmpty(path) ? new[] {new StubStorageFolder(FolderName1)}
: string.Equals(path, FolderName1) ? new[] {new StubStorageFolder(FolderName2), new StubStorageFolder(FolderName3)}
return string.IsNullOrEmpty(path) ? new[] { new StubStorageFolder(FolderName1) }
: string.Equals(path, FolderName1) ? new[] { new StubStorageFolder(FolderName2), new StubStorageFolder(FolderName3) }
: new StubStorageFolder[] { };
};
};
IEnumerable<MediaFolder> mediaFolders = MediaService.GetMediaFolders(null);
Assert.That(mediaFolders.Count(), Is.EqualTo(1), "Root path only has 1 sub directory");
@@ -94,7 +94,7 @@ namespace Orchard.Tests.Modules.Media.Services {
Assert.That(StorageProvider.SavedStreams.Contains(StorageProvider.Combine(FolderName1, FinalDottedWebconfigFileName)), Is.False, "no extension files are never allowed");
Assert.That(StorageProvider.SavedStreams.Contains(StorageProvider.Combine(FolderName1, PaddedWebconfigFileName)), Is.False, "no extension files are never allowed");
Assert.That(StorageProvider.SavedStreams.Contains(StorageProvider.Combine(FolderName1, FinalDottedTextFileName)), Is.False, "no extension files are never allowed");
Assert.That(StorageProvider.SavedStreams.Count, Is.EqualTo(3));
}
@@ -160,29 +160,30 @@ namespace Orchard.Tests.Modules.Media.Services {
}
private MemoryStream CreateZipMemoryStream() {
var entries = new List<string> {
TextFileName, WebconfigFileName, DllFileName, ZipFileName, NoExtensionFileName, PaddedWebconfigFileName,
FinalDottedWebconfigFileName, PaddedTextFileName, FinalDottedTextFileName
};
// Setup memory stream with zip archive for more complex scenarios
MemoryStream memoryStream = new MemoryStream();
using (ZipFile zipOut = new ZipFile()) {
zipOut.AddEntry(TextFileName, new byte[] { 0x01 });
zipOut.AddEntry(WebconfigFileName, new byte[] { 0x02 });
zipOut.AddEntry(DllFileName, new byte[] { 0x03 });
zipOut.AddEntry(ZipFileName, new byte[] { 0x04 });
zipOut.AddEntry(NoExtensionFileName, new byte[] { 0x05 });
zipOut.AddEntry(PaddedWebconfigFileName, new byte[] { 0x06 });
zipOut.AddEntry(FinalDottedWebconfigFileName, new byte[] { 0x07 });
zipOut.AddEntry(PaddedTextFileName, new byte[] { 0x08 });
zipOut.AddEntry(FinalDottedTextFileName, new byte[] { 0x09 });
zipOut.Save(memoryStream);
using (var archive = new ZipArchive(memoryStream, ZipArchiveMode.Create, leaveOpen: true)) {
var content = new byte[] { 0x01 };
foreach (var entry in entries) {
var zipEntry = archive.CreateEntry(entry);
using (var zipStream = zipEntry.Open()) {
zipStream.Write(content, 0, 1);
}
++content[0];
}
}
return new MemoryStream(memoryStream.ToArray());
}
private class MediaServiceAccessor : MediaService {
public MediaServiceAccessor(IStorageProvider storageProvider, IOrchardServices orchardServices)
: base (storageProvider, orchardServices) {}
: base(storageProvider, orchardServices) { }
public void UnzipMediaFileArchiveAccessor(string targetFolder, Stream zipStream) {
UnzipMediaFileArchive(targetFolder, zipStream);

View File

@@ -64,9 +64,6 @@
<Reference Include="Castle.Core, Version=3.3.0.0, Culture=neutral, PublicKeyToken=407dd0808d44fbdc, processorArchitecture=MSIL">
<HintPath>..\packages\Castle.Core.3.3.1\lib\net45\Castle.Core.dll</HintPath>
</Reference>
<Reference Include="DotNetZip, Version=1.12.0.0, Culture=neutral, PublicKeyToken=6583c7c814667745, processorArchitecture=MSIL">
<HintPath>..\packages\DotNetZip.1.12.0\lib\net20\DotNetZip.dll</HintPath>
</Reference>
<Reference Include="FluentNHibernate, Version=2.0.3.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\packages\FluentNHibernate.2.0.3.0\lib\net40\FluentNHibernate.dll</HintPath>
</Reference>
@@ -107,8 +104,8 @@
<Reference Include="Moq, Version=4.2.1510.2205, Culture=neutral, PublicKeyToken=69f491c39445e920, processorArchitecture=MSIL">
<HintPath>..\packages\Moq.4.2.1510.2205\lib\net40\Moq.dll</HintPath>
</Reference>
<Reference Include="Newtonsoft.Json, Version=12.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
<HintPath>..\packages\Newtonsoft.Json.12.0.3\lib\net45\Newtonsoft.Json.dll</HintPath>
<Reference Include="Newtonsoft.Json, Version=13.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
<HintPath>..\packages\Newtonsoft.Json.13.0.3\lib\net45\Newtonsoft.Json.dll</HintPath>
</Reference>
<Reference Include="NHibernate, Version=4.1.0.4000, Culture=neutral, PublicKeyToken=aa95f207798dfdb4, processorArchitecture=MSIL">
<HintPath>..\packages\NHibernate.4.1.2.4000\lib\net40\NHibernate.dll</HintPath>
@@ -134,6 +131,7 @@
<HintPath>..\..\lib\sqlce\System.Data.SqlServerCe.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="System.IO.Compression" />
<Reference Include="System.Web" />
<Reference Include="System.Web.Abstractions">
<RequiredTargetFramework>3.5</RequiredTargetFramework>

View File

@@ -1,4 +1,5 @@
using System.Net;
using System;
using System.Net;
using NUnit.Framework;
using Orchard.Warmup.Services;
@@ -20,7 +21,7 @@ namespace Orchard.Tests.Modules.Warmup {
[Test]
public void StatusCodeShouldBe404ForUnexistingResources() {
var download = _webDownloader.Download("http://orchardproject.net/yepyep");
var download = _webDownloader.Download("https://orchardcore.net/" + Guid.NewGuid());
Assert.That(download, Is.Not.Null);
Assert.That(download.StatusCode, Is.EqualTo(HttpStatusCode.NotFound));
Assert.That(download.Content, Is.Null);
@@ -28,7 +29,7 @@ namespace Orchard.Tests.Modules.Warmup {
[Test]
public void StatusCodeShouldBe200ForValidRequests() {
var download = _webDownloader.Download("http://orchardproject.net/");
var download = _webDownloader.Download("https://orchardcore.net/");
Assert.That(download, Is.Not.Null);
Assert.That(download.StatusCode, Is.EqualTo(HttpStatusCode.OK));
Assert.That(download.Content, Is.Not.Empty);

View File

@@ -2,7 +2,6 @@
<packages>
<package id="Autofac" version="3.5.2" targetFramework="net48" />
<package id="Castle.Core" version="3.3.1" targetFramework="net48" />
<package id="DotNetZip" version="1.12.0" targetFramework="net48" />
<package id="FluentNHibernate" version="2.0.3.0" targetFramework="net48" />
<package id="Iesi.Collections" version="4.0.1.4000" targetFramework="net48" />
<package id="IronRuby" version="1.1.3" targetFramework="net48" />
@@ -12,7 +11,7 @@
<package id="Microsoft.AspNet.WebPages" version="3.2.7" targetFramework="net48" />
<package id="Microsoft.Web.Infrastructure" version="1.0.0.0" targetFramework="net48" />
<package id="Moq" version="4.2.1510.2205" targetFramework="net48" />
<package id="Newtonsoft.Json" version="12.0.3" targetFramework="net48" />
<package id="Newtonsoft.Json" version="13.0.3" targetFramework="net48" />
<package id="NHibernate" version="4.1.2.4000" targetFramework="net48" />
<package id="NUnit" version="2.5.10.11092" targetFramework="net48" />
<package id="Orchard.FluentPath" version="1.0.0.1" targetFramework="net48" />

View File

@@ -24,7 +24,7 @@
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="Newtonsoft.Json" publicKeyToken="30ad4fe6b2a6aeed" />
<bindingRedirect oldVersion="0.0.0.0-12.0.0.0" newVersion="12.0.0.0" />
<bindingRedirect oldVersion="0.0.0.0-13.0.0.0" newVersion="13.0.0.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="Autofac" publicKeyToken="17863af14b0044da" />

View File

@@ -104,8 +104,8 @@
<Reference Include="Moq, Version=4.2.1510.2205, Culture=neutral, PublicKeyToken=69f491c39445e920, processorArchitecture=MSIL">
<HintPath>..\packages\Moq.4.2.1510.2205\lib\net40\Moq.dll</HintPath>
</Reference>
<Reference Include="Newtonsoft.Json, Version=12.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
<HintPath>..\packages\Newtonsoft.Json.12.0.3\lib\net45\Newtonsoft.Json.dll</HintPath>
<Reference Include="Newtonsoft.Json, Version=13.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
<HintPath>..\packages\Newtonsoft.Json.13.0.3\lib\net45\Newtonsoft.Json.dll</HintPath>
</Reference>
<Reference Include="NHibernate, Version=4.1.0.4000, Culture=neutral, PublicKeyToken=aa95f207798dfdb4, processorArchitecture=MSIL">
<HintPath>..\packages\NHibernate.4.1.2.4000\lib\net40\NHibernate.dll</HintPath>

View File

@@ -14,7 +14,7 @@
<package id="Microsoft.AspNet.WebPages" version="3.2.7" targetFramework="net48" />
<package id="Microsoft.Web.Infrastructure" version="1.0.0.0" targetFramework="net48" />
<package id="Moq" version="4.2.1510.2205" targetFramework="net48" />
<package id="Newtonsoft.Json" version="12.0.3" targetFramework="net48" />
<package id="Newtonsoft.Json" version="13.0.3" targetFramework="net48" />
<package id="NHibernate" version="4.1.2.4000" targetFramework="net48" />
<package id="NUnit" version="2.5.10.11092" targetFramework="net48" />
<package id="NUnitTestAdapter" version="2.3.0" targetFramework="net48" />

View File

@@ -16,7 +16,7 @@
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="Newtonsoft.Json" publicKeyToken="30ad4fe6b2a6aeed" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-12.0.0.0" newVersion="12.0.0.0" />
<bindingRedirect oldVersion="0.0.0.0-13.0.0.0" newVersion="13.0.0.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Web.Http" publicKeyToken="31bf3856ad364e35" culture="neutral" />

View File

@@ -1,74 +1,75 @@
using System.Collections.Generic;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web.Mvc;
using System.Web.Routing;
using Orchard.ContentManagement;
using Orchard.ContentManagement.Aspects;
using Orchard.ContentManagement.Handlers;
using Orchard.Core.Contents.Settings;
using Orchard.Core.Navigation.Models;
using Orchard.Core.Navigation.Services;
using Orchard.Core.Navigation.ViewModels;
using Orchard.Localization;
using Orchard.Mvc.Extensions;
using Orchard.UI;
using Orchard.UI.Notify;
using Orchard.UI.Navigation;
using Orchard.Utility;
using System;
using Orchard.ContentManagement.Handlers;
using Orchard.Logging;
using Orchard.Exceptions;
using Orchard.ContentManagement.Aspects;
using Orchard.Utility.Extensions;
using Orchard.Mvc.Html;
using Orchard.Core.Contents.Settings;
using Orchard.Data;
using System.Web.Routing;
using Orchard.Exceptions;
using Orchard.Localization;
using Orchard.Logging;
using Orchard.Mvc.Extensions;
using Orchard.Mvc.Html;
using Orchard.Security;
using Orchard.UI;
using Orchard.UI.Navigation;
using Orchard.UI.Notify;
using Orchard.Utility;
using Orchard.Utility.Extensions;
namespace Orchard.Core.Navigation.Controllers {
[ValidateInput(false)]
public class AdminController : Controller, IUpdateModel {
private readonly IContentManager _contentManager;
private readonly ITransactionManager _transactionManager;
private readonly IAuthorizer _authorizer;
private readonly INotifier _notifier;
private readonly IMenuService _menuService;
private readonly INavigationManager _navigationManager;
private readonly IEnumerable<IContentHandler> _handlers;
private readonly IMenuManager _menuManager;
private readonly IContentManager _contentManager;
private readonly ITransactionManager _transactionManager;
public AdminController(
IOrchardServices orchardServices,
IContentManager contentManager,
ITransactionManager transactionManager,
IMenuService menuService,
IMenuManager menuManager,
INavigationManager navigationManager,
IEnumerable<IContentHandler> handlers) {
_contentManager = contentManager;
_transactionManager = transactionManager;
_contentManager = orchardServices.ContentManager;
_transactionManager = orchardServices.TransactionManager;
_authorizer = orchardServices.Authorizer;
_notifier = orchardServices.Notifier;
_menuService = menuService;
_menuManager = menuManager;
_navigationManager = navigationManager;
_handlers = handlers;
Services = orchardServices;
T = NullLocalizer.Instance;
Logger = NullLogger.Instance;
}
public Localizer T { get; set; }
public ILogger Logger { get; set; }
public IOrchardServices Services { get; set; }
public ActionResult Index(NavigationManagementViewModel model, int? menuId) {
var menus = Services.ContentManager.Query("Menu").List().ToList()
var menus = _contentManager.Query("Menu").List().ToList()
.OrderBy(x => x.ContentManager.GetItemMetadata(x).DisplayText);
if (!menus.Any()) {
if (!Services.Authorizer.Authorize(Permissions.ManageMenus, T("Not allowed to manage menus"))) {
if (!_authorizer.Authorize(Permissions.ManageMenus, T("Not allowed to manage menus"))) {
return new HttpUnauthorizedResult();
}
return RedirectToAction("Create", "Admin", new { area = "Contents", id = "Menu", returnUrl = Request.RawUrl });
}
var allowedMenus = menus.Where(menu => Services.Authorizer.Authorize(Permissions.ManageMenus, menu)).ToList();
var allowedMenus = menus.Where(menu => _authorizer.Authorize(Permissions.ManageMenus, menu)).ToList();
if (!allowedMenus.Any()) {
return new HttpUnauthorizedResult();
@@ -87,7 +88,11 @@ namespace Orchard.Core.Navigation.Controllers {
}
if (model.MenuItemEntries == null || !model.MenuItemEntries.Any()) {
model.MenuItemEntries = _menuService.GetMenuParts(currentMenu.Id).Select(CreateMenuItemEntries).OrderBy(menuPartEntry => menuPartEntry.Position, new FlatPositionComparer()).ToList();
model.MenuItemEntries = _menuService
.GetMenuParts(currentMenu.Id)
.Select(CreateMenuItemEntries)
.OrderBy(menuPartEntry => menuPartEntry.Position, new FlatPositionComparer())
.ToList();
}
model.MenuItemDescriptors = _menuManager.GetMenuItemTypes();
@@ -100,7 +105,10 @@ namespace Orchard.Core.Navigation.Controllers {
[HttpPost, ActionName("Index")]
public ActionResult IndexPOST(IList<MenuItemEntry> menuItemEntries, int? menuId) {
if (!Services.Authorizer.Authorize(Permissions.ManageMenus, (menuId.HasValue) ? _menuService.GetMenu(menuId.Value) : null, T("Couldn't manage the main menu")))
if (!_authorizer.Authorize(
Permissions.ManageMenus,
menuId.HasValue ? _menuService.GetMenu(menuId.Value) : null,
T("Couldn't manage the menu")))
return new HttpUnauthorizedResult();
// See https://github.com/OrchardCMS/Orchard/issues/948
@@ -123,25 +131,15 @@ namespace Orchard.Core.Navigation.Controllers {
return RedirectToAction("Index", new { menuId });
}
private MenuItemEntry CreateMenuItemEntries(MenuPart menuPart) {
return new MenuItemEntry {
MenuItemId = menuPart.Id,
IsMenuItem = menuPart.Is<MenuItemPart>(),
Text = menuPart.MenuText,
Position = menuPart.MenuPosition,
Url = menuPart.Is<MenuItemPart>()
? menuPart.As<MenuItemPart>().Url
: _navigationManager.GetUrl(null, Services.ContentManager.GetItemMetadata(menuPart).DisplayRouteValues),
ContentItem = menuPart.ContentItem,
};
}
[HttpPost]
public ActionResult Delete(int id) {
MenuPart menuPart = _menuService.Get(id);
int? menuId = null;
if (!Services.Authorizer.Authorize(Permissions.ManageMenus, (menuPart != null) ? _menuService.GetMenu(menuPart.Menu.Id) : null, T("Couldn't manage the main menu")))
if (!_authorizer.Authorize(
Permissions.ManageMenus,
menuPart == null ? null : _menuService.GetMenu(menuPart.Menu.Id),
T("Couldn't manage the menu")))
return new HttpUnauthorizedResult();
if (menuPart != null) {
@@ -155,7 +153,8 @@ namespace Orchard.Core.Navigation.Controllers {
foreach (var menuItem in menuItems.Concat(new[] { menuPart })) {
// if the menu item is a concrete content item, don't delete it, just unreference the menu
if (!menuPart.ContentItem.TypeDefinition.Settings.ContainsKey("Stereotype") || menuPart.ContentItem.TypeDefinition.Settings["Stereotype"] != "MenuItem") {
if (!menuPart.ContentItem.TypeDefinition.Settings.ContainsKey("Stereotype")
|| menuPart.ContentItem.TypeDefinition.Settings["Stereotype"] != "MenuItem") {
menuPart.Menu = null;
}
else {
@@ -168,26 +167,18 @@ namespace Orchard.Core.Navigation.Controllers {
return RedirectToAction("Index", new { menuId });
}
bool IUpdateModel.TryUpdateModel<TModel>(TModel model, string prefix, string[] includeProperties, string[] excludeProperties) {
return TryUpdateModel(model, prefix, includeProperties, excludeProperties);
}
void IUpdateModel.AddModelError(string key, LocalizedString errorMessage) {
ModelState.AddModelError(key, errorMessage.ToString());
}
public ActionResult CreateMenuItem(string id, int menuId, string returnUrl) {
if (!Services.Authorizer.Authorize(Permissions.ManageMenus, _menuService.GetMenu(menuId), T("Couldn't manage the main menu")))
if (!_authorizer.Authorize(Permissions.ManageMenus, _menuService.GetMenu(menuId), T("Couldn't manage the menu")))
return new HttpUnauthorizedResult();
// create a new temporary menu item
var menuPart = Services.ContentManager.New<MenuPart>(id);
var menuPart = _contentManager.New<MenuPart>(id);
if (menuPart == null)
return HttpNotFound();
// load the menu
var menu = Services.ContentManager.Get(menuId);
var menu = _contentManager.Get(menuId);
if (menu == null)
return HttpNotFound();
@@ -196,7 +187,7 @@ namespace Orchard.Core.Navigation.Controllers {
// filter the content items for this specific menu
menuPart.MenuPosition = Position.GetNext(_navigationManager.BuildMenu(menu));
menuPart.Menu = menu;
var model = Services.ContentManager.BuildEditor(menuPart);
var model = _contentManager.BuildEditor(menuPart);
return View(model);
}
@@ -206,32 +197,32 @@ namespace Orchard.Core.Navigation.Controllers {
}
Logger.Error(T("Creating menu item failed: {0}", exception.Message).Text);
Services.Notifier.Error(T("Creating menu item failed: {0}", exception.Message));
_notifier.Error(T("Creating menu item failed: {0}", exception.Message));
return this.RedirectLocal(returnUrl, () => RedirectToAction("Index"));
}
}
[HttpPost, ActionName("CreateMenuItem")]
public ActionResult CreateMenuItemPost(string id, int menuId, string returnUrl) {
if (!Services.Authorizer.Authorize(Permissions.ManageMenus, _menuService.GetMenu(menuId), T("Couldn't manage the main menu")))
if (!_authorizer.Authorize(Permissions.ManageMenus, _menuService.GetMenu(menuId), T("Couldn't manage the menu")))
return new HttpUnauthorizedResult();
var menuPart = Services.ContentManager.New<MenuPart>(id);
var menuPart = _contentManager.New<MenuPart>(id);
if (menuPart == null)
return HttpNotFound();
// load the menu
var menu = Services.ContentManager.Get(menuId);
var menu = _contentManager.Get(menuId);
if (menu == null)
return HttpNotFound();
menuPart.Menu = menu;
var model = Services.ContentManager.UpdateEditor(menuPart, this);
var model = _contentManager.UpdateEditor(menuPart, this);
menuPart.MenuPosition = Position.GetNext(_navigationManager.BuildMenu(menu));
Services.ContentManager.Create(menuPart);
_contentManager.Create(menuPart);
if (!ModelState.IsValid) {
Services.TransactionManager.Cancel();
_transactionManager.Cancel();
return View(model);
}
Services.Notifier.Information(T("Your {0} has been added.", menuPart.TypeDefinition.DisplayName));
_notifier.Information(T("Your {0} has been added.", menuPart.TypeDefinition.DisplayName));
return this.RedirectLocal(returnUrl, () => RedirectToAction("Index"));
}
@@ -241,7 +232,7 @@ namespace Orchard.Core.Navigation.Controllers {
if (contentItem == null)
return HttpNotFound();
if (!Services.Authorizer.Authorize(Permissions.ManageMenus, contentItem.Content.MenuPart.Menu, T("Couldn't manage the main menu")))
if (!_authorizer.Authorize(Permissions.ManageMenus, contentItem.Content.MenuPart.Menu, T("Couldn't manage the menu")))
return new HttpUnauthorizedResult();
var model = _contentManager.BuildEditor(contentItem);
@@ -252,19 +243,81 @@ namespace Orchard.Core.Navigation.Controllers {
[Mvc.FormValueRequired("submit.Save")]
public ActionResult EditPOST(int id, string returnUrl) {
return EditPOST(id, returnUrl, contentItem => {
if (!contentItem.Has<IPublishingControlAspect>() && !contentItem.TypeDefinition.Settings.GetModel<ContentTypeSettings>().Draftable)
if (!contentItem.Has<IPublishingControlAspect>()
&& !contentItem.TypeDefinition.Settings.GetModel<ContentTypeSettings>().Draftable
&& contentItem.IsPublished())
_contentManager.Publish(contentItem);
});
}
private ActionResult EditPOST(int id, string returnUrl, Action<ContentItem> conditionallyPublish) {
var contentItem = _contentManager.Get(id, VersionOptions.DraftRequired);
if (contentItem == null)
[HttpPost]
// Copy of Contents/AdminController/Publish, but with different permission check and redirect.
public ActionResult Publish(int id) {
var menuPart = _contentManager.GetLatest<MenuPart>(id);
if (menuPart == null)
return HttpNotFound();
if (!Services.Authorizer.Authorize(Permissions.ManageMenus, contentItem.Content.MenuPart.Menu, T("Couldn't manage the main menu")))
if (!_authorizer.Authorize(Permissions.ManageMenus, menuPart.Menu, T("Couldn't manage the menu")))
return new HttpUnauthorizedResult();
_contentManager.Publish(menuPart.ContentItem);
_notifier.Information(
string.IsNullOrWhiteSpace(menuPart.MenuText)
? string.IsNullOrWhiteSpace(menuPart.TypeDefinition.DisplayName)
? T("Your content has been published.")
: T("Your {0} has been published.", menuPart.TypeDefinition.DisplayName)
: T("'{0}' has been published.", menuPart.MenuText));
return RedirectToAction("Index", new { menuId = menuPart.Menu.Id });
}
[HttpPost]
// Copy of Contents/AdminController/Unpublish, but with different permission check and redirect.
public ActionResult Unpublish(int id) {
var menuPart = _contentManager.GetLatest<MenuPart>(id);
if (menuPart == null)
return HttpNotFound();
if (!_authorizer.Authorize(Permissions.ManageMenus, menuPart.Menu, T("Couldn't manage the menu")))
return new HttpUnauthorizedResult();
_contentManager.Unpublish(menuPart.ContentItem);
_notifier.Information(
string.IsNullOrWhiteSpace(menuPart.MenuText)
? string.IsNullOrWhiteSpace(menuPart.TypeDefinition.DisplayName)
? T("Your content has been unpublished.")
: T("Your {0} has been unpublished.", menuPart.TypeDefinition.DisplayName)
: T("'{0}' has been unpublished.", menuPart.MenuText));
return RedirectToAction("Index", new { menuId = menuPart.Menu.Id });
}
private MenuItemEntry CreateMenuItemEntries(MenuPart menuPart) {
return new MenuItemEntry {
MenuItemId = menuPart.Id,
IsMenuItem = menuPart.Is<MenuItemPart>(),
Text = menuPart.MenuText,
Position = menuPart.MenuPosition,
Url = menuPart.Is<MenuItemPart>()
? menuPart.As<MenuItemPart>().Url
: _navigationManager.GetUrl(null, _contentManager.GetItemMetadata(menuPart).DisplayRouteValues),
ContentItem = menuPart.ContentItem,
};
}
private ActionResult EditPOST(int id, string returnUrl, Action<ContentItem> conditionallyPublish) {
var menuPart = _contentManager.GetDraftRequired<MenuPart>(id);
if (menuPart == null)
return HttpNotFound();
if (!_authorizer.Authorize(Permissions.ManageMenus, menuPart.Menu, T("Couldn't manage the menu")))
return new HttpUnauthorizedResult();
var contentItem = menuPart.ContentItem;
string previousRoute = null;
if (contentItem.Has<IAliasAspect>()
&& !string.IsNullOrWhiteSpace(returnUrl)
@@ -289,11 +342,22 @@ namespace Orchard.Core.Navigation.Controllers {
returnUrl = Url.ItemDisplayUrl(contentItem);
}
Services.Notifier.Information(string.IsNullOrWhiteSpace(contentItem.TypeDefinition.DisplayName)
? T("Your content has been saved.")
: T("Your {0} has been saved.", contentItem.TypeDefinition.DisplayName));
_notifier.Information(
string.IsNullOrWhiteSpace(menuPart.MenuText)
? string.IsNullOrWhiteSpace(contentItem.TypeDefinition.DisplayName)
? T("Your content has been saved.")
: T("Your {0} has been saved.", contentItem.TypeDefinition.DisplayName)
: T("'{0}' has been saved.", menuPart.MenuText));
return this.RedirectLocal(returnUrl, () => RedirectToAction("Edit", new RouteValueDictionary { { "Id", contentItem.Id } }));
return RedirectToAction("Index", new { menuId = menuPart.Menu.Id });
}
bool IUpdateModel.TryUpdateModel<TModel>(TModel model, string prefix, string[] includeProperties, string[] excludeProperties) {
return TryUpdateModel(model, prefix, includeProperties, excludeProperties);
}
void IUpdateModel.AddModelError(string key, LocalizedString errorMessage) {
ModelState.AddModelError(key, errorMessage.ToString());
}
}
}

View File

@@ -19,8 +19,8 @@ namespace Orchard.Core.Navigation.Services {
public IEnumerable<MenuPart> GetMenuParts(int menuId) {
return _contentManager
.Query<MenuPart, MenuPartRecord>()
.Where( x => x.MenuId == menuId)
.Query<MenuPart, MenuPartRecord>(VersionOptions.Latest)
.Where(x => x.MenuId == menuId)
.List();
}

View File

@@ -1,4 +1,6 @@
@model NavigationManagementViewModel
@using Orchard.ContentManagement;
@using Orchard.Core.Navigation.ViewModels;
@using Orchard.Utility.Extensions;
@@ -115,8 +117,21 @@
<span class="navigation-position"><input type="text" class="text" name="@Html.NameOf(m => m.MenuItemEntries[i].Position)" value="@menuPartEntry.Position" /></span>
<span class="navigation-actions">
<input type="hidden" name="@Html.NameOf(m => m.MenuItemEntries[i].MenuItemId)" value="@menuPartEntry.MenuItemId" />
@Html.ItemEditLink(T("Edit").Text, menuPartEntry.ContentItem, new { returnUrl = Request.RawUrl })@T(" | ")
@Html.Link(T("Delete").Text, Url.ItemRemoveUrl(menuPartEntry.ContentItem,null), new { itemprop = "RemoveUrl UnsafeUrl" })
@{
var menuItemHasPublished = menuPartEntry.ContentItem.HasPublished();
}
@Html.Link(
menuItemHasPublished ? T("Unpublish").Text : T("Publish").Text,
Url.Action(
menuItemHasPublished ? "Unpublish": "Publish",
"Admin",
new { area = "Navigation", id = menuPartEntry.ContentItem.Id }),
new { itemprop = "UnsafeUrl" })
@T(" | ")
@Html.ItemEditLink(T("Edit").Text, menuPartEntry.ContentItem, new { returnUrl = Request.RawUrl })
@T(" | ")
@Html.Link(T("Delete").Text, Url.ItemRemoveUrl(menuPartEntry.ContentItem, null), new { itemprop = "RemoveUrl UnsafeUrl" })
</span>
</div>

View File

@@ -54,7 +54,7 @@
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="Newtonsoft.Json" publicKeyToken="30ad4fe6b2a6aeed" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-12.0.0.0" newVersion="12.0.0.0" />
<bindingRedirect oldVersion="0.0.0.0-13.0.0.0" newVersion="13.0.0.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Web.Helpers" publicKeyToken="31bf3856ad364e35" />

View File

@@ -53,7 +53,7 @@
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="Newtonsoft.Json" publicKeyToken="30ad4fe6b2a6aeed" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-12.0.0.0" newVersion="12.0.0.0" />
<bindingRedirect oldVersion="0.0.0.0-13.0.0.0" newVersion="13.0.0.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Web.Helpers" publicKeyToken="31bf3856ad364e35" />

View File

@@ -54,7 +54,7 @@
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="Newtonsoft.Json" publicKeyToken="30ad4fe6b2a6aeed" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-12.0.0.0" newVersion="12.0.0.0" />
<bindingRedirect oldVersion="0.0.0.0-13.0.0.0" newVersion="13.0.0.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Web.Helpers" publicKeyToken="31bf3856ad364e35" />

View File

@@ -54,7 +54,7 @@
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="Newtonsoft.Json" publicKeyToken="30ad4fe6b2a6aeed" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-12.0.0.0" newVersion="12.0.0.0" />
<bindingRedirect oldVersion="0.0.0.0-13.0.0.0" newVersion="13.0.0.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Web.Helpers" publicKeyToken="31bf3856ad364e35" />

View File

@@ -59,8 +59,8 @@
<Reference Include="Microsoft.Web.Infrastructure, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<HintPath>..\..\..\packages\Microsoft.Web.Infrastructure.1.0.0.0\lib\net40\Microsoft.Web.Infrastructure.dll</HintPath>
</Reference>
<Reference Include="Newtonsoft.Json, Version=12.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
<HintPath>..\..\..\packages\Newtonsoft.Json.12.0.3\lib\net45\Newtonsoft.Json.dll</HintPath>
<Reference Include="Newtonsoft.Json, Version=13.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
<HintPath>..\..\..\packages\Newtonsoft.Json.13.0.3\lib\net45\Newtonsoft.Json.dll</HintPath>
</Reference>
<Reference Include="System" />
<Reference Include="System.Data" />
@@ -250,4 +250,4 @@
</FlavorProperties>
</VisualStudio>
</ProjectExtensions>
</Project>
</Project>

View File

@@ -54,7 +54,7 @@
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="Newtonsoft.Json" publicKeyToken="30ad4fe6b2a6aeed" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-12.0.0.0" newVersion="12.0.0.0" />
<bindingRedirect oldVersion="0.0.0.0-13.0.0.0" newVersion="13.0.0.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Web.Helpers" publicKeyToken="31bf3856ad364e35" />

View File

@@ -5,5 +5,5 @@
<package id="Microsoft.AspNet.WebPages" version="3.2.7" targetFramework="net48" />
<package id="Microsoft.CodeDom.Providers.DotNetCompilerPlatform" version="4.1.0" targetFramework="net48" />
<package id="Microsoft.Web.Infrastructure" version="1.0.0.0" targetFramework="net48" />
<package id="Newtonsoft.Json" version="12.0.3" targetFramework="net48" />
</packages>
<package id="Newtonsoft.Json" version="13.0.3" targetFramework="net48" />
</packages>

View File

@@ -54,7 +54,7 @@
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="Newtonsoft.Json" publicKeyToken="30ad4fe6b2a6aeed" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-12.0.0.0" newVersion="12.0.0.0" />
<bindingRedirect oldVersion="0.0.0.0-13.0.0.0" newVersion="13.0.0.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Web.Helpers" publicKeyToken="31bf3856ad364e35" />

View File

@@ -61,8 +61,8 @@
<Reference Include="Microsoft.Web.Infrastructure, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<HintPath>..\..\..\packages\Microsoft.Web.Infrastructure.1.0.0.0\lib\net40\Microsoft.Web.Infrastructure.dll</HintPath>
</Reference>
<Reference Include="Newtonsoft.Json, Version=12.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
<HintPath>..\..\..\packages\Newtonsoft.Json.12.0.3\lib\net45\Newtonsoft.Json.dll</HintPath>
<Reference Include="Newtonsoft.Json, Version=13.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
<HintPath>..\..\..\packages\Newtonsoft.Json.13.0.3\lib\net45\Newtonsoft.Json.dll</HintPath>
</Reference>
<Reference Include="NHibernate, Version=4.1.0.4000, Culture=neutral, PublicKeyToken=aa95f207798dfdb4, processorArchitecture=MSIL">
<HintPath>..\..\..\packages\NHibernate.4.1.2.4000\lib\net40\NHibernate.dll</HintPath>

View File

@@ -56,7 +56,7 @@
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="Newtonsoft.Json" publicKeyToken="30ad4fe6b2a6aeed" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-12.0.0.0" newVersion="12.0.0.0" />
<bindingRedirect oldVersion="0.0.0.0-13.0.0.0" newVersion="13.0.0.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Web.Helpers" publicKeyToken="31bf3856ad364e35" />

View File

@@ -6,7 +6,7 @@
<package id="Microsoft.AspNet.WebPages" version="3.2.7" targetFramework="net48" />
<package id="Microsoft.CodeDom.Providers.DotNetCompilerPlatform" version="4.1.0" targetFramework="net48" />
<package id="Microsoft.Web.Infrastructure" version="1.0.0.0" targetFramework="net48" />
<package id="Newtonsoft.Json" version="12.0.3" targetFramework="net48" />
<package id="Newtonsoft.Json" version="13.0.3" targetFramework="net48" />
<package id="NHibernate" version="4.1.2.4000" targetFramework="net48" />
<package id="XMLDiffPatch" version="1.0.8.28" targetFramework="net48" />
</packages>
</packages>

View File

@@ -53,7 +53,7 @@
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="Newtonsoft.Json" publicKeyToken="30ad4fe6b2a6aeed" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-12.0.0.0" newVersion="12.0.0.0" />
<bindingRedirect oldVersion="0.0.0.0-13.0.0.0" newVersion="13.0.0.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Web.Helpers" publicKeyToken="31bf3856ad364e35" />

View File

@@ -76,14 +76,14 @@
<Reference Include="Microsoft.Data.Services.Client, Version=5.8.4.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<HintPath>..\..\..\packages\Microsoft.Data.Services.Client.5.8.4\lib\net40\Microsoft.Data.Services.Client.dll</HintPath>
</Reference>
<Reference Include="Microsoft.IdentityModel.JsonWebTokens, Version=5.2.4.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<HintPath>..\..\..\packages\Microsoft.IdentityModel.JsonWebTokens.5.2.4\lib\net451\Microsoft.IdentityModel.JsonWebTokens.dll</HintPath>
<Reference Include="Microsoft.IdentityModel.JsonWebTokens, Version=5.7.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<HintPath>..\..\..\packages\Microsoft.IdentityModel.JsonWebTokens.5.7.0\lib\net461\Microsoft.IdentityModel.JsonWebTokens.dll</HintPath>
</Reference>
<Reference Include="Microsoft.IdentityModel.Logging, Version=5.2.4.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<HintPath>..\..\..\packages\Microsoft.IdentityModel.Logging.5.2.4\lib\net451\Microsoft.IdentityModel.Logging.dll</HintPath>
<Reference Include="Microsoft.IdentityModel.Logging, Version=5.7.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<HintPath>..\..\..\packages\Microsoft.IdentityModel.Logging.5.7.0\lib\net461\Microsoft.IdentityModel.Logging.dll</HintPath>
</Reference>
<Reference Include="Microsoft.IdentityModel.Tokens, Version=5.2.4.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<HintPath>..\..\..\packages\Microsoft.IdentityModel.Tokens.5.2.4\lib\net451\Microsoft.IdentityModel.Tokens.dll</HintPath>
<Reference Include="Microsoft.IdentityModel.Tokens, Version=5.7.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<HintPath>..\..\..\packages\Microsoft.IdentityModel.Tokens.5.7.0\lib\net461\Microsoft.IdentityModel.Tokens.dll</HintPath>
</Reference>
<Reference Include="Microsoft.Practices.TransientFaultHandling.Core, Version=5.1.1209.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<HintPath>..\..\..\packages\TransientFaultHandling.Core.5.1.1209.1\lib\NET4\Microsoft.Practices.TransientFaultHandling.Core.dll</HintPath>
@@ -109,8 +109,8 @@
<Reference Include="Microsoft.WindowsAzure.Storage, Version=5.0.2.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<HintPath>..\..\..\packages\WindowsAzure.Storage.5.0.2\lib\net40\Microsoft.WindowsAzure.Storage.dll</HintPath>
</Reference>
<Reference Include="Newtonsoft.Json, Version=12.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
<HintPath>..\..\..\packages\Newtonsoft.Json.12.0.3\lib\net45\Newtonsoft.Json.dll</HintPath>
<Reference Include="Newtonsoft.Json, Version=13.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
<HintPath>..\..\..\packages\Newtonsoft.Json.13.0.3\lib\net45\Newtonsoft.Json.dll</HintPath>
</Reference>
<Reference Include="NHibernate, Version=4.1.0.4000, Culture=neutral, PublicKeyToken=aa95f207798dfdb4, processorArchitecture=MSIL">
<HintPath>..\..\..\packages\NHibernate.4.1.2.4000\lib\net40\NHibernate.dll</HintPath>
@@ -121,8 +121,8 @@
<RequiredTargetFramework>3.5</RequiredTargetFramework>
</Reference>
<Reference Include="System.Data.DataSetExtensions" />
<Reference Include="System.IdentityModel.Tokens.Jwt, Version=5.2.4.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<HintPath>..\..\..\packages\System.IdentityModel.Tokens.Jwt.5.2.4\lib\net451\System.IdentityModel.Tokens.Jwt.dll</HintPath>
<Reference Include="System.IdentityModel.Tokens.Jwt, Version=5.7.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<HintPath>..\..\..\packages\System.IdentityModel.Tokens.Jwt.5.7.0\lib\net461\System.IdentityModel.Tokens.Jwt.dll</HintPath>
</Reference>
<Reference Include="System.Runtime.Serialization" />
<Reference Include="System.Spatial, Version=5.8.4.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">

View File

@@ -51,7 +51,7 @@
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="Newtonsoft.Json" publicKeyToken="30ad4fe6b2a6aeed" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-12.0.0.0" newVersion="12.0.0.0" />
<bindingRedirect oldVersion="0.0.0.0-13.0.0.0" newVersion="13.0.0.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="Microsoft.Data.OData" publicKeyToken="31bf3856ad364e35" culture="neutral" />

View File

@@ -11,15 +11,15 @@
<package id="Microsoft.Data.Edm" version="5.8.4" targetFramework="net48" />
<package id="Microsoft.Data.OData" version="5.8.4" targetFramework="net48" />
<package id="Microsoft.Data.Services.Client" version="5.8.4" targetFramework="net48" />
<package id="Microsoft.IdentityModel.JsonWebTokens" version="5.2.4" targetFramework="net48" />
<package id="Microsoft.IdentityModel.Logging" version="5.2.4" targetFramework="net48" />
<package id="Microsoft.IdentityModel.Tokens" version="5.2.4" targetFramework="net48" />
<package id="Microsoft.IdentityModel.JsonWebTokens" version="5.7.0" targetFramework="net48" />
<package id="Microsoft.IdentityModel.Logging" version="5.7.0" targetFramework="net48" />
<package id="Microsoft.IdentityModel.Tokens" version="5.7.0" targetFramework="net48" />
<package id="Microsoft.Web.Infrastructure" version="1.0.0.0" targetFramework="net48" />
<package id="Microsoft.WindowsAzure.ConfigurationManager" version="3.1.0" targetFramework="net48" />
<package id="Newtonsoft.Json" version="12.0.3" targetFramework="net48" />
<package id="Newtonsoft.Json" version="13.0.3" targetFramework="net48" />
<package id="NHibernate" version="4.1.2.4000" targetFramework="net48" />
<package id="Orchard.WindowsAzure.Diagnostics" version="2.7.0.0" targetFramework="net48" />
<package id="System.IdentityModel.Tokens.Jwt" version="5.2.4" targetFramework="net48" />
<package id="System.IdentityModel.Tokens.Jwt" version="5.7.0" targetFramework="net48" />
<package id="System.Spatial" version="5.8.4" targetFramework="net48" />
<package id="TransientFaultHandling.Core" version="5.1.1209.1" targetFramework="net48" />
<package id="windowsazure.mediaservices" version="3.4.0.0" targetFramework="net48" />

View File

@@ -100,8 +100,8 @@
<Reference Include="Microsoft.WindowsFabric.Data.Common, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<HintPath>..\..\..\packages\Microsoft.WindowsAzure.Caching.2.4.0.0\lib\net40-full\Microsoft.WindowsFabric.Data.Common.dll</HintPath>
</Reference>
<Reference Include="Newtonsoft.Json, Version=12.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
<HintPath>..\..\..\packages\Newtonsoft.Json.12.0.3\lib\net45\Newtonsoft.Json.dll</HintPath>
<Reference Include="Newtonsoft.Json, Version=13.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
<HintPath>..\..\..\packages\Newtonsoft.Json.13.0.3\lib\net45\Newtonsoft.Json.dll</HintPath>
</Reference>
<Reference Include="NHibernate, Version=4.1.0.4000, Culture=neutral, PublicKeyToken=aa95f207798dfdb4, processorArchitecture=MSIL">
<HintPath>..\..\..\packages\NHibernate.4.1.2.4000\lib\net40\NHibernate.dll</HintPath>
@@ -218,4 +218,4 @@
</FlavorProperties>
</VisualStudio>
</ProjectExtensions>
</Project>
</Project>

View File

@@ -89,6 +89,8 @@ namespace Orchard.Azure.Services.FileSystems {
return newPath;
}
private static string GetFolderName(string path) => path.Substring(path.LastIndexOf('/') + 1);
public string Combine(string path1, string path2) {
if (path1 == null) {
throw new ArgumentNullException("path1");
@@ -141,10 +143,10 @@ namespace Orchard.Azure.Services.FileSystems {
}
return BlobClient.ListBlobs(prefix)
.OfType<CloudBlockBlob>()
.Where(blobItem => !blobItem.Uri.AbsoluteUri.EndsWith(FolderEntry))
.Select(blobItem => new AzureBlobFileStorage(blobItem, _absoluteRoot))
.ToArray();
.OfType<CloudBlockBlob>()
.Where(blobItem => !blobItem.Uri.AbsoluteUri.EndsWith(FolderEntry))
.Select(blobItem => new AzureBlobFileStorage(blobItem, _absoluteRoot))
.ToArray();
}
public IEnumerable<IStorageFolder> ListFolders(string path) {
@@ -194,6 +196,11 @@ namespace Orchard.Azure.Services.FileSystems {
public void CreateFolder(string path) {
path = ConvertToRelativeUriPath(path);
if (FileSystemStorageProvider.FolderNameContainsInvalidCharacters(GetFolderName(path))) {
throw new InvalidNameCharacterException("The directory name contains invalid character(s)");
}
Container.EnsureDirectoryDoesNotExist(String.Concat(_root, path));
// Creating a virtually hidden file to make the directory an existing concept
@@ -225,6 +232,10 @@ namespace Orchard.Azure.Services.FileSystems {
path = ConvertToRelativeUriPath(path);
newPath = ConvertToRelativeUriPath(newPath);
if (FileSystemStorageProvider.FolderNameContainsInvalidCharacters(GetFolderName(newPath))) {
throw new InvalidNameCharacterException("The new directory name contains invalid character(s)");
}
if (!path.EndsWith("/"))
path += "/";
@@ -260,6 +271,10 @@ namespace Orchard.Azure.Services.FileSystems {
path = ConvertToRelativeUriPath(path);
newPath = ConvertToRelativeUriPath(newPath);
if (FileSystemStorageProvider.FileNameContainsInvalidCharacters(Path.GetFileName(newPath))) {
throw new InvalidNameCharacterException("The new file name contains invalid character(s)");
}
Container.EnsureBlobExists(String.Concat(_root, path));
Container.EnsureBlobDoesNotExist(String.Concat(_root, newPath));
@@ -284,6 +299,10 @@ namespace Orchard.Azure.Services.FileSystems {
public IStorageFile CreateFile(string path) {
path = ConvertToRelativeUriPath(path);
if (FileSystemStorageProvider.FileNameContainsInvalidCharacters(Path.GetFileName(path))) {
throw new InvalidNameCharacterException("The file name contains invalid character(s)");
}
if (Container.BlobExists(String.Concat(_root, path))) {
throw new ArgumentException("File " + path + " already exists");
}
@@ -371,10 +390,7 @@ namespace Orchard.Azure.Services.FileSystems {
_rootPath = rootPath;
}
public string GetName() {
var path = GetPath();
return path.Substring(path.LastIndexOf('/') + 1);
}
public string GetName() => GetFolderName(GetPath());
public string GetPath() {
return _blob.Uri.ToString().Substring(_rootPath.Length).Trim('/');
@@ -399,11 +415,12 @@ namespace Orchard.Azure.Services.FileSystems {
long size = 0;
foreach (var blobItem in directoryBlob.ListBlobs()) {
if (blobItem is CloudBlockBlob)
size += ((CloudBlockBlob)blobItem).Properties.Length;
if (blobItem is CloudBlobDirectory)
size += GetDirectorySize((CloudBlobDirectory)blobItem);
if (blobItem is CloudBlockBlob blob) {
size += blob.Properties.Length;
}
else if (blobItem is CloudBlobDirectory directory) {
size += GetDirectorySize(directory);
}
}
return size;

View File

@@ -63,7 +63,7 @@
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="Newtonsoft.Json" publicKeyToken="30ad4fe6b2a6aeed" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-12.0.0.0" newVersion="12.0.0.0" />
<bindingRedirect oldVersion="0.0.0.0-13.0.0.0" newVersion="13.0.0.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="Autofac" publicKeyToken="17863af14b0044da" culture="neutral" />

View File

@@ -12,9 +12,9 @@
<package id="Microsoft.Web.Infrastructure" version="1.0.0.0" targetFramework="net48" />
<package id="Microsoft.WindowsAzure.Caching" version="2.4.0.0" targetFramework="net48" />
<package id="Microsoft.WindowsAzure.ConfigurationManager" version="3.1.0" targetFramework="net48" />
<package id="Newtonsoft.Json" version="12.0.3" targetFramework="net48" />
<package id="Newtonsoft.Json" version="13.0.3" targetFramework="net48" />
<package id="NHibernate" version="4.1.2.4000" targetFramework="net48" />
<package id="Orchard.WindowsAzure.ServiceRuntime" version="2.7.0.0" targetFramework="net48" />
<package id="System.Spatial" version="5.8.4" targetFramework="net48" />
<package id="WindowsAzure.Storage" version="5.0.2" targetFramework="net48" />
</packages>
</packages>

View File

@@ -54,7 +54,7 @@
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="Newtonsoft.Json" publicKeyToken="30ad4fe6b2a6aeed" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-12.0.0.0" newVersion="12.0.0.0" />
<bindingRedirect oldVersion="0.0.0.0-13.0.0.0" newVersion="13.0.0.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Web.Helpers" publicKeyToken="31bf3856ad364e35" />

View File

@@ -49,7 +49,7 @@
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="Newtonsoft.Json" publicKeyToken="30ad4fe6b2a6aeed" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-12.0.0.0" newVersion="12.0.0.0" />
<bindingRedirect oldVersion="0.0.0.0-13.0.0.0" newVersion="13.0.0.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Web.Helpers" publicKeyToken="31bf3856ad364e35" />

View File

@@ -47,7 +47,7 @@
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="Newtonsoft.Json" publicKeyToken="30AD4FE6B2A6AEED" culture="neutral"/>
<bindingRedirect oldVersion="0.0.0.0-12.0.0.0" newVersion="12.0.0.0"/>
<bindingRedirect oldVersion="0.0.0.0-13.0.0.0" newVersion="13.0.0.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="NHibernate" publicKeyToken="AA95F207798DFDB4" culture="neutral"/>

View File

@@ -21,7 +21,7 @@
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<CodeAnalysisRuleSet>..\..\..\OrchardBasicCorrectness.ruleset</CodeAnalysisRuleSet>
<CodeAnalysisRuleSet>..\..\..\..\OrchardBasicCorrectness.ruleset</CodeAnalysisRuleSet>
<Prefer32Bit>false</Prefer32Bit>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
@@ -35,16 +35,16 @@
<Prefer32Bit>false</Prefer32Bit>
</PropertyGroup>
<ItemGroup>
<Reference Include="Autofac">
<Reference Include="Autofac, Version=3.5.0.0, Culture=neutral, PublicKeyToken=17863af14b0044da, processorArchitecture=MSIL">
<HintPath>..\..\..\..\packages\Autofac.3.5.2\lib\net40\Autofac.dll</HintPath>
</Reference>
<Reference Include="Moq, Version=4.2.1510.2205, Culture=neutral, PublicKeyToken=69f491c39445e920, processorArchitecture=MSIL">
<HintPath>..\..\..\..\packages\Moq.4.2.1510.2205\lib\net40\Moq.dll</HintPath>
</Reference>
<Reference Include="NHibernate">
<HintPath>..\..\..\..\packages\NHibernate.4.0.1.4000\lib\net40\NHibernate.dll</HintPath>
<Reference Include="NHibernate, Version=4.1.0.4000, Culture=neutral, PublicKeyToken=aa95f207798dfdb4, processorArchitecture=MSIL">
<HintPath>..\..\..\..\packages\NHibernate.4.1.2.4000\lib\net40\NHibernate.dll</HintPath>
</Reference>
<Reference Include="nunit.framework">
<Reference Include="nunit.framework, Version=2.5.10.11092, Culture=neutral, PublicKeyToken=96d09a1eb7f44a77, processorArchitecture=MSIL">
<HintPath>..\..\..\..\packages\NUnit.2.5.10.11092\lib\nunit.framework.dll</HintPath>
</Reference>
<Reference Include="System" />

View File

@@ -0,0 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="Autofac" version="3.5.2" targetFramework="net48" />
<package id="Moq" version="4.2.1510.2205" targetFramework="net48" />
<package id="NHibernate" version="4.1.2.4000" targetFramework="net48" />
<package id="NUnit" version="2.5.10.11092" targetFramework="net48" />
</packages>

View File

@@ -161,6 +161,8 @@ namespace Orchard.CodeGeneration.Commands {
templateText = templateText.Replace("$$ModuleTypeLibGuid$$", Guid.NewGuid().ToString());
File.WriteAllText(propertiesPath + "\\AssemblyInfo.cs", templateText);
content.Add(propertiesPath + "\\AssemblyInfo.cs");
File.WriteAllText(testsPath + "packages.config", File.ReadAllText(_codeGenTemplatePath + "ModuleTestsPackagesConfig.txt"));
content.Add(testsPath + "packages.config");
var itemGroup = CreateProjectItemGroup(testsPath, content, folders);
@@ -168,7 +170,7 @@ namespace Orchard.CodeGeneration.Commands {
csprojText = csprojText.Replace("$$ProjectName$$", projectName);
csprojText = csprojText.Replace("$$TestsProjectGuid$$", projectGuid);
csprojText = csprojText.Replace("$$FileIncludes$$", itemGroup ?? "");
csprojText = csprojText.Replace("$$OrchardReferences$$", GetOrchardReferences());
csprojText = csprojText.Replace("$$OrchardReferences$$", GetOrchardReferences(modulesFolderRelativeDepth: 3));
File.WriteAllText(testsPath + projectName + ".csproj", csprojText);
@@ -327,15 +329,17 @@ namespace Orchard.CodeGeneration.Commands {
return text;
}
private static string GetOrchardReferences() {
private static string GetOrchardReferences(int modulesFolderRelativeDepth = 2) {
var frameworkRelativeDepth = string.Join("\\", Enumerable.Repeat("..", modulesFolderRelativeDepth + 1));
var coreRelativeDepth = string.Join("\\", Enumerable.Repeat("..", modulesFolderRelativeDepth));
return IsSourceEnlistment() ?
@"<ProjectReference Include=""..\..\..\Orchard\Orchard.Framework.csproj"">
<Project>{2D1D92BB-4555-4CBE-8D0E-63563D6CE4C6}</Project>
$@"<ProjectReference Include=""{frameworkRelativeDepth}\Orchard\Orchard.Framework.csproj"">
<Project>{{2D1D92BB-4555-4CBE-8D0E-63563D6CE4C6}}</Project>
<Name>Orchard.Framework</Name>
<Private>$(MvcBuildViews)</Private>
</ProjectReference>
<ProjectReference Include=""..\..\Core\Orchard.Core.csproj"">
<Project>{9916839C-39FC-4CEB-A5AF-89CA7E87119F}</Project>
<ProjectReference Include=""{coreRelativeDepth}\Core\Orchard.Core.csproj"">
<Project>{{9916839C-39FC-4CEB-A5AF-89CA7E87119F}}</Project>
<Name>Orchard.Core</Name>
<Private>$(MvcBuildViews)</Private>
</ProjectReference>" :

View File

@@ -88,6 +88,7 @@
<Compile Include="Services\CodeGenerationCommandInterpreter.cs" />
</ItemGroup>
<ItemGroup>
<Content Include="CodeGenerationTemplates\ModuleTestsPackagesConfig.txt" />
<Content Include="CodeGenerationTemplates\ModuleStylesMinCss.txt" />
<Content Include="CodeGenerationTemplates\ModuleStylesCss.txt" />
<Content Include="CodeGenerationTemplates\ModuleStylesLess.txt" />
@@ -158,4 +159,4 @@
</FlavorProperties>
</VisualStudio>
</ProjectExtensions>
</Project>
</Project>

View File

@@ -49,7 +49,7 @@
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="Newtonsoft.Json" publicKeyToken="30ad4fe6b2a6aeed" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-12.0.0.0" newVersion="12.0.0.0" />
<bindingRedirect oldVersion="0.0.0.0-13.0.0.0" newVersion="13.0.0.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Web.Helpers" publicKeyToken="31bf3856ad364e35" />

View File

@@ -54,7 +54,7 @@
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="Newtonsoft.Json" publicKeyToken="30ad4fe6b2a6aeed" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-12.0.0.0" newVersion="12.0.0.0" />
<bindingRedirect oldVersion="0.0.0.0-13.0.0.0" newVersion="13.0.0.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Web.Helpers" publicKeyToken="31bf3856ad364e35" />

View File

@@ -52,7 +52,7 @@
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="Newtonsoft.Json" publicKeyToken="30ad4fe6b2a6aeed" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-12.0.0.0" newVersion="12.0.0.0" />
<bindingRedirect oldVersion="0.0.0.0-13.0.0.0" newVersion="13.0.0.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Web.Helpers" publicKeyToken="31bf3856ad364e35" />

View File

@@ -54,7 +54,7 @@
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="Newtonsoft.Json" publicKeyToken="30ad4fe6b2a6aeed" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-12.0.0.0" newVersion="12.0.0.0" />
<bindingRedirect oldVersion="0.0.0.0-13.0.0.0" newVersion="13.0.0.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Web.Helpers" publicKeyToken="31bf3856ad364e35" />

View File

@@ -54,7 +54,7 @@
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="Newtonsoft.Json" publicKeyToken="30ad4fe6b2a6aeed" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-12.0.0.0" newVersion="12.0.0.0" />
<bindingRedirect oldVersion="0.0.0.0-13.0.0.0" newVersion="13.0.0.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Web.Helpers" publicKeyToken="31bf3856ad364e35" />

View File

@@ -54,7 +54,7 @@
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="Newtonsoft.Json" publicKeyToken="30ad4fe6b2a6aeed" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-12.0.0.0" newVersion="12.0.0.0" />
<bindingRedirect oldVersion="0.0.0.0-13.0.0.0" newVersion="13.0.0.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Web.Helpers" publicKeyToken="31bf3856ad364e35" />

View File

@@ -54,7 +54,7 @@
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="Newtonsoft.Json" publicKeyToken="30ad4fe6b2a6aeed" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-12.0.0.0" newVersion="12.0.0.0" />
<bindingRedirect oldVersion="0.0.0.0-13.0.0.0" newVersion="13.0.0.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Web.Helpers" publicKeyToken="31bf3856ad364e35" />

View File

@@ -55,7 +55,7 @@
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="Newtonsoft.Json" publicKeyToken="30ad4fe6b2a6aeed" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-12.0.0.0" newVersion="12.0.0.0" />
<bindingRedirect oldVersion="0.0.0.0-13.0.0.0" newVersion="13.0.0.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Web.Helpers" publicKeyToken="31bf3856ad364e35" />

View File

@@ -55,7 +55,7 @@
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="Newtonsoft.Json" publicKeyToken="30ad4fe6b2a6aeed" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-12.0.0.0" newVersion="12.0.0.0" />
<bindingRedirect oldVersion="0.0.0.0-13.0.0.0" newVersion="13.0.0.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Web.Helpers" publicKeyToken="31bf3856ad364e35" />

View File

@@ -1,12 +0,0 @@
using System;
using System.Collections.Specialized;
using System.Linq;
using System.Web;
namespace Orchard.DynamicForms.Helpers {
public static class NameValueCollectionExtensions {
public static string ToQueryString(this NameValueCollection nameValues) {
return String.Join("&", (from string name in nameValues select String.Concat(name, "=", HttpUtility.UrlEncode(nameValues[name]))).ToArray());
}
}
}

View File

@@ -65,8 +65,8 @@
<Reference Include="Microsoft.Web.Infrastructure, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<HintPath>..\..\..\packages\Microsoft.Web.Infrastructure.1.0.0.0\lib\net40\Microsoft.Web.Infrastructure.dll</HintPath>
</Reference>
<Reference Include="Newtonsoft.Json, Version=12.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
<HintPath>..\..\..\packages\Newtonsoft.Json.12.0.3\lib\net45\Newtonsoft.Json.dll</HintPath>
<Reference Include="Newtonsoft.Json, Version=13.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
<HintPath>..\..\..\packages\Newtonsoft.Json.13.0.3\lib\net45\Newtonsoft.Json.dll</HintPath>
</Reference>
<Reference Include="System" />
<Reference Include="System.Data" />
@@ -340,7 +340,6 @@
<Compile Include="Migrations.cs" />
<Compile Include="Handlers\ReadFormValuesHandler.cs" />
<Compile Include="Services\FormElementEventHandlerBase.cs" />
<Compile Include="Helpers\NameValueCollectionExtensions.cs" />
<Compile Include="Models\Submission.cs" />
<Compile Include="Permissions.cs" />
<Compile Include="Services\FormService.cs" />

View File

@@ -467,4 +467,4 @@ namespace Orchard.DynamicForms.Services {
return validatorElementType == elementType || validatorElementType.IsAssignableFrom(elementType);
}
}
}
}

View File

@@ -57,7 +57,7 @@
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="Newtonsoft.Json" publicKeyToken="30ad4fe6b2a6aeed" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-12.0.0.0" newVersion="12.0.0.0" />
<bindingRedirect oldVersion="0.0.0.0-13.0.0.0" newVersion="13.0.0.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Web.Helpers" publicKeyToken="31bf3856ad364e35" />

View File

@@ -7,5 +7,5 @@
<package id="Microsoft.AspNet.WebPages" version="3.2.7" targetFramework="net48" />
<package id="Microsoft.CodeDom.Providers.DotNetCompilerPlatform" version="4.1.0" targetFramework="net48" />
<package id="Microsoft.Web.Infrastructure" version="1.0.0.0" targetFramework="net48" />
<package id="Newtonsoft.Json" version="12.0.3" targetFramework="net48" />
<package id="Newtonsoft.Json" version="13.0.3" targetFramework="net48" />
</packages>

View File

@@ -68,8 +68,8 @@
<Reference Include="MimeKit, Version=3.1.0.0, Culture=neutral, PublicKeyToken=bede1c8a46c66814, processorArchitecture=MSIL">
<HintPath>..\..\..\packages\MimeKit.3.1.1\lib\net48\MimeKit.dll</HintPath>
</Reference>
<Reference Include="Newtonsoft.Json, Version=12.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
<HintPath>..\..\..\packages\Newtonsoft.Json.12.0.3\lib\net45\Newtonsoft.Json.dll</HintPath>
<Reference Include="Newtonsoft.Json, Version=13.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
<HintPath>..\..\..\packages\Newtonsoft.Json.13.0.3\lib\net45\Newtonsoft.Json.dll</HintPath>
</Reference>
<Reference Include="System" />
<Reference Include="System.Buffers, Version=4.0.3.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL">

View File

@@ -55,7 +55,7 @@
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="Newtonsoft.Json" publicKeyToken="30ad4fe6b2a6aeed" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-12.0.0.0" newVersion="12.0.0.0" />
<bindingRedirect oldVersion="0.0.0.0-13.0.0.0" newVersion="13.0.0.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Web.Helpers" publicKeyToken="31bf3856ad364e35" />

View File

@@ -7,7 +7,7 @@
<package id="Microsoft.CodeDom.Providers.DotNetCompilerPlatform" version="4.1.0" targetFramework="net48" />
<package id="Microsoft.Web.Infrastructure" version="1.0.0.0" targetFramework="net48" />
<package id="MimeKit" version="3.1.1" targetFramework="net48" />
<package id="Newtonsoft.Json" version="12.0.3" targetFramework="net48" />
<package id="Newtonsoft.Json" version="13.0.3" targetFramework="net48" />
<package id="Portable.BouncyCastle" version="1.9.0" targetFramework="net48" />
<package id="System.Buffers" version="4.5.1" targetFramework="net48" />
</packages>

View File

@@ -4,46 +4,41 @@ using Orchard.ContentManagement.Handlers;
using Orchard.Fields.Fields;
using Orchard.Fields.Settings;
using Orchard.Localization;
using System;
using System.Collections.Generic;
using System.Linq;
namespace Orchard.Fields.Drivers {
public class EnumerationFieldDriver : ContentFieldDriver<EnumerationField> {
public IOrchardServices Services { get; set; }
private const string TemplateName = "Fields/Enumeration.Edit";
public EnumerationFieldDriver(IOrchardServices services) {
Services = services;
T = NullLocalizer.Instance;
}
public Localizer T { get; set; }
private static string GetPrefix(ContentField field, ContentPart part) {
return part.PartDefinition.Name + "." + field.Name;
}
private static string GetPrefix(ContentField field, ContentPart part) =>
part.PartDefinition.Name + "." + field.Name;
private static string GetDifferentiator(EnumerationField field, ContentPart part) {
return field.Name;
}
private static string GetDifferentiator(EnumerationField field) => field.Name;
protected override DriverResult Display(ContentPart part, EnumerationField field, string displayType, dynamic shapeHelper) {
return ContentShape("Fields_Enumeration", GetDifferentiator(field, part),
() => shapeHelper.Fields_Enumeration());
return ContentShape("Fields_Enumeration", GetDifferentiator(field), () => shapeHelper.Fields_Enumeration());
}
protected override DriverResult Editor(ContentPart part, EnumerationField field, dynamic shapeHelper) {
return ContentShape("Fields_Enumeration_Edit", GetDifferentiator(field, part),
() => {
if (part.IsNew() && String.IsNullOrEmpty(field.Value)) {
var settings = field.PartFieldDefinition.Settings.GetModel<EnumerationFieldSettings>();
if (!String.IsNullOrWhiteSpace(settings.DefaultValue)) {
field.Value = settings.DefaultValue;
}
return ContentShape("Fields_Enumeration_Edit", GetDifferentiator(field), () => {
if (part.IsNew() && string.IsNullOrEmpty(field.Value)) {
var settings = field.PartFieldDefinition.Settings.GetModel<EnumerationFieldSettings>();
if (!string.IsNullOrWhiteSpace(settings.DefaultValue)) {
field.SelectedValues = new string[] { settings.DefaultValue };
}
return shapeHelper.EditorTemplate(TemplateName: TemplateName, Model: field, Prefix: GetPrefix(field, part));
});
}
return shapeHelper.EditorTemplate(TemplateName: TemplateName, Model: field, Prefix: GetPrefix(field, part));
});
}
protected override DriverResult Editor(ContentPart part, EnumerationField field, IUpdateModel updater, dynamic shapeHelper) {

View File

@@ -6,6 +6,7 @@ using Orchard.Fields.Settings;
using Orchard.Localization;
using System;
using System.Collections.Generic;
using System.Security.Policy;
namespace Orchard.Fields.Drivers {
public class LinkFieldDriver : ContentFieldDriver<LinkField> {
@@ -57,11 +58,33 @@ namespace Orchard.Fields.Drivers {
if (settings.Required && String.IsNullOrWhiteSpace(field.Value)) {
updater.AddModelError(GetPrefix(field, part), T("Url is required for {0}", T(field.DisplayName)));
}
else if (!String.IsNullOrWhiteSpace(field.Value) && !Uri.IsWellFormedUriString(field.Value, UriKind.RelativeOrAbsolute)) {
updater.AddModelError(GetPrefix(field, part), T("{0} is an invalid url.", field.Value));
}
else if (settings.LinkTextMode == LinkTextMode.Required && String.IsNullOrWhiteSpace(field.Text)) {
updater.AddModelError(GetPrefix(field, part), T("Text is required for {0}.", T(field.DisplayName)));
} else if (!String.IsNullOrWhiteSpace(field.Value)) {
// Check if it's a valid uri, considering that there may be the link to an anchor only
// e.g.: field.Value = "#divId"
// Take everything before the first "#" character and check if it's a valid uri.
// If there is no character before the first "#", consider the value as a valid one (because it is a reference to a div inside the same page)
if (field.Value.StartsWith("#")) {
// The field value is a tag id reference
// For html 5, a tag id is valid as long as it doesn't contain white spaces
if (field.Value.IndexOf(' ') >= 0) {
updater.AddModelError(GetPrefix(field, part), T("{0} is an invalid url.", field.Value));
}
} else {
var urlAndRef = field.Value.Split(new char[] { '#' }, 2);
// Since field value is a proper url and not a tag id only, assume the first part of the array is the actual url to link to
if (!String.IsNullOrWhiteSpace(urlAndRef[0]) && !Uri.IsWellFormedUriString(urlAndRef[0], UriKind.RelativeOrAbsolute)) {
updater.AddModelError(GetPrefix(field, part), T("{0} is an invalid url.", field.Value));
} else if (urlAndRef.Length > 1) {
// The second part of the url is the id reference
// For html 5, a tag id is valid as long as it doesn't contain white spaces
if (urlAndRef[1].IndexOf(' ') >= 0) {
updater.AddModelError(GetPrefix(field, part), T("{0} is an invalid url.", field.Value));
}
}
}
}
}

View File

@@ -7,28 +7,16 @@ namespace Orchard.Fields.Fields {
private const char Separator = ';';
public string Value {
get { return Storage.Get<string>(); }
set { Storage.Set(value ?? String.Empty); }
get => Storage.Get<string>()?.Trim(Separator) ?? "";
set => Storage.Set(string.IsNullOrWhiteSpace(value)
? string.Empty
// It is now the responsibility of this field to (re-)add the separators.
: Separator + value.Trim(Separator) + Separator);
}
public string[] SelectedValues {
get {
var value = Value;
if(string.IsNullOrWhiteSpace(value)) {
return new string[0];
}
return value.Split(new [] { Separator }, StringSplitOptions.RemoveEmptyEntries);
}
set {
if (value == null || value.Length == 0) {
Value = String.Empty;
}
else {
Value = Separator + string.Join(Separator.ToString(), value) + Separator;
}
}
get => Value?.Split(new[] { Separator }, StringSplitOptions.RemoveEmptyEntries) ?? new string[0];
set => Value = value?.Length > 0 ? string.Join(Separator.ToString(), value) : "";
}
}
}

View File

@@ -1,22 +1,27 @@
@model Orchard.Fields.Fields.EnumerationField
@using Orchard.Fields.Settings;
@{
var settings = Model.PartFieldDefinition.Settings.GetModel<EnumerationFieldSettings>();
string[] options = (!String.IsNullOrWhiteSpace(settings.Options)) ? settings.Options.Split(new string[] { System.Environment.NewLine }, StringSplitOptions.None) : new string[] { T("Select an option").ToString() };
}
<fieldset>
<label for="@Html.FieldIdFor(m => m.Value)" @if (settings.Required) { <text> class="required" </text> }>@Model.DisplayName</label>
<label for="@Html.FieldIdFor(m => m.Value)" @if (settings.Required) { <text> class="required" </text> }>@Model.DisplayName</label>
@switch (settings.ListMode) {
case ListMode.Dropdown:
@Html.DropDownListFor(m => m.Value, new SelectList(options, Model.Value), settings.Required ? new { required = "required" } : null)
@Html.DropDownListFor(m => m.Value, new SelectList(options, Model.SelectedValues.FirstOrDefault()), settings.Required ? new { required = "required" } : null)
break;
case ListMode.Radiobutton:
foreach (var option in options) {
if (string.IsNullOrWhiteSpace(option)) {
<label>@Html.RadioButton("Value", "", string.IsNullOrWhiteSpace(Model.Value), settings.Required ? new { required = "required" } : null)<i>@T("unset")</i></label> }
<label>@Html.RadioButton("Value", "", string.IsNullOrWhiteSpace(Model.SelectedValues.FirstOrDefault()), settings.Required ? new { required = "required" } : null)<i>@T("unset")</i></label>
}
else {
<label>@Html.RadioButton("Value", option, (option == Model.Value), settings.Required ? new { required = "required" } : null)@option</label> }
<label>@Html.RadioButton("Value", option, (option == Model.SelectedValues.FirstOrDefault()), settings.Required ? new { required = "required" } : null)@option</label>
}
}
break;

View File

@@ -25,7 +25,7 @@
</div>
<div class="editor-field">
@(settings.Required ? Html.TextBoxFor(m => m.Value, new { @class = "text large", required = "required" }) : Html.TextBoxFor(m => m.Value, new { @class = "text large" }))
<span class="hint">@T("A valid url, i.e. http://orchardproject.net, /content/file.pdf, ...")</span>
<span class="hint">@T("A valid url, i.e. http://orchardproject.net, /content/file.pdf, #some_id, ...")</span>
</div>
@if (settings.LinkTextMode == LinkTextMode.Optional || settings.LinkTextMode == LinkTextMode.Required) {
<div class="editor-label">

View File

@@ -54,7 +54,7 @@
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="Newtonsoft.Json" publicKeyToken="30ad4fe6b2a6aeed" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-12.0.0.0" newVersion="12.0.0.0" />
<bindingRedirect oldVersion="0.0.0.0-13.0.0.0" newVersion="13.0.0.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Web.Helpers" publicKeyToken="31bf3856ad364e35" />

View File

@@ -54,8 +54,8 @@
<Reference Include="Microsoft.Web.Infrastructure, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<HintPath>..\..\..\packages\Microsoft.Web.Infrastructure.1.0.0.0\lib\net40\Microsoft.Web.Infrastructure.dll</HintPath>
</Reference>
<Reference Include="Newtonsoft.Json, Version=12.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
<HintPath>..\..\..\packages\Newtonsoft.Json.12.0.3\lib\net45\Newtonsoft.Json.dll</HintPath>
<Reference Include="Newtonsoft.Json, Version=13.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
<HintPath>..\..\..\packages\Newtonsoft.Json.13.0.3\lib\net45\Newtonsoft.Json.dll</HintPath>
</Reference>
<Reference Include="System" />
<Reference Include="System.Data" />
@@ -172,4 +172,4 @@
</FlavorProperties>
</VisualStudio>
</ProjectExtensions>
</Project>
</Project>

View File

@@ -51,7 +51,7 @@
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="Newtonsoft.Json" publicKeyToken="30ad4fe6b2a6aeed" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-12.0.0.0" newVersion="12.0.0.0" />
<bindingRedirect oldVersion="0.0.0.0-13.0.0.0" newVersion="13.0.0.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Web.Helpers" publicKeyToken="31bf3856ad364e35" />

View File

@@ -4,5 +4,5 @@
<package id="Microsoft.AspNet.Razor" version="3.2.7" targetFramework="net48" />
<package id="Microsoft.AspNet.WebPages" version="3.2.7" targetFramework="net48" />
<package id="Microsoft.Web.Infrastructure" version="1.0.0.0" targetFramework="net48" />
<package id="Newtonsoft.Json" version="12.0.3" targetFramework="net48" />
</packages>
<package id="Newtonsoft.Json" version="13.0.3" targetFramework="net48" />
</packages>

View File

@@ -55,7 +55,7 @@
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="Newtonsoft.Json" publicKeyToken="30ad4fe6b2a6aeed" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-12.0.0.0" newVersion="12.0.0.0" />
<bindingRedirect oldVersion="0.0.0.0-13.0.0.0" newVersion="13.0.0.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Web.Helpers" publicKeyToken="31bf3856ad364e35" />

View File

@@ -54,7 +54,7 @@
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="Newtonsoft.Json" publicKeyToken="30ad4fe6b2a6aeed" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-12.0.0.0" newVersion="12.0.0.0" />
<bindingRedirect oldVersion="0.0.0.0-13.0.0.0" newVersion="13.0.0.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Web.Helpers" publicKeyToken="31bf3856ad364e35" />

View File

@@ -54,7 +54,7 @@
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="Newtonsoft.Json" publicKeyToken="30ad4fe6b2a6aeed" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-12.0.0.0" newVersion="12.0.0.0" />
<bindingRedirect oldVersion="0.0.0.0-13.0.0.0" newVersion="13.0.0.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Web.Helpers" publicKeyToken="31bf3856ad364e35" />

View File

@@ -60,8 +60,8 @@
<Reference Include="Microsoft.Web.Infrastructure, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<HintPath>..\..\..\packages\Microsoft.Web.Infrastructure.1.0.0.0\lib\net40\Microsoft.Web.Infrastructure.dll</HintPath>
</Reference>
<Reference Include="Newtonsoft.Json, Version=12.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
<HintPath>..\..\..\packages\Newtonsoft.Json.12.0.3\lib\net45\Newtonsoft.Json.dll</HintPath>
<Reference Include="Newtonsoft.Json, Version=13.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
<HintPath>..\..\..\packages\Newtonsoft.Json.13.0.3\lib\net45\Newtonsoft.Json.dll</HintPath>
</Reference>
<Reference Include="System" />
<Reference Include="System.ComponentModel.DataAnnotations" />
@@ -196,4 +196,4 @@
</FlavorProperties>
</VisualStudio>
</ProjectExtensions>
</Project>
</Project>

View File

@@ -55,7 +55,7 @@
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="Newtonsoft.Json" publicKeyToken="30ad4fe6b2a6aeed" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-12.0.0.0" newVersion="12.0.0.0" />
<bindingRedirect oldVersion="0.0.0.0-13.0.0.0" newVersion="13.0.0.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Web.Helpers" publicKeyToken="31bf3856ad364e35" />

View File

@@ -5,5 +5,5 @@
<package id="Microsoft.AspNet.WebPages" version="3.2.7" targetFramework="net48" />
<package id="Microsoft.CodeDom.Providers.DotNetCompilerPlatform" version="4.1.0" targetFramework="net48" />
<package id="Microsoft.Web.Infrastructure" version="1.0.0.0" targetFramework="net48" />
<package id="Newtonsoft.Json" version="12.0.3" targetFramework="net48" />
</packages>
<package id="Newtonsoft.Json" version="13.0.3" targetFramework="net48" />
</packages>

View File

@@ -58,8 +58,8 @@
<Reference Include="Microsoft.Web.Infrastructure, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<HintPath>..\..\..\packages\Microsoft.Web.Infrastructure.1.0.0.0\lib\net40\Microsoft.Web.Infrastructure.dll</HintPath>
</Reference>
<Reference Include="Newtonsoft.Json, Version=12.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
<HintPath>..\..\..\packages\Newtonsoft.Json.12.0.3\lib\net45\Newtonsoft.Json.dll</HintPath>
<Reference Include="Newtonsoft.Json, Version=13.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
<HintPath>..\..\..\packages\Newtonsoft.Json.13.0.3\lib\net45\Newtonsoft.Json.dll</HintPath>
</Reference>
<Reference Include="System" />
<Reference Include="System.Data" />

View File

@@ -43,7 +43,7 @@
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="Newtonsoft.Json" publicKeyToken="30ad4fe6b2a6aeed" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-12.0.0.0" newVersion="12.0.0.0" />
<bindingRedirect oldVersion="0.0.0.0-13.0.0.0" newVersion="13.0.0.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="Autofac" publicKeyToken="17863af14b0044da" culture="neutral" />

View File

@@ -7,6 +7,6 @@
<package id="Microsoft.AspNet.WebPages" version="3.2.7" targetFramework="net48" />
<package id="Microsoft.CodeDom.Providers.DotNetCompilerPlatform" version="4.1.0" targetFramework="net48" />
<package id="Microsoft.Web.Infrastructure" version="1.0.0.0" targetFramework="net48" />
<package id="Newtonsoft.Json" version="12.0.3" targetFramework="net48" />
<package id="Newtonsoft.Json" version="13.0.3" targetFramework="net48" />
<package id="YamlDotNet" version="11.1.1" targetFramework="net48" />
</packages>

View File

@@ -54,7 +54,7 @@
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="Newtonsoft.Json" publicKeyToken="30ad4fe6b2a6aeed" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-12.0.0.0" newVersion="12.0.0.0" />
<bindingRedirect oldVersion="0.0.0.0-13.0.0.0" newVersion="13.0.0.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Web.Helpers" publicKeyToken="31bf3856ad364e35" />

View File

@@ -0,0 +1,48 @@
using System;
using System.Web.Mvc;
using Orchard.Autoroute.Models;
using Orchard.CulturePicker.Services;
using Orchard.Environment.Extensions;
using Orchard.Localization.Providers;
using Orchard.Localization.Services;
using Orchard.Mvc.Extensions;
namespace Orchard.Localization.Controllers {
[OrchardFeature("Orchard.Localization.CultureSelector")]
public class UserCultureSelectorController : Controller {
private readonly ILocalizationService _localizationService;
private readonly ICultureStorageProvider _cultureStorageProvider;
public IOrchardServices Services { get; set; }
public UserCultureSelectorController(
IOrchardServices services,
ILocalizationService localizationService,
ICultureStorageProvider cultureStorageProvider) {
Services = services;
_localizationService = localizationService;
_cultureStorageProvider = cultureStorageProvider;
}
public ActionResult ChangeCulture(string culture) {
if (string.IsNullOrEmpty(culture)) {
throw new ArgumentNullException(culture);
}
var returnUrl = Utils.GetReturnUrl(Services.WorkContext.HttpContext.Request);
if (string.IsNullOrEmpty(returnUrl))
returnUrl = "";
if (_localizationService.TryGetRouteForUrl(returnUrl, out AutoroutePart currentRoutePart)
&& _localizationService.TryFindLocalizedRoute(currentRoutePart.ContentItem, culture, out AutoroutePart localizedRoutePart)) {
returnUrl = localizedRoutePart.Path;
}
_cultureStorageProvider.SetCulture(culture);
if (!returnUrl.StartsWith("~/")) {
returnUrl = "~/" + returnUrl;
}
return this.RedirectLocal(returnUrl);
}
}
}

View File

@@ -9,7 +9,7 @@ Features:
Orchard.Localization:
Description: Enables localization of content items.
Category: Content
Dependencies: Settings
Dependencies: Settings, Orchard.Autoroute
Name: Content Localization
Orchard.Localization.DateTimeFormat:
Description: Enables PO-based translation of date/time formats and names of days and months.
@@ -30,4 +30,4 @@ Features:
Description: Enables transliteration of the autoroute slug when creating a piece of content.
Category: Content
Name: URL Transliteration
Dependencies: Orchard.Localization.Transliteration, Orchard.Autoroute
Dependencies: Orchard.Localization.Transliteration

View File

@@ -89,10 +89,11 @@
</ItemGroup>
<ItemGroup>
<Compile Include="AdminMenu.cs" />
<Compile Include="Controllers\AdminCultureSelectorController.cs" />
<Compile Include="Extensions\Constants.cs" />
<Compile Include="Controllers\AdminController.cs" />
<Compile Include="Controllers\TransliterationAdminController.cs" />
<Compile Include="Controllers\AdminCultureSelectorController.cs" />
<Compile Include="Controllers\UserCultureSelectorController.cs" />
<Compile Include="Models\TransliterationSpecificationRecord.cs" />
<Compile Include="Providers\ContentLocalizationTokens.cs" />
<Compile Include="Selectors\ContentCultureSelector.cs" />
@@ -118,6 +119,7 @@
<Compile Include="Services\LocalizationService.cs" />
<Compile Include="Services\TransliterationService.cs" />
<Compile Include="Events\TransliterationSlugEventHandler.cs" />
<Compile Include="Services\Utils.cs" />
<Compile Include="ViewModels\ContentLocalizationsViewModel.cs" />
<Compile Include="ViewModels\EditLocalizationViewModel.cs" />
<Compile Include="ViewModels\CreateTransliterationViewModel.cs" />
@@ -196,6 +198,9 @@
<ItemGroup>
<None Include="packages.config" />
</ItemGroup>
<ItemGroup>
<Content Include="Views\UserCultureSelector.cshtml" />
</ItemGroup>
<PropertyGroup>
<VisualStudioVersion Condition="'$(VisualStudioVersion)' == ''">10.0</VisualStudioVersion>
<VSToolsPath Condition="'$(VSToolsPath)' == ''">$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)</VSToolsPath>
@@ -229,4 +234,4 @@
</FlavorProperties>
</VisualStudio>
</ProjectExtensions>
</Project>
</Project>

View File

@@ -1,4 +1,3 @@
using System;
using System.Web;
using Orchard.Environment.Configuration;
using Orchard.Environment.Extensions;
@@ -19,7 +18,8 @@ namespace Orchard.Localization.Selectors {
private const string AdminCookieName = "OrchardCurrentCulture-Admin";
private const int DefaultExpireTimeYear = 1;
public CookieCultureSelector(IHttpContextAccessor httpContextAccessor,
public CookieCultureSelector(
IHttpContextAccessor httpContextAccessor,
IClock clock,
ShellSettings shellSettings) {
_httpContextAccessor = httpContextAccessor;
@@ -36,11 +36,10 @@ namespace Orchard.Localization.Selectors {
var cookie = new HttpCookie(cookieName, culture) {
Expires = _clock.UtcNow.AddYears(DefaultExpireTimeYear),
Domain = httpContext.Request.IsLocal ? null : httpContext.Request.Url.Host
};
cookie.Domain = !httpContext.Request.IsLocal ? httpContext.Request.Url.Host : null;
if (!String.IsNullOrEmpty(_shellSettings.RequestUrlPrefix)) {
if (!string.IsNullOrEmpty(_shellSettings.RequestUrlPrefix)) {
cookie.Path = GetCookiePath(httpContext);
}
@@ -73,4 +72,4 @@ namespace Orchard.Localization.Selectors {
return cookiePath;
}
}
}
}

View File

@@ -1,4 +1,5 @@
using System.Collections.Generic;
using Orchard.Autoroute.Models;
using Orchard.ContentManagement;
using Orchard.Localization.Models;
@@ -10,5 +11,7 @@ namespace Orchard.Localization.Services {
void SetContentCulture(IContent content, string culture);
IEnumerable<LocalizationPart> GetLocalizations(IContent content);
IEnumerable<LocalizationPart> GetLocalizations(IContent content, VersionOptions versionOptions);
bool TryFindLocalizedRoute(ContentItem routableContent, string cultureName, out AutoroutePart localizedRoute);
bool TryGetRouteForUrl(string url, out AutoroutePart route);
}
}

View File

@@ -1,53 +1,59 @@
using System.Collections.Generic;
using System;
using System.Collections.Generic;
using System.Linq;
using Orchard.Autoroute.Models;
using Orchard.Autoroute.Services;
using Orchard.ContentManagement;
using Orchard.ContentManagement.Aspects;
using Orchard.Localization.Models;
namespace Orchard.Localization.Services {
public class LocalizationService : ILocalizationService {
private readonly IContentManager _contentManager;
private readonly ICultureManager _cultureManager;
private readonly IHomeAliasService _homeAliasService;
public LocalizationService(IContentManager contentManager, ICultureManager cultureManager) {
public LocalizationService(IContentManager contentManager, ICultureManager cultureManager, IHomeAliasService homeAliasService) {
_contentManager = contentManager;
_cultureManager = cultureManager;
_homeAliasService = homeAliasService;
}
/// <summary>
/// Warning: Returns only the first item of same culture localizations.
/// </summary>
public LocalizationPart GetLocalizedContentItem(IContent content, string culture) =>
GetLocalizedContentItem(content, culture, null);
public LocalizationPart GetLocalizedContentItem(IContent content, string culture) {
// Warning: Returns only the first of same culture localizations.
return GetLocalizedContentItem(content, culture, null);
}
/// <summary>
/// Warning: Returns only the first item of same culture localizations.
/// </summary>
public LocalizationPart GetLocalizedContentItem(IContent content, string culture, VersionOptions versionOptions) {
var cultureRecord = _cultureManager.GetCultureByName(culture);
if (cultureRecord == null) return null;
if (cultureRecord == null) {
return null;
}
var localized = content.As<LocalizationPart>();
if (localized == null) return null;
if (localized == null) {
return null;
}
var masterContentItemId = localized.HasTranslationGroup ? localized.Record.MasterContentItemId : localized.Id;
// Warning: Returns only the first of same culture localizations.
return _contentManager
.Query<LocalizationPart>(versionOptions, content.ContentItem.ContentType)
.Where<LocalizationPartRecord>(l =>
(l.Id == masterContentItemId || l.MasterContentItemId == masterContentItemId) &&
l.CultureId == cultureRecord.Id)
.Where<LocalizationPartRecord>(localization =>
(localization.Id == masterContentItemId || localization.MasterContentItemId == masterContentItemId)
&& localization.CultureId == cultureRecord.Id)
.Slice(1)
.FirstOrDefault();
}
public string GetContentCulture(IContent content) {
var localized = content.As<LocalizationPart>();
return localized?.Culture == null ?
_cultureManager.GetSiteCulture() :
localized.Culture.Culture;
}
public string GetContentCulture(IContent content) =>
content.As<LocalizationPart>()?.Culture?.Culture ?? _cultureManager.GetSiteCulture();
public void SetContentCulture(IContent content, string culture) {
var localized = content.As<LocalizationPart>();
@@ -57,11 +63,14 @@ namespace Orchard.Localization.Services {
localized.Culture = _cultureManager.GetCultureByName(culture);
}
public IEnumerable<LocalizationPart> GetLocalizations(IContent content) {
// Warning: May contain more than one localization of the same culture.
return GetLocalizations(content, null);
}
/// <summary>
/// Warning: May contain more than one localization of the same culture.
/// </summary>
public IEnumerable<LocalizationPart> GetLocalizations(IContent content) => GetLocalizations(content, null);
/// <summary>
/// Warning: May contain more than one localization of the same culture.
/// </summary>
public IEnumerable<LocalizationPart> GetLocalizations(IContent content, VersionOptions versionOptions) {
if (content.ContentItem.Id == 0) return Enumerable.Empty<LocalizationPart>();
@@ -76,16 +85,58 @@ namespace Orchard.Localization.Services {
if (localized.HasTranslationGroup) {
int masterContentItemId = localized.MasterContentItem.ContentItem.Id;
query = query.Where<LocalizationPartRecord>(l =>
l.Id != contentItemId && // Exclude the content
(l.Id == masterContentItemId || l.MasterContentItemId == masterContentItemId));
query = query.Where<LocalizationPartRecord>(localization =>
localization.Id != contentItemId && // Exclude the content
(localization.Id == masterContentItemId || localization.MasterContentItemId == masterContentItemId));
}
else {
query = query.Where<LocalizationPartRecord>(l => l.MasterContentItemId == contentItemId);
query = query.Where<LocalizationPartRecord>(localization => localization.MasterContentItemId == contentItemId);
}
// Warning: May contain more than one localization of the same culture.
return query.List().ToList();
}
public bool TryGetRouteForUrl(string url, out AutoroutePart route) {
route = _contentManager.Query<AutoroutePart, AutoroutePartRecord>()
.ForVersion(VersionOptions.Published)
.Where(r => r.DisplayAlias == url)
.List()
.FirstOrDefault();
route = route ?? _homeAliasService.GetHomePage(VersionOptions.Latest).As<AutoroutePart>();
return route != null;
}
public bool TryFindLocalizedRoute(ContentItem routableContent, string cultureName, out AutoroutePart localizedRoute) {
if (!routableContent.Parts.Any(p => p.Is<ILocalizableAspect>())) {
localizedRoute = null;
return false;
}
IEnumerable<LocalizationPart> localizations = GetLocalizations(routableContent, VersionOptions.Published);
ILocalizableAspect localizationPart = null, siteCultureLocalizationPart = null;
foreach (var localization in localizations) {
if (localization.Culture.Culture.Equals(cultureName, StringComparison.InvariantCultureIgnoreCase)) {
localizationPart = localization;
break;
}
if (localization.Culture == null && siteCultureLocalizationPart == null) {
siteCultureLocalizationPart = localization;
}
}
if (localizationPart == null) {
localizationPart = siteCultureLocalizationPart;
}
localizedRoute = localizationPart?.As<AutoroutePart>();
return localizedRoute != null;
}
}
}
}

View File

@@ -0,0 +1,31 @@
using System.Web;
namespace Orchard.CulturePicker.Services {
public static class Utils {
public static string GetReturnUrl(HttpRequestBase request) {
if (request.UrlReferrer == null) {
return "";
}
string localUrl = GetAppRelativePath(request.UrlReferrer.AbsolutePath, request);
return HttpUtility.UrlDecode(localUrl);
}
public static string GetAppRelativePath(string logicalPath, HttpRequestBase request) {
if (request.ApplicationPath == null) {
return "";
}
logicalPath = logicalPath.ToLower();
string appPath = request.ApplicationPath.ToLower();
if (appPath != "/") {
appPath += "/";
}
else {
return logicalPath.Substring(1);
}
return logicalPath.Replace(appPath, "");
}
}
}

View File

@@ -0,0 +1,34 @@
@using Orchard.Localization.Services
@{
var currentCulture = WorkContext.CurrentCulture;
var supportedCultures = WorkContext.Resolve<ICultureManager>().ListCultures().ToList();
}
<div id="culture-selection">
<ul>
@foreach (var supportedCulture in supportedCultures)
{
var url = Url.Action(
"ChangeCulture",
"UserCultureSelector",
new
{
area = "Orchard.Localization",
culture = supportedCulture,
returnUrl = Html.ViewContext.HttpContext.Request.RawUrl
});
<li>
@if (supportedCulture.Equals(currentCulture))
{
<a href="@url">@T("{0} (current)", supportedCulture)</a>
}
else
{
<a href="@url">@supportedCulture</a>
}
</li>
}
</ul>
</div>

View File

@@ -54,7 +54,7 @@
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="Newtonsoft.Json" publicKeyToken="30ad4fe6b2a6aeed" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-12.0.0.0" newVersion="12.0.0.0" />
<bindingRedirect oldVersion="0.0.0.0-13.0.0.0" newVersion="13.0.0.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Web.Helpers" publicKeyToken="31bf3856ad364e35" />

View File

@@ -52,9 +52,6 @@
<Prefer32Bit>false</Prefer32Bit>
</PropertyGroup>
<ItemGroup>
<Reference Include="DotNetZip, Version=1.12.0.0, Culture=neutral, PublicKeyToken=6583c7c814667745, processorArchitecture=MSIL">
<HintPath>..\..\..\packages\DotNetZip.1.12.0\lib\net20\DotNetZip.dll</HintPath>
</Reference>
<Reference Include="Microsoft.CodeDom.Providers.DotNetCompilerPlatform, Version=4.1.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<HintPath>..\..\..\packages\Microsoft.CodeDom.Providers.DotNetCompilerPlatform.4.1.0\lib\net472\Microsoft.CodeDom.Providers.DotNetCompilerPlatform.dll</HintPath>
</Reference>
@@ -64,6 +61,7 @@
<Reference Include="System" />
<Reference Include="System.ComponentModel.DataAnnotations" />
<Reference Include="System.Data.DataSetExtensions" />
<Reference Include="System.IO.Compression" />
<Reference Include="System.Web" />
<Reference Include="System.Web.ApplicationServices" />
<Reference Include="System.Web.DynamicData" />
@@ -204,4 +202,4 @@
</FlavorProperties>
</VisualStudio>
</ProjectExtensions>
</Project>
</Project>

View File

@@ -1,9 +1,9 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.IO.Compression;
using System.Linq;
using System.Web;
using Ionic.Zip;
using Orchard.ContentManagement;
using Orchard.FileSystems.Media;
using Orchard.Localization;
@@ -194,7 +194,7 @@ namespace Orchard.Media.Services {
/// <param name="bytes">The array of bytes with the file's contents.</param>
/// <param name="extractZip">Boolean value indicating weather zip files should be extracted.</param>
/// <returns>The path to the uploaded file.</returns>
public string UploadMediaFile(string folderPath, string fileName, byte [] bytes, bool extractZip) {
public string UploadMediaFile(string folderPath, string fileName, byte[] bytes, bool extractZip) {
Argument.ThrowIfNullOrEmpty(folderPath, "folderPath");
Argument.ThrowIfNullOrEmpty(fileName, "fileName");
Argument.ThrowIfNull(bytes, "bytes");
@@ -274,16 +274,16 @@ namespace Orchard.Media.Services {
// must be in the whitelist
MediaSettingsPart mediaSettings = currentSite.As<MediaSettingsPart>();
if (mediaSettings == null) {
return false;
}
if(String.IsNullOrWhiteSpace(mediaSettings.UploadAllowedFileTypeWhitelist)) {
return true;
}
}
if(!mediaSettings.UploadAllowedFileTypeWhitelist.ToUpperInvariant().Split(' ').Contains(extension.ToUpperInvariant())) {
if (String.IsNullOrWhiteSpace(mediaSettings.UploadAllowedFileTypeWhitelist)) {
return true;
}
if (!mediaSettings.UploadAllowedFileTypeWhitelist.ToUpperInvariant().Split(' ').Contains(extension.ToUpperInvariant())) {
return false;
}
}
@@ -305,28 +305,26 @@ namespace Orchard.Media.Services {
Argument.ThrowIfNullOrEmpty(targetFolder, "targetFolder");
Argument.ThrowIfNull(zipStream, "zipStream");
using (var fileInflater = ZipFile.Read(zipStream)) {
using (var fileInflater = new ZipArchive(zipStream)) {
// We want to preserve whatever directory structure the zip file contained instead
// of flattening it.
// The API below doesn't necessarily return the entries in the zip file in any order.
// That means the files in subdirectories can be returned as entries from the stream
// before the directories that contain them, so we create directories as soon as first
// file below their path is encountered.
foreach (ZipEntry entry in fileInflater) {
foreach (var entry in fileInflater.Entries) {
if (entry == null) {
continue;
}
if (!entry.IsDirectory && !string.IsNullOrEmpty(entry.FileName)) {
if (!string.IsNullOrEmpty(entry.Name)) {
// skip disallowed files
if (FileAllowed(entry.FileName, false)) {
string fullFileName = _storageProvider.Combine(targetFolder, entry.FileName);
if (FileAllowed(entry.Name, false)) {
string fullFileName = _storageProvider.Combine(targetFolder, entry.FullName);
using (var stream = entry.OpenReader()) {
using (var stream = entry.Open()) {
// the call will return false if the file already exists
if (!_storageProvider.TrySaveStream(fullFileName, stream)) {
// try to delete the file and save again
try {
_storageProvider.DeleteFile(fullFileName);

View File

@@ -54,7 +54,7 @@
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="Newtonsoft.Json" publicKeyToken="30ad4fe6b2a6aeed" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-12.0.0.0" newVersion="12.0.0.0" />
<bindingRedirect oldVersion="0.0.0.0-13.0.0.0" newVersion="13.0.0.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Web.Helpers" publicKeyToken="31bf3856ad364e35" />

View File

@@ -1,6 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="DotNetZip" version="1.12.0" targetFramework="net48" />
<package id="Microsoft.AspNet.Mvc" version="5.2.7" targetFramework="net48" />
<package id="Microsoft.AspNet.Razor" version="3.2.7" targetFramework="net48" />
<package id="Microsoft.AspNet.WebPages" version="3.2.7" targetFramework="net48" />

View File

@@ -3,15 +3,14 @@ using System.Collections.Generic;
using System.IO;
using System.Web.Mvc;
using Orchard.ContentManagement;
using Orchard.FileSystems.Media;
using Orchard.Localization;
using Orchard.Logging;
using Orchard.MediaLibrary.Models;
using Orchard.MediaLibrary.Services;
using Orchard.MediaLibrary.ViewModels;
using Orchard.Themes;
using Orchard.UI.Admin;
using Orchard.MediaLibrary.Models;
using Orchard.Localization;
using System.Linq;
using Orchard.FileSystems.Media;
using Orchard.Logging;
namespace Orchard.MediaLibrary.Controllers {
[Admin, Themed(false)]
@@ -107,10 +106,16 @@ namespace Orchard.MediaLibrary.Controllers {
url = mediaPart.FileName,
});
}
catch (Exception ex) {
Logger.Error(ex, "Unexpected exception when uploading a media.");
catch (InvalidNameCharacterException) {
statuses.Add(new {
error = T(ex.Message).Text,
error = T("The file name contains invalid character(s)").Text,
progress = 1.0,
});
}
catch (Exception ex) {
Logger.Error(ex, T("Unexpected exception when uploading a media.").Text);
statuses.Add(new {
error = ex.Message,
progress = 1.0,
});
}
@@ -130,7 +135,7 @@ namespace Orchard.MediaLibrary.Controllers {
return HttpNotFound();
// Check permission
if (!(_mediaLibraryService.CheckMediaFolderPermission(Permissions.EditMediaContent, replaceMedia.FolderPath) && _mediaLibraryService.CheckMediaFolderPermission(Permissions.ImportMediaContent, replaceMedia.FolderPath))
if (!(_mediaLibraryService.CheckMediaFolderPermission(Permissions.EditMediaContent, replaceMedia.FolderPath) && _mediaLibraryService.CheckMediaFolderPermission(Permissions.ImportMediaContent, replaceMedia.FolderPath))
&& !_mediaLibraryService.CanManageMediaFolder(replaceMedia.FolderPath)) {
return new HttpUnauthorizedResult();
}
@@ -138,7 +143,7 @@ namespace Orchard.MediaLibrary.Controllers {
var statuses = new List<object>();
var settings = Services.WorkContext.CurrentSite.As<MediaLibrarySettingsPart>();
// Loop through each file in the request
for (int i = 0; i < HttpContext.Request.Files.Count; i++) {
// Pointer to file
@@ -146,7 +151,8 @@ namespace Orchard.MediaLibrary.Controllers {
var filename = Path.GetFileName(file.FileName);
// if the file has been pasted, provide a default name
if (file.ContentType.Equals("image/png", StringComparison.InvariantCultureIgnoreCase) && !filename.EndsWith(".png", StringComparison.InvariantCultureIgnoreCase)) {
if (file.ContentType.Equals("image/png", StringComparison.InvariantCultureIgnoreCase)
&& !filename.EndsWith(".png", StringComparison.InvariantCultureIgnoreCase)) {
filename = "clipboard.png";
}
@@ -184,7 +190,7 @@ namespace Orchard.MediaLibrary.Controllers {
});
}
catch (Exception ex) {
Logger.Error(ex, "Unexpected exception when uploading a media.");
Logger.Error(ex, T("Unexpected exception when uploading a media.").Text);
statuses.Add(new {
error = T(ex.Message).Text,

View File

@@ -1,9 +1,9 @@
using System;
using System.IO;
using System.Linq;
using System.Text.RegularExpressions;
using System.Web.Mvc;
using Orchard.ContentManagement;
using Orchard.FileSystems.Media;
using Orchard.Localization;
using Orchard.Logging;
using Orchard.MediaLibrary.Models;
@@ -36,7 +36,7 @@ namespace Orchard.MediaLibrary.Controllers {
public ActionResult Create(string folderPath) {
if (!(_mediaLibraryService.CheckMediaFolderPermission(Permissions.ImportMediaContent, folderPath) || _mediaLibraryService.CheckMediaFolderPermission(Permissions.EditMediaContent, folderPath))) {
Services.Notifier.Error(T("Couldn't create media folder"));
return RedirectToAction("Index", "Admin", new { area = "Orchard.MediaLibrary", folderPath = folderPath });
return RedirectToAction("Index", "Admin", new { area = "Orchard.MediaLibrary", folderPath });
}
// If the user is trying to access a folder above his boundaries, redirect him to his home folder
@@ -68,28 +68,32 @@ namespace Orchard.MediaLibrary.Controllers {
return new HttpUnauthorizedResult();
}
var failed = false;
try {
bool valid = String.IsNullOrWhiteSpace(viewModel.Name) || Regex.IsMatch(viewModel.Name, @"^[^:?#\[\]@!$&'()*+,.;=\s\""\<\>\\\|%]+$");
if (!valid) {
throw new ArgumentException(T("Folder contains invalid characters").ToString());
}
else {
_mediaLibraryService.CreateFolder(viewModel.FolderPath, viewModel.Name);
Services.Notifier.Information(T("Media folder created"));
}
_mediaLibraryService.CreateFolder(viewModel.FolderPath, viewModel.Name);
Services.Notifier.Information(T("Media folder created"));
}
catch (InvalidNameCharacterException) {
Services.Notifier.Error(T("The folder name contains invalid character(s)."));
failed = true;
}
catch (ArgumentException argumentException) {
Services.Notifier.Error(T("Creating Folder failed: {0}", argumentException.Message));
failed = true;
}
if (failed) {
Services.TransactionManager.Cancel();
return View(viewModel);
}
return RedirectToAction("Index", "Admin", new { area = "Orchard.MediaLibrary" });
}
public ActionResult Edit(string folderPath) {
if (!(_mediaLibraryService.CheckMediaFolderPermission(Permissions.ImportMediaContent, folderPath) || _mediaLibraryService.CheckMediaFolderPermission(Permissions.EditMediaContent, folderPath))) {
Services.Notifier.Error(T("Couldn't edit media folder"));
return RedirectToAction("Index", "Admin", new { area = "Orchard.MediaLibrary", folderPath = folderPath });
return RedirectToAction("Index", "Admin", new { area = "Orchard.MediaLibrary", folderPath });
}
if (!_mediaLibraryService.CanManageMediaFolder(folderPath)) {
@@ -125,7 +129,7 @@ namespace Orchard.MediaLibrary.Controllers {
var viewModel = new MediaManagerFolderEditViewModel();
UpdateModel(viewModel);
if (!(_mediaLibraryService.CheckMediaFolderPermission(Permissions.ImportMediaContent, viewModel.FolderPath)
if (!(_mediaLibraryService.CheckMediaFolderPermission(Permissions.ImportMediaContent, viewModel.FolderPath)
|| _mediaLibraryService.CheckMediaFolderPermission(Permissions.EditMediaContent, viewModel.FolderPath))) {
return new HttpUnauthorizedResult();
}
@@ -136,14 +140,12 @@ namespace Orchard.MediaLibrary.Controllers {
}
try {
bool valid = String.IsNullOrWhiteSpace(viewModel.Name) || Regex.IsMatch(viewModel.Name, @"^[^:?#\[\]@!$&'()*+,.;=\s\""\<\>\\\|%]+$");
if (!valid) {
throw new ArgumentException(T("Folder contains invalid characters").ToString());
}
else {
_mediaLibraryService.RenameFolder(viewModel.FolderPath, viewModel.Name);
Services.Notifier.Information(T("Media folder renamed"));
}
_mediaLibraryService.RenameFolder(viewModel.FolderPath, viewModel.Name);
Services.Notifier.Information(T("Media folder renamed"));
}
catch (InvalidNameCharacterException) {
Services.Notifier.Error(T("The folder name contains invalid character(s)."));
return View(viewModel);
}
catch (Exception exception) {
Services.Notifier.Error(T("Editing Folder failed: {0}", exception.Message));
@@ -198,7 +200,7 @@ namespace Orchard.MediaLibrary.Controllers {
// don't try to rename the file if there is no associated media file
if (!string.IsNullOrEmpty(media.FileName)) {
// check permission on source folder
if(!_mediaLibraryService.CheckMediaFolderPermission(Permissions.DeleteMediaContent, media.FolderPath)) {
if (!_mediaLibraryService.CheckMediaFolderPermission(Permissions.DeleteMediaContent, media.FolderPath)) {
return new HttpUnauthorizedResult();
}

View File

@@ -1,14 +1,14 @@
using System;
using Orchard.ContentManagement;
using Orchard.ContentManagement.Drivers;
using Orchard.FileSystems.Media;
using Orchard.Localization;
using Orchard.MediaLibrary.Models;
using Orchard.MediaLibrary.Services;
using Orchard.Security;
using Orchard.UI.Notify;
namespace Orchard.MediaLibrary.MediaFileName
{
namespace Orchard.MediaLibrary.MediaFileName {
public class MediaFileNameDriver : ContentPartDriver<MediaPart> {
private readonly IAuthenticationService _authenticationService;
private readonly IAuthorizationService _authorizationService;
@@ -58,6 +58,8 @@ namespace Orchard.MediaLibrary.MediaFileName
var priorFileName = model.FileName;
if (updater.TryUpdateModel(model, Prefix, null, null)) {
if (model.FileName != null && !model.FileName.Equals(priorFileName, StringComparison.OrdinalIgnoreCase)) {
var fieldName = "MediaFileNameEditorSettings.FileName";
try {
_mediaLibraryService.RenameFile(part.FolderPath, priorFileName, model.FileName);
part.FileName = model.FileName;
@@ -65,14 +67,18 @@ namespace Orchard.MediaLibrary.MediaFileName
_notifier.Add(NotifyType.Information, T("File '{0}' was renamed to '{1}'", priorFileName, model.FileName));
}
catch (OrchardException) {
updater.AddModelError("MediaFileNameEditorSettings.FileName", T("Unable to rename file. Invalid Windows file path."));
updater.AddModelError(fieldName, T("Unable to rename file. Invalid Windows file path."));
}
catch (Exception) {
updater.AddModelError("MediaFileNameEditorSettings.FileName", T("Unable to rename file"));
catch (InvalidNameCharacterException) {
updater.AddModelError(fieldName, T("The file name contains invalid character(s)."));
}
catch (Exception exception) {
updater.AddModelError(fieldName, T("Unable to rename file: {0}", exception.Message));
}
}
}
}
return model;
});
}

View File

@@ -58,8 +58,8 @@
<Reference Include="Microsoft.Web.Infrastructure, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<HintPath>..\..\..\packages\Microsoft.Web.Infrastructure.1.0.0.0\lib\net40\Microsoft.Web.Infrastructure.dll</HintPath>
</Reference>
<Reference Include="Newtonsoft.Json, Version=12.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
<HintPath>..\..\..\packages\Newtonsoft.Json.12.0.3\lib\net45\Newtonsoft.Json.dll</HintPath>
<Reference Include="Newtonsoft.Json, Version=13.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
<HintPath>..\..\..\packages\Newtonsoft.Json.13.0.3\lib\net45\Newtonsoft.Json.dll</HintPath>
</Reference>
<Reference Include="System" />
<Reference Include="System.Data" />
@@ -451,4 +451,4 @@
</FlavorProperties>
</VisualStudio>
</ProjectExtensions>
</Project>
</Project>

View File

@@ -6,13 +6,13 @@ using System.Web;
using Orchard.ContentManagement;
using Orchard.ContentManagement.MetaData.Models;
using Orchard.Core.Common.Models;
using Orchard.Core.Title.Models;
using Orchard.FileSystems.Media;
using Orchard.Localization;
using Orchard.MediaLibrary.Factories;
using Orchard.MediaLibrary.Models;
using Orchard.Core.Title.Models;
using Orchard.Validation;
using Orchard.MediaLibrary.Providers;
using Orchard.Validation;
namespace Orchard.MediaLibrary.Services {
public class MediaLibraryService : IMediaLibraryService {
@@ -21,7 +21,6 @@ namespace Orchard.MediaLibrary.Services {
private readonly IStorageProvider _storageProvider;
private readonly IEnumerable<IMediaFactorySelector> _mediaFactorySelectors;
private readonly IMediaFolderProvider _mediaFolderProvider;
private static char[] HttpUnallowed = new char[] { '<', '>', '*', '%', '&', ':', '\\', '?', '#' };
public MediaLibraryService(
IOrchardServices orchardServices,
@@ -145,12 +144,6 @@ namespace Orchard.MediaLibrary.Services {
}
public string GetUniqueFilename(string folderPath, string filename) {
// remove any char which is unallowed in an HTTP request
foreach (var unallowedChar in HttpUnallowed) {
filename = filename.Replace(unallowedChar.ToString(), "");
}
// compute a unique filename
var uniqueFilename = filename;
var index = 1;
@@ -177,9 +170,9 @@ namespace Orchard.MediaLibrary.Services {
var mediaFile = BuildMediaFile(relativePath, storageFile);
using (var stream = storageFile.OpenRead()) {
var mediaFactory = GetMediaFactory(stream, mimeType, contentType);
if (mediaFactory == null)
throw new Exception(T("No media factory available to handle this resource.").Text);
var mediaFactory = GetMediaFactory(stream, mimeType, contentType)
?? throw new Exception(T("No media factory available to handle this resource.").Text);
var mediaPart = mediaFactory.CreateMedia(stream, mediaFile.Name, mimeType, contentType);
if (mediaPart != null) {
mediaPart.FolderPath = relativePath;
@@ -256,7 +249,7 @@ namespace Orchard.MediaLibrary.Services {
if (_orchardServices.Authorizer.Authorize(Permissions.ManageMediaContent)) {
return true;
}
if (_orchardServices.WorkContext.CurrentUser==null)
if (_orchardServices.WorkContext.CurrentUser == null)
return _orchardServices.Authorizer.Authorize(permission);
// determines the folder type: public, user own folder (my), folder of another user (private)
var rootedFolderPath = this.GetRootedFolderPath(folderPath) ?? "";
@@ -268,7 +261,7 @@ namespace Orchard.MediaLibrary.Services {
isMyfolder = true;
}
if(isMyfolder) {
if (isMyfolder) {
return _orchardServices.Authorizer.Authorize(Permissions.ManageOwnMedia);
}
else { // other

View File

@@ -55,7 +55,7 @@
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="Newtonsoft.Json" publicKeyToken="30ad4fe6b2a6aeed" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-12.0.0.0" newVersion="12.0.0.0" />
<bindingRedirect oldVersion="0.0.0.0-13.0.0.0" newVersion="13.0.0.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Web.Helpers" publicKeyToken="31bf3856ad364e35" />

View File

@@ -5,5 +5,5 @@
<package id="Microsoft.AspNet.WebPages" version="3.2.7" targetFramework="net48" />
<package id="Microsoft.CodeDom.Providers.DotNetCompilerPlatform" version="4.1.0" targetFramework="net48" />
<package id="Microsoft.Web.Infrastructure" version="1.0.0.0" targetFramework="net48" />
<package id="Newtonsoft.Json" version="12.0.3" targetFramework="net48" />
</packages>
<package id="Newtonsoft.Json" version="13.0.3" targetFramework="net48" />
</packages>

Some files were not shown because too many files have changed in this diff Show More