2021-09-18 19:02:40 +05:30
/ *
Technitium DNS Server
2025-01-18 13:08:39 +05:30
Copyright ( C ) 2025 Shreyas Zare ( shreyas @technitium . com )
2021-09-18 19:02:40 +05:30
This program is free software : you can redistribute it and / or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation , either version 3 of the License , or
( at your option ) any later version .
This program is distributed in the hope that it will be useful ,
but WITHOUT ANY WARRANTY ; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
GNU General Public License for more details .
You should have received a copy of the GNU General Public License
along with this program . If not , see < http : //www.gnu.org/licenses/>.
* /
using DnsServerCore.ApplicationCommon ;
2023-01-01 17:44:05 +05:30
using DnsServerCore.Auth ;
2021-09-18 19:02:40 +05:30
using DnsServerCore.Dns.Applications ;
2023-01-01 17:44:05 +05:30
using Microsoft.AspNetCore.Http ;
2021-09-18 19:02:40 +05:30
using System ;
using System.Collections.Generic ;
using System.IO ;
using System.Net ;
using System.Net.Http ;
2022-12-24 13:03:35 +05:30
using System.Text.Json ;
2022-09-18 17:49:36 +05:30
using System.Threading ;
2021-09-18 19:02:40 +05:30
using System.Threading.Tasks ;
2023-03-11 15:20:05 +05:30
using TechnitiumLibrary.Net.Http.Client ;
2021-09-18 19:02:40 +05:30
namespace DnsServerCore
{
2025-02-15 12:51:16 +05:30
public partial class DnsWebService
2021-09-18 19:02:40 +05:30
{
2025-02-15 12:51:16 +05:30
sealed class WebServiceAppsApi : IDisposable
{
#region variables
2021-09-18 19:02:40 +05:30
2025-02-15 12:51:16 +05:30
readonly DnsWebService _dnsWebService ;
readonly Uri _appStoreUri ;
2021-09-18 19:02:40 +05:30
2025-02-15 12:51:16 +05:30
string _storeAppsJsonData ;
DateTime _storeAppsJsonDataUpdatedOn ;
const int STORE_APPS_JSON_DATA_CACHE_TIME_SECONDS = 900 ;
2021-09-18 19:02:40 +05:30
2025-02-15 12:51:16 +05:30
Timer _appUpdateTimer ;
const int APP_UPDATE_TIMER_INITIAL_INTERVAL = 10000 ;
const int APP_UPDATE_TIMER_PERIODIC_INTERVAL = 86400000 ;
2022-09-18 17:49:36 +05:30
2025-02-15 12:51:16 +05:30
#endregion
2021-09-18 19:02:40 +05:30
2025-02-15 12:51:16 +05:30
#region constructor
2021-09-18 19:02:40 +05:30
2025-02-15 12:51:16 +05:30
public WebServiceAppsApi ( DnsWebService dnsWebService , Uri appStoreUri )
{
_dnsWebService = dnsWebService ;
_appStoreUri = appStoreUri ;
}
2021-09-18 19:02:40 +05:30
2025-02-15 12:51:16 +05:30
#endregion
2021-09-18 19:02:40 +05:30
2025-02-15 12:51:16 +05:30
#region IDisposable
2022-09-18 17:49:36 +05:30
2025-02-15 12:51:16 +05:30
bool _disposed ;
2022-09-18 17:49:36 +05:30
2025-02-15 12:51:16 +05:30
public void Dispose ( )
{
if ( _disposed )
return ;
2022-09-18 17:49:36 +05:30
2025-02-15 12:51:16 +05:30
if ( _appUpdateTimer is not null )
_appUpdateTimer . Dispose ( ) ;
2022-09-18 17:49:36 +05:30
2025-02-15 12:51:16 +05:30
_disposed = true ;
}
2022-09-18 17:49:36 +05:30
2025-02-15 12:51:16 +05:30
#endregion
2022-09-18 17:49:36 +05:30
2025-02-15 12:51:16 +05:30
#region private
2021-09-18 19:02:40 +05:30
2025-02-15 12:51:16 +05:30
private void StartAutomaticUpdate ( )
2022-09-18 17:49:36 +05:30
{
2025-02-15 12:51:16 +05:30
if ( _appUpdateTimer is null )
2022-09-18 17:49:36 +05:30
{
2025-02-15 12:51:16 +05:30
_appUpdateTimer = new Timer ( async delegate ( object state )
2022-09-18 17:49:36 +05:30
{
2025-02-15 12:51:16 +05:30
try
{
if ( _dnsWebService . _dnsServer . DnsApplicationManager . Applications . Count < 1 )
return ;
2022-09-18 17:49:36 +05:30
2025-02-15 12:51:16 +05:30
_dnsWebService . _log . Write ( "DNS Server has started automatic update check for DNS Apps." ) ;
2022-09-24 11:51:56 +05:30
2025-02-15 12:51:16 +05:30
string storeAppsJsonData = await GetStoreAppsJsonData ( true ) ;
using JsonDocument jsonDocument = JsonDocument . Parse ( storeAppsJsonData ) ;
JsonElement jsonStoreAppsArray = jsonDocument . RootElement ;
2022-09-18 17:49:36 +05:30
2025-02-15 12:51:16 +05:30
foreach ( DnsApplication application in _dnsWebService . _dnsServer . DnsApplicationManager . Applications . Values )
2022-09-18 17:49:36 +05:30
{
2025-02-15 12:51:16 +05:30
foreach ( JsonElement jsonStoreApp in jsonStoreAppsArray . EnumerateArray ( ) )
2022-09-18 17:49:36 +05:30
{
2025-02-15 12:51:16 +05:30
string name = jsonStoreApp . GetProperty ( "name" ) . GetString ( ) ;
if ( name . Equals ( application . Name ) )
2022-09-18 17:49:36 +05:30
{
2025-02-15 12:51:16 +05:30
string url = null ;
Version storeAppVersion = null ;
Version lastServerVersion = null ;
2022-09-18 17:49:36 +05:30
2025-02-15 12:51:16 +05:30
foreach ( JsonElement jsonVersion in jsonStoreApp . GetProperty ( "versions" ) . EnumerateArray ( ) )
{
string strServerVersion = jsonVersion . GetProperty ( "serverVersion" ) . GetString ( ) ;
Version requiredServerVersion = new Version ( strServerVersion ) ;
2022-09-18 17:49:36 +05:30
2025-02-15 12:51:16 +05:30
if ( _dnsWebService . _currentVersion < requiredServerVersion )
continue ;
2022-09-18 17:49:36 +05:30
2025-02-15 12:51:16 +05:30
if ( ( lastServerVersion is not null ) & & ( lastServerVersion > requiredServerVersion ) )
continue ;
2022-09-18 17:49:36 +05:30
2025-02-15 12:51:16 +05:30
string version = jsonVersion . GetProperty ( "version" ) . GetString ( ) ;
url = jsonVersion . GetProperty ( "url" ) . GetString ( ) ;
2022-09-18 17:49:36 +05:30
2025-02-15 12:51:16 +05:30
storeAppVersion = new Version ( version ) ;
lastServerVersion = requiredServerVersion ;
2022-09-18 17:49:36 +05:30
}
2025-02-15 12:51:16 +05:30
if ( ( storeAppVersion is not null ) & & ( storeAppVersion > application . Version ) )
2022-09-18 17:49:36 +05:30
{
2025-02-15 12:51:16 +05:30
try
{
await DownloadAndUpdateAppAsync ( application . Name , url , true ) ;
_dnsWebService . _log . Write ( "DNS application '" + application . Name + "' was automatically updated successfully from: " + url ) ;
}
catch ( Exception ex )
{
_dnsWebService . _log . Write ( "Failed to automatically download and update DNS application '" + application . Name + "': " + ex . ToString ( ) ) ;
}
2022-09-18 17:49:36 +05:30
}
2025-02-15 12:51:16 +05:30
break ;
}
2022-09-18 17:49:36 +05:30
}
}
}
2025-02-15 12:51:16 +05:30
catch ( Exception ex )
{
_dnsWebService . _log . Write ( ex ) ;
}
} ) ;
2022-09-18 17:49:36 +05:30
2025-02-15 12:51:16 +05:30
_appUpdateTimer . Change ( APP_UPDATE_TIMER_INITIAL_INTERVAL , APP_UPDATE_TIMER_PERIODIC_INTERVAL ) ;
}
2022-09-18 17:49:36 +05:30
}
2025-02-15 12:51:16 +05:30
private void StopAutomaticUpdate ( )
2021-09-18 19:02:40 +05:30
{
2025-02-15 12:51:16 +05:30
if ( _appUpdateTimer is not null )
2021-09-18 19:02:40 +05:30
{
2025-02-15 12:51:16 +05:30
_appUpdateTimer . Dispose ( ) ;
_appUpdateTimer = null ;
2021-09-18 19:02:40 +05:30
}
}
2025-02-15 12:51:16 +05:30
private async Task < string > GetStoreAppsJsonData ( bool doRetry )
2022-09-18 17:49:36 +05:30
{
2025-02-15 12:51:16 +05:30
if ( ( _storeAppsJsonData is null ) | | ( DateTime . UtcNow > _storeAppsJsonDataUpdatedOn . AddSeconds ( STORE_APPS_JSON_DATA_CACHE_TIME_SECONDS ) ) )
2022-09-18 17:49:36 +05:30
{
SocketsHttpHandler handler = new SocketsHttpHandler ( ) ;
2025-02-15 12:51:16 +05:30
handler . Proxy = _dnsWebService . _dnsServer . Proxy ;
handler . UseProxy = _dnsWebService . _dnsServer . Proxy is not null ;
2023-01-14 15:02:38 +05:30
handler . AutomaticDecompression = DecompressionMethods . All ;
2022-09-18 17:49:36 +05:30
2025-02-15 12:51:16 +05:30
HttpClientNetworkHandler networkHandler = new HttpClientNetworkHandler ( handler , _dnsWebService . _dnsServer . PreferIPv6 ? HttpClientNetworkType . PreferIPv6 : HttpClientNetworkType . Default , _dnsWebService . _dnsServer ) ;
2023-03-18 13:38:32 +05:30
if ( ! doRetry )
networkHandler . Retries = 1 ;
using ( HttpClient http = new HttpClient ( networkHandler ) )
2022-09-18 17:49:36 +05:30
{
2025-02-15 12:51:16 +05:30
_storeAppsJsonData = await http . GetStringAsync ( _appStoreUri ) ;
_storeAppsJsonDataUpdatedOn = DateTime . UtcNow ;
2022-09-18 17:49:36 +05:30
}
}
2025-02-15 12:51:16 +05:30
return _storeAppsJsonData ;
2022-09-18 17:49:36 +05:30
}
2025-02-15 12:51:16 +05:30
private async Task < DnsApplication > DownloadAndUpdateAppAsync ( string applicationName , string url , bool doRetry )
2022-09-18 17:49:36 +05:30
{
2025-02-15 12:51:16 +05:30
string tmpFile = Path . GetTempFileName ( ) ;
2022-09-18 17:49:36 +05:30
try
{
2025-02-15 12:51:16 +05:30
using ( FileStream fS = new FileStream ( tmpFile , FileMode . Create , FileAccess . ReadWrite ) )
{
//download to temp file
SocketsHttpHandler handler = new SocketsHttpHandler ( ) ;
handler . Proxy = _dnsWebService . _dnsServer . Proxy ;
handler . UseProxy = _dnsWebService . _dnsServer . Proxy is not null ;
handler . AutomaticDecompression = DecompressionMethods . All ;
HttpClientNetworkHandler networkHandler = new HttpClientNetworkHandler ( handler , _dnsWebService . _dnsServer . PreferIPv6 ? HttpClientNetworkType . PreferIPv6 : HttpClientNetworkType . Default , _dnsWebService . _dnsServer ) ;
if ( ! doRetry )
networkHandler . Retries = 1 ;
using ( HttpClient http = new HttpClient ( networkHandler ) )
{
using ( Stream httpStream = await http . GetStreamAsync ( url ) )
{
await httpStream . CopyToAsync ( fS ) ;
}
}
//update app
fS . Position = 0 ;
return await _dnsWebService . _dnsServer . DnsApplicationManager . UpdateApplicationAsync ( applicationName , fS ) ;
}
2022-09-18 17:49:36 +05:30
}
2025-02-15 12:51:16 +05:30
finally
2022-09-18 17:49:36 +05:30
{
2025-02-15 12:51:16 +05:30
try
{
File . Delete ( tmpFile ) ;
}
catch ( Exception ex )
{
_dnsWebService . _log . Write ( ex ) ;
}
2022-09-18 17:49:36 +05:30
}
}
2025-02-15 12:51:16 +05:30
private void WriteAppAsJson ( Utf8JsonWriter jsonWriter , DnsApplication application , JsonElement jsonStoreAppsArray = default )
{
jsonWriter . WriteStartObject ( ) ;
2021-09-18 19:02:40 +05:30
2025-02-15 12:51:16 +05:30
jsonWriter . WriteString ( "name" , application . Name ) ;
jsonWriter . WriteString ( "description" , application . Description ) ;
jsonWriter . WriteString ( "version" , DnsWebService . GetCleanVersion ( application . Version ) ) ;
2021-09-18 19:02:40 +05:30
2025-02-15 12:51:16 +05:30
if ( jsonStoreAppsArray . ValueKind ! = JsonValueKind . Undefined )
2021-09-18 19:02:40 +05:30
{
2025-02-15 12:51:16 +05:30
foreach ( JsonElement jsonStoreApp in jsonStoreAppsArray . EnumerateArray ( ) )
2022-10-09 15:39:28 +05:30
{
2025-02-15 12:51:16 +05:30
string name = jsonStoreApp . GetProperty ( "name" ) . GetString ( ) ;
if ( name . Equals ( application . Name ) )
2022-10-09 15:39:28 +05:30
{
2025-02-15 12:51:16 +05:30
string version = null ;
string url = null ;
Version storeAppVersion = null ;
Version lastServerVersion = null ;
2021-09-18 19:02:40 +05:30
2025-02-15 12:51:16 +05:30
foreach ( JsonElement jsonVersion in jsonStoreApp . GetProperty ( "versions" ) . EnumerateArray ( ) )
{
string strServerVersion = jsonVersion . GetProperty ( "serverVersion" ) . GetString ( ) ;
Version requiredServerVersion = new Version ( strServerVersion ) ;
2021-09-18 19:02:40 +05:30
2025-02-15 12:51:16 +05:30
if ( _dnsWebService . _currentVersion < requiredServerVersion )
continue ;
2021-09-18 19:02:40 +05:30
2025-02-15 12:51:16 +05:30
if ( ( lastServerVersion is not null ) & & ( lastServerVersion > requiredServerVersion ) )
continue ;
2021-09-18 19:02:40 +05:30
2025-02-15 12:51:16 +05:30
version = jsonVersion . GetProperty ( "version" ) . GetString ( ) ;
url = jsonVersion . GetProperty ( "url" ) . GetString ( ) ;
storeAppVersion = new Version ( version ) ;
lastServerVersion = requiredServerVersion ;
}
2022-09-18 17:49:36 +05:30
2025-02-15 12:51:16 +05:30
if ( storeAppVersion is null )
break ; //no compatible update available
2022-09-18 17:49:36 +05:30
2025-02-15 12:51:16 +05:30
jsonWriter . WriteString ( "updateVersion" , version ) ;
jsonWriter . WriteString ( "updateUrl" , url ) ;
jsonWriter . WriteBoolean ( "updateAvailable" , storeAppVersion > application . Version ) ;
break ;
}
2022-10-09 15:39:28 +05:30
}
}
2022-09-18 17:49:36 +05:30
2025-02-15 12:51:16 +05:30
jsonWriter . WritePropertyName ( "dnsApps" ) ;
2022-10-09 15:39:28 +05:30
{
2025-02-15 12:51:16 +05:30
jsonWriter . WriteStartArray ( ) ;
2021-09-18 19:02:40 +05:30
2025-02-15 12:51:16 +05:30
foreach ( KeyValuePair < string , IDnsApplication > dnsApp in application . DnsApplications )
2022-10-09 15:39:28 +05:30
{
2025-02-15 12:51:16 +05:30
jsonWriter . WriteStartObject ( ) ;
2021-09-18 19:02:40 +05:30
2025-02-15 12:51:16 +05:30
jsonWriter . WriteString ( "classPath" , dnsApp . Key ) ;
jsonWriter . WriteString ( "description" , dnsApp . Value . Description ) ;
2022-11-12 15:13:22 +05:30
2025-02-15 12:51:16 +05:30
if ( dnsApp . Value is IDnsAppRecordRequestHandler appRecordHandler )
{
jsonWriter . WriteBoolean ( "isAppRecordRequestHandler" , true ) ;
jsonWriter . WriteString ( "recordDataTemplate" , appRecordHandler . ApplicationRecordDataTemplate ) ;
}
else
{
jsonWriter . WriteBoolean ( "isAppRecordRequestHandler" , false ) ;
}
2021-09-18 19:02:40 +05:30
2025-02-15 12:51:16 +05:30
jsonWriter . WriteBoolean ( "isRequestController" , dnsApp . Value is IDnsRequestController ) ;
jsonWriter . WriteBoolean ( "isAuthoritativeRequestHandler" , dnsApp . Value is IDnsAuthoritativeRequestHandler ) ;
jsonWriter . WriteBoolean ( "isRequestBlockingHandler" , dnsApp . Value is IDnsRequestBlockingHandler ) ;
jsonWriter . WriteBoolean ( "isQueryLogger" , dnsApp . Value is IDnsQueryLogger ) ;
jsonWriter . WriteBoolean ( "isQueryLogs" , dnsApp . Value is IDnsQueryLogs ) ;
jsonWriter . WriteBoolean ( "isPostProcessor" , dnsApp . Value is IDnsPostProcessor ) ;
2021-09-18 19:02:40 +05:30
2025-02-15 12:51:16 +05:30
jsonWriter . WriteEndObject ( ) ;
}
2021-09-18 19:02:40 +05:30
2025-02-15 12:51:16 +05:30
jsonWriter . WriteEndArray ( ) ;
}
2021-09-18 19:02:40 +05:30
2025-02-15 12:51:16 +05:30
jsonWriter . WriteEndObject ( ) ;
}
2021-09-18 19:02:40 +05:30
2025-02-15 12:51:16 +05:30
#endregion
2023-01-01 17:44:05 +05:30
2025-02-15 12:51:16 +05:30
#region public
public async Task ListInstalledAppsAsync ( HttpContext context )
2023-01-01 17:44:05 +05:30
{
2025-02-15 12:51:16 +05:30
UserSession session = context . GetCurrentSession ( ) ;
2023-01-01 17:44:05 +05:30
2025-02-15 12:51:16 +05:30
if (
! _dnsWebService . _authManager . IsPermitted ( PermissionSection . Apps , session . User , PermissionFlag . View ) & &
! _dnsWebService . _authManager . IsPermitted ( PermissionSection . Zones , session . User , PermissionFlag . View ) & &
! _dnsWebService . _authManager . IsPermitted ( PermissionSection . Logs , session . User , PermissionFlag . View )
)
{
throw new DnsWebServiceException ( "Access was denied." ) ;
}
2021-09-18 19:02:40 +05:30
2025-02-15 12:51:16 +05:30
List < string > apps = new List < string > ( _dnsWebService . _dnsServer . DnsApplicationManager . Applications . Keys ) ;
apps . Sort ( ) ;
2022-12-24 13:03:35 +05:30
2025-02-15 12:51:16 +05:30
JsonDocument jsonDocument = null ;
try
2022-10-09 15:39:28 +05:30
{
2025-02-15 12:51:16 +05:30
JsonElement jsonStoreAppsArray = default ;
if ( apps . Count > 0 )
2022-12-24 13:03:35 +05:30
{
2025-02-15 12:51:16 +05:30
try
2024-09-14 19:32:27 +05:30
{
2025-02-15 12:51:16 +05:30
string storeAppsJsonData = await TechnitiumLibrary . TaskExtensions . TimeoutAsync ( delegate ( CancellationToken cancellationToken1 )
{
return GetStoreAppsJsonData ( false ) ;
} , 5000 ) ;
2024-09-14 19:32:27 +05:30
2025-02-15 12:51:16 +05:30
jsonDocument = JsonDocument . Parse ( storeAppsJsonData ) ;
jsonStoreAppsArray = jsonDocument . RootElement ;
}
catch ( Exception ex )
{
_dnsWebService . _log . Write ( ex ) ;
}
2024-02-04 18:03:37 +05:30
}
2022-10-09 15:39:28 +05:30
2025-02-15 12:51:16 +05:30
Utf8JsonWriter jsonWriter = context . GetCurrentJsonWriter ( ) ;
2023-01-01 17:44:05 +05:30
2025-02-15 12:51:16 +05:30
jsonWriter . WritePropertyName ( "apps" ) ;
jsonWriter . WriteStartArray ( ) ;
2022-12-24 13:03:35 +05:30
2025-02-15 12:51:16 +05:30
foreach ( string app in apps )
{
if ( _dnsWebService . _dnsServer . DnsApplicationManager . Applications . TryGetValue ( app , out DnsApplication application ) )
WriteAppAsJson ( jsonWriter , application , jsonStoreAppsArray ) ;
}
jsonWriter . WriteEndArray ( ) ;
}
finally
2022-12-24 13:03:35 +05:30
{
2025-02-15 12:51:16 +05:30
if ( jsonDocument is not null )
jsonDocument . Dispose ( ) ;
2022-12-24 13:03:35 +05:30
}
2021-09-18 19:02:40 +05:30
}
2025-02-15 12:51:16 +05:30
public async Task ListStoreApps ( HttpContext context )
{
UserSession session = context . GetCurrentSession ( ) ;
2023-01-01 17:44:05 +05:30
2025-02-15 12:51:16 +05:30
if ( ! _dnsWebService . _authManager . IsPermitted ( PermissionSection . Apps , session . User , PermissionFlag . View ) )
throw new DnsWebServiceException ( "Access was denied." ) ;
2023-01-01 17:44:05 +05:30
2025-02-15 12:51:16 +05:30
string storeAppsJsonData = await TechnitiumLibrary . TaskExtensions . TimeoutAsync ( delegate ( CancellationToken cancellationToken1 )
{
return GetStoreAppsJsonData ( false ) ;
} , 30000 ) ;
2024-09-14 19:32:27 +05:30
2025-02-15 12:51:16 +05:30
using JsonDocument jsonDocument = JsonDocument . Parse ( storeAppsJsonData ) ;
JsonElement jsonStoreAppsArray = jsonDocument . RootElement ;
2021-09-18 19:02:40 +05:30
2025-02-15 12:51:16 +05:30
Utf8JsonWriter jsonWriter = context . GetCurrentJsonWriter ( ) ;
2023-01-01 17:44:05 +05:30
2025-02-15 12:51:16 +05:30
jsonWriter . WritePropertyName ( "storeApps" ) ;
jsonWriter . WriteStartArray ( ) ;
2021-09-18 19:02:40 +05:30
2025-02-15 12:51:16 +05:30
foreach ( JsonElement jsonStoreApp in jsonStoreAppsArray . EnumerateArray ( ) )
2022-09-18 17:49:36 +05:30
{
2025-02-15 12:51:16 +05:30
string name = jsonStoreApp . GetProperty ( "name" ) . GetString ( ) ;
string description = jsonStoreApp . GetProperty ( "description" ) . GetString ( ) ;
string version = null ;
string url = null ;
string size = null ;
Version storeAppVersion = null ;
Version lastServerVersion = null ;
foreach ( JsonElement jsonVersion in jsonStoreApp . GetProperty ( "versions" ) . EnumerateArray ( ) )
{
string strServerVersion = jsonVersion . GetProperty ( "serverVersion" ) . GetString ( ) ;
Version requiredServerVersion = new Version ( strServerVersion ) ;
2022-09-18 17:49:36 +05:30
2025-02-15 12:51:16 +05:30
if ( _dnsWebService . _currentVersion < requiredServerVersion )
continue ;
2022-09-18 17:49:36 +05:30
2025-02-15 12:51:16 +05:30
if ( ( lastServerVersion is not null ) & & ( lastServerVersion > requiredServerVersion ) )
continue ;
2022-09-18 17:49:36 +05:30
2025-02-15 12:51:16 +05:30
version = jsonVersion . GetProperty ( "version" ) . GetString ( ) ;
url = jsonVersion . GetProperty ( "url" ) . GetString ( ) ;
size = jsonVersion . GetProperty ( "size" ) . GetString ( ) ;
2022-09-18 17:49:36 +05:30
2025-02-15 12:51:16 +05:30
storeAppVersion = new Version ( version ) ;
lastServerVersion = requiredServerVersion ;
}
2022-09-18 17:49:36 +05:30
2025-02-15 12:51:16 +05:30
if ( storeAppVersion is null )
continue ; //app is not compatible
2021-09-18 19:02:40 +05:30
2025-02-15 12:51:16 +05:30
jsonWriter . WriteStartObject ( ) ;
2021-09-18 19:02:40 +05:30
2025-02-15 12:51:16 +05:30
jsonWriter . WriteString ( "name" , name ) ;
jsonWriter . WriteString ( "description" , description ) ;
jsonWriter . WriteString ( "version" , version ) ;
jsonWriter . WriteString ( "url" , url ) ;
jsonWriter . WriteString ( "size" , size ) ;
2021-09-18 19:02:40 +05:30
2025-02-15 12:51:16 +05:30
bool installed = _dnsWebService . _dnsServer . DnsApplicationManager . Applications . TryGetValue ( name , out DnsApplication installedApp ) ;
2021-09-18 19:02:40 +05:30
2025-02-15 12:51:16 +05:30
jsonWriter . WriteBoolean ( "installed" , installed ) ;
2021-09-18 19:02:40 +05:30
2025-02-15 12:51:16 +05:30
if ( installed )
{
jsonWriter . WriteString ( "installedVersion" , DnsWebService . GetCleanVersion ( installedApp . Version ) ) ;
jsonWriter . WriteBoolean ( "updateAvailable" , storeAppVersion > installedApp . Version ) ;
}
jsonWriter . WriteEndObject ( ) ;
2021-09-18 19:02:40 +05:30
}
2025-02-15 12:51:16 +05:30
jsonWriter . WriteEndArray ( ) ;
2021-09-18 19:02:40 +05:30
}
2025-02-15 12:51:16 +05:30
public async Task DownloadAndInstallAppAsync ( HttpContext context )
{
UserSession session = context . GetCurrentSession ( ) ;
2023-01-01 17:44:05 +05:30
2025-02-15 12:51:16 +05:30
if ( ! _dnsWebService . _authManager . IsPermitted ( PermissionSection . Apps , session . User , PermissionFlag . Delete ) )
throw new DnsWebServiceException ( "Access was denied." ) ;
2021-09-18 19:02:40 +05:30
2025-02-15 12:51:16 +05:30
HttpRequest request = context . Request ;
2021-09-18 19:02:40 +05:30
2025-02-15 12:51:16 +05:30
string name = request . GetQueryOrForm ( "name" ) . Trim ( ) ;
string url = request . GetQueryOrForm ( "url" ) ;
2021-09-18 19:02:40 +05:30
2025-02-15 12:51:16 +05:30
if ( ! url . StartsWith ( "https://" , StringComparison . OrdinalIgnoreCase ) )
throw new DnsWebServiceException ( "Parameter 'url' value must start with 'https://'." ) ;
2021-09-18 19:02:40 +05:30
2025-02-15 12:51:16 +05:30
string tmpFile = Path . GetTempFileName ( ) ;
try
2021-09-18 19:02:40 +05:30
{
2025-02-15 12:51:16 +05:30
using ( FileStream fS = new FileStream ( tmpFile , FileMode . Create , FileAccess . ReadWrite ) )
2021-09-18 19:02:40 +05:30
{
2025-02-15 12:51:16 +05:30
//download to temp file
SocketsHttpHandler handler = new SocketsHttpHandler ( ) ;
handler . Proxy = _dnsWebService . _dnsServer . Proxy ;
handler . UseProxy = _dnsWebService . _dnsServer . Proxy is not null ;
handler . AutomaticDecompression = DecompressionMethods . All ;
using ( HttpClient http = new HttpClient ( new HttpClientNetworkHandler ( handler , _dnsWebService . _dnsServer . PreferIPv6 ? HttpClientNetworkType . PreferIPv6 : HttpClientNetworkType . Default , _dnsWebService . _dnsServer ) ) )
2021-09-18 19:02:40 +05:30
{
2025-02-15 12:51:16 +05:30
using ( Stream httpStream = await http . GetStreamAsync ( url ) )
{
await httpStream . CopyToAsync ( fS ) ;
}
2021-09-18 19:02:40 +05:30
}
2025-02-15 12:51:16 +05:30
//install app
fS . Position = 0 ;
DnsApplication application = await _dnsWebService . _dnsServer . DnsApplicationManager . InstallApplicationAsync ( name , fS ) ;
2021-09-18 19:02:40 +05:30
2025-02-15 12:51:16 +05:30
_dnsWebService . _log . Write ( context . GetRemoteEndPoint ( _dnsWebService . _webServiceRealIpHeader ) , "[" + session . User . Username + "] DNS application '" + name + "' was installed successfully from: " + url ) ;
2023-01-01 17:44:05 +05:30
2025-02-15 12:51:16 +05:30
Utf8JsonWriter jsonWriter = context . GetCurrentJsonWriter ( ) ;
2022-10-09 15:39:28 +05:30
2025-02-15 12:51:16 +05:30
jsonWriter . WritePropertyName ( "installedApp" ) ;
WriteAppAsJson ( jsonWriter , application ) ;
}
2021-09-18 19:02:40 +05:30
}
2025-02-15 12:51:16 +05:30
finally
2021-09-18 19:02:40 +05:30
{
2025-02-15 12:51:16 +05:30
try
{
File . Delete ( tmpFile ) ;
}
catch ( Exception ex )
{
_dnsWebService . _log . Write ( ex ) ;
}
2021-09-18 19:02:40 +05:30
}
}
2025-02-15 12:51:16 +05:30
public async Task DownloadAndUpdateAppAsync ( HttpContext context )
{
UserSession session = context . GetCurrentSession ( ) ;
2023-01-01 17:44:05 +05:30
2025-02-15 12:51:16 +05:30
if ( ! _dnsWebService . _authManager . IsPermitted ( PermissionSection . Apps , session . User , PermissionFlag . Delete ) )
throw new DnsWebServiceException ( "Access was denied." ) ;
2021-09-18 19:02:40 +05:30
2025-02-15 12:51:16 +05:30
HttpRequest request = context . Request ;
2021-09-18 19:02:40 +05:30
2025-02-15 12:51:16 +05:30
string name = request . GetQueryOrForm ( "name" ) . Trim ( ) ;
string url = request . GetQueryOrForm ( "url" ) ;
2021-09-18 19:02:40 +05:30
2025-02-15 12:51:16 +05:30
if ( ! url . StartsWith ( "https://" , StringComparison . OrdinalIgnoreCase ) )
throw new DnsWebServiceException ( "Parameter 'url' value must start with 'https://'." ) ;
2021-09-18 19:02:40 +05:30
2025-02-15 12:51:16 +05:30
DnsApplication application = await DownloadAndUpdateAppAsync ( name , url , false ) ;
2021-09-18 19:02:40 +05:30
2025-02-15 12:51:16 +05:30
_dnsWebService . _log . Write ( context . GetRemoteEndPoint ( _dnsWebService . _webServiceRealIpHeader ) , "[" + session . User . Username + "] DNS application '" + name + "' was updated successfully from: " + url ) ;
2023-01-01 17:44:05 +05:30
2025-02-15 12:51:16 +05:30
Utf8JsonWriter jsonWriter = context . GetCurrentJsonWriter ( ) ;
2022-10-09 15:39:28 +05:30
2025-02-15 12:51:16 +05:30
jsonWriter . WritePropertyName ( "updatedApp" ) ;
WriteAppAsJson ( jsonWriter , application ) ;
}
2021-09-18 19:02:40 +05:30
2025-02-15 12:51:16 +05:30
public async Task InstallAppAsync ( HttpContext context )
{
UserSession session = context . GetCurrentSession ( ) ;
2021-09-18 19:02:40 +05:30
2025-02-15 12:51:16 +05:30
if ( ! _dnsWebService . _authManager . IsPermitted ( PermissionSection . Apps , session . User , PermissionFlag . Delete ) )
throw new DnsWebServiceException ( "Access was denied." ) ;
2021-09-18 19:02:40 +05:30
2025-02-15 12:51:16 +05:30
HttpRequest request = context . Request ;
2021-09-18 19:02:40 +05:30
2025-02-15 12:51:16 +05:30
string name = request . GetQueryOrForm ( "name" ) . Trim ( ) ;
2021-09-18 19:02:40 +05:30
2025-02-15 12:51:16 +05:30
if ( ! request . HasFormContentType | | ( request . Form . Files . Count = = 0 ) )
throw new DnsWebServiceException ( "DNS application zip file is missing." ) ;
2021-09-18 19:02:40 +05:30
2025-02-15 12:51:16 +05:30
string tmpFile = Path . GetTempFileName ( ) ;
try
2021-09-18 19:02:40 +05:30
{
2025-02-15 12:51:16 +05:30
using ( FileStream fS = new FileStream ( tmpFile , FileMode . Create , FileAccess . ReadWrite ) )
{
//write to temp file
await request . Form . Files [ 0 ] . CopyToAsync ( fS ) ;
2021-09-18 19:02:40 +05:30
2025-02-15 12:51:16 +05:30
//install app
fS . Position = 0 ;
DnsApplication application = await _dnsWebService . _dnsServer . DnsApplicationManager . InstallApplicationAsync ( name , fS ) ;
2021-09-18 19:02:40 +05:30
2025-02-15 12:51:16 +05:30
_dnsWebService . _log . Write ( context . GetRemoteEndPoint ( _dnsWebService . _webServiceRealIpHeader ) , "[" + session . User . Username + "] DNS application '" + name + "' was installed successfully." ) ;
2023-01-01 17:44:05 +05:30
2025-02-15 12:51:16 +05:30
Utf8JsonWriter jsonWriter = context . GetCurrentJsonWriter ( ) ;
2022-10-09 15:39:28 +05:30
2025-02-15 12:51:16 +05:30
jsonWriter . WritePropertyName ( "installedApp" ) ;
WriteAppAsJson ( jsonWriter , application ) ;
}
2021-09-18 19:02:40 +05:30
}
2025-02-15 12:51:16 +05:30
finally
2021-09-18 19:02:40 +05:30
{
2025-02-15 12:51:16 +05:30
try
{
File . Delete ( tmpFile ) ;
}
catch ( Exception ex )
{
_dnsWebService . _log . Write ( ex ) ;
}
2021-09-18 19:02:40 +05:30
}
}
2025-02-15 12:51:16 +05:30
public async Task UpdateAppAsync ( HttpContext context )
{
UserSession session = context . GetCurrentSession ( ) ;
2021-09-18 19:02:40 +05:30
2025-02-15 12:51:16 +05:30
if ( ! _dnsWebService . _authManager . IsPermitted ( PermissionSection . Apps , session . User , PermissionFlag . Delete ) )
throw new DnsWebServiceException ( "Access was denied." ) ;
2021-09-18 19:02:40 +05:30
2025-02-15 12:51:16 +05:30
HttpRequest request = context . Request ;
2021-09-18 19:02:40 +05:30
2025-02-15 12:51:16 +05:30
string name = request . GetQueryOrForm ( "name" ) . Trim ( ) ;
2021-09-18 19:02:40 +05:30
2025-02-15 12:51:16 +05:30
if ( ! request . HasFormContentType | | ( request . Form . Files . Count = = 0 ) )
throw new DnsWebServiceException ( "DNS application zip file is missing." ) ;
2021-09-18 19:02:40 +05:30
2025-02-15 12:51:16 +05:30
string tmpFile = Path . GetTempFileName ( ) ;
try
2021-09-18 19:02:40 +05:30
{
2025-02-15 12:51:16 +05:30
using ( FileStream fS = new FileStream ( tmpFile , FileMode . Create , FileAccess . ReadWrite ) )
{
//write to temp file
await request . Form . Files [ 0 ] . CopyToAsync ( fS ) ;
2021-09-18 19:02:40 +05:30
2025-02-15 12:51:16 +05:30
//update app
fS . Position = 0 ;
DnsApplication application = await _dnsWebService . _dnsServer . DnsApplicationManager . UpdateApplicationAsync ( name , fS ) ;
2021-09-18 19:02:40 +05:30
2025-02-15 12:51:16 +05:30
_dnsWebService . _log . Write ( context . GetRemoteEndPoint ( _dnsWebService . _webServiceRealIpHeader ) , "[" + session . User . Username + "] DNS application '" + name + "' was updated successfully." ) ;
2023-01-01 17:44:05 +05:30
2025-02-15 12:51:16 +05:30
Utf8JsonWriter jsonWriter = context . GetCurrentJsonWriter ( ) ;
2022-10-09 15:39:28 +05:30
2025-02-15 12:51:16 +05:30
jsonWriter . WritePropertyName ( "updatedApp" ) ;
WriteAppAsJson ( jsonWriter , application ) ;
}
2021-09-18 19:02:40 +05:30
}
2025-02-15 12:51:16 +05:30
finally
2021-09-18 19:02:40 +05:30
{
2025-02-15 12:51:16 +05:30
try
{
File . Delete ( tmpFile ) ;
}
catch ( Exception ex )
{
_dnsWebService . _log . Write ( ex ) ;
}
2021-09-18 19:02:40 +05:30
}
}
2025-02-15 12:51:16 +05:30
public void UninstallApp ( HttpContext context )
{
UserSession session = context . GetCurrentSession ( ) ;
2023-01-01 17:44:05 +05:30
2025-02-15 12:51:16 +05:30
if ( ! _dnsWebService . _authManager . IsPermitted ( PermissionSection . Apps , session . User , PermissionFlag . Delete ) )
throw new DnsWebServiceException ( "Access was denied." ) ;
2021-09-18 19:02:40 +05:30
2025-02-15 12:51:16 +05:30
HttpRequest request = context . Request ;
2023-01-01 17:44:05 +05:30
2025-02-15 12:51:16 +05:30
string name = request . GetQueryOrForm ( "name" ) . Trim ( ) ;
2021-09-18 19:02:40 +05:30
2025-02-15 12:51:16 +05:30
_dnsWebService . _dnsServer . DnsApplicationManager . UninstallApplication ( name ) ;
_dnsWebService . _log . Write ( context . GetRemoteEndPoint ( _dnsWebService . _webServiceRealIpHeader ) , "[" + session . User . Username + "] DNS application '" + name + "' was uninstalled successfully." ) ;
}
2021-09-18 19:02:40 +05:30
2025-02-15 12:51:16 +05:30
public async Task GetAppConfigAsync ( HttpContext context )
{
UserSession session = context . GetCurrentSession ( ) ;
2023-01-01 17:44:05 +05:30
2025-02-15 12:51:16 +05:30
if ( ! _dnsWebService . _authManager . IsPermitted ( PermissionSection . Apps , session . User , PermissionFlag . View ) )
throw new DnsWebServiceException ( "Access was denied." ) ;
2021-09-18 19:02:40 +05:30
2025-02-15 12:51:16 +05:30
HttpRequest request = context . Request ;
2023-01-01 17:44:05 +05:30
2025-02-15 12:51:16 +05:30
string name = request . GetQueryOrForm ( "name" ) . Trim ( ) ;
2021-09-18 19:02:40 +05:30
2025-02-15 12:51:16 +05:30
if ( ! _dnsWebService . _dnsServer . DnsApplicationManager . Applications . TryGetValue ( name , out DnsApplication application ) )
throw new DnsWebServiceException ( "DNS application was not found: " + name ) ;
2021-09-18 19:02:40 +05:30
2025-02-15 12:51:16 +05:30
string config = await application . GetConfigAsync ( ) ;
2021-09-18 19:02:40 +05:30
2025-02-15 12:51:16 +05:30
Utf8JsonWriter jsonWriter = context . GetCurrentJsonWriter ( ) ;
jsonWriter . WriteString ( "config" , config ) ;
}
2021-09-18 19:02:40 +05:30
2025-02-15 12:51:16 +05:30
public async Task SetAppConfigAsync ( HttpContext context )
{
UserSession session = context . GetCurrentSession ( ) ;
2021-09-18 19:02:40 +05:30
2025-02-15 12:51:16 +05:30
if ( ! _dnsWebService . _authManager . IsPermitted ( PermissionSection . Apps , session . User , PermissionFlag . Modify ) )
throw new DnsWebServiceException ( "Access was denied." ) ;
2021-09-18 19:02:40 +05:30
2025-02-15 12:51:16 +05:30
HttpRequest request = context . Request ;
2021-09-18 19:02:40 +05:30
2025-02-15 12:51:16 +05:30
string name = request . GetQueryOrForm ( "name" ) . Trim ( ) ;
2021-09-18 19:02:40 +05:30
2025-02-15 12:51:16 +05:30
if ( ! _dnsWebService . _dnsServer . DnsApplicationManager . Applications . TryGetValue ( name , out DnsApplication application ) )
throw new DnsWebServiceException ( "DNS application was not found: " + name ) ;
2021-09-18 19:02:40 +05:30
2025-02-15 12:51:16 +05:30
string config = request . QueryOrForm ( "config" ) ;
if ( config is null )
throw new DnsWebServiceException ( "Parameter 'config' missing." ) ;
2021-09-18 19:02:40 +05:30
2025-02-15 12:51:16 +05:30
if ( config . Length = = 0 )
config = null ;
2021-09-19 18:50:06 +05:30
2025-02-15 12:51:16 +05:30
await application . SetConfigAsync ( config ) ;
2021-09-19 18:50:06 +05:30
2025-02-15 12:51:16 +05:30
_dnsWebService . _log . Write ( context . GetRemoteEndPoint ( _dnsWebService . _webServiceRealIpHeader ) , "[" + session . User . Username + "] DNS application '" + name + "' app config was saved successfully." ) ;
}
2021-09-18 19:02:40 +05:30
2025-02-15 12:51:16 +05:30
#endregion
2022-09-18 17:49:36 +05:30
2025-02-15 12:51:16 +05:30
#region properties
2022-09-18 17:49:36 +05:30
2025-02-15 12:51:16 +05:30
public bool EnableAutomaticUpdate
2022-09-18 17:49:36 +05:30
{
2025-02-15 12:51:16 +05:30
get { return _appUpdateTimer is not null ; }
set
{
if ( value )
StartAutomaticUpdate ( ) ;
else
StopAutomaticUpdate ( ) ;
}
2022-09-18 17:49:36 +05:30
}
2025-02-15 12:51:16 +05:30
#endregion
}
2021-09-18 19:02:40 +05:30
}
}