@@ -47,106 +47,123 @@ public LoadOptions(string filePath) {
4747 public static readonly int MaxLoadThreads = Environment . ProcessorCount ;
4848 public static SemaphoreSlim LoadThrottle = new SemaphoreSlim ( MaxLoadThreads ) ;
4949
50+ //public static void Extract(LoadOptions options, CancellationTokenSource tknSrc = null) {
51+ // if (tknSrc?.IsCancellationRequested == true) return;
52+
53+ // //objInfo to be returned
54+ // var objInfo = new ObjectInfo(options.FilePath, options.Flags) {
55+ // FileName = Path.GetFileName(options.FilePath)
56+ // };
57+
58+ // var done = new HashSet<string>();
59+ // var trials = 0;
60+ // bool trial1() {
61+ // if (!(Setting.MappedPasswords.Rows.Find(options.FilePath) is DataRow row)) return false;
62+ // options.Password = (string)row[nameof(Column.Password)];
63+ // return extractZip(options, objInfo, done, tknSrc);
64+ // }
65+
66+ // while (trials < 5) {
67+ // if (tknSrc?.IsCancellationRequested == true) break;
68+
69+ // }
70+ //}
71+
72+
5073 /// <summary>
51- /// Load image based on the type of file and try passwords when possible.
5274 /// <para>
53- /// If filePath points to an archive, ObjectInfo.Flags in ObjInfoCallback will contain FileFlag.Error when extraction fails.
75+ /// ObjectInfo.Flags in ObjInfoCallback will contain FileFlag.Error when extraction fails.
5476 /// ObjectInfo.SourcePaths in ObjInfoCallback contains the file list inside archive.
5577 /// ObjectInfo in CldInfoCallback contains information for files inside archive.
5678 /// </para>
5779 /// Should be called from a background thread.
5880 /// Callback can be used to manipulate the loaded images. For e.g. display it in the ViewWindow, or add to ObjectList as thumbnails.
5981 /// Callback is called for each image loaded.
6082 /// Use Dispatcher if callback needs to access the UI thread.
61- /// <param name="flags">Only checks for Image and Archive.</param>
6283 /// </summary>
63- internal static void LoadFile ( LoadOptions options , CancellationTokenSource tknSrc = null ) {
84+ public static void ExtractZip ( LoadOptions options , CancellationTokenSource tknSrc = null ) {
6485 if ( tknSrc ? . IsCancellationRequested == true ) return ;
6586
6687 //objInfo to be returned
6788 var objInfo = new ObjectInfo ( options . FilePath , options . Flags ) {
6889 FileName = Path . GetFileName ( options . FilePath )
6990 } ;
7091
71- //when file is an image
72- if ( options . Flags . HasFlag ( FileFlags . Image ) && ! options . Flags . HasFlag ( FileFlags . Archive ) ) {
73- //objInfo.SourcePaths = new[] { options.FilePath };
74- if ( options . LoadImage )
75- objInfo . ImageSource = GetImageSource ( options . FilePath , options . DecodeSize ) ;
92+ //some files may get loaded from cache therefore unaware of whether password is correct
93+ //the HashSet records processed files through retries
94+ var done = new HashSet < string > ( ) ;
95+ for ( int caseIdx = 0 ; caseIdx < 4 ; caseIdx ++ ) {
96+ if ( tknSrc ? . IsCancellationRequested == true ) break ;
97+
98+ var success = tryExtract ( caseIdx , options , objInfo , done , tknSrc ) ;
99+ if ( success ) break ;
76100 }
77- //when file is an archive
78- else if ( options . Flags . HasFlag ( FileFlags . Archive ) ) {
79- //some files may get loaded from cache therefore unaware of whether password is correct
80- //the HashSet records processed files through retries
81- var done = new HashSet < string > ( ) ;
82- for ( int caseIdx = 0 ; caseIdx < 4 ; caseIdx ++ ) {
83- if ( tknSrc ? . IsCancellationRequested == true ) break ;
84101
85- var success = false ;
86- switch ( caseIdx ) {
87- //first check if there is a match in saved passwords
88- case 0 when Setting . MappedPasswords . Rows . Find ( options . FilePath ) is DataRow row :
89- options . Password = ( string ) row [ nameof ( Column . Password ) ] ;
90- success = extractZip ( options , objInfo , done , tknSrc ) ;
91- break ;
92- //then try no password
93- case 1 :
94- options . Password = null ;
95- success = extractZip ( options , objInfo , done , tknSrc ) ;
96- break ;
97- //then try all saved passwords with no filename
98- case 2 :
99- foreach ( var fp in Setting . FallbackPasswords ) {
100- options . Password = fp ;
102+ if ( tknSrc ? . IsCancellationRequested == true ) return ;
103+ options . ObjInfoCallback ? . Invoke ( objInfo ) ;
104+ }
105+
106+
107+ private static bool tryExtract ( int trial , LoadOptions options , ObjectInfo objInfo , HashSet < string > done , CancellationTokenSource tknSrc = null ) {
108+ var success = false ;
109+ switch ( trial ) {
110+ //first check if there is a match in saved passwords
111+ case 0 when Setting . MappedPasswords . Rows . Find ( options . FilePath ) is DataRow row :
112+ options . Password = ( string ) row [ nameof ( Column . Password ) ] ;
113+ success = extractZip ( options , objInfo , done , tknSrc ) ;
114+ break ;
115+ //then try no password
116+ case 1 :
117+ options . Password = null ;
118+ success = extractZip ( options , objInfo , done , tknSrc ) ;
119+ break ;
120+ //then try all saved passwords with no filename
121+ case 2 :
122+ foreach ( var fp in Setting . FallbackPasswords ) {
123+ options . Password = fp ;
124+ success = extractZip ( options , objInfo , done , tknSrc ) ;
125+ if ( success ) break ;
126+ }
127+ break ;
128+ case 3 :
129+ //if all fails, prompt for password then extract with it
130+ if ( options . LoadImage &&
131+ ( options . FileNames == null || options . DecodeSize == default ) ) {
132+ //ask for password when opening explicitly the archive or opening viewer for images inside archive
133+ while ( ! success ) {
134+ string pwd = null ;
135+ bool isFb = true ;
136+ Application . Current . Dispatcher . Invoke ( ( ) => {
137+ var win = new InputWindow ( ) ;
138+ if ( win . ShowDialog ( ) == true ) {
139+ pwd = win . TB_Password . Text ;
140+ isFb = win . CB_Fallback . IsChecked == true ;
141+ }
142+ win . Close ( ) ;
143+ } ) ;
144+
145+ if ( ! string . IsNullOrEmpty ( pwd ) ) {
146+ options . Password = pwd ;
101147 success = extractZip ( options , objInfo , done , tknSrc ) ;
102- if ( success ) break ;
103- }
104- break ;
105- case 3 :
106- //if all fails, prompt for password then extract with it
107- if ( options . LoadImage &&
108- ( options . FileNames == null || options . DecodeSize == default ) ) {
109- //ask for password when opening explicitly the archive or opening viewer for images inside archive
110- while ( ! success ) {
111- string pwd = null ;
112- bool isFb = true ;
113- Application . Current . Dispatcher . Invoke ( ( ) => {
114- var win = new InputWindow ( ) ;
115- if ( win . ShowDialog ( ) == true ) {
116- pwd = win . TB_Password . Text ;
117- isFb = win . CB_Fallback . IsChecked == true ;
118- }
119- win . Close ( ) ;
120- } ) ;
121-
122- if ( ! string . IsNullOrEmpty ( pwd ) ) {
123- options . Password = pwd ;
124- success = extractZip ( options , objInfo , done , tknSrc ) ;
125- if ( success ) {
126- //make sure the password is saved when task is cancelled
127- Setting . MappedPasswords . UpdateDataTable ( options . FilePath , nameof ( Column . Password ) , pwd ) ;
128- if ( isFb ) {
129- Setting . FallbackPasswords [ pwd ] = new Observable < string > ( pwd ) ;
130- }
131- break ;
132- }
148+ if ( success ) {
149+ //make sure the password is saved when task is cancelled
150+ Setting . MappedPasswords . UpdateDataTable ( options . FilePath , nameof ( Column . Password ) , pwd ) ;
151+ if ( isFb ) {
152+ Setting . FallbackPasswords [ pwd ] = new Observable < string > ( pwd ) ;
133153 }
134- else break ;
154+ break ;
135155 }
136156 }
137- if ( ! success ) {
138- objInfo . Flags |= FileFlags . Error ;
139- objInfo . Comments = $ "Extraction failed. Bad password or not supported image formats.";
140- }
141- break ;
157+ else break ;
158+ }
142159 }
143-
144- if ( success ) break ;
145- }
160+ if ( ! success ) {
161+ objInfo . Flags |= FileFlags . Error ;
162+ objInfo . Comments = $ "Extraction failed. Bad password or not supported image formats.";
163+ }
164+ break ;
146165 }
147-
148- if ( tknSrc ? . IsCancellationRequested == true ) return ;
149- options . ObjInfoCallback ? . Invoke ( objInfo ) ;
166+ return success ;
150167 }
151168
152169 /// <summary>
@@ -322,7 +339,7 @@ public static string[] GetSourcePaths(ObjectInfo objInfo) {
322339 }
323340 break ;
324341 case FileFlags . Archive :
325- LoadFile ( new LoadOptions ( objInfo . FileSystemPath ) {
342+ ExtractZip ( new LoadOptions ( objInfo . FileSystemPath ) {
326343 Flags = FileFlags . Archive ,
327344 LoadImage = false ,
328345 ObjInfoCallback = oi => {
@@ -399,7 +416,7 @@ public static ImageSource GetImageSource(ObjectInfo objInfo, string sourcePath,
399416 break ;
400417 case FileFlags . Archive :
401418 if ( sourcePath != null ) {
402- LoadFile ( new LoadOptions ( objInfo . FileSystemPath ) {
419+ ExtractZip ( new LoadOptions ( objInfo . FileSystemPath ) {
403420 DecodeSize = decodeSize ,
404421 LoadImage = true ,
405422 TryCache = tryCache ,
@@ -623,7 +640,7 @@ public static void CacheFolder(string path, ref CancellationTokenSource tknSrc,
623640 try {
624641 if ( pathType == FileFlags . Archive ) {
625642 var all = GetSourcePaths ( new ObjectInfo ( path , pathType ) ) ;
626- LoadFile ( new LoadOptions ( path ) {
643+ ExtractZip ( new LoadOptions ( path ) {
627644 Flags = FileFlags . Archive ,
628645 LoadImage = true ,
629646 DecodeSize = decodeSize ,
0 commit comments