Logo Search packages:      
Sourcecode: filezilla version File versions

xmlfunctions.cpp

#include "FileZilla.h"
#include "xmlfunctions.h"
#include "filezillaapp.h"

CXmlFile::CXmlFile(const wxString& fileName)
{
      m_pPrinter = 0;
      SetFileName(fileName);
      m_pDocument = 0;
}

CXmlFile::CXmlFile(const wxFileName& fileName /*=wxFileName()*/)
{
      m_pPrinter = 0;
      SetFileName(fileName);
      m_pDocument = 0;
}

void CXmlFile::SetFileName(const wxString& name)
{
      m_fileName = wxFileName(wxGetApp().GetSettingsDir(), name + _T(".xml"));
      m_modificationTime = wxDateTime();
}

void CXmlFile::SetFileName(const wxFileName& fileName)
{
      m_fileName = fileName;
      m_modificationTime = wxDateTime();
}

CXmlFile::~CXmlFile()
{
      delete m_pPrinter;
      delete m_pDocument;
}

TiXmlElement* CXmlFile::Load(const wxString& name)
{
      wxFileName fileName(wxGetApp().GetSettingsDir(), name + _T(".xml"));
      return Load(fileName);
}

TiXmlElement* CXmlFile::Load(const wxFileName& fileName)
{
      if (fileName.IsOk())
            SetFileName(fileName);

      wxCHECK(m_fileName.IsOk(), 0);

      delete m_pDocument;
      m_pDocument = 0;

      TiXmlElement* pElement = GetXmlFile(m_fileName);
      if (!pElement)
      {
            m_modificationTime = wxDateTime();
            return 0;
      }

      {
            wxLogNull log;
            m_modificationTime = m_fileName.GetModificationTime();
      }

      m_pDocument = pElement->GetDocument();
      return pElement;
}

TiXmlElement* CXmlFile::GetElement()
{
      if (!m_pDocument)
            return 0;

      TiXmlElement* pElement = m_pDocument->FirstChildElement("FileZilla3");
      if (!pElement)
      {
            delete m_pDocument;
            m_pDocument = 0;
            return 0;
      }
      else
            return pElement;
}

const TiXmlElement* CXmlFile::GetElement() const
{
      if (!m_pDocument)
            return 0;

      const TiXmlElement* pElement = m_pDocument->FirstChildElement("FileZilla3");
      return pElement;
}

bool CXmlFile::Modified()
{
      wxCHECK(m_fileName.IsOk(), false);

      if (!m_modificationTime.IsValid())
            return false;

      wxLogNull log;
      wxDateTime modificationTime;
      if (!m_fileName.FileExists())
            return true;

      modificationTime = m_fileName.GetModificationTime();
      if (modificationTime.IsValid() && modificationTime == m_modificationTime)
            return false;

      return true;
}

void CXmlFile::Close()
{
      delete m_pDocument;
      m_pDocument = 0;
}

bool CXmlFile::Save(wxString* error)
{
      wxCHECK(m_fileName.IsOk(), false);

      wxCHECK(m_pDocument, false);

      bool res = SaveXmlFile(m_fileName, GetElement(), error);
      wxLogNull log;
      m_modificationTime = m_fileName.GetModificationTime();
      return res;
}

TiXmlElement* CXmlFile::CreateEmpty()
{
      delete m_pDocument;

      m_pDocument = new TiXmlDocument();
      m_pDocument->InsertEndChild(TiXmlDeclaration("1.0", "UTF-8", "yes"));

      return m_pDocument->InsertEndChild(TiXmlElement("FileZilla3"))->ToElement();
}

char* ConvUTF8(const wxString& value)
{
      // First convert the string into unicode if neccessary.
      const wxWCharBuffer buffer = wxConvCurrent->cWX2WC(value);

      // Calculate utf-8 string length
      wxMBConvUTF8 conv;
      int len = conv.WC2MB(0, buffer, 0);

      // Not convert the string
      char *utf8 = new char[len + 1];
      conv.WC2MB(utf8, buffer, len + 1);

      return utf8;
}

wxString ConvLocal(const char *value)
{
      return wxString(wxConvUTF8.cMB2WC(value), *wxConvCurrent);
}

void AddTextElement(TiXmlElement* node, const char* name, const wxString& value)
{
      wxASSERT(node);

      TiXmlElement element(name);

      char* utf8 = ConvUTF8(value);
      if (!utf8)
            return;
      
    element.InsertEndChild(TiXmlText(utf8));
      delete [] utf8;

      node->InsertEndChild(element);
}

void AddTextElement(TiXmlElement* node, const char* name, int value)
{
      AddTextElement(node, name, wxString::Format(_T("%d"), value));
}

void AddTextElement(TiXmlElement* node, const wxString& value)
{
      wxASSERT(node);

      char* utf8 = ConvUTF8(value);
      if (!utf8)
            return;

      for (TiXmlNode* pChild = node->FirstChild(); pChild; pChild = pChild->NextSibling())
      {
            if (!pChild->ToText())
                  continue;

            node->RemoveChild(pChild);
            break;
      }
      
    node->InsertEndChild(TiXmlText(utf8));
      delete [] utf8;
}

void AddTextElement(TiXmlElement* node, int value)
{
      AddTextElement(node, wxString::Format(_T("%d"), value));
}

wxString GetTextElement(TiXmlElement* node, const char* name)
{
      wxASSERT(node);

      TiXmlElement* element = node->FirstChildElement(name);
      if (!element)
            return _T("");

      TiXmlNode* textNode = element->FirstChild();
      if (!textNode || !textNode->ToText())
            return _T("");

      return ConvLocal(textNode->Value());
}

wxString GetTextElement(TiXmlElement* node)
{
      wxASSERT(node);

      for (TiXmlNode* pChild = node->FirstChild(); pChild; pChild = pChild->NextSibling())
      {
            if (!pChild->ToText())
                  continue;

            return ConvLocal(pChild->Value());
      }

      return _T("");
}

int GetTextElementInt(TiXmlElement* node, const char* name, int defValue /*=0*/)
{
      wxASSERT(node);

      TiXmlElement* element = node->FirstChildElement(name);
      if (!element)
            return defValue;

      TiXmlNode* textNode = element->FirstChild();
      if (!textNode || !textNode->ToText())
            return defValue;

      const char* str = textNode->Value();
      const char* p = str;

      int value = 0;
      bool negative = false;
      if (*p == '-')
      {
            negative = true;
            p++;
      }
      while (*p)
      {
            if (*p < '0' || *p > '9')
                  return defValue;

            value *= 10;
            value += *p - '0';

            p++;
      }

      return negative ? -value : value;
}

wxLongLong GetTextElementLongLong(TiXmlElement* node, const char* name, int defValue /*=0*/)
{
      wxASSERT(node);

      TiXmlElement* element = node->FirstChildElement(name);
      if (!element)
            return defValue;

      TiXmlNode* textNode = element->FirstChild();
      if (!textNode || !textNode->ToText())
            return defValue;

      const char* str = textNode->Value();
      const char* p = str;

      wxLongLong value = 0;
      bool negative = false;
      if (*p == '-')
      {
            negative = true;
            p++;
      }
      while (*p)
      {
            if (*p < '0' || *p > '9')
                  return defValue;

            value *= 10;
            value += *p - '0';

            p++;
      }

      return negative ? -value : value;
}

// Opens the specified XML file if it exists or creates a new one otherwise.
// Returns 0 on error.
TiXmlElement* GetXmlFile(wxFileName file)
{
      if (wxFileExists(file.GetFullPath()) && file.GetSize() > 0)
      {
            // File does exist, open it

            TiXmlDocument* pXmlDocument = new TiXmlDocument();
            if (!pXmlDocument->LoadFile(file.GetFullPath().mb_str()))
            {
                  delete pXmlDocument;
                  return 0;
            }
            if (!pXmlDocument->FirstChildElement("FileZilla3"))
            {
                  delete pXmlDocument;
                  return 0;
            }

            TiXmlElement* pElement = pXmlDocument->FirstChildElement("FileZilla3");
            if (!pElement)
            {
                  delete pXmlDocument;
                  return 0;
            }
            else
                  return pElement;
      }
      else
      {
            // File does not exist, create new XML document

            TiXmlDocument* pXmlDocument = new TiXmlDocument();
            pXmlDocument->InsertEndChild(TiXmlDeclaration("1.0", "UTF-8", "yes"));
      
            pXmlDocument->InsertEndChild(TiXmlElement("FileZilla3"));

            if (!pXmlDocument->SaveFile(file.GetFullPath().mb_str()))
            {
                  delete pXmlDocument;
                  return 0;
            }
            
            return pXmlDocument->FirstChildElement("FileZilla3");
      }
}

bool SaveXmlFile(const wxFileName& file, TiXmlNode* node, wxString* error /*=0*/)
{
      if (!node)
            return true;

      const wxString& fullPath = file.GetFullPath();

      TiXmlDocument* pDocument = node->GetDocument();

      bool exists = false;
      if (wxFileExists(fullPath))
      {
            exists = true;
            if (!wxCopyFile(fullPath, fullPath + _T("~")))
            {
                  const wxString msg = _("Failed to create backup copy of xml file");
                  if (error)
                        *error = msg;
                  else
                        wxMessageBox(msg);
                  return false;
            }
      }

      if (!pDocument->SaveFile(fullPath.mb_str()))
      {
            wxRemoveFile(fullPath);
            if (exists)
                  wxRenameFile(fullPath + _T("~"), fullPath);
            const wxString msg = _("Failed to write xml file");
            if (error)
                  *error = msg;
            else
                  wxMessageBox(msg);
            return false;
      }

      if (exists)
            wxRemoveFile(fullPath + _T("~"));

      return true;
}

bool GetServer(TiXmlElement *node, CServer& server)
{
      wxASSERT(node);
      
      wxString host = GetTextElement(node, "Host");
      if (host == _T(""))
            return false;

      int port = GetTextElementInt(node, "Port");
      if (port < 1 || port > 65535)
            return false;

      if (!server.SetHost(host, port))
            return false;
      
      int protocol = GetTextElementInt(node, "Protocol");
      if (protocol < 0)
            return false;

      server.SetProtocol((enum ServerProtocol)protocol);
      
      int type = GetTextElementInt(node, "Type");
      if (type < 0)
            return false;

      server.SetType((enum ServerType)type);

      int logonType = GetTextElementInt(node, "Logontype");
      if (logonType < 0)
            return false;

      server.SetLogonType((enum LogonType)logonType);
      
      if (server.GetLogonType() != ANONYMOUS)
      {
            wxString user = GetTextElement(node, "User");
            if (user == _T(""))
                  return false;
      
            wxString pass;
            if ((long)NORMAL == logonType || (long)ACCOUNT == logonType)
                  pass = GetTextElement(node, "Pass");

            if (!server.SetUser(user, pass))
                  return false;
            
            if ((long)ACCOUNT == logonType)
            {
                  wxString account = GetTextElement(node, "Account");
                  if (account == _T(""))
                        return false;
                  if (!server.SetAccount(account))
                        return false;
            }
      }

      int timezoneOffset = GetTextElementInt(node, "TimezoneOffset");
      if (!server.SetTimezoneOffset(timezoneOffset))
            return false;
      
      wxString pasvMode = GetTextElement(node, "PasvMode");
      if (pasvMode == _T("MODE_PASSIVE"))
            server.SetPasvMode(MODE_PASSIVE);
      else if (pasvMode == _T("MODE_ACTIVE"))
            server.SetPasvMode(MODE_ACTIVE);
      else
            server.SetPasvMode(MODE_DEFAULT);
      
      int maximumMultipleConnections = GetTextElementInt(node, "MaximumMultipleConnections");
      server.MaximumMultipleConnections(maximumMultipleConnections);

      wxString encodingType = GetTextElement(node, "EncodingType");
      if (encodingType == _T("Auto"))
            server.SetEncodingType(ENCODING_AUTO);
      else if (encodingType == _T("UTF-8"))
            server.SetEncodingType(ENCODING_UTF8);
      else if (encodingType == _T("Custom"))
      {
            wxString customEncoding = GetTextElement(node, "CustomEncoding");
            if (customEncoding == _T(""))
                  return false;
            if (!server.SetEncodingType(ENCODING_CUSTOM, customEncoding))
                  return false;
      }
      else
            server.SetEncodingType(ENCODING_AUTO);

      if (protocol == FTP || protocol == FTPS || protocol == FTPES)
      {
            std::vector<wxString> postLoginCommands;
            TiXmlElement* pElement = node->FirstChildElement("PostLoginCommands");
            if (pElement)
            {
                  TiXmlElement* pCommandElement = pElement->FirstChildElement("Command");
                  while (pCommandElement)
                  {
                        TiXmlNode* textNode = pCommandElement->FirstChild();
                        if (textNode && textNode->ToText())
                        {
                              wxString command = ConvLocal(textNode->Value());
                              if (command != _T(""))
                                    postLoginCommands.push_back(command);
                        }

                        pCommandElement = pCommandElement->NextSiblingElement("Command");
                  }
            }
            if (!server.SetPostLoginCommands(postLoginCommands))
                  return false;
      }
      
      return true;
}

void SetServer(TiXmlElement *node, const CServer& server)
{
      if (!node)
            return;
      
      node->Clear();
      
      AddTextElement(node, "Host", server.GetHost());
      AddTextElement(node, "Port", server.GetPort());
      AddTextElement(node, "Protocol", server.GetProtocol());
      AddTextElement(node, "Type", server.GetType());
      AddTextElement(node, "Logontype", server.GetLogonType());
      
      if (server.GetLogonType() != ANONYMOUS)
      {
            AddTextElement(node, "User", server.GetUser());

            if (server.GetLogonType() == NORMAL || server.GetLogonType() == ACCOUNT)
                  AddTextElement(node, "Pass", server.GetPass());
            
            if (server.GetLogonType() == ACCOUNT)
                  AddTextElement(node, "Account", server.GetAccount());
      }

      AddTextElement(node, "TimezoneOffset", server.GetTimezoneOffset());
      switch (server.GetPasvMode())
      {
      case MODE_PASSIVE:
            AddTextElement(node, "PasvMode", _T("MODE_PASSIVE"));
            break;
      case MODE_ACTIVE:
            AddTextElement(node, "PasvMode", _T("MODE_ACTIVE"));
            break;
      default:
            AddTextElement(node, "PasvMode", _T("MODE_DEFAULT"));
            break;
      }
      AddTextElement(node, "MaximumMultipleConnections", server.MaximumMultipleConnections());

      switch (server.GetEncodingType())
      {
      case ENCODING_AUTO:
            AddTextElement(node, "EncodingType", _T("Auto"));
            break;
      case ENCODING_UTF8:
            AddTextElement(node, "EncodingType", _T("UTF-8"));
            break;
      case ENCODING_CUSTOM:
            AddTextElement(node, "EncodingType", _T("Custom"));
            AddTextElement(node, "CustomEncoding", server.GetCustomEncoding());
            break;
      }

      const enum ServerProtocol protocol = server.GetProtocol();
      if (protocol == FTP || protocol == FTPS || protocol == FTPES)
      {
            const std::vector<wxString>& postLoginCommands = server.GetPostLoginCommands();
            if (!postLoginCommands.empty())
            {
                  TiXmlElement* pElement = node->InsertEndChild(TiXmlElement("PostLoginCommands"))->ToElement();
                  for (std::vector<wxString>::const_iterator iter = postLoginCommands.begin(); iter != postLoginCommands.end(); iter++)
                        AddTextElement(pElement, "Command", *iter);
            }
      }
}

void SetTextAttribute(TiXmlElement* node, const char* name, const wxString& value)
{
      wxASSERT(node);

      char* utf8 = ConvUTF8(value);
      if (!utf8)
            return;
      
    node->SetAttribute(name, utf8);
      delete [] utf8;
}

wxString GetTextAttribute(TiXmlElement* node, const char* name)
{
      wxASSERT(node);

      const char* value = node->Attribute(name);
      if (!value)
            return _T("");
      
      return ConvLocal(value);
}

TiXmlElement* FindElementWithAttribute(TiXmlElement* node, const char* element, const char* attribute, const char* value)
{
      TiXmlElement* child;
      if (element)
            child = node->FirstChildElement(element);
      else
            child = node->FirstChildElement();

      while (child)
      {
            const char* nodeVal = child->Attribute(attribute);
            if (nodeVal && !strcmp(value, nodeVal))
                  return child;                 

            if (element)
                  child = child->NextSiblingElement(element);
            else
                  child = child->NextSiblingElement();
      }

      return 0;
}

TiXmlElement* FindElementWithAttribute(TiXmlElement* node, const char* element, const char* attribute, int value)
{
      TiXmlElement* child;
      if (element)
            child = node->FirstChildElement(element);
      else
            child = node->FirstChildElement();

      while (child)
      {
            int nodeValue;
            const char* nodeVal = child->Attribute(attribute, &nodeValue);
            if (nodeVal && nodeValue == value)
                  return child;                 

            if (element)
                  child = child->NextSiblingElement(element);
            else
                  child = child->NextSiblingElement();
      }

      return 0;
}

int GetAttributeInt(TiXmlElement* node, const char* name)
{
      int value;
      if (!node->Attribute(name, &value))
            return 0;

      return value;
}

void SetAttributeInt(TiXmlElement* node, const char* name, int value)
{
      node->SetAttribute(name, value);
}

int CXmlFile::GetRawDataLength()
{
      if (!m_pDocument)
            return 0;

      delete m_pPrinter;
      m_pPrinter = new TiXmlPrinter;
      m_pPrinter->SetStreamPrinting();

      m_pDocument->Accept(m_pPrinter);
      return m_pPrinter->Size();
}

void CXmlFile::GetRawDataHere(char* p) // p has to big enough to hold at least GetRawDataLength() bytes
{
      if (!m_pPrinter)
      {
            wxFAIL;
            return;
      }

      memcpy(p, m_pPrinter->CStr(), m_pPrinter->Size());
}

bool CXmlFile::ParseData(char* data)
{
      delete m_pDocument;
      m_pDocument = new TiXmlDocument;
      m_pDocument->Parse(data);
      
      if (!m_pDocument->FirstChildElement("FileZilla3"))
      {
            delete m_pDocument;
            m_pDocument = 0;
            return false;
      }
      
      return true;
}

Generated by  Doxygen 1.6.0   Back to index