bool Id3v2TagFrameIO::putFrameData(ByteBuffer* src)
{
   bool rval = true;

   // read until frame buffer is full
   if(!mFrameBuffer.isFull())
   {
      src->get(&mFrameBuffer, src->length(), false);
   }

   // process frame buffer if it is full
   if(mFrameBuffer.isFull())
   {
      // only interested in XBMC frame
      if(strcmp(mCurrentHeader->getId(), "XBMC") == 0)
      {
         // skip 4 bytes of uncompressed size
         // (part of id3v2 compressed frame standard)
         mFrameBuffer.clear(4);
         ByteArrayInputStream bais(&mFrameBuffer, false);

         // decompress zlib-compressed data
         Deflater def;
         def.startInflating(false);
         MutatorInputStream mis(&bais, false, &def, false);

         // create/clear contract as necessary
         if(mContract.isNull())
         {
            mContract = Contract();
         }
         else
         {
            mContract->clear();
         }

         // decompress JSON-formatted contract
         JsonReader reader;
         reader.start(mContract);
         rval = (reader.read(&mis) && reader.finish());
         mis.close();

         // set media
         mMedia.setNull();
         if(mContract->hasMember("media"))
         {
            mMedia = mContract["media"];
         }
      }
   }

   return rval;
}
// FIXME: This code has an issue if the config file has a changed id or
// FIXME: changed contents since it was first loaded. Just assuming this code
// FIXME: is the only code that manages the file for now.
bool NodeConfigManager::saveSystemUserConfig()
{
   bool rval;
   Config cfg = getNodeConfig();
   const char* suPath;
   string path;

   rval = !cfg.isNull();

   if(rval)
   {
      // get system user config and expand any home path
      suPath = cfg["systemUserConfig"]->getString();
      rval = expandBitmunkHomePath(suPath, path);
   }

   if(rval)
   {
      // FIXME: do we need locking for load/save/get/remove?
      MO_CAT_DEBUG(BM_NODE_CAT,
         "NodeConfigManager: save system user config: path=%s",
         path.c_str());
      // read
      File file(path.c_str());
      // new config
      Config c;
      if(file->exists())
      {
         FileInputStream fis(file);
         JsonReader reader;
         reader.start(c);
         rval = reader.read(&fis) && reader.finish();
         fis.close();
      }
      else
      {
         c[ConfigManager::VERSION] = MO_DEFAULT_CONFIG_VERSION;
         c[ConfigManager::ID] = "custom system user";
         c[ConfigManager::GROUP] = "system user";
      }
      // update
      if(rval &&
         getConfigManager()->hasConfig(c[ConfigManager::ID]->getString()))
      {
         // get old raw config
         Config active = getConfigManager()->getConfig(
            c[ConfigManager::ID]->getString(), true);
         c.merge(active, false);
      }
      // backup old file
      if(rval && file->exists())
      {
         string backupPath = path + ".bak";
         File backupFile(backupPath.c_str());
         rval = file->rename(backupFile);
      }
      // make sure dirs exist
      rval = rval && file->mkdirs();
      // write
      if(rval)
      {
         FileOutputStream fos(file);
         JsonWriter writer;
         writer.setCompact(false);
         rval = writer.write(c, &fos);
         fos.close();
      }
   }

   if(!rval)
   {
      ExceptionRef e = new Exception(
         "Could not save system user config.",
         "bitmunk.node.NodeConfigManager.ConfigError");
      e->getDetails()["path"] = path.c_str();
      Exception::push(e);
   }

   return rval;
}