1 /*
2  * Part of WCM Commander
3  * https://github.com/corporateshark/WCMCommander
4  * wcm@linderdaum.com
5  */
6 
7 #pragma once
8 
9 #include <sys/stat.h>
10 #include <time.h>
11 #include <atomic>
12 
13 #include "wal.h"
14 #include "ncdialogs.h"
15 
16 #include "vfspath.h"
17 #include "strconfig.h"
18 #include "globals.h"
19 
20 
21 #ifdef _WIN32
22 class FSTime
23 {
24 	enum { FILETIME_OK = 1, TIME_T_OK = 2 };
25 	char flags;
26 	FILETIME ft;
27 	time_t tt;
28 public:
29 	enum TIMESTAMP { TIME_CURRENT };
FSTime()30 	FSTime() : flags(0) {}
FSTime(TIMESTAMP timestamp)31 	FSTime(TIMESTAMP timestamp)
32 	{
33 		time_t t;
34 		time(&t);
35 		SetTimeT(t);
36 	}
FSTime(time_t t)37 	FSTime( time_t t ): flags( TIME_T_OK ), tt( t ) {}
FSTime(FILETIME t)38 	FSTime( FILETIME t ): flags( FILETIME_OK ), ft( t ) {}
39 	time_t GetTimeT();
40 	FILETIME GetFileTime();
SetTimeT(time_t val)41 	void SetTimeT( time_t val ) { tt = val; flags = TIME_T_OK; }
SetFileTime(FILETIME val)42 	void SetFileTime( FILETIME val ) { ft = val; flags = FILETIME_OK; }
43 
time_t()44 	operator time_t() { return GetTimeT(); }
FILETIME()45 	operator FILETIME() { return GetFileTime(); }
46 	FSTime& operator = ( time_t t ) { SetTimeT( t ); return *this; }
47 	FSTime& operator = ( FILETIME ft ) { SetFileTime( ft ); return *this; }
48 };
49 #else
50 typedef time_t FSTime;
51 #endif
52 
53 #ifdef _WIN32
54 #  if !defined( S_IFMT )
55 #     define S_IFMT 0170000  //bitmask for the file type bitfields
56 #  endif
57 #  if !defined( S_IFSOCK )
58 #     define S_IFSOCK  0140000  //socket
59 #  endif
60 #  if !defined( S_IFLNK )
61 #     define S_IFLNK   0120000  //symbolic link
62 #  endif
63 #  if !defined( S_IFREG )
64 #     define S_IFREG   0100000  //regular file
65 #  endif
66 #  if !defined( S_IFBLK )
67 #     define S_IFBLK   0060000  //block device
68 #  endif
69 #  if !defined( S_IFDIR )
70 #     define S_IFDIR   0040000  //directory
71 #  endif
72 #  if !defined( S_IFCHR )
73 #     define S_IFCHR   0020000  //character device
74 #  endif
75 #  if !defined( S_IFIFO )
76 #     define S_IFIFO   0010000  //fifo
77 #  endif
78 #  if !defined( S_ISUID )
79 #     define S_ISUID   0004000  //set UID bit
80 #  endif
81 #  if !defined( S_ISGID )
82 #     define S_ISGID   0002000  //set GID bit (see below)
83 #  endif
84 #  if !defined( S_ISVTX )
85 #     define S_ISVTX   0001000  //sticky bit (see below)
86 #  endif
87 #  if !defined( S_IRWXU )
88 #     define S_IRWXU    00700   //mask for file owner permissions
89 #  endif
90 #  if !defined( S_IRUSR )
91 #     define S_IRUSR   00400 //owner has read permission
92 #  endif
93 #  if !defined( S_IWUSR )
94 #     define S_IWUSR   00200 //owner has write permission
95 #  endif
96 #  if !defined( S_IXUSR )
97 #     define S_IXUSR   00100 //owner has execute permission
98 #  endif
99 #  if !defined( S_IRWXG )
100 #     define S_IRWXG   00070 //mask for group permissions
101 #  endif
102 #  if !defined( S_IRGRP )
103 #     define S_IRGRP   00040 //group has read permission
104 #  endif
105 #  if !defined( S_IWGRP )
106 #     define S_IWGRP   00020 //group has write permission
107 #  endif
108 #  if !defined( S_IXGRP )
109 #     define S_IXGRP   00010 //group has execute permission
110 #  endif
111 #  if !defined( S_IRWXO )
112 #     define S_IRWXO   00007 //mask for permissions for others (not in group)
113 #  endif
114 #  if !defined( S_IROTH )
115 #     define S_IROTH   00004 //others have read permission
116 #  endif
117 #  if !defined( S_IWOTH )
118 #     define S_IWOTH   00002 //others have write permisson
119 #  endif
120 #  if !defined( S_IXOTH )
121 #     define S_IXOTH   00001 //others have execute permission
122 #  endif
123 #endif
124 
125 struct FSStatVfs
126 {
127 	int64_t size;
128 	int64_t avail;
129 
FSStatVfsFSStatVfs130 	FSStatVfs() : size( -1 ), avail( -1 ) {}
131 };
132 
133 struct FSStat
134 {
135 	FSString link;
136 
137 #ifdef _WIN32
138 	DWORD dwFileAttributes;
139 #endif
140 	int mode;
141 	int64_t size;
142 	FSTime m_CreationTime;
143 	FSTime m_LastAccessTime;
144 	FSTime m_LastWriteTime;
145 	// for future use with ZwQueryDirectoryFile()
146 	FSTime m_ChangeTime;
147 	int uid;
148 	int gid;
149 
150 	dev_t dev;
151 	ino_t ino;
152 
FSStatFSStat153 	FSStat():
154 #ifdef _WIN32
155 		dwFileAttributes( 0 ),
156 #endif
157 		mode( 0 ), size( 0 ), m_CreationTime( 0 ), m_LastAccessTime( 0 ), m_LastWriteTime( 0 ), m_ChangeTime( 0 ), uid( -1 ), gid( -1 ), dev( 0 ), ino( 0 )
158 	{}
159 
FSStatFSStat160 	FSStat( const FSStat& a )
161 	: mode( a.mode )
162 	, size( a.size )
163 	, m_CreationTime( a.m_CreationTime )
164 	, m_LastAccessTime( a.m_LastAccessTime )
165 	, m_LastWriteTime( a.m_LastWriteTime )
166 	, m_ChangeTime( a.m_ChangeTime )
167 	, uid( a.uid )
168 	, gid( a.gid )
169 	, dev( a.dev )
170 	, ino( a.ino )
171 	{
172 		link.Copy( a.link );
173 	}
174 	FSStat& operator = ( const FSStat& a )
175 	{
176 		link.Copy( a.link );
177 		mode = a.mode;
178 		size = a.size;
179 		m_CreationTime = a.m_CreationTime;
180 		m_LastAccessTime = a.m_LastAccessTime;
181 		m_LastWriteTime = a.m_LastWriteTime;
182 		m_ChangeTime = a.m_ChangeTime;
183 		uid = a.uid;
184 		gid = a.gid;
185 		dev = a.dev;
186 		ino = a.ino;
187 		return *this;
188 	}
189 
IsLnkFSStat190 	bool IsLnk() const { return !link.IsNull(); }
IsRegFSStat191 	bool IsReg() const { return ( mode & S_IFMT ) == S_IFREG; }
IsDirFSStat192 	bool IsDir() const { return ( mode & S_IFMT ) == S_IFDIR; }
IsExeFSStat193 	bool IsExe() const { return ( mode & ( S_IXUSR | S_IXGRP | S_IXOTH ) ) != 0; }
IsBadFSStat194 	bool IsBad() const { return ( mode & S_IFMT ) == 0; }
SetBadFSStat195 	void SetBad() { mode = 0; }
196 
197 	unicode_t* GetMTimeStr( unicode_t buf[64] );
198 	unicode_t* GetModeStr( unicode_t buf[64] );
199 	unicode_t* GetPrintableSizeStr( unicode_t buf[64] );
200 
~FSStatFSStat201 	~FSStat() {};
202 };
203 
204 #ifdef _WIN32
205 class W32NetRes
206 {
207 	struct Node
208 	{
209 		int size;
210 		NETRESOURCEW rs;
211 	};
212 	unsigned char* data;
Clear()213 	void Clear() { if ( data ) { delete [] data; data = 0; } };
214 	static unsigned char* Copy( const unsigned char* );
215 public:
W32NetRes()216 	W32NetRes(): data( 0 ) {}
217 	void Set( NETRESOURCEW* p );
218 
W32NetRes(NETRESOURCEW * p)219 	W32NetRes( NETRESOURCEW* p ): data( 0 ) {Set( p );}
W32NetRes(const W32NetRes & a)220 	W32NetRes( const W32NetRes& a ): data( Copy( a.data ) ) {}
221 	W32NetRes& operator = ( const W32NetRes& a ) { Clear(); data = Copy( a.data ); return *this; }
Get()222 	NETRESOURCEW* Get() volatile { return ( data ) ? &( ( ( Node* )data )->rs ) : 0; }
~W32NetRes()223 	~W32NetRes() { if ( data ) { delete [] data; } }
224 };
225 #endif
226 
227 
228 struct FSNode: public iIntrusiveCounter
229 {
230 	enum EXTTYPES {   SERVER = 1, WORKGROUP, FILESHARE };
231 
232 #ifdef _WIN32
233 	W32NetRes _w32NetRes;
234 #endif
235 
236 	bool isSelected;
237 	int extType;
238 	FSStat st;
239 	FSString name;
240 	FSNode* next;
241 	FSNode* originNode;
242 
FSNodeFSNode243 	FSNode(): isSelected( false ), extType( 0 ), next( 0 ), originNode( 0 ) {}
FSNodeFSNode244 	FSNode( const FSNode& a ): isSelected( a.isSelected ), extType( a.extType ), st( a.st ), next( 0 ), originNode( 0 ) { name.Copy( a.name ); }
245 	FSNode& operator = ( const FSNode& a )
246 	{ isSelected = a.isSelected; extType = a.extType; st = a.st; next = 0; name.Copy( a.name ); originNode = a.originNode; return *this;}
247 
NameFSNode248 	FSString& Name() { return name; }
SizeFSNode249 	int64_t Size() const { return st.size; }
IsDirFSNode250 	bool IsDir() const { return st.IsDir(); }
IsLnkFSNode251 	bool IsLnk() const { return st.IsLnk(); }
IsRegFSNode252 	bool IsReg() const { return st.IsReg(); }
253 #ifdef _WIN32
254 	bool IsExe();
255 #else
IsExeFSNode256 	bool IsExe() const { return st.IsExe(); }
257 #endif
IsBadFSNode258 	bool IsBad() const { return st.IsBad(); }
259 
260 #ifdef _WIN32
261 	/// should be hidden in panels
IsHiddenFSNode262 	bool IsHidden() const { return IsAttrHidden() || IsAttrSystem(); }
IsAttrHiddenFSNode263 	bool IsAttrHidden() const { return ( st.dwFileAttributes & FILE_ATTRIBUTE_HIDDEN ) != 0; }
IsAttrSystemFSNode264 	bool IsAttrSystem() const { return ( st.dwFileAttributes & FILE_ATTRIBUTE_SYSTEM ) != 0; }
IsAttrReadOnlyFSNode265 	bool IsAttrReadOnly() const { return ( st.dwFileAttributes & FILE_ATTRIBUTE_READONLY ) != 0; }
IsAttrArchiveFSNode266 	bool IsAttrArchive() const { return ( st.dwFileAttributes & FILE_ATTRIBUTE_ARCHIVE ) != 0; }
IsAttrCompressedFSNode267 	bool IsAttrCompressed() const { return ( st.dwFileAttributes & FILE_ATTRIBUTE_COMPRESSED ) != 0; }
IsAttrEncryptedFSNode268 	bool IsAttrEncrypted() const { return ( st.dwFileAttributes & FILE_ATTRIBUTE_ENCRYPTED ) != 0; }
IsAttrNotIndexedFSNode269 	bool IsAttrNotIndexed() const { return ( st.dwFileAttributes & FILE_ATTRIBUTE_NOT_CONTENT_INDEXED ) != 0; }
IsAttrSparseFSNode270 	bool IsAttrSparse() const { return ( st.dwFileAttributes & FILE_ATTRIBUTE_SPARSE_FILE ) != 0; }
IsAttrTemporaryFSNode271 	bool IsAttrTemporary() const { return ( st.dwFileAttributes & FILE_ATTRIBUTE_TEMPORARY ) != 0; }
IsAttrOfflineFSNode272 	bool IsAttrOffline() const { return ( st.dwFileAttributes & FILE_ATTRIBUTE_OFFLINE ) != 0; }
IsAttrReparsePointFSNode273 	bool IsAttrReparsePoint() const { return ( st.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT ) != 0; }
IsAttrVirtualFSNode274 	bool IsAttrVirtual() const { return ( st.dwFileAttributes & FILE_ATTRIBUTE_VIRTUAL ) != 0; }
275 
SetAttrFSNode276 	void SetAttr( bool a, int Mask )
277 	{
278 		if ( a )
279 		{
280 			st.dwFileAttributes |= Mask;
281 		}
282 		else
283 		{
284 			st.dwFileAttributes &= ~Mask;
285 		}
286 	}
287 
SetAttrReadOnlyFSNode288 	void SetAttrReadOnly( bool a ) { SetAttr( a, FILE_ATTRIBUTE_READONLY ); }
SetAttrArchiveFSNode289 	void SetAttrArchive( bool a ) { SetAttr( a, FILE_ATTRIBUTE_ARCHIVE ); }
SetAttrHiddenFSNode290 	void SetAttrHidden( bool a ) { SetAttr( a, FILE_ATTRIBUTE_HIDDEN ); }
SetAttrSystemFSNode291 	void SetAttrSystem( bool a ) { SetAttr( a, FILE_ATTRIBUTE_SYSTEM ); }
SetAttrNotIndexedFSNode292 	void SetAttrNotIndexed( bool a ) { SetAttr( a, FILE_ATTRIBUTE_NOT_CONTENT_INDEXED ); }
SetAttrTemporaryFSNode293 	void SetAttrTemporary( bool a ) { SetAttr( a, FILE_ATTRIBUTE_TEMPORARY ); }
294 #else
IsHiddenFSNode295 	bool IsHidden() { return name.GetUnicode()[0] == '.'; }
296 
SetAttrFSNode297     void SetAttr( bool a, int Mask )
298     {
299         if ( a )
300         {
301             st.mode |= Mask;
302         }
303         else
304         {
305             st.mode &= ~Mask;
306         }
307     }
308 
IsAttrUserReadFSNode309     bool IsAttrUserRead() const { return ( st.mode & S_IRUSR ) != 0; }
IsAttrUserWriteFSNode310     bool IsAttrUserWrite() const { return ( st.mode & S_IWUSR ) != 0; }
IsAttrUserExecuteFSNode311     bool IsAttrUserExecute() const { return ( st.mode & S_IXUSR ) != 0; }
IsAttrGroupReadFSNode312     bool IsAttrGroupRead() const { return ( st.mode & S_IRGRP ) != 0; }
IsAttrGroupWriteFSNode313     bool IsAttrGroupWrite() const { return ( st.mode & S_IWGRP ) != 0; }
IsAttrGroupExecuteFSNode314     bool IsAttrGroupExecute() const { return ( st.mode & S_IXGRP ) != 0; }
IsAttrOthersReadFSNode315     bool IsAttrOthersRead() const { return ( st.mode & S_IROTH ) != 0; }
IsAttrOthersWriteFSNode316     bool IsAttrOthersWrite() const { return ( st.mode & S_IWOTH ) != 0; }
IsAttrOthersExecuteFSNode317     bool IsAttrOthersExecute() const { return ( st.mode & S_IXOTH ) != 0; }
318 
SetAttrUserReadFSNode319     void SetAttrUserRead( bool a ) { SetAttr( a, S_IRUSR ); }
SetAttrUserWriteFSNode320     void SetAttrUserWrite( bool a ) { SetAttr( a, S_IWUSR ); }
SetAttrUserExecuteFSNode321     void SetAttrUserExecute( bool a ) { SetAttr( a, S_IXUSR ); }
SetAttrGroupReadFSNode322     void SetAttrGroupRead( bool a ) { SetAttr( a, S_IRGRP ); }
SetAttrGroupWriteFSNode323     void SetAttrGroupWrite( bool a ) { SetAttr( a, S_IWGRP ); }
SetAttrGroupExecuteFSNode324     void SetAttrGroupExecute( bool a ) { SetAttr( a, S_IXGRP ); }
SetAttrOthersReadFSNode325     void SetAttrOthersRead( bool a ) { SetAttr( a, S_IROTH ); }
SetAttrOthersWriteFSNode326     void SetAttrOthersWrite( bool a ) { SetAttr( a, S_IWOTH ); }
SetAttrOthersExecuteFSNode327     void SetAttrOthersExecute( bool a ) { SetAttr( a, S_IXOTH ); }
328 #endif
GetLastWriteTimeFSNode329 	FSTime GetLastWriteTime() const { return st.m_LastWriteTime; };
GetCreationTimeFSNode330 	FSTime GetCreationTime() const { return st.m_CreationTime; };
GetLastAccessTimeFSNode331 	FSTime GetLastAccessTime() const { return st.m_LastAccessTime; };
GetChangeTimeFSNode332 	FSTime GetChangeTime() const { return st.m_ChangeTime; }
333 
SetLastWriteTimeFSNode334 	void SetLastWriteTime( FSTime t ) { st.m_LastWriteTime = t; };
SetCreationTimeFSNode335 	void SetCreationTime( FSTime t ) { st.m_CreationTime = t; };
SetLastAccessTimeFSNode336 	void SetLastAccessTime( FSTime t ) { st.m_LastAccessTime = t; };
SetChangeTimeFSNode337 	void SetChangeTime( FSTime t ) { st.m_ChangeTime = t; }
338 
IsSelectedFSNode339 	bool IsSelected() const { return isSelected; }
SetSelectedFSNode340 	void SetSelected() { isSelected = true; }
ClearSelectedFSNode341 	void ClearSelected() { isSelected = false; }
GetUnicodeNameFSNode342 	const unicode_t* GetUnicodeName() const { return name.GetUnicode(); }
GetUtf8NameFSNode343 	const char* GetUtf8Name() const { return name.GetUtf8(); }
344 
GetUIDFSNode345 	int GetUID() const { return st.uid; }
GetGIDFSNode346 	int GetGID() const { return st.gid; }
347 
CmpByNameFSNode348 	int CmpByName( FSNode& a, bool case_sensitive ) { return case_sensitive ? name.Cmp( a.name ) : name.CmpNoCase( a.name ); }
349 	int CmpByExt( FSNode& a, bool case_sensitive );
350 
351 	~FSNode();
352 };
353 
354 enum BSearchMode
355 {
356 	EXACT_MATCH_ONLY,
357 	EXACT_OR_CLOSEST_PRECEDING_NODE,
358 	EXACT_OR_CLOSEST_SUCCEEDING_NODE,
359 };
360 
361 enum SORT_MODE
362 {
363 	SORT_NONE = 0, //unsorted
364 	SORT_NAME,
365 	SORT_EXT,
366 	SORT_SIZE,
367 	SORT_MTIME
368 };
369 
370 class FSList: public iIntrusiveCounter
371 {
372 	FSNode* first, *last;
373 	int count;
374 public:
FSList()375 	FSList(): first( 0 ), last( 0 ), count( 0 ) {};
Count()376 	int Count() const { return count; };
377 
First()378 	FSNode* First() { return first; }
379 
380 	void Append( clPtr<FSNode> );
381 	void Clear();
382 
383 	std::vector<FSNode*> GetArray();
384 
385 	std::vector<FSNode*> GetFilteredArray( bool showHidden, int* pCount );
386 
387 	void CopyFrom( const FSList& a, bool onlySelected = false );
388 	void CopyOne( FSNode* node );
389 
~FSList()390 	~FSList() { Clear(); }
391 
392 	CLASS_COPY_PROTECTION( FSList );
393 };
394 
395 typedef int FSNodeCmpFunc(FSNode* n1, FSNode* n2);
396 class FSNodeVectorSorter
397 {
398 	static FSNodeCmpFunc* getCmpFunc(bool isAscending, bool isCaseSensitive, SORT_MODE sortMode);
399 
400 public:
401 	static void Sort(std::vector<FSNode*>& nodeVector, bool isAscending, bool isCaseSensitive, SORT_MODE sortMode);
402 	static int BSearch(FSNode& n, const std::vector<FSNode*>& nodeVector, BSearchMode searchMode, bool isAscending, bool isCaseSensitive, SORT_MODE sortMode);
403 };
404 
405 struct FSSmbParam
406 {
407 
408 	volatile char server[0x100]; //all utf8
409 	volatile char domain[0x100];
410 	volatile char user[0x100];
411 	volatile char pass[0x100];
412 	volatile bool isSet;
413 
FSSmbParamFSSmbParam414 	FSSmbParam(): isSet( 0 ) { server[0] = domain[0] = user[0] = pass[0] = 0;  }
415 
SetServerFSSmbParam416 	void SetServer( const char* s )
417 	{
418 		volatile char* p = server;
419 		int n = sizeof( server ) - 1;
420 
421 		for ( ; *s && n > 0; s++, p++, n-- )
422 		{
423 			*p = *s;
424 		}
425 
426 		*p = 0;
427 	}
428 
GetConfFSSmbParam429 	void GetConf( StrConfig& conf )
430 	{
431 		conf.Set( "SERVER", const_cast<char*>( server ) );
432 		conf.Set( "DOMAIN", const_cast<char*>( domain ) );
433 		conf.Set( "USER", const_cast<char*>( user ) );
434 	}
435 
_copyFSSmbParam436 	static void _copy( char* dest, const char* src, int destSize )
437 	{
438 		int n = destSize;
439 
440 		for ( ; *src && n > 1; src++, dest++, n-- ) { *dest = *src; }
441 
442 		*dest = 0;
443 	}
444 
445 
SetConfFSSmbParam446 	void SetConf( StrConfig& conf )
447 	{
448 		const char* s = conf.GetStrVal( "SERVER" );
449 
450 		if ( s ) { _copy( const_cast<char*>( server ), s, sizeof( server ) ); }
451 
452 		s = conf.GetStrVal( "DOMAIN" );
453 
454 		if ( s ) { _copy( const_cast<char*>( domain ), s, sizeof( domain ) ); }
455 
456 		s = conf.GetStrVal( "USER" );
457 
458 		if ( s ) { _copy( const_cast<char*>( user ), s, sizeof( user ) ); }
459 	}
460 };
461 
462 struct FSFtpParam
463 {
464 	std::string server;
465 	volatile int port;
466 	volatile int charset;
467 	volatile bool anonymous;
468 	std::string user;
469 	std::string pass;
470 	volatile bool passive;
471 	volatile bool isSet;
472 
FSFtpParamFSFtpParam473 	FSFtpParam(): port( 21 ),
474 #ifdef _WIN32
475 		charset( CS_UTF8 ),
476 #else
477 		charset( sys_charset_id ),
478 #endif
479 		anonymous( true ),
480 		passive( true ),
481 		isSet( false )
482 	{}
483 
GetConfFSFtpParam484 	void GetConf( StrConfig& conf )
485 	{
486 		conf.Set( "SERVER", server.c_str() );
487 		conf.Set( "USER", user.c_str() );
488 		conf.Set( "PASSWORD", g_WcmConfig.systemStorePasswords ? pass.c_str() : "" );
489 		conf.Set( "PORT", port );
490 		conf.Set( "ANONYMOUS", anonymous ? 1 : 0 );
491 		conf.Set( "PASSIVE", passive ? 1 : 0 );
492 
493 		conf.Set( "CHARSET", charset_table.NameById( charset ) );
494 	}
495 
SetConfFSFtpParam496 	void SetConf( StrConfig& conf )
497 	{
498 		const char* s = conf.GetStrVal( "SERVER" );
499 
500 		if ( s ) { server = s; }
501 
502 		s = conf.GetStrVal( "USER" );
503 
504 		if ( s ) { user = s; }
505 
506 		s = conf.GetStrVal( "PASSWORD" );
507 
508 		if ( s ) { pass = s; }
509 
510 		int n = conf.GetIntVal( "PORT" );
511 
512 		if ( n > 0 ) { port = n; }
513 
514 		n = conf.GetIntVal( "ANONYMOUS" );
515 		anonymous = n == 0 ? false : true;
516 
517 		n = conf.GetIntVal( "PASSIVE" );
518 		passive = n == 0 ? false : true;
519 
520 		charset = charset_table.IdByName( conf.GetStrVal( "CHARSET" ) );
521 
522 		isSet = anonymous;
523 	}
524 
525 	inline bool operator == ( const FSFtpParam& Other ) const
526 	{
527 		return
528 			( this->server == Other.server ) &&
529 			( this->anonymous == Other.anonymous && ( this->anonymous || (this->user == Other.user) ) ) &&
530 			( this->port == Other.port );
531 	}
532 };
533 
534 
535 struct FSSftpParam
536 {
537 	std::string server;
538 	volatile int port;
539 	volatile int charset;
540 	std::string user;
541 	volatile bool isSet;
FSSftpParamFSSftpParam542 	FSSftpParam(): port( 22 ),
543 #ifdef _WIN32
544 		charset( CS_UTF8 ),
545 #else
546 		charset( sys_charset_id ),
547 #endif
548 		isSet( false ) {}
549 
GetConfFSSftpParam550 	void GetConf( StrConfig& conf )
551 	{
552 		conf.Set( "SERVER", server.c_str() );
553 		conf.Set( "USER", user.c_str() );
554 //		conf.Set( "PASSWORD", g_WcmConfig.systemStorePasswords ? pass.c_str() : "" );
555 		conf.Set( "PORT", port );
556 		conf.Set( "CHARSET", charset_table.NameById( charset ) );
557 	}
558 
SetConfFSSftpParam559 	void SetConf( StrConfig& conf )
560 	{
561 		const char* s = conf.GetStrVal( "SERVER" );
562 
563 		if ( s ) { server = s; }
564 
565 		s = conf.GetStrVal( "USER" );
566 
567 		if ( s ) { user = s; }
568 
569 //		s = conf.GetStrVal( "PASSWORD" );
570 
571 //		if ( s ) { pass = s; }
572 
573 		int n = conf.GetIntVal( "PORT" );
574 
575 		if ( n > 0 ) { port = n; }
576 
577 		charset = charset_table.IdByName( conf.GetStrVal( "CHARSET" ) );
578 	}
579 
580 	inline bool operator == ( const FSSftpParam& Other ) const
581 	{
582 		return
583 			this->server == Other.server &&
584 			this->user == Other.user &&
585 			this->port == Other.port;
586 	}
587 };
588 
589 struct FSPromptData
590 {
591 	volatile bool visible;
592 	std::string prompt;
593 };
594 
595 class FSCInfo
596 {
597 public:
FSCInfo()598 	FSCInfo() {}
599 	virtual ~FSCInfo();
600 	virtual bool IsStopped() const;
601 	virtual bool SmbLogon( FSSmbParam* a );
602 	virtual bool FtpLogon( FSFtpParam* a );
603 	virtual bool Prompt( const unicode_t* header, const unicode_t* message, FSPromptData* p, int count );
604 };
605 
606 class FSCSimpleInfo: public FSCInfo
607 {
608 public:
609 	std::atomic<bool> m_Stopped;
FSCSimpleInfo()610 	FSCSimpleInfo()
611 	: m_Stopped( false )
612 	{}
613 	virtual ~FSCSimpleInfo();
Reset()614 	void Reset() { m_Stopped = false; }
SetStop()615 	void SetStop() { m_Stopped = true; }
616 	virtual bool IsStopped() const override;
617 };
618 
619 
620 /*
621    все фанкции, возвращающие int возвращают 0 при успехе  -1 при ошибке и -2 при StopEvent
622    одна FS (один и тот же объект) может в один период времени мспользоваться только одним потоком
623 
624    id файла - int
625 */
626 
627 
628 class FS: public iIntrusiveCounter
629 {
630 public:
631 	enum TYPES { SYSTEM = 0, SFTP = 1, SAMBA = 2, FTP = 3, WIN32NET = 4, TMP = 5 };
632 	enum FLAGS { HAVE_READ = 1, HAVE_WRITE = 2, HAVE_SYMLINK = 4, HAVE_SEEK = 8 };
633 	enum OPENFLAGS { SHARE_READ = 1, SHARE_WRITE = 2 };
634 private:
635 	int _type;
636 public:
FS(int t)637 	FS( int t ): _type( t ) { }
Type()638 	int Type() const { return _type; }
IsPersistent()639 	virtual bool IsPersistent() { return true; } // persistent FS location can be saved on app exit and restored on next startup
640 
SetError(int * p,int err)641 	static int SetError(int* p, int err) { if (p) { *p = err; }; return err; }
642 
643 	virtual unsigned Flags()      = 0;
644 	virtual bool IsEEXIST( int err )      = 0;
645 	virtual bool IsENOENT( int err )      = 0;
646 	virtual bool IsEXDEV( int err )    = 0;
IsNORENAME(int err)647 	bool IsNORENAME( int err ) { return IsEXDEV( err ); };
648 	virtual FSString StrError( int err )  = 0; //строка ощибки с указанным идентификатором
649 	virtual bool Equal( FS* fs ) = 0; //должна отрабатывать null (как false)
650 
651 	virtual int OpenRead ( FSPath& path, int flags, int* err, FSCInfo* info );
652 	virtual int OpenCreate  ( FSPath& path, bool overwrite, int mode, int flags, int* err, FSCInfo* info );
653 	virtual int Close ( int fd, int* err, FSCInfo* info );
654 	virtual int Read  ( int fd, void* buf, int size, int* err, FSCInfo* info );
655 	virtual int Write ( int fd, void* buf, int size, int* err, FSCInfo* info );
656 	virtual int Seek  ( int fd, SEEK_FILE_MODE mode, seek_t pos, seek_t* pRet,  int* err, FSCInfo* info );
657 	virtual int Rename   ( FSPath&  oldpath, FSPath& newpath, int* err, FSCInfo* info );
658 	virtual int MkDir ( FSPath& path, int mode, int* err,  FSCInfo* info );
659 	virtual int Delete   ( FSPath& path, int* err, FSCInfo* info );
660 	virtual int RmDir ( FSPath& path, int* err, FSCInfo* info );
661 	virtual int SetFileTime ( FSPath& path, FSTime cTime, FSTime aTime, FSTime mTime, int* err, FSCInfo* info );
662 	virtual int ReadDir  ( FSList* list, FSPath& path,  int* err, FSCInfo* info );
663 	virtual int Stat( FSPath& path, FSStat* st, int* err, FSCInfo* info );
664 	/// apply attributes to a file
665 	virtual int StatSetAttr( FSPath& path, const FSStat* st, int* err, FSCInfo* info );
666 	virtual int FStat( int fd, FSStat* st, int* err, FSCInfo* info );
667 	virtual int Symlink  ( FSPath& path, FSString& str, int* err, FSCInfo* info );
668 	virtual int StatVfs( FSPath& path, FSStatVfs* st, int* err, FSCInfo* info );
669 	virtual int64_t GetFileSystemFreeSpace( FSPath& path, int* err );
670 
671 	virtual FSString Uri( FSPath& path )                    = 0;
672 
673 	virtual unicode_t* GetUserName( int user, unicode_t buf[64] );
674 	virtual unicode_t* GetGroupName( int group, unicode_t buf[64] );
675 
676 	virtual ~FS();
677 	CLASS_COPY_PROTECTION( FS );
678 };
679 
680 #ifdef _WIN32
681 class FSSysHandles
682 {
683 	Mutex mutex;
684 	enum { SIZE = 32 };
685 	struct Node
686 	{
687 		volatile bool busy;
688 		volatile HANDLE handle;
689 	};
690 	Node table[SIZE];
691 public:
FSSysHandles()692 	FSSysHandles() { for ( int i = 0; i < SIZE; i++ ) { table[i].busy = false; } }
New()693 	int New()
694 	{
695 		MutexLock lock( &mutex );
696 
697 		for ( int i = 0; i < SIZE; i++ )
698 			if ( !table[i].busy ) { table[i].handle = INVALID_HANDLE_VALUE; table[i].busy = true; return i; }
699 
700 		return -1;
701 	};
Handle(int n)702 	HANDLE* Handle( int n )
703 	{
704 		MutexLock lock( &mutex );
705 
706 		if ( n >= 0 && n < SIZE && table[n].busy )
707 		{
708 			return const_cast<HANDLE*>( &( table[n].handle ) );
709 		}
710 
711 		return 0;
712 	}
Free(int n)713 	void Free( int n )
714 	{
715 		MutexLock lock( &mutex );
716 
717 		if ( n >= 0 && n < SIZE && table[n].busy )
718 		{
719 			table[n].busy = false;
720 			table[n].handle =  INVALID_HANDLE_VALUE;
721 		}
722 	}
723 };
724 #endif
725 
726 
727 class FSSys: public FS
728 {
729 #ifdef _WIN32
730 	volatile int _drive;
731 	FSSysHandles handles;
732 public:
FSSys()733 	FSSys()
734 	: _drive(-1)
735 	, FS( FS::SYSTEM )
736 	{}
737 #endif // _WIN32
738 public:
739 #ifdef _WIN32
740 	//0-'A'...'Z', -1 - network
FSSys(int drive)741 	explicit FSSys( int drive ): FS( FS::SYSTEM ), _drive( drive ) {}
Drive()742 	int Drive() const { return _drive; }
743 #else
744 	FSSys(): FS( FS::SYSTEM ) {}
745 #endif
746 	virtual unsigned Flags();
747 	virtual bool IsEEXIST( int err );
748 	virtual bool IsENOENT( int err );
749 	virtual bool IsEXDEV( int err );
750 	virtual FSString StrError( int err );
751 	virtual bool Equal( FS* fs );
752 
753 	virtual int OpenRead ( FSPath& path, int flags, int* err, FSCInfo* info );
754 	virtual int OpenCreate  ( FSPath& path, bool overwrite, int mode, int flags, int* err, FSCInfo* info );
755 	virtual int Close ( int fd, int* err, FSCInfo* info );
756 	virtual int Read  ( int fd, void* buf, int size, int* err, FSCInfo* info );
757 	virtual int Write ( int fd, void* buf, int size, int* err, FSCInfo* info );
758 	virtual int Seek  ( int fd, SEEK_FILE_MODE mode, seek_t pos, seek_t* pRet,  int* err, FSCInfo* info );
759 	virtual int Rename   ( FSPath&  oldpath, FSPath& newpath, int* err,  FSCInfo* info );
760 	virtual int MkDir ( FSPath& path, int mode, int* err,  FSCInfo* info );
761 	virtual int Delete   ( FSPath& path, int* err, FSCInfo* info );
762 	virtual int RmDir ( FSPath& path, int* err, FSCInfo* info );
763 	virtual int SetFileTime ( FSPath& path, FSTime cTime, FSTime aTime, FSTime mTime, int* err, FSCInfo* info ) override;
764 	virtual int ReadDir  ( FSList* list, FSPath& path, int* err, FSCInfo* info );
765 	virtual int Stat  ( FSPath& path, FSStat* st, int* err, FSCInfo* info );
766 	virtual int StatSetAttr( FSPath& path, const FSStat* st, int* err, FSCInfo* info );
767 	virtual int FStat( int fd, FSStat* st, int* err, FSCInfo* info );
768 	virtual int Symlink  ( FSPath& path, FSString& str, int* err, FSCInfo* info );
769 	virtual int StatVfs( FSPath& path, FSStatVfs* st, int* err, FSCInfo* info );
770 	virtual FSString Uri( FSPath& path );
771 	virtual int64_t GetFileSystemFreeSpace( FSPath& path, int* err );
772 
773 	virtual unicode_t* GetUserName( int user, unicode_t buf[64] );
774 	virtual unicode_t* GetGroupName( int group, unicode_t buf[64] );
775 
776 	virtual ~FSSys();
777 };
778 
779 
780 
781 #ifdef _WIN32
782 
783 class FSWin32Net: public FS
784 {
785 	volatile W32NetRes  _res;
786 public:
787 	enum { ERRNOSUPPORT = -1000 };
FSWin32Net(NETRESOURCEW * p)788 	FSWin32Net( NETRESOURCEW* p ): FS( FS::WIN32NET ), _res( p ) {};
789 	virtual unsigned Flags() override;
790 	virtual bool IsEEXIST( int err ) override;
791 	virtual bool IsENOENT( int err ) override;
792 	virtual bool IsEXDEV( int err ) override;
793 	virtual FSString StrError( int err ) override;
794 	virtual bool Equal( FS* fs ) override;
795 	virtual int OpenRead ( FSPath& path, int flags, int* err, FSCInfo* info ) override;
796 	virtual int OpenCreate  ( FSPath& path, bool overwrite, int mode, int flags, int* err, FSCInfo* info ) override;
797 	virtual int Close ( int fd, int* err, FSCInfo* info ) override;
798 	virtual int Read  ( int fd, void* buf, int size, int* err, FSCInfo* info ) override;
799 	virtual int Write ( int fd, void* buf, int size, int* err, FSCInfo* info ) override;
800 	virtual int Seek  ( int fd, SEEK_FILE_MODE mode, seek_t pos, seek_t* pRet,  int* err, FSCInfo* info ) override;
801 	virtual int Rename   ( FSPath&  oldpath, FSPath& newpath, int* err,  FSCInfo* info ) override;
802 	virtual int MkDir ( FSPath& path, int mode, int* err,  FSCInfo* info ) override;
803 	virtual int Delete   ( FSPath& path, int* err, FSCInfo* info ) override;
804 	virtual int RmDir ( FSPath& path, int* err, FSCInfo* info ) override;
805 	virtual int SetFileTime ( FSPath& path, FSTime cTIme, FSTime aTime, FSTime mTime, int* err, FSCInfo* info ) override;
806 	virtual int ReadDir  ( FSList* list, FSPath& path, int* err, FSCInfo* info ) override;
807 	virtual int Stat  ( FSPath& path, FSStat* st, int* err, FSCInfo* info ) override;
808 	virtual int Symlink  ( FSPath& path, FSString& str, int* err, FSCInfo* info ) override;
809 	virtual FSString Uri( FSPath& path ) override;
810 	virtual ~FSWin32Net();
811 };
812 
813 #endif
814 
815 
816 //path - должен быть абсолютным (если нет - то вернет false)
817 extern bool ParzeLink( FSPath& path, FSString& link );
818 
819 /// HH:MM:SS
820 std::string GetFSTimeStrTime( FSTime TimeValue );
821 /// DD:MM:YYYY
822 std::string GetFSTimeStrDate( FSTime TimeValue );
823 /// DD:MM:YYYY, HH:MM:SS
824 FSTime GetFSTimeFromStr( const std::string& Date, const std::string& Time );
825 
826