AREXPORT void ArClientHandlerConfig::saveConfigToServer(
	  ArConfig *config, 
	  const std::set<std::string, ArStrCaseCmpOp> *ignoreTheseSections)
{
  //ArConfigArg param;
  ArClientArg clientArg;

  ArNetPacket sending;
  ArLog::log(ArLog::Normal, "%sSaving config to server", myLogPrefix.c_str());

  myDataMutex.lock();
  std::list<ArConfigSection *> *sections = config->getSections();
  for (std::list<ArConfigSection *>::iterator sIt = sections->begin(); 
       sIt != sections->end(); 
       sIt++)
  {
    ArConfigSection *section = (*sIt);
    // if we're ignoring sections and we're ignoring this one, then
    // don't send it
    if (ignoreTheseSections != NULL && 
	(ignoreTheseSections->find(section->getName()) != 
	 ignoreTheseSections->end()))
    {
      ArLog::log(ArLog::Verbose, "Not sending section %s", 
		 section->getName());
      continue;
    }
    sending.strToBuf("Section");
    sending.strToBuf(section->getName());
    std::list<ArConfigArg> *params = section->getParams();

    for (std::list<ArConfigArg>::iterator pIt = params->begin(); 
         pIt != params->end(); 
         pIt++)
    {
      ArConfigArg &param = (*pIt);

      if (!clientArg.isSendableParamType(param)) {
        continue;
      }

      sending.strToBuf(param.getName());

      clientArg.argTextToBuf(param, &sending);

    } // end for each param
  } // end for each section

  myDataMutex.unlock();
  myClient->requestOnce("setConfig", &sending);
}
/**
 * @param client the ArServerClient * to which to send the config
 * @param packet the ArNetPacket * which accompanied the client's request
 * @param isMultiplePackets a bool set to true if the server should send a
 * packet for each config section followed by the empty packet; false if 
 * the server should send the entire config in one packet (i.e. the old style)
 * @param lastPriority the last ArPriority::Priority that should be sent 
 * to the client (this is the greatest numerical value and the least 
 * semantic priority).
**/
AREXPORT void ArServerHandlerConfig::handleGetConfig(ArServerClient *client, 
                                                     ArNetPacket *packet,
                                                     bool isMultiplePackets,
                                                     ArPriority::Priority lastPriority)
{

  ArConfigArg param;

 
  // The multiple packets method also sends display hints with the parameters;
  // the old single packet method does not.
  ArClientArg clientArg(isMultiplePackets,
                        lastPriority);

  std::set<std::string> sent;

  ArNetPacket sending;
  ArLog::log(ArLog::Normal, "Config requested.");

  std::list<ArConfigSection *> *sections = myConfig->getSections();
  for (std::list<ArConfigSection *>::iterator sIt = sections->begin(); 
       sIt != sections->end(); 
       sIt++)
  {
    // Clear the packet...
    if (isMultiplePackets) {
      sending.empty();
    }

    // clear out the sent list between sections
    sent.clear();

    ArConfigSection *section = (*sIt);
    if (section == NULL) {
      continue;
    }

    sending.byteToBuf('S');
    sending.strToBuf(section->getName());
    sending.strToBuf(section->getComment());

    ArLog::log(ArLog::Verbose, "Sending config section %s...", section->getName());

    //printf("S %s %s\n", section->getName(), section->getComment());
    std::list<ArConfigArg> *params = section->getParams();
    for (std::list<ArConfigArg>::iterator pIt = params->begin(); 
         pIt != params->end(); 
         pIt++)
    {
      param = (*pIt);

      bool isCheckableName = 
      (param.getType() != ArConfigArg::DESCRIPTION_HOLDER && 
       param.getType() != ArConfigArg::SEPARATOR &&
       param.getType() != ArConfigArg::STRING_HOLDER);

      // if we've already sent it don't send it again
      if (isCheckableName &&
          sent.find(param.getName()) != sent.end()) {
        continue;
      }
      else if (isCheckableName) {
        sent.insert(param.getName());
      }

      if (clientArg.isSendableParamType(param))
      {
        sending.byteToBuf('P');

        bool isSuccess = clientArg.createPacket(param,
                                                &sending);

      }
    } // end for each parameter

    if (!sending.isValid()) {

      ArLog::log(ArLog::Terse, "Config section %s cannot be sent; packet size exceeded",
                 section->getName());

    } // end if length exceeded...
    else if (isMultiplePackets) {

      client->sendPacketTcp(&sending);

    } // end else send in chunks...

  } // end for each section

  // If sending each section in individual packets, then send an empty packet 
  // to indicate the end of the config data.
  if (isMultiplePackets) {

    sending.empty();
    client->sendPacketTcp(&sending);
  }
  else { //  send the entire config in one packet

    // If the config is too big to fit in the packet, then just send an empty
    // packet (to try to prevent an older client from crashing)
    // TODO: Is there any better way to notify the user of an error....
    if (!sending.isValid()) {
      ArLog::log(ArLog::Terse, "Error sending config; packet size exceeded");
      sending.empty();
    }

    client->sendPacketTcp(&sending);

  } // end else send the entire packet

} // end method getConfigBySections
AREXPORT void ArServerHandlerConfig::getConfigDefaults(ArServerClient *client, 
                                                       ArNetPacket *packet)
{
  char sectionRequested[512];
  sectionRequested[0] = '\0';
  ArNetPacket sending;

  if (myDefault == NULL)
  {
    ArLog::log(ArLog::Normal, "ArServerHandlerConfig::getConfigDefaults: No default config to get");
    client->sendPacketTcp(&sending);
    return;
  }
  myConfigMutex.lock();
  // if we have a section name pick it up, otherwise we send everything
  if (packet->getDataReadLength() < packet->getDataLength())
    packet->bufToStr(sectionRequested, sizeof(sectionRequested));

  //ArConfigArg param;

  ArClientArg clientArg;

  if (sectionRequested[0] == '\0')
    ArLog::log(ArLog::Normal, "Sending all defaults to client");
  else
    ArLog::log(ArLog::Normal, "Sending defaults for section '%s' to client",
               sectionRequested);


  std::list<ArConfigSection *> *sections = myDefault->getSections();

  for (std::list<ArConfigSection *>::iterator sIt = sections->begin(); 
       sIt != sections->end(); 
       sIt++)
  {
    ArConfigSection *section = (*sIt);

    if (section == NULL) {
      continue; // Should never happen...
    }

    // if we're not sending them all and not in the right section just cont
    if (sectionRequested[0] != '\0' &&
        ArUtil::strcasecmp(sectionRequested, section->getName()) != 0) {
      continue;
    }

    sending.strToBuf("Section");
    sending.strToBuf(section->getName());

    std::list<ArConfigArg> *params = section->getParams();

    for (std::list<ArConfigArg>::iterator pIt = params->begin(); 
         pIt != params->end(); 
         pIt++)
    {
      ArConfigArg &param = (*pIt);

      if (!clientArg.isSendableParamType(param)) {
        continue;
      }

      sending.strToBuf(param.getName());
      clientArg.argTextToBuf(param, &sending);

    } // end for each param
  } // end for each section
  myConfigMutex.unlock();

  client->sendPacketTcp(&sending);
}
/** 
    @internal

    doesn't delete the old one, do that if you're going to call this
    yourself and make sure you lock around all that (okay, it deletes
    it now, but the stuff that calls it should still take care of it)
**/
void ArServerHandlerConfig::createDefaultConfig(const char *defaultFileBaseDir)
{
  if (myDefault != NULL)
  {
    delete myDefault;
    myDefault = NULL;
  }
  // copy that config (basedir will be NULL if we're not loading from
  // a file)... don't have the default save unknown values
  myDefault = new ArConfig(defaultFileBaseDir, false, false, false, false);

  std::list<ArConfigSection *>::iterator sectionIt;
  std::list<ArConfigArg>::iterator paramIt;
  ArConfigSection *section = NULL;
  std::list<ArConfigArg> *params = NULL;
  ArConfigArg param;
  for (sectionIt = myConfig->getSections()->begin(); 
       sectionIt != myConfig->getSections()->end(); 
       sectionIt++)
  {
    section = (*sectionIt);
    params = section->getParams();
    for (paramIt = params->begin(); paramIt != params->end(); paramIt++)
    {
      param = (*paramIt);
      switch (param.getType()) {
      case ArConfigArg::INT:
	myDefault->addParam(
		ArConfigArg(param.getName(), param.getInt(), 
			    param.getDescription(), 
			    param.getMinInt(), param.getMaxInt()), 
		section->getName(), 
		param.getConfigPriority(),
		param.getDisplayHint());
	break;
      case ArConfigArg::DOUBLE:
	myDefault->addParam(
		ArConfigArg(param.getName(), param.getDouble(), 
			    param.getDescription(),
			    param.getMinDouble(), param.getMaxDouble()), 
		section->getName(), 
		param.getConfigPriority(),
		param.getDisplayHint());
	break;
	
      case ArConfigArg::BOOL:
	myDefault->addParam(
		ArConfigArg(param.getName(), param.getBool(), 
			    param.getDescription()),
		section->getName(), 
		param.getConfigPriority(),
		param.getDisplayHint());
	break;
	
      case ArConfigArg::STRING:
	myDefault->addParam(
		ArConfigArg(param.getName(), (char *)param.getString(), 
			    param.getDescription(), 0),
		section->getName(), 
		param.getConfigPriority(),
		param.getDisplayHint());
	break;
	
      case ArConfigArg::SEPARATOR:
	myDefault->addParam(
		ArConfigArg(ArConfigArg::SEPARATOR),
		section->getName(), 
		param.getConfigPriority(),
		param.getDisplayHint());
	break;
      default:
	break;
      } // end switch param type
    } // end for each param
  } // end for each section
}