Logo Search packages:      
Sourcecode: filezilla version File versions

serverpath.cpp

#include "FileZilla.h"
#include "serverpath.h"

#define FTP_MVS_DOUBLE_QUOTE (wxChar)0xDC
CServerPath::CServerPath()
{
      m_type = DEFAULT;
      m_bEmpty = true;
}

CServerPath::CServerPath(const CServerPath &path, wxString subdir /*=_T("")*/)
{
      m_type = path.m_type;
      m_bEmpty = path.m_bEmpty;
      m_prefix = path.m_prefix;
      m_Segments = path.m_Segments;

      subdir.Trim(true);
      subdir.Trim(false);
      
      if (subdir == _T(""))
            return;

      if (!ChangePath(subdir))
            Clear();
}

CServerPath::CServerPath(wxString path, ServerType type /*=DEFAULT*/)
{
      m_type = type;

      SetPath(path);
}

CServerPath::~CServerPath()
{
}

void CServerPath::Clear()
{
      m_bEmpty = true;
      m_type = DEFAULT;
      m_prefix = _T("");
      m_Segments.clear();
}

bool CServerPath::SetPath(wxString newPath)
{
      return SetPath(newPath, false);
}

bool CServerPath::SetPath(wxString &newPath, bool isFile)
{
      m_Segments.clear();
      m_prefix = _T("");

      wxString path = newPath;
      wxString file;

      path.Trim(true);
      path.Trim(false);

      if (path == _T(""))
      {
            m_bEmpty = true;
            return false;
      }
      else
            m_bEmpty = false;

      if (m_type == DEFAULT)
      {
            int pos1 = path.Find(_T(":["));
            if (pos1 != -1)
            {
                  int pos2 = path.Find(']', true);
                  if (pos2 != -1 && static_cast<size_t>(pos2) == (path.Length() - 1) && !isFile)
                        m_type = VMS;
                  else if (isFile && pos2 > pos1)
                        m_type = VMS;
            }
            else if (path.Length() >= 3 &&
                  ((path.c_str()[0] >= 'A' && path.c_str()[0] <= 'Z') || (path.c_str()[0] >= 'a' && path.c_str()[0] <= 'z')) &&
                  path.c_str()[1] == ':' && (path.c_str()[2] == '\\' || path.c_str()[2] == '/'))
                        m_type = DOS;
            else if (path.c_str()[0] == FTP_MVS_DOUBLE_QUOTE && path.Last() == FTP_MVS_DOUBLE_QUOTE)
                  m_type = MVS;
            else if (path[0] == ':' && (pos1 = path.Mid(1).Find(':')) > 0)
            {
                  int slash = path.Find('/');
                  if (slash == -1 || slash > pos1)
                        m_type = VXWORKS;
            }
            
            if (m_type == DEFAULT)
                  m_type = UNIX;
      }

      int pos;
      switch (m_type)
      {
      case VMS:
            if (isFile)
            {
                  pos = path.Find(']', true);
                  if (pos == -1)
                  {
                        m_bEmpty = true;
                        return false;
                  }
                  file = path.Mid(pos + 1);
                  path = path.Left(pos + 1);
            }
            pos = path.Find(_T("["));
            if (pos == -1 || path.Right(1) != _T("]"))
            {
                  m_bEmpty = true;
                  return false;
            }
            path.RemoveLast();
            if (pos)
                  m_prefix = path.Left(pos);
            path = path.Mid(pos + 1);
            pos = path.Find(_T("."));
            while (pos != -1)
            {
                  m_Segments.push_back(path.Left(pos));
                  path = path.Mid(pos + 1);
                  pos = path.Find(_T("."));
            }
            if (path != _T(""))
                  m_Segments.push_back(path);
            break;
      case MVS:
            {
                  int i = 0;
                  wxChar c = path.c_str()[i];
                  while (c == FTP_MVS_DOUBLE_QUOTE || c == '\'' || c == '.')
                        c = path.c_str()[++i];
                  path.Remove(0, i);
                  
                  while (path != _T(""))
                  {
                        c = path.Last();
                        if (c != FTP_MVS_DOUBLE_QUOTE && c != '\'')
                              break;
                        else
                              path.RemoveLast();
                  }

                  while (path.Replace(_T(".."), _T(".")));

                  int pos = path.Find(_T("."));
                  while (pos != -1)
                  {
                        m_Segments.push_back(path.Left(pos));
                        path = path.Mid(pos + 1);
                        pos = path.Find( _T(".") );
                  }
                  if (path != _T(""))
                        m_Segments.push_back(path);
                  else
                        m_prefix = _T(".");

                  if (isFile)
                  {
                        if (m_prefix == _T("."))
                              return false;

                        if (m_Segments.empty())
                              return false;
                        file = m_Segments.back();
                        m_Segments.pop_back();

                        int pos = file.Find('(');
                        int pos2 = file.Find(')');
                        if (pos != -1)
                        {
                              if (!pos || pos2 <= pos || pos2 != (int)file.Length() - 2)
                                    return false;
                              m_Segments.push_back(file.Left(pos));
                              file = file.Mid(pos + 1, pos2 - pos - 1);
                              m_prefix = _T("");
                        }
                        else if (pos2 != -1)
                              return false;
                        else
                              m_prefix = _T(".");
                  }
            }
            break;
      case VXWORKS:
            {
                  int colon2;
                  if (path[0] != ':' || (colon2 = path.Mid(1).Find(':')) < 1)
                  {
                        m_bEmpty = true;
                        return false;
                  }
                  int slash = path.Find('/');
                  if (slash != -1 && slash <= colon2)
                  {
                        m_bEmpty = true;
                        return false;
                  }
                  
                  m_prefix = path.Left(colon2 + 2);
                  path = path.Mid(colon2 + 1);
                  goto set_path_default;
            }
            break;
      case DOS:
            // Check for starting drive letter
            path.Replace(_T("\\"), _T("/"));
            pos = path.Find('/');
            if (pos != 2 || path.c_str()[1] != ':' ||
                  !((path.c_str()[0] >= 'A' && path.c_str()[0] <= 'Z') || (path.c_str()[0] >= 'a' && path.c_str()[0] <= 'z')))
            {
                  m_bEmpty = true;
                  return false;
            }
            // No break on purpose!
      default:
set_path_default:
            while (path.Replace(_T("//"), _T("/")));

            if (path.c_str()[0] == '/')
                  path.Remove(0, 1);

            if (isFile)
            {
                  pos = path.Find('/', true);
                  if (pos == -1 || static_cast<size_t>(pos) == (path.Length() - 1))
                  {
                        m_bEmpty = true;
                        return false;
                  }
                  file = path.Mid(pos + 1);
                  path = path.Left(pos + 1);

                  if (file == _T(".") || file == _T(".."))
                  {
                        m_bEmpty = true;
                        return false;
                  }
            }
            else if (path != _T("") && path.Right(1) != _T("/"))
                  path = path + _T("/");

            pos = path.Find(_T("/"));
            while (pos != -1)
            {
                  wxString segment = path.Left(pos);
                  if (segment == _T(".."))
                  {
                        if (m_Segments.empty())
                        {
                              m_bEmpty = true;
                              return false;
                        }
                        m_Segments.pop_back();
                  }
                  else if (segment != _T("."))
                        m_Segments.push_back(segment);
                  path = path.Mid(pos + 1);
                  pos = path.Find(_T("/"));
            }

            break;
      }

      if (isFile)
            newPath = file;
      return true;
}

wxString CServerPath::GetPath() const
{
      if (m_bEmpty)
            return _T("");

      wxString path;

      switch (m_type)
      {
      case VMS:
            {
                  path = m_prefix + _T("[");
                  for (tConstSegmentIter iter = m_Segments.begin(); iter != m_Segments.end(); iter++)
                        path += *iter + _T(".");
                  path.RemoveLast();
                  path += _T("]");
            }
            break;
      case DOS:
            {
                  for (tConstSegmentIter iter = m_Segments.begin(); iter != m_Segments.end(); iter++)
                        path += *iter + _T("\\");
            }
            break;
      case MVS:
            path = _T("'");
            for (tConstSegmentIter iter = m_Segments.begin(); iter != m_Segments.end(); iter++)
            {
                  if (iter != m_Segments.begin())
                        path += _T(".");
                  path += *iter;
            }
            path += m_prefix + _T("'");
            break;
      case VXWORKS:
            path = m_prefix;
            for (tConstSegmentIter iter = m_Segments.begin(); iter != m_Segments.end(); iter++)
            {
                  if (iter != m_Segments.begin())
                        path += _T("/");
                  path += *iter;
            }
            break;
      default:
            path = _T("/");
            for (tConstSegmentIter iter = m_Segments.begin(); iter != m_Segments.end(); iter++)
                  path += *iter + _T("/");

            break;
      }

      return path;
}

bool CServerPath::HasParent() const
{
      if (m_bEmpty)
            return false;

      if (m_type == DOS || m_type == VMS || m_type == MVS)
            return m_Segments.size() > 1;

      return !m_Segments.empty();
}

CServerPath CServerPath::GetParent() const
{
      if (!HasParent())
            return CServerPath();

      CServerPath parent = *this;
      parent.m_Segments.pop_back();

      if (m_type == MVS)
            parent.m_prefix = _T(".");

      return parent;
}

wxString CServerPath::GetLastSegment() const
{
      if (!HasParent())
            return _T("");

      if (!m_Segments.empty())
            return m_Segments.back();
      else
            return _T("");
}

wxString CServerPath::GetSafePath() const
{
      if (m_bEmpty)
            return _T("");

      wxString safepath;
      safepath.Printf(_T("%d %d "), m_type, m_prefix.Length());
      if (m_prefix != _T(""))
            safepath += m_prefix + _T(" ");

      for (tConstSegmentIter iter = m_Segments.begin(); iter != m_Segments.end(); iter++)
            safepath += wxString::Format(_T("%d %s "), iter->Length(), iter->c_str());

      if (!m_Segments.empty())
            safepath.RemoveLast();

      return safepath;
}

bool CServerPath::SetSafePath(wxString path)
{
      m_bEmpty = true;
      m_prefix = _T("");
      m_Segments.clear();

      int pos = path.Find(' ');
      if (pos < 1)
            return false;

      long type;
      if (!path.Left(pos).ToLong(&type))
            return false;
      m_type = (ServerType)type;
      path = path.Mid(pos + 1);

      pos = path.Find(' ');
      if (pos == -1)
      {
            if (path != _T("0"))
                  return false;
            else
            {
                  // Is root folder, like / on unix like systems.
                  m_bEmpty = false;
                  return true;
            }
      }
      if (pos < 1)
            return false;

      unsigned long len;
      if (!path.Left(pos).ToULong(&len))
            return false;
      path = path.Mid(pos + 1);
      if (path.Length() < len)
            return false;
      
      if (len)
      {
            m_prefix = path.Left(len);
            path = path.Mid(len);
      }

      while (path != _T(""))
      {
            pos = path.Find(' ');
            if (pos < 1)
                  return false;
            
            if (!path.Left(pos).ToULong(&len))
                  return false;
            path = path.Mid(pos + 1);
            if (path.Length() < len)
                  return false;

            if (!len)
                  return false;

            if (path.Length() < len)
                  return false;

            m_Segments.push_back(path.Left(len));
            path = path.Mid(len + 1);
      }
      
      m_bEmpty = false;

      return true;
}

bool CServerPath::SetType(enum ServerType type)
{
      if (!m_bEmpty && m_type != DEFAULT)
            return false;

      m_type = type;

      return true;
}

enum ServerType CServerPath::GetType() const
{
      return m_type;
}

bool CServerPath::IsSubdirOf(const CServerPath &path, bool cmpNoCase) const
{
      if (m_bEmpty || path.m_bEmpty)
            return false;

      if (cmpNoCase && m_prefix.CmpNoCase(path.m_prefix))
            return false;
      if (!cmpNoCase && m_prefix != path.m_prefix)
            return false;

      if (m_type != path.m_type)
            return false;

      if (!HasParent())
            return false;

      tConstSegmentIter iter1 = m_Segments.begin();
      tConstSegmentIter iter2 = path.m_Segments.begin();
      while (iter1 != m_Segments.end())
      {
            if (iter2 == path.m_Segments.end())
                  return true;
            if (cmpNoCase)
            {
                  if (iter1->CmpNoCase(*iter2))
                        return false;
            }
            else if (*iter1 != *iter2)
                  return false;

            iter1++;
            iter2++;
      }

      return false;
}

bool CServerPath::IsParentOf(const CServerPath &path, bool cmpNoCase) const
{
      if (!this)
            return false;

      return path.IsSubdirOf(*this, cmpNoCase);
}

bool CServerPath::ChangePath(wxString subdir)
{
      wxString subdir2 = subdir;
      return ChangePath(subdir2, false);
}

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;
      }

      switch (m_type)
      {
      case VMS:
            {
                  int pos1 = subdir.Find(_T("["));
                  if (pos1 == -1)
                  {
                        int pos2 = dir.Find(']', true);
                        if (pos2 != -1)
                              return false;

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

                              subdir = dir;
                              return true;
                        }

                        while (dir.Replace(_T(".."), _T(".")));
                  }
                  else
                  {
                        int pos2 = dir.Find(']', true);
                        if (pos2 == -1)
                              return false;

                        if (isFile && static_cast<size_t>(pos2) == (dir.Length() - 1))
                              return false;
                        if (isFile && static_cast<size_t>(pos2) != (dir.Length() - 1))
                              return false;
                        if (pos2 <= pos1)
                              return false;

                        if (isFile)
                              file = dir.Mid(pos2 + 1);
                        dir = dir.Left(pos2);
                        
                        if (pos1)
                              m_prefix = dir.Left(pos1);
                        else
                              m_prefix = _T("");
                        dir = dir.Mid(pos1 + 1);

                        m_Segments.clear();
                  }
                  int pos = dir.Find(_T("."));
                  while (pos != -1)
                  {
                        m_Segments.push_back(dir.Left(pos));
                        dir = dir.Mid(pos + 1);
                        pos = dir.Find(_T("."));
                  }
                  if (dir != _T(""))
                        m_Segments.push_back(dir);
            }
            break;
      case DOS:
            {
                  dir.Replace(_T("\\"), _T("/"));
                  while (dir.Replace(_T("//"), _T("/")));
                  if (dir.Length() >= 2 && dir.c_str()[1] == ':')
                        m_Segments.clear();
                  else if (dir.Left(1) == _T("/"))
                  {
                        if (m_Segments.empty())
                        {
                              Clear();
                              return false;
                        }
                        wxString first = m_Segments.front();
                        m_Segments.clear();
                        m_Segments.push_back(first);
                        dir = dir.Mid(1);
                  }
                  
                  if (isFile)
                  {
                        int pos = dir.Find('/', true);
                        if (pos == (int)dir.Length() - 1)
                        {
                              Clear();
                              return false;
                        }
                        if (pos == -1)
                        {
                              subdir = dir;
                              return true;
                        }
                        else
                        {
                              file = dir.Mid(pos + 1);
                              dir = dir.Left(pos + 1);
                        }
                  }
                  else if (dir != _T("") && dir.Right(1) != _T("/"))
                        dir += _T("/");

                  int pos = dir.Find(_T("/"));
                  while (pos != -1)
                  {
                        wxString segment = dir.Left(pos);
                        if (segment == _T(".."))
                        {
                              if (m_Segments.size() <= 1)
                              {
                                    Clear();
                                    return false;
                              }
                              m_Segments.pop_back();
                        }
                        else if (segment != _T("."))
                              m_Segments.push_back(segment);
                        dir = dir.Mid(pos + 1);
                        pos = dir.Find(_T("/"));
                  }
            }
            break;
      case MVS:
            {
                  int i = 0;
                  wxChar c = subdir.c_str()[i];
                  while (c == FTP_MVS_DOUBLE_QUOTE)
                        c = subdir.c_str()[++i];
                  subdir.Remove(0, i);
                  
                  while (subdir != _T(""))
                  {
                        c = subdir.Last();
                        if (c != FTP_MVS_DOUBLE_QUOTE)
                              break;
                        else
                              subdir.RemoveLast();
                  }
            }
            if (subdir == _T(""))
                  return false;

            while (subdir.Replace(_T(".."), _T(".")));
            
            if (subdir.c_str()[0] == '\'')
            {
                  if (subdir.Last() != '\'')
                        return false;

                  if (SetPath(subdir, isFile))
                        file = subdir;
                  else
                        return false;
            }
            else if (subdir.Last() == '\'')
                  return false;
            else if (!IsEmpty())
            {
                  if (m_prefix != _T("."))
                        return false;

                  if (subdir.c_str()[0] == '.')
                        subdir.Remove(0, 1);
                  
                  int pos = subdir.Find('.');
                  while (pos != -1)
                  {
                        m_Segments.push_back(subdir.Left(pos));
                        subdir = subdir.Mid(pos + 1);
                  }
                  if (subdir != _T(""))
                  {
                        m_Segments.push_back(subdir);
                        m_prefix = _T("");
                  }
                  else
                        m_prefix = _T(".");

                  if (isFile)
                  {
                        if (m_prefix == _T("."))
                              return false;

                        if (m_Segments.empty())
                              return false;
                        file = m_Segments.back();
                        m_Segments.pop_back();

                        int pos = file.Find('(');
                        int pos2 = file.Find(')');
                        if (pos != -1)
                        {
                              if (!pos || pos2 <= pos || pos2 != (int)file.Length() - 2)
                                    return false;
                              m_Segments.push_back(file.Left(pos));
                              file = file.Mid(pos + 1, pos2 - pos - 1);
                        }
                        else if (pos2 != -1)
                              return false;
                        else
                              m_prefix = _T(".");
                  }
            }
            else if (SetPath(subdir, isFile))
                  file = subdir;
            else
                  return false;
            break;
      case VXWORKS:
            {
                  if (dir[0] != ':')
                  {
                        if (IsEmpty())
                              return false;
                  }
                  else
                  {
                        int colon2;
                        if ((colon2 = dir.Mid(1).Find(':')) < 1)
                              return false;

                        int slash = dir.Find('/');
                        if (slash != -1 && slash <= colon2)
                              return false;

                        m_prefix = dir.Left(colon2 + 2);
                        dir = dir.Mid(colon2 + 1);

                        if (dir[0] == '/')
                              return false;

                        m_Segments.clear();

                  }
                  if (isFile && dir.Find('/') == -1)
                        return false;
            }
            // No break on purpose
      default:
            {
                  while (dir.Replace(_T("//"), _T("/")));
                  if (dir.c_str()[0] == '/')
                  {
                        m_prefix = _T("");
                        m_Segments.clear();
                        dir = dir.Mid(1);
                  }
                  
                  if (isFile)
                  {
                        int pos = dir.Find('/', true);
                        if (pos == (int)dir.Length() - 1)
                        {
                              Clear();
                              return false;
                        }
                        if (pos == -1)
                        {
                              subdir = dir;
                              return true;
                        }
                        else
                        {
                              file = dir.Mid(pos + 1);
                              dir = dir.Left(pos + 1);
                        }
                  }
                  else if (dir != _T("") && dir.Right(1) != _T("/"))
                        dir += _T("/");
                  
                  int pos = dir.Find(_T("/"));
                  while (pos != -1)
                  {
                        wxString segment = dir.Left(pos);
                        if (segment == _T(".."))
                        {
                              if (m_Segments.empty())
                              {
                                    Clear();
                                    return false;
                              }
                              m_Segments.pop_back();
                        }
                        else if (segment != _T("."))
                              m_Segments.push_back(segment);
                        dir = dir.Mid(pos + 1);
                        pos = dir.Find(_T("/"));
                  }
            }
            break;
      }

      if (isFile)
            subdir = file;

      m_bEmpty = false;
      return true;

}

bool CServerPath::operator==(const CServerPath &op) const
{
      if (m_bEmpty != op.m_bEmpty)
            return false;
      else if (m_prefix != op.m_prefix)
            return false;
      else if (m_type != op.m_type)
            return false;
      else if (m_Segments != op.m_Segments)
            return false;

      return true;
}

bool CServerPath::operator!=(const CServerPath &op) const
{
      if (!this)
            return false;

      return !(*this == op);
}

wxString CServerPath::FormatFilename(const wxString &filename, bool omitPath /*=false*/) const
{
      if (m_bEmpty)
            return filename;

      if (filename == _T(""))
            return _T("");

      wxString fullpath;
      tConstSegmentIter iter;
      switch (m_type)
      {
      case MVS:
            if (m_prefix == _T(".") && omitPath)
                  return filename;

            fullpath = _T("'");
            for (iter = m_Segments.begin(); iter != m_Segments.end(); iter++)
                  fullpath += *iter + _T(".");
            if (m_prefix != _T("."))
            {
                  if (fullpath.Last() == '.')
                        fullpath.RemoveLast();
                  fullpath += _T("(") + filename + _T(")");
            }
            else
                  fullpath += filename;
            fullpath += _T("'");
            break;
      case VXWORKS:
            if (omitPath)
                  fullpath = filename;
            else
                  fullpath = GetPath() + _T("/") + filename;
            break;
      default:
            if (omitPath)
                  fullpath = filename;
            else
                  fullpath = GetPath() + filename;
      }
      return fullpath;
}

int CServerPath::CmpNoCase(const CServerPath &op) const
{
      if (m_bEmpty != op.m_bEmpty)
            return 1;
      else if (m_prefix != op.m_prefix)
            return 1;
      else if (m_type != op.m_type)
            return 1;

      if (m_Segments.size() > op.m_Segments.size())
            return 1;
      else if (m_Segments.size() < op.m_Segments.size())
            return -1;

      tConstSegmentIter iter = m_Segments.begin();
      tConstSegmentIter iter2 = op.m_Segments.begin();
      while (iter != m_Segments.end())
      {
            int res = iter++->CmpNoCase(*iter2++);
            if (res)
                  return res;
      }
      
      return 0;
}

bool CServerPath::AddSegment(const wxString& segment)
{
      if (IsEmpty())
            return false;

      // TODO: Check for invalid characters
      m_Segments.push_back(segment);

      return true;
}

CServerPath CServerPath::GetCommonParent(const CServerPath& path) const
{
      if (m_bEmpty || path.m_bEmpty)
            return CServerPath();

      if (m_type != path.m_type ||
            m_prefix != path.m_prefix)
            return CServerPath();

      if (!HasParent() || !path.HasParent())
            return CServerPath();

      CServerPath parent;
      parent.m_bEmpty = false;
      parent.m_type = m_type;
      parent.m_prefix = m_prefix;

      std::list<wxString>::const_iterator iter = m_Segments.begin();
      std::list<wxString>::const_iterator iter2 = path.m_Segments.begin();
      while (iter != m_Segments.end() && iter2 != path.m_Segments.end())
      {
            if (*iter != *iter2)
                  return parent;

            parent.m_Segments.push_back(*iter);

            iter++;
            iter2++;
      }

      return parent;
}

Generated by  Doxygen 1.6.0   Back to index