///
/// Save the MIME types configuration to a memory buffer.
/// Returns negative on error.
///
int MIMEtypeXML::saveMemBuf(MemBuf & buffer)
{
   XmlParser xmlFile;
   int ret = save_core(xmlFile);
   xmlFile.saveMemBuf(buffer);
   xmlFile.close();
   return ret;
}
///
/// Save the MIME types configuration to file.
/// Returns negative on error.
///
int MIMEtypeXML::save(const char * filename)
{
   XmlParser xmlFile;
   int ret = save_core(xmlFile);
   xmlFile.save((char *)filename); // But, but, but I promis
   xmlFile.close();
   return ret;
}
///
/// Close the xml file.
/// This is called before LanguageEnd at the end of the program.
///
void LanguageXMLclose()
{
   if(loaded)
     {
	xmlFile.close();
	loaded = false;
     }
}
///
/// Load the MIME types configuration from memory.
/// returns -1 on error.
///
int MIMEtypeXML::loadMemBuf(MemBuf & buffer)
{
   XmlParser parser;
   if(parser.openMemBuf(buffer))
     return -1;
   int ret = load_core(parser);
   parser.close();
   return ret;
}
///
/// Load the MIME types configuration file.
/// Returns -1 on error.
///
int MIMEtypeXML::load(const char * filename)
{
   XmlParser parser;
   if(parser.open((char *)filename)) // but I promis I wont modify
     return -1;
   int ret = load_core(parser);
   parser.close();
   return ret;
}
/*!
  Load the virtual hosts from a XML configuration file
  Returns non-null on errors.
  \param filename The XML file to open.
 */
int XmlVhostHandler::load (const char *filename)
{
  XmlParser parser;
  xmlDocPtr doc;
  xmlNodePtr node;
  if (parser.open (filename))
    {
      Server::getInstance ()->log (MYSERVER_LOG_MSG_ERROR,
                                         _("Error opening %s"), filename);
      return -1;
    }
  doc = parser.getDoc ();
  node = doc->children->children;

  for (; node; node = node->next )
    {
      xmlNodePtr lcur;
      Vhost *vh;
      if (xmlStrcmp (node->name, (const xmlChar *) "VHOST"))
        continue;
      lcur = node->children;
      vh = new Vhost (logManager);
      SslContext* sslContext = vh->getVhostSSLContext ();

      while (lcur)
        {
          XmlConf::build (lcur, vh->getHashedDataTrees (),
                          vh->getHashedData ());

          if (!xmlStrcmp (lcur->name, (const xmlChar *) "HOST"))
            {
              int useRegex = 0;
              for (xmlAttr *attrs = lcur->properties; attrs; attrs = attrs->next)
                {
                  if (!xmlStrcmp (attrs->name, (const xmlChar *) "isRegex")
                      && attrs->children && attrs->children->content
                      && (!xmlStrcmp (attrs->children->content,
                                     (const xmlChar *) "YES")))
                        useRegex = 1;
                }

              vh->addHost ((const char *)lcur->children->content, useRegex);
            }
          else if (!xmlStrcmp (lcur->name, (const xmlChar *) "NAME"))
            {
              vh->setName ((char *) lcur->children->content);
            }
          else if (!xmlStrcmp (lcur->name, (const xmlChar *) "LOCATION"))
            {
              string loc;

              for (xmlAttr *attrs = lcur->properties; attrs; attrs = attrs->next)
                if (!xmlStrcmp (attrs->name, (const xmlChar *) "path"))
                  loc = ((const char *) attrs->children->content);

              MimeRecord *record = XmlMimeHandler::readRecord (lcur);
              MimeRecord *prev = vh->addLocationMime (loc, record);
              if (prev)
                {
                  Server::getInstance ()->log (MYSERVER_LOG_MSG_ERROR,
                     _("The location `%s' is registered multiple times"),
                                               loc.c_str ());

                  delete prev;
                }

              vh->getLocationsMime ()->put (loc, record);
            }
          else if (!xmlStrcmp (lcur->name, (const xmlChar *) "SSL_PRIVATEKEY"))
            {
              string pk ((char *) lcur->children->content);
              sslContext->setPrivateKeyFile (pk);
            }
          else if (!xmlStrcmp (lcur->name, (const xmlChar *) "SSL_CERTIFICATE"))
            {
              string certificate ((char *) lcur->children->content);
              sslContext->setCertificateFile (certificate);
            }
          else if (!xmlStrcmp (lcur->name, (const xmlChar *) "CONNECTIONS_PRIORITY"))
            {
              vh->setDefaultPriority (atoi ((const char *)lcur->children->content));
            }
          else if (!xmlStrcmp (lcur->name, (const xmlChar *) "SSL_PASSWORD"))
            {
              string pw ((char *) lcur->children->content);
              sslContext->setPassword (pw);
            }
          else if (!xmlStrcmp (lcur->name, (const xmlChar *) "IP"))
            {
              int useRegex = 0;
              xmlAttr *attrs = lcur->properties;

              while (attrs)
                {
                  if (!xmlStrcmp (attrs->name, (const xmlChar *) "isRegex")
                      && !xmlStrcmp (attrs->children->content,
                                     (const xmlChar *) "YES"))
                    useRegex = 1;

                  attrs = attrs->next;
                }

              vh->addIP ((char *) lcur->children->content, useRegex);
            }
          else if (!xmlStrcmp (lcur->name, (const xmlChar *) "PORT"))
            {
              int val = atoi ((char *) lcur->children->content);
              if (val > (1 << 16) || val <= 0)
                Server::getInstance ()->log (MYSERVER_LOG_MSG_ERROR,
                      _("An invalid port was specified: %s"),
                                             lcur->children->content);
              vh->setPort ((u_short)val);
            }
          else if (!xmlStrcmp (lcur->name, (const xmlChar *) "PROTOCOL"))
            {
              char* lastChar = (char *) lcur->children->content;
              while (*lastChar != '\0')
                {
                  *lastChar = tolower (*lastChar);
                  lastChar++;
                }
              vh->setProtocolName ((char *) lcur->children->content);
            }
          else if (!xmlStrcmp (lcur->name, (const xmlChar *) "DOCROOT"))
            {
              char* lastChar = (char *) lcur->children->content;
              while (*(lastChar+1) != '\0')
                lastChar++;

              if (*lastChar == '\\' || *lastChar == '/')
                *lastChar = '\0';

              vh->setDocumentRoot ((const char *)lcur->children->content);
            }
          else if (!xmlStrcmp (lcur->name, (const xmlChar *) "SYSROOT"))
            {
              char* lastChar = (char *) lcur->children->content;

              while (*(lastChar+1) != '\0')
                lastChar++;

              if (*lastChar == '\\' || *lastChar == '/')
                *lastChar = '\0';

              vh->setSystemRoot ((const char *)lcur->children->content);
            }
          else if (!xmlStrcmp (lcur->name, (const xmlChar *) "CACHEROOT"))
            {
              char* lastChar = (char *) lcur->children->content;

              while (*(lastChar+1) != '\0')
                lastChar++;

              if (*lastChar == '\\' || *lastChar == '/')
                *lastChar = '\0';

              vh->setCacheRoot ((const char *)lcur->children->content);
            }
          else if (!xmlStrcmp (lcur->name, (const xmlChar *) "ACCESSLOG"))
            {
              loadXMLlogData ("ACCESSLOG", vh, lcur);
            }
          else if (!xmlStrcmp (lcur->name, (const xmlChar *) "WARNINGLOG"))
            {
              loadXMLlogData ("WARNINGLOG", vh, lcur);
            }
          else if (!xmlStrcmp (lcur->name, (const xmlChar *) "MIME_FILE"))
            {
              string hnd ("xml");
              for (xmlAttr *attrs = lcur->properties; attrs; attrs = attrs->next)
                {
                  if (!xmlStrcmp (attrs->name, (const xmlChar *) "name")
                      && attrs->children && attrs->children->content)
                    hnd.assign((const char *) attrs->children->content);
                }

              const char *filename = (const char *) lcur->children->content;
              MimeManagerHandler *handler =
                Server::getInstance ()->getMimeManager ()->buildHandler (hnd);

              try
                {
                  handler->load (filename);
                }
              catch (...)
                {
                  delete handler;
                  handler = NULL;
                  Server::getInstance ()->log (MYSERVER_LOG_MSG_ERROR,
                                         _("Error loading mime types file: %s"),
                                               filename);

                }
              vh->setMimeHandler (handler);
            }
          else if (!xmlStrcmp (lcur->name, (const xmlChar *) "THROTTLING_RATE"))
            {
              u_long rate = (u_long)atoi ((char *) lcur->children->content);
              vh->setThrottlingRate (rate);
            }

          lcur = lcur->next;
        }/* while (lcur)  */

      if (vh->openLogFiles ())
        {
          Server::getInstance ()->log (MYSERVER_LOG_MSG_ERROR,
                                             _("Error opening log files"));
          delete vh;
          vh = 0;
          continue;
        }

      if (vh->initializeSSL () < 0)
        {
          Server::getInstance ()->log (MYSERVER_LOG_MSG_ERROR,
                                             _("Error initializing SSL for %s"),
                                             vh->getName ());
          delete vh;
          vh = 0;
          continue;
        }

      if (addVHost (vh))
        {
          Server::getInstance ()->log (MYSERVER_LOG_MSG_ERROR,
                                             _("Internal error"));
          delete vh;
          vh = 0;
          continue;
        }
    }
  parser.close ();

  changeLocationsOwner ();

  return 0;
}
///
/// The *hack* to load the correct xml file.
/// This looks for the myserver.xml file and grabs the name of the
/// lanugage file.  Then it tries to load that file in the default
/// locations.
///
void LanguageXMLload()
{
   char languages_path[MAX_PATH];
   char language_file[MAX_PATH];
   char main_configuration_file[MAX_PATH];
   char * chrptr;
   XmlParser xmlFile;
   bool langFound = true;
   bool confFound = true;
   int ret;

   LanguageXMLinit();

   // Find the language files:
#ifdef WIN32
   strncpy(languages_path, "languages/", MAX_PATH);
#else
   if(FilesUtility::fileExists("languages"))
     {
	strncpy(languages_path, "languages/", MAX_PATH);
     }
   else
     {
# ifdef PREFIX
	snprintf(languages_path, MAX_PATH, "%s/share/myserver/languages/", PREFIX);
# else
	strncpy(languages_path, "/usr/share/myserver/languages/", MAX_PATH);
# endif
     }
   if(!(FilesUtility::fileExists(languages_path)))
     {
	loadok = false;
	langFound = false;
	return;
     }
#endif

   // Search for myserver.xml
   /* Under an *nix environment look for .xml files in the following order.
    * 1) myserver executable working directory
    * 2) ~/.myserver/
    * 3) /etc/myserver/
    */
#ifndef WIN32
   // just a little hack
   snprintf(main_configuration_file, MAX_PATH, "%s/.myserver/myserver.xml", getenv("HOME"));
#endif
   if(FilesUtility::fileExists("myserver.xml"))
     {
	strncpy(main_configuration_file,"myserver.xml", MAX_PATH);
     }
#ifndef WIN32
   else if(FilesUtility::fileExists(main_configuration_file))
     {
	// do nothing
     }
   else if(FilesUtility::fileExists("/etc/myserver/myserver.xml"))
     {
	strncpy(main_configuration_file,"/etc/myserver/myserver.xml", MAX_PATH);
     }
#endif
   else
     {
	confFound = false;
	loadok = false;
	return;
     }

   // Load the language file for configure
   if(confFound && langFound)
     {
	xmlFile.open(main_configuration_file);
	chrptr = xmlFile.getValue("LANGUAGE");
	if(chrptr != NULL)
	  snprintf(language_file, MAX_PATH, "%sconfigure/%s", languages_path, chrptr);
	xmlFile.close();
	ret = LanguageXMLfile(language_file);
	if(ret)
	  loadok = false;
     }

}