mirror of https://github.com/Radarr/Radarr
Added Growl (Not yet visible on the GUI).
This commit is contained in:
parent
dd7dcf4db8
commit
3fe1e80ccb
|
@ -80,6 +80,7 @@
|
||||||
<Compile Include="JobTests\BacklogSearchJobTest.cs" />
|
<Compile Include="JobTests\BacklogSearchJobTest.cs" />
|
||||||
<Compile Include="JobTests\BannerDownloadJobTest.cs" />
|
<Compile Include="JobTests\BannerDownloadJobTest.cs" />
|
||||||
<Compile Include="ProviderTests\ConfigFileProviderTest.cs" />
|
<Compile Include="ProviderTests\ConfigFileProviderTest.cs" />
|
||||||
|
<Compile Include="ProviderTests\GrowlProviderTest.cs" />
|
||||||
<Compile Include="ProviderTests\DiskProviderTests\ExtractArchiveFixture.cs" />
|
<Compile Include="ProviderTests\DiskProviderTests\ExtractArchiveFixture.cs" />
|
||||||
<Compile Include="ProviderTests\PostDownloadProviderTests\PostDownloadProviderFixture.cs" />
|
<Compile Include="ProviderTests\PostDownloadProviderTests\PostDownloadProviderFixture.cs" />
|
||||||
<Compile Include="JobTests\SearchJobTest.cs" />
|
<Compile Include="JobTests\SearchJobTest.cs" />
|
||||||
|
|
|
@ -0,0 +1,73 @@
|
||||||
|
using System;
|
||||||
|
using AutoMoq;
|
||||||
|
using FizzWare.NBuilder;
|
||||||
|
using FluentAssertions;
|
||||||
|
using Moq;
|
||||||
|
using NUnit.Framework;
|
||||||
|
using NzbDrone.Core.Model;
|
||||||
|
using NzbDrone.Core.Providers;
|
||||||
|
using NzbDrone.Core.Repository;
|
||||||
|
using NzbDrone.Core.Repository.Quality;
|
||||||
|
using NzbDrone.Core.Test.Framework;
|
||||||
|
|
||||||
|
// ReSharper disable InconsistentNaming
|
||||||
|
|
||||||
|
namespace NzbDrone.Core.Test.ProviderTests
|
||||||
|
{
|
||||||
|
[Explicit]
|
||||||
|
[TestFixture]
|
||||||
|
public class GrowlProviderTest : TestBase
|
||||||
|
{
|
||||||
|
[Test]
|
||||||
|
public void Register_should_add_new_application_to_local_growl_instance()
|
||||||
|
{
|
||||||
|
//Setup
|
||||||
|
var mocker = new AutoMoqer(MockBehavior.Strict);
|
||||||
|
|
||||||
|
//Act
|
||||||
|
mocker.Resolve<GrowlProvider>().Register("localhost", 23053, "");
|
||||||
|
|
||||||
|
//Assert
|
||||||
|
mocker.VerifyAllMocks();
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void TestNotification_should_send_a_message_to_local_growl_instance()
|
||||||
|
{
|
||||||
|
//Setup
|
||||||
|
var mocker = new AutoMoqer(MockBehavior.Strict);
|
||||||
|
|
||||||
|
//Act
|
||||||
|
mocker.Resolve<GrowlProvider>().TestNotification("localhost", 23053, "");
|
||||||
|
|
||||||
|
//Assert
|
||||||
|
mocker.VerifyAllMocks();
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void OnGrab_should_send_a_message_to_local_growl_instance()
|
||||||
|
{
|
||||||
|
//Setup
|
||||||
|
var mocker = new AutoMoqer(MockBehavior.Strict);
|
||||||
|
|
||||||
|
//Act
|
||||||
|
mocker.Resolve<GrowlProvider>().SendNotification("Episode Grabbed", "Series Title - 1x05 - Episode Title", "GRAB", "localhost", 23053, "");
|
||||||
|
|
||||||
|
//Assert
|
||||||
|
mocker.VerifyAllMocks();
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void OnDownload_should_send_a_message_to_local_growl_instance()
|
||||||
|
{
|
||||||
|
//Setup
|
||||||
|
var mocker = new AutoMoqer(MockBehavior.Strict);
|
||||||
|
|
||||||
|
//Act
|
||||||
|
mocker.Resolve<GrowlProvider>().SendNotification("Episode Downloaded", "Series Title - 1x05 - Episode Title", "DOWNLOAD", "localhost", 23053, "");
|
||||||
|
|
||||||
|
//Assert
|
||||||
|
mocker.VerifyAllMocks();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -35,7 +35,6 @@ namespace NzbDrone.Core
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public static void InitializeApp()
|
public static void InitializeApp()
|
||||||
{
|
{
|
||||||
BindKernel();
|
BindKernel();
|
||||||
|
@ -107,6 +106,7 @@ namespace NzbDrone.Core
|
||||||
_kernel.Bind<ExternalNotificationBase>().To<Xbmc>();
|
_kernel.Bind<ExternalNotificationBase>().To<Xbmc>();
|
||||||
_kernel.Bind<ExternalNotificationBase>().To<Smtp>();
|
_kernel.Bind<ExternalNotificationBase>().To<Smtp>();
|
||||||
_kernel.Bind<ExternalNotificationBase>().To<Twitter>();
|
_kernel.Bind<ExternalNotificationBase>().To<Twitter>();
|
||||||
|
_kernel.Bind<ExternalNotificationBase>().To<Growl>();
|
||||||
|
|
||||||
var notifiers = _kernel.GetAll<ExternalNotificationBase>();
|
var notifiers = _kernel.GetAll<ExternalNotificationBase>();
|
||||||
_kernel.Get<ExternalNotificationProvider>().InitializeNotifiers(notifiers.ToList());
|
_kernel.Get<ExternalNotificationProvider>().InitializeNotifiers(notifiers.ToList());
|
||||||
|
|
|
@ -125,6 +125,12 @@
|
||||||
<SpecificVersion>False</SpecificVersion>
|
<SpecificVersion>False</SpecificVersion>
|
||||||
<HintPath>..\Libraries\Exceptioneer.WindowsFormsClient.dll</HintPath>
|
<HintPath>..\Libraries\Exceptioneer.WindowsFormsClient.dll</HintPath>
|
||||||
</Reference>
|
</Reference>
|
||||||
|
<Reference Include="Growl.Connector">
|
||||||
|
<HintPath>..\packages\Growl.0.6\lib\Growl.Connector.dll</HintPath>
|
||||||
|
</Reference>
|
||||||
|
<Reference Include="Growl.CoreLibrary">
|
||||||
|
<HintPath>..\packages\Growl.0.6\lib\Growl.CoreLibrary.dll</HintPath>
|
||||||
|
</Reference>
|
||||||
<Reference Include="Ionic.Zip">
|
<Reference Include="Ionic.Zip">
|
||||||
<HintPath>..\packages\DotNetZip.1.9.1.8\lib\net20\Ionic.Zip.dll</HintPath>
|
<HintPath>..\packages\DotNetZip.1.9.1.8\lib\net20\Ionic.Zip.dll</HintPath>
|
||||||
</Reference>
|
</Reference>
|
||||||
|
@ -221,8 +227,10 @@
|
||||||
<Compile Include="Providers\Converting\HandbrakeProvider.cs" />
|
<Compile Include="Providers\Converting\HandbrakeProvider.cs" />
|
||||||
<Compile Include="Providers\Core\ConfigFileProvider.cs" />
|
<Compile Include="Providers\Core\ConfigFileProvider.cs" />
|
||||||
<Compile Include="Providers\Core\UdpProvider.cs" />
|
<Compile Include="Providers\Core\UdpProvider.cs" />
|
||||||
|
<Compile Include="Providers\ExternalNotification\Growl.cs" />
|
||||||
<Compile Include="Providers\ExternalNotification\Twitter.cs" />
|
<Compile Include="Providers\ExternalNotification\Twitter.cs" />
|
||||||
<Compile Include="Providers\ExternalNotification\Smtp.cs" />
|
<Compile Include="Providers\ExternalNotification\Smtp.cs" />
|
||||||
|
<Compile Include="Providers\GrowlProvider.cs" />
|
||||||
<Compile Include="Providers\Jobs\BacklogSearchJob.cs" />
|
<Compile Include="Providers\Jobs\BacklogSearchJob.cs" />
|
||||||
<Compile Include="Providers\Jobs\BannerDownloadJob.cs" />
|
<Compile Include="Providers\Jobs\BannerDownloadJob.cs" />
|
||||||
<Compile Include="Providers\Jobs\ConvertEpisodeJob.cs" />
|
<Compile Include="Providers\Jobs\ConvertEpisodeJob.cs" />
|
||||||
|
@ -352,6 +360,10 @@
|
||||||
<Name>NzbDrone.Common</Name>
|
<Name>NzbDrone.Common</Name>
|
||||||
</ProjectReference>
|
</ProjectReference>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<Content Include="NzbDrone.ico" />
|
||||||
|
<Content Include="license.txt" />
|
||||||
|
</ItemGroup>
|
||||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<PostBuildEvent>
|
<PostBuildEvent>
|
||||||
|
|
Binary file not shown.
After Width: | Height: | Size: 76 KiB |
|
@ -338,6 +338,32 @@ namespace NzbDrone.Core.Providers.Core
|
||||||
set { SetValue("TwitterAccessTokenSecret", value); }
|
set { SetValue("TwitterAccessTokenSecret", value); }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public virtual Boolean GrowlNotifyOnGrab
|
||||||
|
{
|
||||||
|
get { return GetValueBoolean("GrowlNotifyOnGrab"); }
|
||||||
|
|
||||||
|
set { SetValue("GrowlNotifyOnGrab", value); }
|
||||||
|
}
|
||||||
|
|
||||||
|
public virtual Boolean GrowlNotifyOnDownload
|
||||||
|
{
|
||||||
|
get { return GetValueBoolean("GrowlNotifyOnDownload"); }
|
||||||
|
|
||||||
|
set { SetValue("GrowlNotifyOnDownload", value); }
|
||||||
|
}
|
||||||
|
|
||||||
|
public virtual string GrowlHost
|
||||||
|
{
|
||||||
|
get { return GetValue("GrowlHost", String.Empty); }
|
||||||
|
set { SetValue("GrowlHost", value); }
|
||||||
|
}
|
||||||
|
|
||||||
|
public virtual string GrowlPassword
|
||||||
|
{
|
||||||
|
get { return GetValue("GrowlPassword", String.Empty); }
|
||||||
|
set { SetValue("GrowlPassword", value); }
|
||||||
|
}
|
||||||
|
|
||||||
private string GetValue(string key)
|
private string GetValue(string key)
|
||||||
{
|
{
|
||||||
return GetValue(key, String.Empty);
|
return GetValue(key, String.Empty);
|
||||||
|
|
|
@ -0,0 +1,78 @@
|
||||||
|
using System;
|
||||||
|
using NLog;
|
||||||
|
using NzbDrone.Core.Providers.Core;
|
||||||
|
using NzbDrone.Core.Repository;
|
||||||
|
|
||||||
|
namespace NzbDrone.Core.Providers.ExternalNotification
|
||||||
|
{
|
||||||
|
public class Growl : ExternalNotificationBase
|
||||||
|
{
|
||||||
|
private readonly GrowlProvider _growlProvider;
|
||||||
|
|
||||||
|
private readonly Logger Logger = LogManager.GetCurrentClassLogger();
|
||||||
|
|
||||||
|
public Growl(ConfigProvider configProvider, GrowlProvider growlProvider)
|
||||||
|
: base(configProvider)
|
||||||
|
{
|
||||||
|
_growlProvider = growlProvider;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override string Name
|
||||||
|
{
|
||||||
|
get { return "Growl"; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void OnGrab(string message)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if(_configProvider.GrowlNotifyOnGrab)
|
||||||
|
{
|
||||||
|
_logger.Trace("Sending Notification to Growl");
|
||||||
|
const string title = "Episode Grabbed";
|
||||||
|
|
||||||
|
var growlHost = _configProvider.GrowlHost.Split(':');
|
||||||
|
var host = growlHost[0];
|
||||||
|
var port = Convert.ToInt32(growlHost[1]);
|
||||||
|
|
||||||
|
_growlProvider.SendNotification(title, message, host, "GRAB", port, _configProvider.GrowlPassword);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Logger.WarnException(ex.Message, ex);
|
||||||
|
throw;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void OnDownload(string message, Series series)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if (_configProvider.GrowlNotifyOnDownload)
|
||||||
|
{
|
||||||
|
_logger.Trace("Sending Notification to Growl");
|
||||||
|
const string title = "Episode Downloaded";
|
||||||
|
|
||||||
|
var growlHost = _configProvider.GrowlHost.Split(':');
|
||||||
|
var host = growlHost[0];
|
||||||
|
var port = Convert.ToInt32(growlHost[1]);
|
||||||
|
|
||||||
|
_growlProvider.SendNotification(title, message, host, "DOWNLOAD", port, _configProvider.GrowlPassword);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Logger.WarnException(ex.Message, ex);
|
||||||
|
throw;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void OnRename(string message, Series series)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,61 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using Growl.Connector;
|
||||||
|
using NLog;
|
||||||
|
|
||||||
|
namespace NzbDrone.Core.Providers
|
||||||
|
{
|
||||||
|
public class GrowlProvider
|
||||||
|
{
|
||||||
|
private readonly Logger Logger = LogManager.GetCurrentClassLogger();
|
||||||
|
|
||||||
|
private readonly Application _growlApplication = new Application("NzbDrone");
|
||||||
|
private GrowlConnector _growlConnector;
|
||||||
|
private List<NotificationType> _notificationTypes;
|
||||||
|
|
||||||
|
public GrowlProvider()
|
||||||
|
{
|
||||||
|
_notificationTypes = GetNotificationTypes();
|
||||||
|
_growlApplication.Icon = "https://github.com/NzbDrone/NzbDrone/raw/master/NzbDrone.Core/NzbDrone.jpg";
|
||||||
|
}
|
||||||
|
|
||||||
|
public virtual void Register(string hostname, int port, string password)
|
||||||
|
{
|
||||||
|
Logger.Trace("Registering NzbDrone with Growl host: {0}:{1}", hostname, port);
|
||||||
|
_growlConnector = new GrowlConnector(password, hostname, port);
|
||||||
|
_growlConnector.Register(_growlApplication, _notificationTypes.ToArray());
|
||||||
|
}
|
||||||
|
|
||||||
|
public virtual void TestNotification(string hostname, int port, string password)
|
||||||
|
{
|
||||||
|
const string title = "Test Notification";
|
||||||
|
const string message = "This is a test message from NzbDrone";
|
||||||
|
|
||||||
|
SendNotification(title, message, "TEST", hostname, port, password);
|
||||||
|
}
|
||||||
|
|
||||||
|
public virtual void SendNotification(string title, string message, string notificationTypeName, string hostname, int port, string password)
|
||||||
|
{
|
||||||
|
var notificationType = _notificationTypes.Single(n => n.Name == notificationTypeName);
|
||||||
|
|
||||||
|
var notification = new Notification("NzbDrone", notificationType.Name, DateTime.Now.Ticks.ToString(), title, message);
|
||||||
|
|
||||||
|
_growlConnector = new GrowlConnector(password, hostname, port);
|
||||||
|
|
||||||
|
Logger.Trace("Sending Notification to: {0}:{1}", hostname, port);
|
||||||
|
_growlConnector.Notify(notification);
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<NotificationType> GetNotificationTypes()
|
||||||
|
{
|
||||||
|
var notificationTypes = new List<NotificationType>();
|
||||||
|
notificationTypes.Add(new NotificationType("TEST", "Test"));
|
||||||
|
notificationTypes.Add(new NotificationType("GRAB", "Episode Grabbed"));
|
||||||
|
notificationTypes.Add(new NotificationType("DOWNLOAD", "Episode Complete"));
|
||||||
|
|
||||||
|
return notificationTypes;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -37,7 +37,7 @@
|
||||||
|
|
||||||
public static System.Drawing.Bitmap GetIconAsImage(string Name)
|
public static System.Drawing.Bitmap GetIconAsImage(string Name)
|
||||||
{
|
{
|
||||||
System.IO.Stream stm = typeof(ResourceManager).Assembly.GetManifestResourceStream(string.Format("{0}.Icons.{1}.ico", typeof(ResourceManager).Namespace, Name));
|
System.IO.Stream stm = typeof(ResourceManager).Assembly.GetManifestResourceStream(string.Format("NzbDrone.Core.{0}.ico", Name));
|
||||||
if (stm == null) return null;
|
if (stm == null) return null;
|
||||||
System.Drawing.Bitmap bmp;
|
System.Drawing.Bitmap bmp;
|
||||||
using (System.Drawing.Icon ico = new System.Drawing.Icon(stm))
|
using (System.Drawing.Icon ico = new System.Drawing.Icon(stm))
|
||||||
|
|
|
@ -0,0 +1,25 @@
|
||||||
|
Growl.NET GNTP Connector Library
|
||||||
|
-----------------------------------------------
|
||||||
|
Copyright (c) 2008 - Growl for Windows
|
||||||
|
All rights reserved
|
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without modification,
|
||||||
|
are permitted provided that the following conditions are met:
|
||||||
|
|
||||||
|
1. Redistributions of source code must retain the above copyright
|
||||||
|
notice, this list of conditions and the following disclaimer.
|
||||||
|
2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
notice, this list of conditions and the following disclaimer in the
|
||||||
|
documentation and/or other materials provided with the distribution.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
|
||||||
|
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||||
|
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
|
||||||
|
SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||||
|
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
|
||||||
|
TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
|
||||||
|
BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||||
|
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||||
|
ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
|
||||||
|
DAMAGE.
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<packages>
|
<packages>
|
||||||
<package id="DotNetZip" version="1.9.1.8" />
|
<package id="DotNetZip" version="1.9.1.8" />
|
||||||
|
<package id="Growl" version="0.6" />
|
||||||
<package id="MiniProfiler" version="1.9" />
|
<package id="MiniProfiler" version="1.9" />
|
||||||
<package id="Newtonsoft.Json" version="3.5.8" />
|
<package id="Newtonsoft.Json" version="3.5.8" />
|
||||||
<package id="Ninject" version="2.2.1.4" />
|
<package id="Ninject" version="2.2.1.4" />
|
||||||
|
|
Binary file not shown.
|
@ -0,0 +1,23 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Windows.Forms;
|
||||||
|
using Growl.Connector;
|
||||||
|
using Growl.CoreLibrary;
|
||||||
|
|
||||||
|
namespace $rootnamespace$
|
||||||
|
{
|
||||||
|
class GrowlHelper
|
||||||
|
{
|
||||||
|
public static void simpleGrowl(string title, string message = "")
|
||||||
|
{
|
||||||
|
GrowlConnector simpleGrowl = new GrowlConnector();
|
||||||
|
Growl.Connector.Application thisApp = new Growl.Connector.Application(System.Windows.Forms.Application.ProductName);
|
||||||
|
NotificationType simpleGrowlType = new NotificationType("SIMPLEGROWL");
|
||||||
|
simpleGrowl.Register(thisApp, new NotificationType[] { simpleGrowlType });
|
||||||
|
Notification myGrowl = new Notification(System.Windows.Forms.Application.ProductName, "SIMPLEGROWL", title, title, message);
|
||||||
|
simpleGrowl.Notify(myGrowl);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,25 @@
|
||||||
|
Growl.NET GNTP Connector Library
|
||||||
|
-----------------------------------------------
|
||||||
|
Copyright (c) 2008 - Growl for Windows
|
||||||
|
All rights reserved
|
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without modification,
|
||||||
|
are permitted provided that the following conditions are met:
|
||||||
|
|
||||||
|
1. Redistributions of source code must retain the above copyright
|
||||||
|
notice, this list of conditions and the following disclaimer.
|
||||||
|
2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
notice, this list of conditions and the following disclaimer in the
|
||||||
|
documentation and/or other materials provided with the distribution.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
|
||||||
|
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||||
|
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
|
||||||
|
SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||||
|
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
|
||||||
|
TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
|
||||||
|
BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||||
|
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||||
|
ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
|
||||||
|
DAMAGE.
|
||||||
|
|
Binary file not shown.
Binary file not shown.
Loading…
Reference in New Issue