bool CServerPath::DoChangePath(std::wstring &subdir, bool isFile)
{
	std::wstring dir = subdir;
	std::wstring file;

	if (dir.empty()) {
		if (empty() || isFile) {
			return false;
		}
		else {
			return true;
		}
	}

	bool const was_empty = empty();
	CServerPathData& data = m_data.get();

	switch (m_type)
	{
	case VMS:
		{
			size_t pos1 = dir.find(traits[m_type].left_enclosure);
			if (pos1 == std::wstring::npos) {
				size_t pos2 = dir.rfind(traits[m_type].right_enclosure);
				if (pos2 != std::wstring::npos) {
					return false;
				}

				if (isFile) {
					if (was_empty) {
						return false;
					}

					file = dir;
					break;
				}
			}
			else {
				size_t pos2 = dir.rfind(traits[m_type].right_enclosure);
				if (pos2 == std::wstring::npos || pos2 <= pos1 + 1) {
					return false;
				}

				bool enclosure_is_last = pos2 == (dir.size() - 1);
				if (isFile == enclosure_is_last) {
					return false;
				}

				if (isFile) {
					file = dir.substr(pos2 + 1);
				}
				dir = dir.substr(0, pos2);

				if (pos1) {
					data.m_prefix = fz::sparse_optional<std::wstring>(dir.substr(0, pos1));
				}
				dir = dir.substr(pos1 + 1);

				data.m_segments.clear();
			}

			if (!Segmentize(dir, data.m_segments)) {
				return false;
			}
			if (data.m_segments.empty() && was_empty) {
				return false;
			}
		}
		break;
	case DOS:
	case DOS_FWD_SLASHES:
		{
			bool is_absolute = false;
			size_t sep = dir.find_first_of(traits[m_type].separators);
			if (sep == std::wstring::npos) {
				sep = dir.size();
			}
			size_t colon = dir.find(':');
			if (colon != std::wstring::npos && colon > 0 && colon == sep - 1) {
				is_absolute = true;
			}

			if (is_absolute) {
				data.m_segments.clear();
			}
			else if (IsSeparator(dir[0])) {
				// Drive-relative path
				if (data.m_segments.empty()) {
					return false;
				}
				std::wstring first = data.m_segments.front();
				data.m_segments.clear();
				data.m_segments.push_back(first);
				dir = dir.substr(1);
			}
			// else: Any other relative path

			if (isFile && !ExtractFile(dir, file)) {
				return false;
			}

			if (!Segmentize(dir, data.m_segments)) {
				return false;
			}
			if (data.m_segments.empty() && was_empty) {
				return false;
			}
		}
		break;
	case MVS:
		{
			// Remove the double quoation some servers send in PWD reply
			size_t i = 0;
			wchar_t c = dir[i];
			while (c == FTP_MVS_DOUBLE_QUOTE) {
				c = dir[++i];
			}
			dir.erase(0, i);

			while (!dir.empty()) {
				c = dir.back();
				if (c != FTP_MVS_DOUBLE_QUOTE) {
					break;
				}
				else {
					dir.pop_back();
				}
			}
		}
		if (dir.empty()) {
			return false;
		}

		if (dir[0] == traits[m_type].left_enclosure) {
			if (dir.back() != traits[m_type].right_enclosure) {
				return false;
			}

			dir = dir.substr(1, dir.size() - 2);

			data.m_segments.clear();
		}
		else if (dir.back() == traits[m_type].right_enclosure) {
			return false;
		}
		else if (was_empty) {
			return false;
		}

		if (!dir.empty() && dir.back() == ')') {
			// Partitioned dataset member
			if (!isFile) {
				return false;
			}

			size_t pos = dir.find('(');
			if (pos == std::wstring::npos) {
				return false;
			}
			dir.pop_back();
			file = dir.substr(pos + 1);
			dir = dir.substr(0, pos);

			if (!was_empty && !data.m_prefix && !dir.empty()) {
				return false;
			}

			data.m_prefix.clear();
		}
		else {
			if (!was_empty && !data.m_prefix) {
				if (dir.find('.') != std::wstring::npos || !isFile) {
					return false;
				}
			}

			if (isFile) {
				if (!ExtractFile(dir, file)) {
					return false;
				}
				data.m_prefix = fz::sparse_optional<std::wstring>(L".");
			}
			else if (!dir.empty() && dir.back() == '.') {
				data.m_prefix = fz::sparse_optional<std::wstring>(L".");
			}
			else {
				data.m_prefix.clear();
			}
		}

		if (!Segmentize(dir, data.m_segments)) {
			return false;
		}
		break;
	case HPNONSTOP:
		if (dir[0] == '\\') {
			data.m_segments.clear();
		}

		if (isFile && !ExtractFile(dir, file)) {
			return false;
		}

		if (!Segmentize(dir, data.m_segments)) {
			return false;
		}
		if (data.m_segments.empty() && was_empty) {
			return false;
		}

		break;
	case VXWORKS:
		{
			if (dir[0] != ':') {
				if (was_empty) {
					return false;
				}
			}
			else {
				size_t colon2 =  dir.find(':', 1);
				if (colon2 == std::wstring::npos || colon2 == 1) {
					return false;
				}
				data.m_prefix = fz::sparse_optional<std::wstring>(dir.substr(0, colon2 + 1));
				dir = dir.substr(colon2 + 1);

				data.m_segments.clear();
			}

			if (isFile && !ExtractFile(dir, file)) {
				return false;
			}

			if (!Segmentize(dir, data.m_segments)) {
				return false;
			}
		}
		break;
	case CYGWIN:
		{
			if (IsSeparator(dir[0])) {
				data.m_segments.clear();
				data.m_prefix.clear();
			}
			else if (was_empty) {
				return false;
			}
			if (dir[0] == '/' && dir[1] == '/') {
				data.m_prefix = fz::sparse_optional<std::wstring>(std::wstring(1, traits[m_type].separators[0]));
				dir = dir.substr(1);
			}

			if (isFile && !ExtractFile(dir, file)) {
				return false;
			}

			if (!Segmentize(dir, data.m_segments)) {
				return false;
			}
		}
		break;
	default:
		{
			if (IsSeparator(dir[0])) {
				data.m_segments.clear();
			}
			else if (was_empty) {
				return false;
			}

			if (isFile && !ExtractFile(dir, file)) {
				return false;
			}

			if (!Segmentize(dir, data.m_segments)) {
				return false;
			}
		}
		break;
	}

	if (!traits[m_type].has_root && data.m_segments.empty()) {
		return false;
	}

	if (isFile) {
		if (traits[m_type].has_dots) {
			if (file == L".." || file == L".") {
				return false;
			}
		}
		subdir = file;
	}

	return true;
}
Beispiel #2
0
bool CServerPath::ChangePath(wxString &subdir, bool isFile)
{
	wxString dir = subdir;
	wxString file;

	dir.Trim(true);
	dir.Trim(false);

	if (dir == _T(""))
	{
		if (IsEmpty() || isFile)
			return false;
		else
			return true;
	}

	CServerPathData& data = m_data.Get();

	switch (m_type)
	{
	case VMS:
		{
			int pos1 = dir.Find(traits[m_type].left_enclosure);
			if (pos1 == -1)
			{
				int pos2 = dir.Find(traits[m_type].right_enclosure, true);
				if (pos2 != -1)
					return false;

				if (isFile)
				{
					if (IsEmpty())
						return false;

					file = dir;
					break;
				}
			}
			else
			{
				int pos2 = dir.Find(traits[m_type].right_enclosure, true);
				if (pos2 == -1 || pos2 <= pos1 + 1)
					return false;

				bool enclosure_is_last = static_cast<size_t>(pos2) == (dir.Length() - 1);
				if (isFile == enclosure_is_last)
					return false;

				if (isFile)
					file = dir.Mid(pos2 + 1);
				dir = dir.Left(pos2);

				if (pos1)
					data.m_prefix = dir.Left(pos1);
				dir = dir.Mid(pos1 + 1);

				data.m_segments.clear();
			}

			if (!Segmentize(dir, data.m_segments))
				return false;
			if (data.m_segments.empty() && m_bEmpty)
				return false;
		}
		break;
	case DOS:
		{
			bool is_relative = false;
			int sep = dir.Find(traits[m_type].separator);
			if (sep == -1)
				sep = dir.Len();
			int colon = dir.Find(':');
			if (colon > 0 && colon == sep - 1)
				is_relative = true;

			if (is_relative)
				data.m_segments.clear();
			else if (dir[0] == traits[m_type].separator)
			{
				if (data.m_segments.empty())
					return false;
				wxString first = data.m_segments.front();
				data.m_segments.clear();
				data.m_segments.push_back(first);
				dir = dir.Mid(1);
			}

			if (isFile && !ExtractFile(dir, file))
				return false;

			if (!Segmentize(dir, data.m_segments))
				return false;
			if (data.m_segments.empty() && m_bEmpty)
				return false;
		}
		break;
	case MVS:
		{
			// Remove the double quoation some servers send in PWD reply
			int i = 0;
			wxChar c = dir.c_str()[i];
			while (c == FTP_MVS_DOUBLE_QUOTE)
				c = dir.c_str()[++i];
			dir.Remove(0, i);

			while (dir != _T(""))
			{
				c = dir.Last();
				if (c != FTP_MVS_DOUBLE_QUOTE)
					break;
				else
					dir.RemoveLast();
			}
		}
		if (dir == _T(""))
			return false;

		if (dir.c_str()[0] == traits[m_type].left_enclosure)
		{
			if (dir.Last() != traits[m_type].right_enclosure)
				return false;

			dir.RemoveLast();
			dir = dir.Mid(1);

			data.m_segments.clear();
		}
		else if (dir.Last() == traits[m_type].right_enclosure)
			return false;
		else if (m_bEmpty)
			return false;

		if (dir.Last() == ')')
		{
			// Partitioned dataset member
			if (!isFile)
				return false;

			int pos = dir.Find('(');
			if (pos == -1)
				return false;
			dir.RemoveLast();
			file = dir.Mid(pos + 1);
			dir = dir.Left(pos);

			if (!m_bEmpty && data.m_prefix == _T("") && !dir.empty())
				return false;

			data.m_prefix.clear();
		}
		else
		{
			if (!m_bEmpty && data.m_prefix == _T(""))
			{
				if (dir.Find('.') != -1 || !isFile)
					return false;
			}

			if (isFile)
			{
				if (!ExtractFile(dir, file))
					return false;
				data.m_prefix = _T(".");
			}
			else if (dir.Last() == '.')
				data.m_prefix = _T(".");
			else
				data.m_prefix.clear();
		}

		if (!Segmentize(dir, data.m_segments))
			return false;
		break;
	case HPNONSTOP:
		if (dir[0] == '\\')
			data.m_segments.clear();

		if (isFile && !ExtractFile(dir, file))
			return false;

		if (!Segmentize(dir, data.m_segments))
			return false;
		if (data.m_segments.empty() && m_bEmpty)
			return false;

		break;
	case VXWORKS:
		{
			if (dir[0] != ':')
			{
				if (IsEmpty())
					return false;
			}
			else
			{
				int colon2;
				if ((colon2 = dir.Mid(1).Find(':')) < 1)
					return false;
				data.m_prefix = dir.Left(colon2 + 2);
				dir = dir.Mid(colon2 + 2);

				data.m_segments.clear();
			}

			if (isFile && !ExtractFile(dir, file))
				return false;

			if (!Segmentize(dir, data.m_segments))
				return false;
		}
		break;
	case CYGWIN:
		{
			if (dir[0] == traits[m_type].separator)
			{
				data.m_segments.clear();
				data.m_prefix.clear();
			}
			else if (m_bEmpty)
				return false;
			if (dir.Left(2) == _T("//"))
			{
				data.m_prefix = traits[m_type].separator;
				dir = dir.Mid(1);
			}

			if (isFile && !ExtractFile(dir, file))
				return false;

			if (!Segmentize(dir, data.m_segments))
				return false;
		}
		break;
	default:
		{
			if (dir[0] == traits[m_type].separator)
				data.m_segments.clear();
			else if (m_bEmpty)
				return false;

			if (isFile && !ExtractFile(dir, file))
				return false;

			if (!Segmentize(dir, data.m_segments))
				return false;
		}
		break;
	}

	if (!traits[m_type].has_root && data.m_segments.empty())
		return false;

	if (isFile)
	{
		if (traits[m_type].has_dots)
		{
			if (file == _T("..") || file == _T("."))
				return false;
		}
		subdir = file;
	}

	m_bEmpty = false;
	return true;
}