2017-05-18 18:16:32 +01:00
//
// Author:
// Natalia Portillo claunia@claunia.com
//
// Copyright (c) 2017, © Claunia.com
//
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
//
// * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
// * 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.
// * Neither the name of the [ORGANIZATION] nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
//
// 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.
//
2017-12-30 00:32:21 +00:00
2017-05-18 18:16:32 +01:00
using System ;
using System.Collections.Generic ;
using System.Diagnostics ;
using System.IO ;
using System.Linq ;
2017-06-13 18:21:12 +01:00
using System.Threading ;
2017-05-18 18:16:32 +01:00
using System.Xml ;
using System.Xml.Serialization ;
using DiscImageChef.Checksums ;
2017-12-30 00:32:21 +00:00
using DiscImageChef.Interop ;
2017-05-18 18:16:32 +01:00
using Newtonsoft.Json ;
using Schemas ;
2017-12-30 00:32:21 +00:00
using SharpCompress.Compressors ;
2017-05-18 18:16:32 +01:00
using SharpCompress.Compressors.BZip2 ;
using SharpCompress.Compressors.Deflate ;
using SharpCompress.Compressors.LZMA ;
2017-12-30 00:32:21 +00:00
using PlatformID = DiscImageChef . Interop . PlatformID ;
2017-05-18 18:16:32 +01:00
namespace osrepodbmgr.Core
{
public static partial class Workers
{
public static void FindFiles ( )
{
string filesPath ;
2017-12-30 00:32:21 +00:00
if ( ! string . IsNullOrEmpty ( Context . TmpFolder ) & & Directory . Exists ( Context . TmpFolder ) )
filesPath = Context . TmpFolder ;
else filesPath = Context . Path ;
2017-05-18 18:16:32 +01:00
2017-12-30 00:32:21 +00:00
if ( string . IsNullOrEmpty ( filesPath ) ) Failed ? . Invoke ( "Path is null or empty" ) ;
2017-05-18 18:16:32 +01:00
2017-12-30 00:32:21 +00:00
if ( ! Directory . Exists ( filesPath ) ) Failed ? . Invoke ( "Directory not found" ) ;
2017-05-18 18:16:32 +01:00
try
{
2017-12-30 00:32:21 +00:00
#if DEBUG
2017-05-19 03:24:34 +01:00
stopwatch . Restart ( ) ;
2017-12-30 00:32:21 +00:00
#endif
Context . Files = IO . EnumerateFiles ( filesPath , "*" , SearchOption . AllDirectories , false , false ) ;
Context . Files . Sort ( ) ;
#if DEBUG
2017-05-19 03:24:34 +01:00
stopwatch . Stop ( ) ;
2017-12-30 00:32:21 +00:00
Console . WriteLine ( "Core.FindFiles(): Took {0} seconds to find all files" ,
stopwatch . Elapsed . TotalSeconds ) ;
2017-05-19 03:24:34 +01:00
stopwatch . Restart ( ) ;
2017-12-30 00:32:21 +00:00
#endif
Context . Folders = IO . EnumerateDirectories ( filesPath , "*" , SearchOption . AllDirectories , false , false ) ;
Context . Folders . Sort ( ) ;
#if DEBUG
2017-05-19 03:24:34 +01:00
stopwatch . Stop ( ) ;
2017-12-30 00:32:21 +00:00
Console . WriteLine ( "Core.FindFiles(): Took {0} seconds to find all folders" ,
stopwatch . Elapsed . TotalSeconds ) ;
2017-08-23 17:47:41 +01:00
stopwatch . Restart ( ) ;
2017-12-30 00:32:21 +00:00
#endif
Context . Symlinks = IO . EnumerateSymlinks ( filesPath , "*" , SearchOption . AllDirectories ) ;
Context . Symlinks . Sort ( ) ;
#if DEBUG
2017-08-23 17:47:41 +01:00
stopwatch . Stop ( ) ;
2017-12-30 00:32:21 +00:00
Console . WriteLine ( "Core.FindFiles(): Took {0} seconds to find all symbolic links" ,
stopwatch . Elapsed . TotalSeconds ) ;
#endif
Finished ? . Invoke ( ) ;
2017-05-18 18:16:32 +01:00
}
2017-12-30 00:32:21 +00:00
catch ( ThreadAbortException ) { }
2017-05-18 18:16:32 +01:00
catch ( Exception ex )
{
2017-12-30 00:32:21 +00:00
if ( Debugger . IsAttached ) throw ;
Failed ? . Invoke ( $"Exception {ex.Message}\n{ex.InnerException}" ) ;
#if DEBUG
2017-06-13 18:21:12 +01:00
Console . WriteLine ( "Exception {0}\n{1}" , ex . Message , ex . InnerException ) ;
2017-12-30 00:32:21 +00:00
#endif
2017-05-18 18:16:32 +01:00
}
}
public static void HashFiles ( )
{
try
{
2017-12-30 00:32:21 +00:00
Context . Hashes = new Dictionary < string , DbOsFile > ( ) ;
Context . FoldersDict = new Dictionary < string , DbFolder > ( ) ;
Context . SymlinksDict = new Dictionary < string , string > ( ) ;
2017-05-18 18:16:32 +01:00
List < string > alreadyMetadata = new List < string > ( ) ;
2017-12-30 00:32:21 +00:00
bool foundMetadata = false ;
2017-05-18 18:16:32 +01:00
// For metadata
2017-12-30 00:32:21 +00:00
List < ArchitecturesTypeArchitecture > architectures = new List < ArchitecturesTypeArchitecture > ( ) ;
List < BarcodeType > barcodes = new List < BarcodeType > ( ) ;
List < BlockMediaType > disks = new List < BlockMediaType > ( ) ;
List < string > categories = new List < string > ( ) ;
List < string > keywords = new List < string > ( ) ;
List < LanguagesTypeLanguage > languages = new List < LanguagesTypeLanguage > ( ) ;
List < OpticalDiscType > discs = new List < OpticalDiscType > ( ) ;
List < string > subcategories = new List < string > ( ) ;
List < string > systems = new List < string > ( ) ;
bool releaseDateSpecified = false ;
DateTime releaseDate = DateTime . MinValue ;
CICMMetadataTypeReleaseType releaseType = CICMMetadataTypeReleaseType . Retail ;
bool releaseTypeSpecified = false ;
List < string > authors = new List < string > ( ) ;
List < string > developers = new List < string > ( ) ;
List < string > performers = new List < string > ( ) ;
List < string > publishers = new List < string > ( ) ;
string metadataName = null ;
string metadataPartNo = null ;
string metadataSerial = null ;
string metadataVersion = null ;
List < MagazineType > magazines = new List < MagazineType > ( ) ;
List < BookType > books = new List < BookType > ( ) ;
List < RequiredOperatingSystemType > requiredOses = new List < RequiredOperatingSystemType > ( ) ;
List < UserManualType > usermanuals = new List < UserManualType > ( ) ;
List < AdvertisementType > adverts = new List < AdvertisementType > ( ) ;
List < LinearMediaType > linearmedias = new List < LinearMediaType > ( ) ;
List < PCIType > pcis = new List < PCIType > ( ) ;
List < AudioMediaType > audiomedias = new List < AudioMediaType > ( ) ;
2017-05-18 18:16:32 +01:00
// End for metadata
2017-12-30 00:32:21 +00:00
if ( ( DetectOS . GetRealPlatformID ( ) = = PlatformID . WinCE | |
DetectOS . GetRealPlatformID ( ) = = PlatformID . Win32S | |
DetectOS . GetRealPlatformID ( ) = = PlatformID . Win32NT | |
DetectOS . GetRealPlatformID ( ) = = PlatformID . Win32Windows | |
DetectOS . GetRealPlatformID ( ) = = PlatformID . WindowsPhone ) & & Context . Symlinks . Count > 0 )
2017-08-23 17:47:41 +01:00
{
2017-12-30 00:32:21 +00:00
Failed ? . Invoke ( "Source contain unsupported symbolic links, not continuing." ) ;
2017-08-23 17:47:41 +01:00
return ;
}
2017-12-30 00:32:21 +00:00
#if DEBUG
2017-05-19 03:24:34 +01:00
stopwatch . Restart ( ) ;
2017-12-30 00:32:21 +00:00
#endif
2017-05-18 18:16:32 +01:00
long counter = 1 ;
2017-12-30 00:32:21 +00:00
foreach ( string file in Context . Files )
2017-05-18 18:16:32 +01:00
{
// An already known metadata file, skip it
if ( alreadyMetadata . Contains ( file ) )
{
counter + + ;
continue ;
}
2017-12-30 00:32:21 +00:00
switch ( Path . GetExtension ( file ) . ToLowerInvariant ( ) )
2017-05-18 18:16:32 +01:00
{
2017-12-30 00:32:21 +00:00
case ".xml" :
FileStream xrs = new FileStream ( file , FileMode . Open , FileAccess . Read ) ;
XmlReaderSettings xrt = new XmlReaderSettings { DtdProcessing = DtdProcessing . Ignore } ;
2017-08-16 00:13:49 +01:00
2017-12-30 00:32:21 +00:00
XmlReader xr = XmlReader . Create ( xrs , xrt ) ;
XmlSerializer xs = new XmlSerializer ( typeof ( CICMMetadataType ) ) ;
try
{
if ( xs . CanDeserialize ( xr ) )
{
CICMMetadataType thisMetadata = ( CICMMetadataType ) xs . Deserialize ( xr ) ;
if ( thisMetadata . Architectures ! = null )
architectures . AddRange ( thisMetadata . Architectures ) ;
if ( thisMetadata . Barcodes ! = null ) barcodes . AddRange ( thisMetadata . Barcodes ) ;
if ( thisMetadata . BlockMedia ! = null ) disks . AddRange ( thisMetadata . BlockMedia ) ;
if ( thisMetadata . Categories ! = null ) categories . AddRange ( thisMetadata . Categories ) ;
if ( thisMetadata . Keywords ! = null ) keywords . AddRange ( thisMetadata . Keywords ) ;
if ( thisMetadata . Languages ! = null ) languages . AddRange ( thisMetadata . Languages ) ;
if ( thisMetadata . OpticalDisc ! = null ) discs . AddRange ( thisMetadata . OpticalDisc ) ;
if ( thisMetadata . Subcategories ! = null )
subcategories . AddRange ( thisMetadata . Subcategories ) ;
if ( thisMetadata . Systems ! = null ) systems . AddRange ( thisMetadata . Systems ) ;
if ( thisMetadata . Author ! = null ) authors . AddRange ( thisMetadata . Author ) ;
if ( thisMetadata . Developer ! = null ) developers . AddRange ( thisMetadata . Developer ) ;
if ( thisMetadata . Performer ! = null ) performers . AddRange ( thisMetadata . Performer ) ;
if ( thisMetadata . Publisher ! = null ) publishers . AddRange ( thisMetadata . Publisher ) ;
if ( string . IsNullOrWhiteSpace ( metadataName ) & &
! string . IsNullOrWhiteSpace ( thisMetadata . Name ) ) metadataName = thisMetadata . Name ;
if ( string . IsNullOrWhiteSpace ( metadataPartNo ) & &
! string . IsNullOrWhiteSpace ( thisMetadata . PartNumber ) )
metadataPartNo = thisMetadata . PartNumber ;
if ( string . IsNullOrWhiteSpace ( metadataSerial ) & &
! string . IsNullOrWhiteSpace ( thisMetadata . SerialNumber ) )
metadataSerial = thisMetadata . SerialNumber ;
if ( string . IsNullOrWhiteSpace ( metadataVersion ) & &
! string . IsNullOrWhiteSpace ( thisMetadata . Version ) )
metadataVersion = thisMetadata . Version ;
if ( thisMetadata . ReleaseDateSpecified )
if ( thisMetadata . ReleaseDate > releaseDate )
{
releaseDateSpecified = true ;
releaseDate = thisMetadata . ReleaseDate ;
}
if ( thisMetadata . ReleaseTypeSpecified )
{
releaseTypeSpecified = true ;
releaseType = thisMetadata . ReleaseType ;
}
if ( thisMetadata . Magazine ! = null )
magazines . AddRange ( thisMetadata . Magazine ) ;
if ( thisMetadata . Book ! = null ) books . AddRange ( thisMetadata . Book ) ;
if ( thisMetadata . RequiredOperatingSystems ! = null )
requiredOses . AddRange ( thisMetadata . RequiredOperatingSystems ) ;
if ( thisMetadata . UserManual ! = null )
usermanuals . AddRange ( thisMetadata . UserManual ) ;
if ( thisMetadata . Advertisement ! = null ) adverts . AddRange ( thisMetadata . Advertisement ) ;
if ( thisMetadata . LinearMedia ! = null )
linearmedias . AddRange ( thisMetadata . LinearMedia ) ;
if ( thisMetadata . PCICard ! = null ) pcis . AddRange ( thisMetadata . PCICard ) ;
if ( thisMetadata . AudioMedia ! = null ) audiomedias . AddRange ( thisMetadata . AudioMedia ) ;
foundMetadata = true ;
string metadataFileWithoutExtension =
Path . Combine ( Path . GetDirectoryName ( file ) ,
Path . GetFileNameWithoutExtension ( file ) ) ;
alreadyMetadata . Add ( metadataFileWithoutExtension + ".xml" ) ;
alreadyMetadata . Add ( metadataFileWithoutExtension + ".xmL" ) ;
alreadyMetadata . Add ( metadataFileWithoutExtension + ".xMl" ) ;
alreadyMetadata . Add ( metadataFileWithoutExtension + ".xML" ) ;
alreadyMetadata . Add ( metadataFileWithoutExtension + ".Xml" ) ;
alreadyMetadata . Add ( metadataFileWithoutExtension + ".XmL" ) ;
alreadyMetadata . Add ( metadataFileWithoutExtension + ".XMl" ) ;
alreadyMetadata . Add ( metadataFileWithoutExtension + ".XML" ) ;
alreadyMetadata . Add ( metadataFileWithoutExtension + ".json" ) ;
alreadyMetadata . Add ( metadataFileWithoutExtension + ".jsoN" ) ;
alreadyMetadata . Add ( metadataFileWithoutExtension + ".jsOn" ) ;
alreadyMetadata . Add ( metadataFileWithoutExtension + ".jsON" ) ;
alreadyMetadata . Add ( metadataFileWithoutExtension + ".jSon" ) ;
alreadyMetadata . Add ( metadataFileWithoutExtension + ".jSoN" ) ;
alreadyMetadata . Add ( metadataFileWithoutExtension + ".jSOn" ) ;
alreadyMetadata . Add ( metadataFileWithoutExtension + ".jSON" ) ;
alreadyMetadata . Add ( metadataFileWithoutExtension + ".Json" ) ;
alreadyMetadata . Add ( metadataFileWithoutExtension + ".JsoN" ) ;
alreadyMetadata . Add ( metadataFileWithoutExtension + ".JsOn" ) ;
alreadyMetadata . Add ( metadataFileWithoutExtension + ".JsON" ) ;
alreadyMetadata . Add ( metadataFileWithoutExtension + ".JSon" ) ;
alreadyMetadata . Add ( metadataFileWithoutExtension + ".JSoN" ) ;
alreadyMetadata . Add ( metadataFileWithoutExtension + ".JSOn" ) ;
alreadyMetadata . Add ( metadataFileWithoutExtension + ".JSON" ) ;
xr . Close ( ) ;
xrs . Close ( ) ;
continue ;
}
}
catch ( XmlException )
{
xr . Close ( ) ;
xrs . Close ( ) ;
}
break ;
case ".json" :
FileStream jrs = new FileStream ( file , FileMode . Open , FileAccess . Read ) ;
TextReader jr = new StreamReader ( jrs ) ;
JsonSerializer js = new JsonSerializer ( ) ;
try
2017-05-18 18:16:32 +01:00
{
2017-12-30 00:32:21 +00:00
CICMMetadataType thisMetadata =
( CICMMetadataType ) js . Deserialize ( jr , typeof ( CICMMetadataType ) ) ;
2017-08-22 18:05:18 +01:00
if ( thisMetadata . Architectures ! = null )
2017-08-16 00:13:49 +01:00
architectures . AddRange ( thisMetadata . Architectures ) ;
2017-12-30 00:32:21 +00:00
if ( thisMetadata . Barcodes ! = null ) barcodes . AddRange ( thisMetadata . Barcodes ) ;
if ( thisMetadata . BlockMedia ! = null ) disks . AddRange ( thisMetadata . BlockMedia ) ;
if ( thisMetadata . Categories ! = null ) categories . AddRange ( thisMetadata . Categories ) ;
if ( thisMetadata . Keywords ! = null ) keywords . AddRange ( thisMetadata . Keywords ) ;
if ( thisMetadata . Languages ! = null ) languages . AddRange ( thisMetadata . Languages ) ;
if ( thisMetadata . OpticalDisc ! = null ) discs . AddRange ( thisMetadata . OpticalDisc ) ;
2017-08-22 18:05:18 +01:00
if ( thisMetadata . Subcategories ! = null )
2017-08-16 00:13:49 +01:00
subcategories . AddRange ( thisMetadata . Subcategories ) ;
2017-12-30 00:32:21 +00:00
if ( thisMetadata . Systems ! = null ) systems . AddRange ( thisMetadata . Systems ) ;
if ( thisMetadata . Author ! = null ) authors . AddRange ( thisMetadata . Author ) ;
if ( thisMetadata . Developer ! = null ) developers . AddRange ( thisMetadata . Developer ) ;
if ( thisMetadata . Performer ! = null ) performers . AddRange ( thisMetadata . Performer ) ;
if ( thisMetadata . Publisher ! = null ) publishers . AddRange ( thisMetadata . Publisher ) ;
if ( string . IsNullOrWhiteSpace ( metadataName ) & &
! string . IsNullOrWhiteSpace ( thisMetadata . Name ) ) metadataName = thisMetadata . Name ;
if ( string . IsNullOrWhiteSpace ( metadataPartNo ) & &
! string . IsNullOrWhiteSpace ( thisMetadata . PartNumber ) )
2017-08-16 00:13:49 +01:00
metadataPartNo = thisMetadata . PartNumber ;
2017-12-30 00:32:21 +00:00
if ( string . IsNullOrWhiteSpace ( metadataSerial ) & &
! string . IsNullOrWhiteSpace ( thisMetadata . SerialNumber ) )
2017-08-16 00:13:49 +01:00
metadataSerial = thisMetadata . SerialNumber ;
2017-12-30 00:32:21 +00:00
if ( string . IsNullOrWhiteSpace ( metadataVersion ) & &
! string . IsNullOrWhiteSpace ( thisMetadata . Version ) )
2017-08-16 00:13:49 +01:00
metadataVersion = thisMetadata . Version ;
2017-08-22 18:05:18 +01:00
if ( thisMetadata . ReleaseDateSpecified )
if ( thisMetadata . ReleaseDate > releaseDate )
2017-08-16 00:13:49 +01:00
{
releaseDateSpecified = true ;
2017-12-30 00:32:21 +00:00
releaseDate = thisMetadata . ReleaseDate ;
2017-08-16 00:13:49 +01:00
}
2017-12-30 00:32:21 +00:00
2017-08-22 18:05:18 +01:00
if ( thisMetadata . ReleaseTypeSpecified )
2017-08-16 00:13:49 +01:00
{
releaseTypeSpecified = true ;
2017-12-30 00:32:21 +00:00
releaseType = thisMetadata . ReleaseType ;
2017-05-18 18:16:32 +01:00
}
2017-12-30 00:32:21 +00:00
2017-09-30 17:47:54 +01:00
if ( thisMetadata . Magazine ! = null )
magazines . AddRange ( thisMetadata . Magazine ) ;
2017-12-30 00:32:21 +00:00
if ( thisMetadata . Book ! = null ) books . AddRange ( thisMetadata . Book ) ;
2017-09-30 17:47:54 +01:00
if ( thisMetadata . RequiredOperatingSystems ! = null )
requiredOses . AddRange ( thisMetadata . RequiredOperatingSystems ) ;
2017-12-30 00:32:21 +00:00
if ( thisMetadata . UserManual ! = null ) usermanuals . AddRange ( thisMetadata . UserManual ) ;
if ( thisMetadata . Advertisement ! = null ) adverts . AddRange ( thisMetadata . Advertisement ) ;
if ( thisMetadata . LinearMedia ! = null ) linearmedias . AddRange ( thisMetadata . LinearMedia ) ;
if ( thisMetadata . PCICard ! = null ) pcis . AddRange ( thisMetadata . PCICard ) ;
if ( thisMetadata . AudioMedia ! = null ) audiomedias . AddRange ( thisMetadata . AudioMedia ) ;
2017-05-18 18:16:32 +01:00
2017-08-16 00:13:49 +01:00
foundMetadata = true ;
2017-05-18 18:16:32 +01:00
2017-12-30 00:32:21 +00:00
string metadataFileWithoutExtension =
Path . Combine ( Path . GetDirectoryName ( file ) , Path . GetFileNameWithoutExtension ( file ) ) ;
2017-08-16 00:13:49 +01:00
alreadyMetadata . Add ( metadataFileWithoutExtension + ".xml" ) ;
alreadyMetadata . Add ( metadataFileWithoutExtension + ".xmL" ) ;
alreadyMetadata . Add ( metadataFileWithoutExtension + ".xMl" ) ;
alreadyMetadata . Add ( metadataFileWithoutExtension + ".xML" ) ;
alreadyMetadata . Add ( metadataFileWithoutExtension + ".Xml" ) ;
alreadyMetadata . Add ( metadataFileWithoutExtension + ".XmL" ) ;
alreadyMetadata . Add ( metadataFileWithoutExtension + ".XMl" ) ;
alreadyMetadata . Add ( metadataFileWithoutExtension + ".XML" ) ;
alreadyMetadata . Add ( metadataFileWithoutExtension + ".json" ) ;
alreadyMetadata . Add ( metadataFileWithoutExtension + ".jsoN" ) ;
alreadyMetadata . Add ( metadataFileWithoutExtension + ".jsOn" ) ;
alreadyMetadata . Add ( metadataFileWithoutExtension + ".jsON" ) ;
alreadyMetadata . Add ( metadataFileWithoutExtension + ".jSon" ) ;
alreadyMetadata . Add ( metadataFileWithoutExtension + ".jSoN" ) ;
alreadyMetadata . Add ( metadataFileWithoutExtension + ".jSOn" ) ;
alreadyMetadata . Add ( metadataFileWithoutExtension + ".jSON" ) ;
alreadyMetadata . Add ( metadataFileWithoutExtension + ".Json" ) ;
alreadyMetadata . Add ( metadataFileWithoutExtension + ".JsoN" ) ;
alreadyMetadata . Add ( metadataFileWithoutExtension + ".JsOn" ) ;
alreadyMetadata . Add ( metadataFileWithoutExtension + ".JsON" ) ;
alreadyMetadata . Add ( metadataFileWithoutExtension + ".JSon" ) ;
alreadyMetadata . Add ( metadataFileWithoutExtension + ".JSoN" ) ;
alreadyMetadata . Add ( metadataFileWithoutExtension + ".JSOn" ) ;
alreadyMetadata . Add ( metadataFileWithoutExtension + ".JSON" ) ;
2017-05-18 18:16:32 +01:00
2017-12-30 00:32:21 +00:00
jr . Close ( ) ;
jrs . Close ( ) ;
2017-08-16 00:13:49 +01:00
continue ;
}
2017-12-30 00:32:21 +00:00
catch ( JsonException )
2017-05-18 18:16:32 +01:00
{
2017-12-30 00:32:21 +00:00
jr . Close ( ) ;
jrs . Close ( ) ;
2017-05-18 18:16:32 +01:00
}
2017-12-30 00:32:21 +00:00
break ;
2017-05-18 18:16:32 +01:00
}
2017-12-30 00:32:21 +00:00
string filesPath ;
2017-05-18 18:16:32 +01:00
FileInfo fi = new FileInfo ( file ) ;
2017-12-30 00:32:21 +00:00
if ( ! string . IsNullOrEmpty ( Context . TmpFolder ) & & Directory . Exists ( Context . TmpFolder ) )
filesPath = Context . TmpFolder ;
else filesPath = Context . Path ;
2017-05-18 18:16:32 +01:00
string relpath = file . Substring ( filesPath . Length + 1 ) ;
2017-05-21 14:26:21 +01:00
2017-12-30 00:32:21 +00:00
UpdateProgress ? . Invoke ( $"Hashing file {counter} of {Context.Files.Count}" , null , counter ,
Context . Files . Count ) ;
2017-05-18 18:16:32 +01:00
FileStream fileStream = new FileStream ( file , FileMode . Open , FileAccess . Read ) ;
2017-12-30 00:32:21 +00:00
byte [ ] dataBuffer ;
2017-12-29 19:31:26 +00:00
Sha256Context sha256Context = new Sha256Context ( ) ;
2017-05-18 18:16:32 +01:00
sha256Context . Init ( ) ;
2017-12-30 00:32:21 +00:00
if ( fileStream . Length > BUFFER_SIZE )
2017-05-18 18:16:32 +01:00
{
long offset ;
2017-12-30 00:32:21 +00:00
long remainder = fileStream . Length % BUFFER_SIZE ;
for ( offset = 0 ; offset < fileStream . Length - remainder ; offset + = ( int ) BUFFER_SIZE )
2017-05-18 18:16:32 +01:00
{
2017-12-30 00:32:21 +00:00
UpdateProgress2 ? . Invoke ( $"{offset / (double)fileStream.Length:P}" , relpath , offset ,
fileStream . Length ) ;
dataBuffer = new byte [ BUFFER_SIZE ] ;
fileStream . Read ( dataBuffer , 0 , ( int ) BUFFER_SIZE ) ;
2017-05-18 18:16:32 +01:00
sha256Context . Update ( dataBuffer ) ;
}
2017-12-30 00:32:21 +00:00
UpdateProgress2 ? . Invoke ( $"{offset / (double)fileStream.Length:P}" , relpath , offset ,
fileStream . Length ) ;
2017-05-18 18:16:32 +01:00
dataBuffer = new byte [ remainder ] ;
fileStream . Read ( dataBuffer , 0 , ( int ) remainder ) ;
sha256Context . Update ( dataBuffer ) ;
}
else
{
2017-12-30 00:32:21 +00:00
UpdateProgress2 ? . Invoke ( $"{0 / (double)fileStream.Length:P}" , relpath , 0 , fileStream . Length ) ;
2017-05-18 18:16:32 +01:00
dataBuffer = new byte [ fileStream . Length ] ;
fileStream . Read ( dataBuffer , 0 , ( int ) fileStream . Length ) ;
sha256Context . Update ( dataBuffer ) ;
}
fileStream . Close ( ) ;
2017-12-30 00:32:21 +00:00
string hash = Stringify ( sha256Context . Final ( ) ) ;
2017-05-18 18:16:32 +01:00
2017-12-30 00:32:21 +00:00
DbOsFile dbFile = new DbOsFile
{
Attributes = fi . Attributes ,
CreationTimeUtc = fi . CreationTimeUtc ,
LastAccessTimeUtc = fi . LastAccessTimeUtc ,
LastWriteTimeUtc = fi . LastWriteTimeUtc ,
Length = fi . Length ,
Path = relpath ,
Sha256 = hash
} ;
2017-05-18 18:16:32 +01:00
// TODO: Add common cracker group names?
2017-12-30 00:32:21 +00:00
dbFile . Crack | = relpath . ToLowerInvariant ( ) . Contains ( "crack" ) | | // Typical crack
relpath . ToLowerInvariant ( ) . Contains ( "crack" ) | | // Typical keygen
relpath . ToLowerInvariant ( ) . Contains ( "[k]" ) ;
2017-05-18 18:16:32 +01:00
2017-12-30 00:32:21 +00:00
Context . Hashes . Add ( relpath , dbFile ) ;
2017-05-18 18:16:32 +01:00
counter + + ;
}
2017-12-30 00:32:21 +00:00
#if DEBUG
2017-05-19 03:24:34 +01:00
stopwatch . Stop ( ) ;
2017-12-30 00:32:21 +00:00
Console . WriteLine ( "Core.HashFiles(): Took {0} seconds to hash all files" ,
stopwatch . Elapsed . TotalSeconds ) ;
2017-05-19 03:24:34 +01:00
stopwatch . Restart ( ) ;
2017-12-30 00:32:21 +00:00
#endif
2017-05-18 18:16:32 +01:00
counter = 1 ;
2017-12-30 00:32:21 +00:00
foreach ( string folder in Context . Folders )
2017-05-18 18:16:32 +01:00
{
2017-12-30 00:32:21 +00:00
string filesPath ;
2017-05-18 18:16:32 +01:00
DirectoryInfo di = new DirectoryInfo ( folder ) ;
2017-12-30 00:32:21 +00:00
if ( ! string . IsNullOrEmpty ( Context . TmpFolder ) & & Directory . Exists ( Context . TmpFolder ) )
filesPath = Context . TmpFolder ;
else filesPath = Context . Path ;
2017-05-18 18:16:32 +01:00
string relpath = folder . Substring ( filesPath . Length + 1 ) ;
2017-12-30 00:32:21 +00:00
UpdateProgress ? . Invoke ( $"Checking folder {counter} of {Context.Folders.Count}" , null , counter ,
Context . Folders . Count ) ;
2017-05-18 18:16:32 +01:00
2017-12-30 00:32:21 +00:00
DbFolder dbFolder = new DbFolder
{
Attributes = di . Attributes ,
CreationTimeUtc = di . CreationTimeUtc ,
LastAccessTimeUtc = di . LastAccessTimeUtc ,
LastWriteTimeUtc = di . LastWriteTimeUtc ,
Path = relpath
} ;
Context . FoldersDict . Add ( relpath , dbFolder ) ;
2017-05-18 18:16:32 +01:00
counter + + ;
}
2017-12-30 00:32:21 +00:00
#if DEBUG
2017-05-19 03:24:34 +01:00
stopwatch . Stop ( ) ;
2017-12-30 00:32:21 +00:00
Console . WriteLine ( "Core.HashFiles(): Took {0} seconds to iterate all folders" ,
stopwatch . Elapsed . TotalSeconds ) ;
2017-08-23 17:47:41 +01:00
stopwatch . Restart ( ) ;
2017-12-30 00:32:21 +00:00
#endif
2017-08-23 17:47:41 +01:00
counter = 2 ;
2017-12-30 00:32:21 +00:00
foreach ( string symlink in Context . Symlinks )
2017-08-23 17:47:41 +01:00
{
string filesPath ;
2017-12-30 00:32:21 +00:00
if ( ! string . IsNullOrEmpty ( Context . TmpFolder ) & & Directory . Exists ( Context . TmpFolder ) )
filesPath = Context . TmpFolder ;
else filesPath = Context . Path ;
2017-08-23 17:47:41 +01:00
string relpath = symlink . Substring ( filesPath . Length + 1 ) ;
2017-12-30 00:32:21 +00:00
UpdateProgress ? . Invoke ( $"Resolving symlink {counter} of {Context.Symlinks.Count}" , null , counter ,
Context . Symlinks . Count ) ;
2017-08-23 17:47:41 +01:00
string target = Symlinks . ReadLink ( symlink ) ;
2017-12-30 00:32:21 +00:00
if ( target = = null )
2017-08-23 17:47:41 +01:00
{
2017-12-30 00:32:21 +00:00
Failed ? . Invoke ( $"Could not resolve symbolic link at {relpath}, not continuing." ) ;
2017-08-23 17:47:41 +01:00
return ;
}
2017-12-30 00:32:21 +00:00
Context . SymlinksDict . Add ( relpath , target ) ;
2017-08-23 17:47:41 +01:00
counter + + ;
}
2017-12-30 00:32:21 +00:00
#if DEBUG
2017-08-23 17:47:41 +01:00
stopwatch . Stop ( ) ;
2017-12-30 00:32:21 +00:00
Console . WriteLine ( "Core.HashFiles(): Took {0} seconds to resolve all symbolic links" ,
stopwatch . Elapsed . TotalSeconds ) ;
#endif
2017-05-18 18:16:32 +01:00
if ( foundMetadata )
{
2017-12-30 00:32:21 +00:00
Context . Metadata = new CICMMetadataType ( ) ;
if ( architectures . Count > 0 ) Context . Metadata . Architectures = architectures . Distinct ( ) . ToArray ( ) ;
if ( authors . Count > 0 ) Context . Metadata . Author = authors . Distinct ( ) . ToArray ( ) ;
2017-05-18 18:16:32 +01:00
// TODO: Check for uniqueness
2017-12-30 00:32:21 +00:00
if ( barcodes . Count > 0 ) Context . Metadata . Barcodes = barcodes . ToArray ( ) ;
if ( disks . Count > 0 ) Context . Metadata . BlockMedia = disks . ToArray ( ) ;
if ( categories . Count > 0 ) Context . Metadata . Categories = categories . Distinct ( ) . ToArray ( ) ;
if ( developers . Count > 0 ) Context . Metadata . Developer = developers . Distinct ( ) . ToArray ( ) ;
if ( keywords . Count > 0 ) Context . Metadata . Keywords = keywords . Distinct ( ) . ToArray ( ) ;
if ( languages . Count > 0 ) Context . Metadata . Languages = languages . Distinct ( ) . ToArray ( ) ;
Context . Metadata . Name = metadataName ;
if ( discs . Count > 0 ) Context . Metadata . OpticalDisc = discs . ToArray ( ) ;
Context . Metadata . PartNumber = metadataPartNo ;
if ( performers . Count > 0 ) Context . Metadata . Performer = performers . Distinct ( ) . ToArray ( ) ;
if ( publishers . Count > 0 ) Context . Metadata . Publisher = publishers . Distinct ( ) . ToArray ( ) ;
2017-05-18 18:16:32 +01:00
if ( releaseDateSpecified )
{
2017-12-30 00:32:21 +00:00
Context . Metadata . ReleaseDate = releaseDate ;
Context . Metadata . ReleaseDateSpecified = true ;
2017-05-18 18:16:32 +01:00
}
2017-12-30 00:32:21 +00:00
2017-05-18 18:16:32 +01:00
if ( releaseTypeSpecified )
{
2017-12-30 00:32:21 +00:00
Context . Metadata . ReleaseType = releaseType ;
Context . Metadata . ReleaseTypeSpecified = true ;
2017-05-18 18:16:32 +01:00
}
2017-12-30 00:32:21 +00:00
Context . Metadata . SerialNumber = metadataSerial ;
if ( subcategories . Count > 0 ) Context . Metadata . Subcategories = subcategories . Distinct ( ) . ToArray ( ) ;
if ( systems . Count > 0 ) Context . Metadata . Systems = systems . Distinct ( ) . ToArray ( ) ;
Context . Metadata . Version = metadataVersion ;
Context . Metadata . Magazine = magazines . ToArray ( ) ;
Context . Metadata . Book = books . ToArray ( ) ;
Context . Metadata . RequiredOperatingSystems = requiredOses . ToArray ( ) ;
Context . Metadata . UserManual = usermanuals . ToArray ( ) ;
Context . Metadata . Advertisement = adverts . ToArray ( ) ;
Context . Metadata . LinearMedia = linearmedias . ToArray ( ) ;
Context . Metadata . PCICard = pcis . ToArray ( ) ;
Context . Metadata . AudioMedia = audiomedias . ToArray ( ) ;
foreach ( string metadataFile in alreadyMetadata ) Context . Files . Remove ( metadataFile ) ;
2017-05-18 18:16:32 +01:00
}
2017-12-30 00:32:21 +00:00
else Context . Metadata = null ;
Finished ? . Invoke ( ) ;
2017-05-18 18:16:32 +01:00
}
2017-12-30 00:32:21 +00:00
catch ( ThreadAbortException ) { }
2017-05-18 18:16:32 +01:00
catch ( Exception ex )
{
2017-12-30 00:32:21 +00:00
if ( Debugger . IsAttached ) throw ;
Failed ? . Invoke ( $"Exception {ex.Message}\n{ex.InnerException}" ) ;
#if DEBUG
2017-06-13 18:21:12 +01:00
Console . WriteLine ( "Exception {0}\n{1}" , ex . Message , ex . InnerException ) ;
2017-12-30 00:32:21 +00:00
#endif
2017-05-18 18:16:32 +01:00
}
}
public static void RemoveTempFolder ( )
{
try
{
2017-12-30 00:32:21 +00:00
if ( ! Directory . Exists ( Context . TmpFolder ) ) return ;
Directory . Delete ( Context . TmpFolder , true ) ;
Finished ? . Invoke ( ) ;
2017-05-18 18:16:32 +01:00
}
2017-12-30 00:32:21 +00:00
catch ( ThreadAbortException ) { }
2017-06-13 18:21:12 +01:00
catch ( IOException )
2017-05-18 18:16:32 +01:00
{
// Could not delete temporary files, do not crash.
2017-12-30 00:32:21 +00:00
Finished ? . Invoke ( ) ;
2017-05-18 18:16:32 +01:00
}
catch ( Exception ex )
{
2017-12-30 00:32:21 +00:00
if ( Debugger . IsAttached ) throw ;
Failed ? . Invoke ( $"Exception {ex.Message}\n{ex.InnerException}" ) ;
#if DEBUG
2017-06-13 18:21:12 +01:00
Console . WriteLine ( "Exception {0}\n{1}" , ex . Message , ex . InnerException ) ;
2017-12-30 00:32:21 +00:00
#endif
2017-05-18 18:16:32 +01:00
}
}
public static void CopyFile ( )
{
try
{
2017-12-30 00:32:21 +00:00
if ( ! File . Exists ( Context . Path ) )
2017-05-18 18:16:32 +01:00
{
2017-12-30 00:32:21 +00:00
Failed ? . Invoke ( "Specified file cannot be found" ) ;
2017-05-18 18:16:32 +01:00
return ;
}
2017-12-30 00:32:21 +00:00
if ( string . IsNullOrWhiteSpace ( Context . TmpFolder ) )
2017-05-18 18:16:32 +01:00
{
2017-12-30 00:32:21 +00:00
Failed ? . Invoke ( "Destination cannot be empty" ) ;
2017-05-18 18:16:32 +01:00
return ;
}
2017-12-30 00:32:21 +00:00
if ( Directory . Exists ( Context . TmpFolder ) )
2017-05-18 18:16:32 +01:00
{
2017-12-30 00:32:21 +00:00
Failed ? . Invoke ( "Destination cannot be a folder" ) ;
2017-05-18 18:16:32 +01:00
return ;
}
2017-12-30 00:32:21 +00:00
FileStream inFs = new FileStream ( Context . Path , FileMode . Open , FileAccess . Read ) ;
FileStream outFs = new FileStream ( Context . TmpFolder , FileMode . Create , FileAccess . Write ) ;
2017-05-18 18:16:32 +01:00
2017-12-30 00:32:21 +00:00
#if DEBUG
2017-05-19 03:24:34 +01:00
stopwatch . Restart ( ) ;
2017-12-30 00:32:21 +00:00
#endif
byte [ ] buffer = new byte [ BUFFER_SIZE ] ;
2017-05-18 18:16:32 +01:00
2017-12-30 00:32:21 +00:00
while ( inFs . Position + BUFFER_SIZE < = inFs . Length )
2017-05-18 18:16:32 +01:00
{
2017-12-30 00:32:21 +00:00
UpdateProgress ? . Invoke ( "Copying file..." , $"{inFs.Position} / {inFs.Length} bytes" , inFs . Position ,
inFs . Length ) ;
2017-05-18 18:16:32 +01:00
inFs . Read ( buffer , 0 , buffer . Length ) ;
outFs . Write ( buffer , 0 , buffer . Length ) ;
}
buffer = new byte [ inFs . Length - inFs . Position ] ;
2017-12-30 00:32:21 +00:00
UpdateProgress ? . Invoke ( "Copying file..." , $"{inFs.Position} / {inFs.Length} bytes" , inFs . Position ,
inFs . Length ) ;
2017-05-18 18:16:32 +01:00
inFs . Read ( buffer , 0 , buffer . Length ) ;
outFs . Write ( buffer , 0 , buffer . Length ) ;
inFs . Close ( ) ;
outFs . Close ( ) ;
2017-12-30 00:32:21 +00:00
#if DEBUG
2017-05-19 03:24:34 +01:00
stopwatch . Stop ( ) ;
Console . WriteLine ( "Core.CopyFile(): Took {0} seconds to copy file" , stopwatch . Elapsed . TotalSeconds ) ;
2017-12-30 00:32:21 +00:00
#endif
2017-05-18 18:16:32 +01:00
2017-12-30 00:32:21 +00:00
Finished ? . Invoke ( ) ;
2017-05-18 18:16:32 +01:00
}
2017-12-30 00:32:21 +00:00
catch ( ThreadAbortException ) { }
2017-05-18 18:16:32 +01:00
catch ( Exception ex )
{
2017-12-30 00:32:21 +00:00
if ( Debugger . IsAttached ) throw ;
Failed ? . Invoke ( $"Exception {ex.Message}\n{ex.InnerException}" ) ;
#if DEBUG
2017-06-13 18:21:12 +01:00
Console . WriteLine ( "Exception {0}\n{1}" , ex . Message , ex . InnerException ) ;
2017-12-30 00:32:21 +00:00
#endif
2017-05-18 18:16:32 +01:00
}
}
public static void SaveAs ( )
{
try
{
2017-12-30 00:32:21 +00:00
if ( string . IsNullOrWhiteSpace ( Context . Path ) )
2017-05-18 18:16:32 +01:00
{
2017-12-30 00:32:21 +00:00
Failed ? . Invoke ( "Destination cannot be empty" ) ;
2017-05-18 18:16:32 +01:00
return ;
}
2017-12-30 00:32:21 +00:00
if ( File . Exists ( Context . Path ) )
2017-05-18 18:16:32 +01:00
{
2017-12-30 00:32:21 +00:00
Failed ? . Invoke ( "Destination cannot be a file" ) ;
2017-05-18 18:16:32 +01:00
return ;
}
2017-12-30 00:32:21 +00:00
if ( Context . DbInfo . Id = = 0 )
2017-05-18 18:16:32 +01:00
{
2017-12-30 00:32:21 +00:00
Failed ? . Invoke ( "Operating system must be set" ) ;
2017-05-18 18:16:32 +01:00
return ;
}
2017-12-30 00:32:21 +00:00
bool symlinksSupported = DetectOS . GetRealPlatformID ( ) ! = PlatformID . WinCE & &
DetectOS . GetRealPlatformID ( ) ! = PlatformID . Win32S & &
DetectOS . GetRealPlatformID ( ) ! = PlatformID . Win32NT & &
DetectOS . GetRealPlatformID ( ) ! = PlatformID . Win32Windows & &
DetectOS . GetRealPlatformID ( ) ! = PlatformID . WindowsPhone ;
2017-08-22 18:05:18 +01:00
Dictionary < string , string > symlinks = new Dictionary < string , string > ( ) ;
2017-05-18 18:16:32 +01:00
2017-12-30 00:32:21 +00:00
UpdateProgress ? . Invoke ( "" , "Asking DB for files..." , 1 , 100 ) ;
2017-05-18 18:16:32 +01:00
2017-12-30 00:32:21 +00:00
dbCore . DbOps . GetAllFilesInOs ( out List < DbOsFile > files , Context . DbInfo . Id ) ;
2017-05-18 18:16:32 +01:00
2017-12-30 00:32:21 +00:00
UpdateProgress ? . Invoke ( "" , "Asking DB for folders..." , 2 , 100 ) ;
2017-05-18 18:16:32 +01:00
2017-12-30 00:32:21 +00:00
dbCore . DbOps . GetAllFolders ( out List < DbFolder > folders , Context . DbInfo . Id ) ;
2017-05-18 18:16:32 +01:00
2017-12-30 00:32:21 +00:00
UpdateProgress ? . Invoke ( "" , "Asking DB for symbolic links..." , 3 , 100 ) ;
2017-08-22 18:05:18 +01:00
2017-12-30 00:32:21 +00:00
if ( dbCore . DbOps . HasSymlinks ( Context . DbInfo . Id ) )
2017-08-22 18:05:18 +01:00
{
if ( ! symlinksSupported )
{
2017-12-30 00:32:21 +00:00
Failed ? . Invoke ( "Symbolic links cannot be created on this platform." ) ;
2017-08-22 18:05:18 +01:00
return ;
}
2017-12-30 00:32:21 +00:00
dbCore . DbOps . GetAllSymlinks ( out symlinks , Context . DbInfo . Id ) ;
2017-08-22 18:05:18 +01:00
}
2017-12-30 00:32:21 +00:00
UpdateProgress ? . Invoke ( "" , "Creating folders..." , 4 , 100 ) ;
2017-05-18 18:16:32 +01:00
2017-12-30 00:32:21 +00:00
#if DEBUG
2017-05-19 03:24:34 +01:00
stopwatch . Restart ( ) ;
2017-12-30 00:32:21 +00:00
#endif
long counter = 0 ;
foreach ( DbFolder folder in folders )
2017-05-18 18:16:32 +01:00
{
2017-12-30 00:32:21 +00:00
UpdateProgress2 ? . Invoke ( "" , folder . Path , counter , folders . Count ) ;
2017-05-18 18:16:32 +01:00
2017-12-30 00:32:21 +00:00
DirectoryInfo di = Directory . CreateDirectory ( Path . Combine ( Context . Path , folder . Path ) ) ;
di . Attributes = folder . Attributes ;
di . CreationTimeUtc = folder . CreationTimeUtc ;
2017-05-18 18:16:32 +01:00
di . LastAccessTimeUtc = folder . LastAccessTimeUtc ;
2017-12-30 00:32:21 +00:00
di . LastWriteTimeUtc = folder . LastWriteTimeUtc ;
2017-05-18 18:16:32 +01:00
counter + + ;
}
2017-12-30 00:32:21 +00:00
#if DEBUG
2017-05-19 03:24:34 +01:00
stopwatch . Stop ( ) ;
2017-12-30 00:32:21 +00:00
Console . WriteLine ( "Core.SaveAs(): Took {0} seconds to create all folders" ,
stopwatch . Elapsed . TotalSeconds ) ;
#endif
2017-05-19 03:24:34 +01:00
2017-12-30 00:32:21 +00:00
UpdateProgress ? . Invoke ( "" , "Creating symbolic links..." , 4 , 100 ) ;
2017-08-22 18:05:18 +01:00
2017-12-30 00:32:21 +00:00
#if DEBUG
2017-05-19 03:24:34 +01:00
stopwatch . Restart ( ) ;
2017-12-30 00:32:21 +00:00
#endif
2017-08-22 18:05:18 +01:00
counter = 0 ;
foreach ( KeyValuePair < string , string > kvp in symlinks )
{
2017-12-30 00:32:21 +00:00
UpdateProgress2 ? . Invoke ( "" , kvp . Key , counter , folders . Count ) ;
2017-08-22 18:05:18 +01:00
Symlinks . Symlink ( kvp . Value , kvp . Key ) ;
counter + + ;
}
2017-12-30 00:32:21 +00:00
#if DEBUG
2017-08-22 18:05:18 +01:00
stopwatch . Stop ( ) ;
2017-12-30 00:32:21 +00:00
Console . WriteLine ( "Core.SaveAs(): Took {0} seconds to create all symbolic links" ,
stopwatch . Elapsed . TotalSeconds ) ;
#endif
2017-08-22 18:05:18 +01:00
2017-12-30 00:32:21 +00:00
#if DEBUG
2017-08-22 18:05:18 +01:00
stopwatch . Restart ( ) ;
2017-12-30 00:32:21 +00:00
#endif
2017-08-22 18:05:18 +01:00
counter = 4 ;
2017-12-30 00:32:21 +00:00
foreach ( DbOsFile file in files )
2017-05-18 18:16:32 +01:00
{
2017-12-30 00:32:21 +00:00
UpdateProgress ? . Invoke ( "" , $"Creating {file.Path}..." , counter , 4 + files . Count ) ;
2017-05-18 18:16:32 +01:00
2017-12-30 00:32:21 +00:00
Stream zStream = null ;
string repoPath ;
2017-05-18 18:16:32 +01:00
AlgoEnum algorithm ;
if ( File . Exists ( Path . Combine ( Settings . Current . RepositoryPath , file . Sha256 [ 0 ] . ToString ( ) ,
file . Sha256 [ 1 ] . ToString ( ) , file . Sha256 [ 2 ] . ToString ( ) ,
file . Sha256 [ 3 ] . ToString ( ) , file . Sha256 [ 4 ] . ToString ( ) ,
file . Sha256 + ".gz" ) ) )
{
repoPath = Path . Combine ( Settings . Current . RepositoryPath , file . Sha256 [ 0 ] . ToString ( ) ,
file . Sha256 [ 1 ] . ToString ( ) , file . Sha256 [ 2 ] . ToString ( ) ,
file . Sha256 [ 3 ] . ToString ( ) , file . Sha256 [ 4 ] . ToString ( ) ,
file . Sha256 + ".gz" ) ;
algorithm = AlgoEnum . GZip ;
}
else if ( File . Exists ( Path . Combine ( Settings . Current . RepositoryPath , file . Sha256 [ 0 ] . ToString ( ) ,
2017-12-30 00:32:21 +00:00
file . Sha256 [ 1 ] . ToString ( ) , file . Sha256 [ 2 ] . ToString ( ) ,
file . Sha256 [ 3 ] . ToString ( ) , file . Sha256 [ 4 ] . ToString ( ) ,
file . Sha256 + ".bz2" ) ) )
2017-05-18 18:16:32 +01:00
{
repoPath = Path . Combine ( Settings . Current . RepositoryPath , file . Sha256 [ 0 ] . ToString ( ) ,
file . Sha256 [ 1 ] . ToString ( ) , file . Sha256 [ 2 ] . ToString ( ) ,
file . Sha256 [ 3 ] . ToString ( ) , file . Sha256 [ 4 ] . ToString ( ) ,
file . Sha256 + ".bz2" ) ;
algorithm = AlgoEnum . BZip2 ;
}
else if ( File . Exists ( Path . Combine ( Settings . Current . RepositoryPath , file . Sha256 [ 0 ] . ToString ( ) ,
2017-12-30 00:32:21 +00:00
file . Sha256 [ 1 ] . ToString ( ) , file . Sha256 [ 2 ] . ToString ( ) ,
file . Sha256 [ 3 ] . ToString ( ) , file . Sha256 [ 4 ] . ToString ( ) ,
file . Sha256 + ".lzma" ) ) )
2017-05-18 18:16:32 +01:00
{
repoPath = Path . Combine ( Settings . Current . RepositoryPath , file . Sha256 [ 0 ] . ToString ( ) ,
file . Sha256 [ 1 ] . ToString ( ) , file . Sha256 [ 2 ] . ToString ( ) ,
file . Sha256 [ 3 ] . ToString ( ) , file . Sha256 [ 4 ] . ToString ( ) ,
file . Sha256 + ".lzma" ) ;
algorithm = AlgoEnum . LZMA ;
}
2017-06-06 22:50:45 +01:00
else if ( File . Exists ( Path . Combine ( Settings . Current . RepositoryPath , file . Sha256 [ 0 ] . ToString ( ) ,
2017-12-30 00:32:21 +00:00
file . Sha256 [ 1 ] . ToString ( ) , file . Sha256 [ 2 ] . ToString ( ) ,
file . Sha256 [ 3 ] . ToString ( ) , file . Sha256 [ 4 ] . ToString ( ) ,
file . Sha256 + ".lz" ) ) )
2017-06-06 22:50:45 +01:00
{
repoPath = Path . Combine ( Settings . Current . RepositoryPath , file . Sha256 [ 0 ] . ToString ( ) ,
file . Sha256 [ 1 ] . ToString ( ) , file . Sha256 [ 2 ] . ToString ( ) ,
file . Sha256 [ 3 ] . ToString ( ) , file . Sha256 [ 4 ] . ToString ( ) ,
file . Sha256 + ".lz" ) ;
algorithm = AlgoEnum . LZip ;
}
2017-05-18 18:16:32 +01:00
else
{
2017-12-30 00:32:21 +00:00
Failed ? . Invoke ( $"Cannot find file with hash {file.Sha256} in the repository" ) ;
2017-05-18 18:16:32 +01:00
return ;
}
2017-12-30 00:32:21 +00:00
FileStream inFs = new FileStream ( repoPath , FileMode . Open , FileAccess . Read ) ;
FileStream outFs = new FileStream ( Path . Combine ( Context . Path , file . Path ) , FileMode . CreateNew ,
FileAccess . Write ) ;
2017-05-18 18:16:32 +01:00
switch ( algorithm )
{
case AlgoEnum . GZip :
2017-12-30 00:32:21 +00:00
zStream = new GZipStream ( inFs , CompressionMode . Decompress ) ;
2017-05-18 18:16:32 +01:00
break ;
case AlgoEnum . BZip2 :
2017-12-30 00:32:21 +00:00
zStream = new BZip2Stream ( inFs , CompressionMode . Decompress ) ;
2017-05-18 18:16:32 +01:00
break ;
case AlgoEnum . LZMA :
byte [ ] properties = new byte [ 5 ] ;
inFs . Read ( properties , 0 , 5 ) ;
inFs . Seek ( 8 , SeekOrigin . Current ) ;
zStream = new LzmaStream ( properties , inFs ) ;
break ;
2017-06-06 22:50:45 +01:00
case AlgoEnum . LZip :
2017-12-30 00:32:21 +00:00
zStream = new LZipStream ( inFs , CompressionMode . Decompress ) ;
2017-06-06 22:50:45 +01:00
break ;
2017-05-18 18:16:32 +01:00
}
2017-12-30 00:32:21 +00:00
byte [ ] buffer = new byte [ BUFFER_SIZE ] ;
2017-05-18 18:16:32 +01:00
2017-12-30 00:32:21 +00:00
while ( outFs . Position + BUFFER_SIZE < = file . Length )
2017-05-18 18:16:32 +01:00
{
2017-12-30 00:32:21 +00:00
UpdateProgress2 ? . Invoke ( $"{outFs.Position / (double)file.Length:P}" ,
$"{outFs.Position} / {file.Length} bytes" , outFs . Position , file . Length ) ;
2017-05-18 18:16:32 +01:00
zStream . Read ( buffer , 0 , buffer . Length ) ;
outFs . Write ( buffer , 0 , buffer . Length ) ;
}
buffer = new byte [ file . Length - outFs . Position ] ;
2017-12-30 00:32:21 +00:00
UpdateProgress2 ? . Invoke ( $"{outFs.Position / (double)file.Length:P}" ,
$"{outFs.Position} / {file.Length} bytes" , outFs . Position , file . Length ) ;
2017-05-18 18:16:32 +01:00
zStream . Read ( buffer , 0 , buffer . Length ) ;
outFs . Write ( buffer , 0 , buffer . Length ) ;
2017-12-30 00:32:21 +00:00
UpdateProgress2 ? . Invoke ( $"{file.Length / (double)file.Length:P}" , "Finishing..." , inFs . Length ,
inFs . Length ) ;
2017-05-18 18:16:32 +01:00
zStream . Close ( ) ;
outFs . Close ( ) ;
2017-12-30 00:32:21 +00:00
FileInfo fi = new FileInfo ( Path . Combine ( Context . Path , file . Path ) )
{
Attributes = file . Attributes ,
CreationTimeUtc = file . CreationTimeUtc ,
LastAccessTimeUtc = file . LastAccessTimeUtc ,
LastWriteTimeUtc = file . LastWriteTimeUtc
} ;
2017-05-18 18:16:32 +01:00
counter + + ;
}
2017-12-30 00:32:21 +00:00
#if DEBUG
2017-05-19 03:24:34 +01:00
stopwatch . Stop ( ) ;
2017-12-30 00:32:21 +00:00
Console . WriteLine ( "Core.SaveAs(): Took {0} seconds to create all files" ,
stopwatch . Elapsed . TotalSeconds ) ;
#endif
2017-05-18 18:16:32 +01:00
2017-12-30 00:32:21 +00:00
Finished ? . Invoke ( ) ;
2017-05-18 18:16:32 +01:00
}
2017-12-30 00:32:21 +00:00
catch ( ThreadAbortException ) { }
2017-05-18 18:16:32 +01:00
catch ( Exception ex )
{
2017-12-30 00:32:21 +00:00
if ( Debugger . IsAttached ) throw ;
Failed ? . Invoke ( $"Exception {ex.Message}\n{ex.InnerException}" ) ;
#if DEBUG
2017-06-13 18:21:12 +01:00
Console . WriteLine ( "Exception {0}\n{1}" , ex . Message , ex . InnerException ) ;
2017-12-30 00:32:21 +00:00
#endif
2017-05-18 18:16:32 +01:00
}
}
2017-05-19 16:57:28 +01:00
public static void CleanFiles ( )
{
2017-12-30 00:32:21 +00:00
ulong count = dbCore . DbOps . GetFilesCount ( ) ;
const ulong page = 2500 ;
ulong offset = 0 ;
2017-05-19 16:57:28 +01:00
2017-12-30 00:32:21 +00:00
List < DbFile > filesPage ;
List < DbFile > allFiles = new List < DbFile > ( ) ;
2017-05-19 16:57:28 +01:00
2017-12-30 00:32:21 +00:00
#if DEBUG
2017-05-19 16:57:28 +01:00
stopwatch . Restart ( ) ;
2017-12-30 00:32:21 +00:00
#endif
while ( dbCore . DbOps . GetFiles ( out filesPage , offset , page ) )
2017-05-19 16:57:28 +01:00
{
2017-12-30 00:32:21 +00:00
if ( filesPage . Count = = 0 ) break ;
2017-05-19 16:57:28 +01:00
2017-12-30 00:32:21 +00:00
UpdateProgress ? . Invoke ( null , $"Loaded file {offset} of {count}" , ( long ) offset , ( long ) count ) ;
2017-05-19 16:57:28 +01:00
allFiles . AddRange ( filesPage ) ;
offset + = page ;
}
2017-12-30 00:32:21 +00:00
#if DEBUG
2017-05-19 16:57:28 +01:00
stopwatch . Stop ( ) ;
2017-12-30 00:32:21 +00:00
Console . WriteLine ( "Core.CleanFiles(): Took {0} seconds to get all files from the database" ,
stopwatch . Elapsed . TotalSeconds ) ;
#endif
2017-05-19 16:57:28 +01:00
filesPage = null ;
2017-12-30 00:32:21 +00:00
UpdateProgress ? . Invoke ( null , "Getting OSes from the database" , 0 , 0 ) ;
#if DEBUG
2017-05-19 16:57:28 +01:00
stopwatch . Restart ( ) ;
2017-12-30 00:32:21 +00:00
#endif
dbCore . DbOps . GetAllOSes ( out List < DbEntry > oses ) ;
#if DEBUG
2017-05-19 16:57:28 +01:00
stopwatch . Stop ( ) ;
2017-12-30 00:32:21 +00:00
Console . WriteLine ( "Core.CleanFiles(): Took {0} seconds to get OSes from database" ,
stopwatch . Elapsed . TotalSeconds ) ;
#endif
2017-05-19 16:57:28 +01:00
List < string > orphanFiles = new List < string > ( ) ;
2017-12-30 00:32:21 +00:00
#if DEBUG
2017-05-19 16:57:28 +01:00
stopwatch . Restart ( ) ;
Stopwatch stopwatch2 = new Stopwatch ( ) ;
2017-12-30 00:32:21 +00:00
#endif
2017-05-19 16:57:28 +01:00
int counterF = 0 ;
2017-12-30 00:32:21 +00:00
foreach ( DbFile file in allFiles )
2017-05-19 16:57:28 +01:00
{
2017-12-30 00:32:21 +00:00
UpdateProgress ? . Invoke ( null , $"Checking file {counterF} of {allFiles.Count}" , counterF , allFiles . Count ) ;
2017-05-19 16:57:28 +01:00
bool fileExists = false ;
2017-12-30 00:32:21 +00:00
int counterO = 0 ;
#if DEBUG
2017-05-19 16:57:28 +01:00
stopwatch2 . Restart ( ) ;
2017-12-30 00:32:21 +00:00
#endif
foreach ( DbEntry os in oses )
2017-05-19 16:57:28 +01:00
{
2017-12-30 00:32:21 +00:00
UpdateProgress2 ? . Invoke ( null , $"Checking OS {counterO} of {oses.Count}" , counterO , oses . Count ) ;
2017-05-19 16:57:28 +01:00
2017-12-30 00:32:21 +00:00
if ( dbCore . DbOps . ExistsFileInOs ( file . Sha256 , os . Id ) )
2017-05-19 16:57:28 +01:00
{
fileExists = true ;
break ;
}
counterO + + ;
}
2017-12-30 00:32:21 +00:00
#if DEBUG
2017-05-19 16:57:28 +01:00
stopwatch2 . Stop ( ) ;
2017-12-30 00:32:21 +00:00
Console . WriteLine ( "Core.CleanFiles(): Took {0} seconds to check file in all OSes" ,
stopwatch2 . Elapsed . TotalSeconds ) ;
#endif
2017-05-19 16:57:28 +01:00
2017-12-30 00:32:21 +00:00
if ( ! fileExists ) orphanFiles . Add ( file . Sha256 ) ;
2017-05-19 16:57:28 +01:00
counterF + + ;
}
2017-12-30 00:32:21 +00:00
#if DEBUG
2017-05-19 16:57:28 +01:00
stopwatch . Stop ( ) ;
Console . WriteLine ( "Core.CleanFiles(): Took {0} seconds to check all files" , stopwatch . Elapsed . TotalSeconds ) ;
2017-12-30 00:32:21 +00:00
#endif
2017-05-19 16:57:28 +01:00
2017-12-30 00:32:21 +00:00
UpdateProgress2 ? . Invoke ( null , null , 0 , 0 ) ;
2017-05-19 16:57:28 +01:00
2017-12-30 00:32:21 +00:00
#if DEBUG
2017-05-19 16:57:28 +01:00
stopwatch . Restart ( ) ;
2017-12-30 00:32:21 +00:00
#endif
2017-05-19 16:57:28 +01:00
counterF = 0 ;
foreach ( string hash in orphanFiles )
{
2017-12-30 00:32:21 +00:00
UpdateProgress ? . Invoke ( null , $"Deleting file {counterF} of {orphanFiles.Count} from database" , counterF ,
orphanFiles . Count ) ;
2017-05-19 16:57:28 +01:00
2017-12-30 00:32:21 +00:00
dbCore . DbOps . DeleteFile ( hash ) ;
2017-05-19 16:57:28 +01:00
counterF + + ;
}
2017-12-30 00:32:21 +00:00
#if DEBUG
2017-05-19 16:57:28 +01:00
stopwatch . Stop ( ) ;
2017-12-30 00:32:21 +00:00
Console . WriteLine ( "Core.CleanFiles(): Took {0} seconds to remove all orphan files from database" ,
stopwatch . Elapsed . TotalSeconds ) ;
#endif
2017-05-19 16:57:28 +01:00
2017-12-30 00:32:21 +00:00
UpdateProgress ? . Invoke ( null , "Listing files in repository" , 0 , 0 ) ;
2017-05-19 16:57:28 +01:00
2017-12-30 00:32:21 +00:00
#if DEBUG
2017-05-19 16:57:28 +01:00
stopwatch . Restart ( ) ;
2017-12-30 00:32:21 +00:00
#endif
List < string > repoFiles =
new List < string > ( Directory . EnumerateFiles ( Settings . Current . RepositoryPath , "*" ,
SearchOption . AllDirectories ) ) ;
2017-05-19 16:57:28 +01:00
repoFiles . Sort ( ) ;
2017-12-30 00:32:21 +00:00
#if DEBUG
2017-05-19 16:57:28 +01:00
stopwatch . Stop ( ) ;
Console . WriteLine ( "Core.CleanFiles(): Took {0} seconds to find all files" , stopwatch . Elapsed . TotalSeconds ) ;
stopwatch . Restart ( ) ;
2017-12-30 00:32:21 +00:00
#endif
counterF = 0 ;
2017-05-19 16:57:28 +01:00
List < string > filesToDelete = new List < string > ( ) ;
foreach ( string file in repoFiles )
{
2017-12-30 00:32:21 +00:00
UpdateProgress ? . Invoke ( null , $"Checking file {counterF} of {repoFiles.Count} from repository" , counterF ,
repoFiles . Count ) ;
2017-05-19 16:57:28 +01:00
// Allow database to be inside repo
2017-12-30 00:32:21 +00:00
if ( file = = Settings . Current . DatabasePath ) continue ;
2017-05-19 16:57:28 +01:00
2017-12-30 00:32:21 +00:00
if ( Path . GetExtension ( file ) ? . ToLowerInvariant ( ) = = ".xml" | |
Path . GetExtension ( file ) ? . ToLowerInvariant ( ) = = ".json" )
2017-05-19 16:57:28 +01:00
{
2017-12-30 00:32:21 +00:00
if ( ! dbCore . DbOps . ExistsOs ( Path . GetFileNameWithoutExtension ( file ) ) ) filesToDelete . Add ( file ) ;
2017-05-19 16:57:28 +01:00
}
2017-12-30 00:32:21 +00:00
else if ( ! dbCore . DbOps . ExistsFile ( Path . GetFileNameWithoutExtension ( file ) ) )
2017-05-19 16:57:28 +01:00
filesToDelete . Add ( file ) ;
counterF + + ;
}
2017-12-30 00:32:21 +00:00
#if DEBUG
2017-05-19 16:57:28 +01:00
stopwatch . Stop ( ) ;
2017-12-30 00:32:21 +00:00
Console . WriteLine ( "Core.CleanFiles(): Took {0} seconds to check all repository files" ,
stopwatch . Elapsed . TotalSeconds ) ;
2017-05-19 16:57:28 +01:00
stopwatch . Restart ( ) ;
2017-12-30 00:32:21 +00:00
#endif
2017-05-19 16:57:28 +01:00
counterF = 0 ;
foreach ( string file in filesToDelete )
{
2017-12-30 00:32:21 +00:00
UpdateProgress ? . Invoke ( null , $"Deleting file {counterF} of {filesToDelete.Count} from repository" ,
counterF , filesToDelete . Count ) ;
2017-05-19 16:57:28 +01:00
2017-12-30 00:32:21 +00:00
try { File . Delete ( file ) ; }
#pragma warning disable RECS0022 // A catch clause that catches System.Exception and has an empty body
2017-05-19 18:16:16 +01:00
catch
2017-12-30 00:32:21 +00:00
#pragma warning restore RECS0022 // A catch clause that catches System.Exception and has an empty body
2017-05-19 18:16:16 +01:00
{
2017-05-19 16:57:28 +01:00
// Do not crash
}
counterF + + ;
}
2017-12-30 00:32:21 +00:00
#if DEBUG
2017-05-19 16:57:28 +01:00
stopwatch . Stop ( ) ;
2017-12-30 00:32:21 +00:00
Console . WriteLine ( "Core.CleanFiles(): Took {0} seconds to delete all orphan files" ,
stopwatch . Elapsed . TotalSeconds ) ;
#endif
2017-05-19 16:57:28 +01:00
2017-12-30 00:32:21 +00:00
Finished ? . Invoke ( ) ;
2017-05-19 16:57:28 +01:00
}
2017-05-18 18:16:32 +01:00
}
2017-12-30 00:32:21 +00:00
}