clPtr<FS> ParzeFtpURI( const unicode_t* uri, FSPath& path, clPtr<FS>* checkFS, int count )
{
	path.Set( rootPathStr );

	if ( !uri[0] ) { return clPtr<FS>(); }

	FSFtpParam param;

	const unicode_t* userDelimiter = FindFirstChar( uri, '@' );

	if ( *userDelimiter )
	{
		param.user = FSString( CS_UNICODE, uri, userDelimiter - uri ).GetUnicode();
		uri = userDelimiter + 1;
		param.anonymous = false;
	}
	else
	{
		param.anonymous = true;
	}


	const unicode_t* host_port_End = FindFirstChar( uri, '/' );
	const unicode_t* host_End = FindFirstChar( uri, ':' );

	FSString host( CS_UNICODE, uri, ( ( host_End < host_port_End ) ? host_End :  host_port_End )  - uri );

	int port  = 0;

	for ( const unicode_t* s = host_End + 1; s < host_port_End; s++ )
		if ( *s >= '0' && *s <= '9' ) { port = port * 10 + ( *s - '0' ); }
		else { break; }

	if ( port > 0 && port < 65536 ) { param.port = port; }

	param.server = host.GetUnicode();

	uri = host_port_End;

	FSString link = uri;

	if ( !ParzeLink( path, link ) ) { return clPtr<FS>(); }

	for ( int i = 0; i < count; i++ )
		if ( checkFS[i].Ptr() && checkFS[i]->Type() == FS::FTP )
		{
			FSFtp* p = ( FSFtp* )checkFS[i].Ptr();
			FSFtpParam checkParam;
			p->GetParam( &checkParam );

			if (  !CmpStr<const unicode_t>( param.server.Data(), checkParam.server.Data() ) &&
			      ( param.anonymous == checkParam.anonymous && ( param.anonymous || !CmpStr<const unicode_t>( param.user.Data(), checkParam.user.Data() ) ) ) &&
			      param.port == checkParam.port )
			{
				return checkFS[i];
			}
		}

	return new FSFtp( &param );
}
clPtr<FS> ParzeSmbURI( const unicode_t* uri, FSPath& path, clPtr<FS>* checkFS, int count )
{
	path.Set( rootPathStr );

	if ( !uri[0] ) { return new FSSmb(); }

	FSSmbParam param;

	const unicode_t* userDelimiter = FindFirstChar( uri, '@' );

	if ( *userDelimiter )
	{
		FSString s( CS_UNICODE, uri, userDelimiter - uri );
		SetString( const_cast<char*>( param.user ), sizeof( param.user ), s.GetUtf8() );
		uri = userDelimiter + 1;
	}

	const unicode_t* hostEnd = FindFirstChar( uri, '/' );
	FSString host( CS_UNICODE, uri, hostEnd - uri );
	SetString( const_cast<char*>( param.server ), sizeof( param.server ), host.GetUtf8() );

	uri = hostEnd;

	FSString link = uri;

	if ( !ParzeLink( path, link ) ) { return clPtr<FS>(); }

	return new FSSmb( &param );
}
Example #3
0
void OperRDThread::Run()
{
	int n = 8;
	int ret_err;

	while (true) 
	{
		if (!(fs->Flags() & FS::HAVE_SYMLINK))
			break;
		
		FSStat st;

		if (fs->Stat(path, &st, &ret_err, Info()))
			throw_msg("%s", fs->StrError(ret_err).GetUtf8());
			
		if (!st.IsLnk()) 
			break;
		n--;
		if (n<0) 
			throw_msg("too more symbolic links '%s'", path.GetUtf8());
			
		path.Pop();
		if (!ParzeLink(path, st.link))
			throw_msg("invalid symbolic link '%s'", path.GetUtf8());
	}

	cptr<FSList> list = new FSList;
	int ret = fs->ReadDir(list.ptr(), path, &ret_err, Info());
	if (ret) 
		throw_msg("%s", fs->StrError(ret_err).GetUtf8());
	
	MutexLock lock(Node().GetMutex()); //!!!
	if (Node().NBStopped()) return;
	OperRDData *data = ((OperRDData*)Node().Data());
	data->list = list;
	data->path = path;
	data->executed = true;
}
Example #4
0
void OperRDThread::Run()
{
	if ( !fs.Ptr() ) { return; }

	int n = 8;
	int ret_err;

	int havePostponedStatError = 0;
	FSString postponedStrError;

	while ( true )
	{
		if ( !( fs->Flags() & FS::HAVE_SYMLINK ) )
		{
			break;
		}

		FSStat st;

		// if path is inaccessible, try .. path. Throw the exception later
		// This makes panel at least having some valid folder
		while ( fs->Stat( path, &st, &ret_err, Info() ) )
		{
			havePostponedStatError = 1;
			postponedStrError = fs->StrError( ret_err );

			if ( !path.IsAbsolute() || path.Count() <= 1 || !path.Pop() )
			{
				throw_msg( "%s", postponedStrError.GetUtf8() );
			}
		}

		// yell immediately if the path is inaccessible (orig behavior)
		//if (fs->Stat(path, &st, &ret_err, Info()))
		// throw_msg("%s", fs->StrError(ret_err).GetUtf8());

		if ( !st.IsLnk() )
		{
			break;
		}

		n--;

		if ( n < 0 )
		{
			throw_msg( "too many symbolic links '%s'", path.GetUtf8() );
		}

		path.Pop();

		if ( !ParzeLink( path, st.link ) )
		{
			throw_msg( "invalid symbolic link '%s'", path.GetUtf8() );
		}
	}

	clPtr<FSList> list = new FSList;

	int havePostponedReadError = 0;

	// if directory is not readable, try .. path. Throw the exception later
	// "Stat" call above does not catch this: it checks only folder existence, but not accessibilly
	while ( fs->ReadDir( list.ptr(), path, &ret_err, Info() ) )
	{
		havePostponedReadError = 1;
		postponedStrError = fs->StrError( ret_err );

		if ( !path.IsAbsolute() || path.Count() <= 1 || !path.Pop() )
		{
			throw_msg( "%s", postponedStrError.GetUtf8() );
		}
	}

	// yell immediately if the dir is unreadable (orig behavior)
	//int ret = fs->ReadDir(list.ptr(), path, &ret_err, Info());
	//if (ret)
	// throw_msg("%s", fs->StrError(ret_err).GetUtf8());

	FSStatVfs vst;
	fs->StatVfs( path, &vst, &ret_err, Info() );

	MutexLock lock( Node().GetMutex() ); //!!!

	if ( Node().NBStopped() ) { return; }

	OperRDData* data = ( ( OperRDData* )Node().Data() );
	data->list = list;
	data->path = path;
	data->executed = true;
	data->vst = vst;

	if ( havePostponedReadError || havePostponedStatError )
	{
		data->nonFatalErrorString = postponedStrError;
	}
}
clPtr<FS> ParzeURI( const unicode_t* uri, FSPath& path, clPtr<FS>* checkFS, int count )
{

#ifdef LIBSMBCLIENT_EXIST

	if ( uri[0] == 's' && uri[1] == 'm' && uri[2] == 'b' && uri[3] == ':' && uri[4] == '/' && uri[5] == '/' )
	{
		return ParzeSmbURI( uri + 6, path, checkFS, count );
	}

#endif

	if ( uri[0] == 'f' && uri[1] == 't' && uri[2] == 'p' && uri[3] == ':' && uri[4] == '/' && uri[5] == '/' )
	{
		return ParzeFtpURI( uri + 6, path, checkFS, count );
	}

#if defined(LIBSSH_EXIST) || defined(LIBSSH2_EXIST)

	if ( uri[0] == 's' && uri[1] == 'f' && uri[2] == 't' && uri[3] == 'p' && uri[4] == ':' && uri[5] == '/' && uri[6] == '/' )
	{
		return ParzeSftpURI( uri + 7, path, checkFS, count );
	}

#endif

	if ( uri[0] == 'f' && uri[1] == 'i' && uri[2] == 'l' && uri[3] == 'e' && uri[4] == ':' && uri[5] == '/' && uri[6] == '/' )
	{
		uri += 6;   //оставляем 1 символ '/'
	}


#ifdef _WIN32
	int c = uri[0];

	if ( c == '\\' || c == '/' )
	{
		if ( uri[1] == '/' || uri[1] == '\\' )
		{
			FSString link = uri + 1;

			if ( !ParzeLink( path, link ) ) { return clPtr<FS>(); }

			if ( path.Count() == 1 )
			{
				clPtr<FS> netFs = new FSWin32Net( 0 );
				path.Set( CS_UTF8, "/" );
				return netFs;
			}

			if ( path.Count() == 2 )
			{
				static unicode_t aa[] = {'\\', '\\', 0};
				std::vector<wchar_t> name = UnicodeToUtf16( carray_cat<unicode_t>( aa, path.GetItem( 1 )->GetUnicode() ).data() );

				NETRESOURCEW r;
				r.dwScope = RESOURCE_GLOBALNET;
				r.dwType = RESOURCETYPE_ANY;
				r.dwDisplayType = RESOURCEDISPLAYTYPE_GENERIC;
				r.dwUsage = RESOURCEUSAGE_CONTAINER;
				r.lpLocalName = 0;
				r.lpRemoteName = name.data();
				r.lpComment = 0;
				r.lpProvider = 0;

				clPtr<FS> netFs = new FSWin32Net( &r );
				path.Set( CS_UTF8, "/" );
				return netFs;
			}

			return new FSSys( -1 );
		}

		FSString link = uri;

		if ( !ParzeLink( path, link ) ) { return clPtr<FS>(); }

		return ( count > 0 && !checkFS[0].IsNull() ) ? checkFS[0] : clPtr<FS>();
	}

	if ( c >= 'A' && c <= 'Z' ) { c = c - 'A' + 'a'; }

	if ( c < 'a' || c > 'z' || uri[1] != ':' || ( uri[2] != '/' && uri[2] != '\\' ) )
	{
		FSString link = uri;

		if ( !ParzeLink( path, link ) ) { return clPtr<FS>(); }

		return ( count > 0 && !checkFS[0].IsNull() ) ? checkFS[0] : clPtr<FS>();
	}

	FSString link = uri + 2;

	if ( !ParzeLink( path, link ) ) { return clPtr<FS>(); }

	return new FSSys( c - 'a' );
#else
	FSString link = uri;

	if ( !ParzeLink( path, link ) ) { return clPtr<FS>(); }

	if ( uri[0] != '/' )
	{
		return ( count > 0 && !checkFS[0].IsNull() ) ? checkFS[0] : clPtr<FS>();
	}

	return new FSSys(); //systemclPtr<FS>;
#endif
}