Esempio n. 1
0
/**
 * Recursively applies context to the given input object.
 *
 * @param ctx the context to use.
 * @param usedCtx the used context values.
 * @param predicate the related predicate or NULL if none.
 * @param in the input object.
 * @param out the contextualized output object.
 */
static void _applyContext(
   DynamicObject& ctx, DynamicObject& usedCtx,
   const char* predicate, DynamicObject& in, DynamicObject& out)
{
   if(in.isNull())
   {
      out.setNull();
   }
   else
   {
      // initialize output
      DynamicObjectType inType = in->getType();
      out->setType(inType);

      if(inType == Map)
      {
         // add context to each property in the map
         char* tmp = NULL;
         DynamicObjectIterator i = in.getIterator();
         while(i->hasNext())
         {
            // compact predicate
            DynamicObject& next = i->next();
            DynamicObject cp(NULL);
            const char* p;
            if(strcmp(i->getName(), "@") == 0)
            {
               p = "@";
            }
            else
            {
               cp = _compactString(ctx, usedCtx, NULL, i->getName(), &tmp);
               p = cp;
            }
            // recurse
            _applyContext(ctx, usedCtx, p, next, out[p]);
         }
         free(tmp);
      }
      else if(inType == Array)
      {
         // apply context to each object in the array
         DynamicObjectIterator i = in.getIterator();
         while(i->hasNext())
         {
            DynamicObject& next = i->next();
            _applyContext(ctx, usedCtx, predicate, next, out->append());
         }
      }
      // only strings need context applied, numbers & booleans don't
      else if(inType == String)
      {
         // compact string
         char* tmp = NULL;
         out = _compactString(ctx, usedCtx, predicate, in->getString(), &tmp);
         free(tmp);
      }
   }
}
Esempio n. 2
0
void DatabaseClient::appendValuesSql(string& sql, DynamicObject& params)
{
   string values;

   bool first = true;
   DynamicObjectIterator i = params.getIterator();
   while(i->hasNext())
   {
      DynamicObject& name = i->next()["name"];
      if(first)
      {
         first = false;
         sql.append(" (");
         values.append(" VALUES (?");
      }
      else
      {
         sql.append(",");
         values.append(",?");
      }

      // append unaliased name
      sql.push_back('`');
      sql.append(name->getString());
      sql.push_back('`');
   }

   if(!first)
   {
      sql.append(")");
      values.append(")");
   }

   sql.append(values);
}
Esempio n. 3
0
void DatabaseClient::appendSetSql(string& sql, DynamicObject& params)
{
   bool first = true;
   DynamicObjectIterator i = params.getIterator();
   while(i->hasNext())
   {
      DynamicObject& param = i->next();
      if(first)
      {
         first = false;
         sql.append(" ");
      }
      else
      {
         sql.append(",");
      }

      // append name
      if(param->hasMember("tableAlias"))
      {
         sql.append(param["tableAlias"]->getString());
         sql.push_back('.');
      }
      sql.append(param["name"]->getString());
      sql.append("=?");
   }
}
Esempio n. 4
0
/**
 * Recursively filter input to output.
 *
 * @param filter the fitler to use.
 * @param in the input object.
 * @param out the filtered output object.
 */
static void _filter(
   DynamicObject& filter, DynamicObject& in, DynamicObject& out)
{
   if(!in.isNull())
   {
      DynamicObjectType inType = in->getType();

      if(inType == Map)
      {
         // check if this object matches filter
         if(_filterOne(filter, in))
         {
            out["@"]->append(in);
         }
      }
      if(inType == Map || inType == Array)
      {
         // filter each object
         DynamicObjectIterator i = in.getIterator();
         while(i->hasNext())
         {
            _filter(filter, i->next(), out);
         }
      }
   }
}
Esempio n. 5
0
void DatabaseClient::appendColumnNames(
   string& sql, DynamicObject& columnSchemas)
{
   bool first = true;
   DynamicObjectIterator i = columnSchemas.getIterator();
   while(i->hasNext())
   {
      DynamicObject& next = i->next();
      if(first)
      {
         first = false;
         sql.append(" ");
      }
      else
      {
         sql.append(",");
      }

      if(next->hasMember("tableAlias"))
      {
         sql.append(next["tableAlias"]->getString());
         sql.append(".");
      }
      sql.append(next["column"]["name"]->getString());
   }
}
Esempio n. 6
0
void EventController::unregisterObserver(
   Observer* observer, DynamicObject& eventTypes)
{
   DynamicObjectIterator i = eventTypes.getIterator();
   while(i->hasNext())
   {
      DynamicObject& type = i->next();
      unregisterObserver(observer, type->getString());
   }
}
Esempio n. 7
0
string X509Certificate::getField(DynamicObject& subjectOrIssuer, const char* sn)
{
   string rval;

   DynamicObjectIterator i = subjectOrIssuer.getIterator();
   while(i->hasNext())
   {
      DynamicObject& entry = i->next();
      if(strcmp(entry["type"]->getString(), sn) == 0)
      {
         rval = entry["value"]->getString();
         break;
      }
   }

   return rval;
}
Esempio n. 8
0
static bool _setDecodedParam(
   Statement* s, unsigned int index,
   DynamicObject& param, DynamicObject& value)
{
   bool rval = true;

   if(param->hasMember("encode"))
   {
      // FIXME: could use streams here and handle types other than string,
      // but the DatabaseClient API might be abandoned before this actually
      // ever really gets used to that extent

      // fill byte buffer with initial data
      ByteBuffer b;
      b.put(value->getString(), value->length(), true);

      // apply each decoding
      // FIXME: optimize this by doing it once and storing it when
      // defining the schema
      DynamicObject decode = param["encode"].clone();
      decode->reverse();
      DynamicObjectIterator i = decode.getIterator();
      while(rval && i->hasNext())
      {
         const char* type = i->next()->getString();

         // convert hex to binary
         if(strcmp(type, "hex") == 0)
         {
            const char* hex = b.bytes();
            unsigned int len = b.length();
            unsigned int binLen = (len >> 1) + 1;
            char bin[binLen];
            rval = Convert::hexToBytes(hex, len, bin, binLen);
            if(rval)
            {
               b.clear();
               b.put(bin, binLen, true);
            }
         }
      }

      // only blobs are supported at the moment
      rval = rval && s->setBlob(index, b.bytes(), b.length());
   }
Esempio n. 9
0
void EventController::registerObserver(
   Observer* observer, DynamicObject& eventTypes)
{
   DynamicObjectIterator i = eventTypes.getIterator();
   while(i->hasNext())
   {
      // register all types
      DynamicObject& next = i->next();
      if(next->getType() == String)
      {
         registerObserver(observer, next->getString());
      }
      else if(next->getType() == Map)
      {
         registerObserver(
            observer, next["type"]->getString(),
            next->hasMember("filter") ? &next["filter"] : NULL);
      }
   }
}
Esempio n. 10
0
/**
 * Recursively removes context from the given input object.
 *
 * @param ctx the context to use (changes during recursion as necessary).
 * @param in the input object.
 * @param out the normalized output object.
 * @param bnodeId the last blank node ID used.
 *
 * @return true on success, false on failure with exception set.
 */
static bool _removeContext(
   DynamicObject& ctx, DynamicObject& in, DynamicObject& out, int& bnodeId)
{
   bool rval = true;

   if(in.isNull())
   {
      out.setNull();
   }
   else
   {
      // initialize output
      DynamicObjectType inType = in->getType();
      out->setType(inType);

      // update context
      if(inType == Map && in->hasMember("#"))
      {
         ctx = in["#"];
      }

      if(inType == Map)
      {
         rval = _normalize(ctx, in, NULL, &out, bnodeId);
      }
      else if(inType == Array)
      {
         // strip context from each object in the array
         DynamicObjectIterator i = in.getIterator();
         while(i->hasNext())
         {
            DynamicObject& next = i->next();
            rval = _removeContext(ctx, next, out->append(), bnodeId);
         }
      }
   }

   return rval;
}
Esempio n. 11
0
bool Contains::isValid(
   DynamicObject& obj,
   ValidatorContext* context)
{
   bool rval = false;

   // check if objects are equal
   rval = (obj == mObject);

   // if not equal, check if target contains the validation object
   if(!rval && !obj.isNull() &&
      (obj->getType() == Array || obj->getType() == Map))
   {
      DynamicObjectIterator i = obj.getIterator();
      while(!rval && i->hasNext())
      {
         DynamicObject& next = i->next();
         rval = (next == mObject);
      }
   }

   if(!rval)
   {
      DynamicObject detail =
         context->addError("monarch.validation.NotFound", &obj);
      detail["validator"] = "monarch.validator.Contains";
      detail["expectedValue"] = mObject;
      detail["message"] = mErrorMessage ? mErrorMessage :
         "The input object was not equal to or found in the validator.";
   }

   if(rval)
   {
      context->addSuccess();
   }

   return rval;
}
Esempio n. 12
0
void DatabaseClient::appendOrderSql(
   string& sql, DynamicObject& params, bool useTableAlias)
{
   bool first = true;
   DynamicObjectIterator i = params.getIterator();
   while(i->hasNext())
   {
      DynamicObject& param = i->next();
      if(first)
      {
         first = false;
         sql.append(" ORDER BY ");
      }
      else
      {
         sql.append(", ");
      }

      // append aliased name
      if(useTableAlias)
      {
         sql.append(param["tableAlias"]->getString());
         sql.append(".");
      }
      sql.append(param["name"]->getString());

      // direction
      if(param["direction"]->getInt32() == ASC)
      {
         sql.append(" ASC");
      }
      else
      {
         sql.append(" DESC");
      }
   }
}
Esempio n. 13
0
// a helper function that converts message parameters into a dom element
static void paramsToElement(SoapMessage& msg, DynamicObject& params, Element& e)
{
   if(params->getType() == Map)
   {
      DynamicObjectIterator pi = params.getIterator();
      while(pi->hasNext())
      {
         DynamicObject& p = pi->next();

         // add param element
         Element param;
         param["name"] = pi->getName();
         param["namespace"] = msg["namespace"]->getString();
         e["children"][pi->getName()]->append(param);
         paramsToElement(msg, p, param);
      }
   }
   else
   {
      // use 0/1 for booleans
      e["data"] = (params->getType() == Boolean) ?
         (params->getBoolean() ? "1" : "0") : params->getString();
   }
}
Esempio n. 14
0
static bool _filterOne(DynamicObject& filter, DynamicObject& object)
{
   bool rval = true;

   // loop over all filter properties
   DynamicObjectIterator i;
   i = filter.getIterator();
   while(rval && i->hasNext())
   {
      DynamicObject& next = i->next();
      const char* name = i->getName();
      // check if object has property
      rval = object->hasMember(name);
      if(rval)
      {
         // loop over all filter values
         DynamicObjectIterator fpi;
         fpi = next.getIterator();
         while(rval && fpi->hasNext())
         {
            DynamicObject& fpnext = fpi->next();
            // make sure value appears in object property
            DynamicObjectIterator opi;
            opi = object[name].getIterator();
            rval = false;
            while(!rval && opi->hasNext())
            {
               DynamicObject& opnext = opi->next();
               rval = (fpnext == opnext);
            }
         }
      }
   }

   return rval;
}
Esempio n. 15
0
bool WebServiceContainer::addService(
   WebServiceRef& service,
   WebService::SecurityType st,
   bool initialize,
   const char* domain)
{
   bool rval = true;

   if(initialize)
   {
      rval = service->initialize();
   }

   if(rval)
   {
      // build list of domains to add service to
      DynamicObject domains(NULL);
      DynamicObject added;
      added->setType(Array);
      if(domain != NULL)
      {
         domains = DynamicObject();
         domains->append(domain);
      }
      else
      {
         domains = mDefaultDomains;
      }

      HttpRequestServicer* hrs = &(*service);
      const char* path = hrs->getPath();

      // prevent other container access
      mContainerLock.lockExclusive();

      DynamicObjectIterator di = domains.getIterator();
      while(rval && di->hasNext())
      {
         const char* dom = di->next()->getString();
         rval = internalAddService(service, st, dom);
         if(rval)
         {
            added->append(dom);
         }
      }

      di = rval ? domains.getIterator() : added.getIterator();
      while(di->hasNext())
      {
         const char* dom = di->next()->getString();

         // success, add domain to http servicer
         if(rval)
         {
            if(st == WebService::Secure || st == WebService::Both)
            {
               mHttpConnectionServicer.addRequestServicer(hrs, true, dom);
               MO_CAT_DEBUG(MO_WS_CAT,
                  "Added secure web service: %s%s", dom, path);
            }
            if(st != WebService::Secure)
            {
               mHttpConnectionServicer.addRequestServicer(hrs, false, dom);
               MO_CAT_DEBUG(MO_WS_CAT,
                  "Added non-secure web service: %s%s", dom, path);
            }
         }
         // could not add service to all domains, so remove it
         else
         {
            internalRemoveService(path, st, dom, NULL);
         }
      }

      // permit access again
      mContainerLock.unlockExclusive();
   }

   // failed to add service
   if(!rval)
   {
      // service was initialized, so clean it up
      if(initialize)
      {
         service->cleanup();
      }

      // set exception
      ExceptionRef e = new Exception(
         "Could not add web service.",
         "monarch.ws.AddWebServiceFailure");
      Exception::push(e);
   }

   return rval;
}
Esempio n. 16
0
bool SampleService::sendm3u(BtpAction* action, DynamicObject& fileInfos)
{
   bool rval = true;

   // build m3u file
   string content;
   content.append("#EXTM3U\n");

   // create play list
   char temp[22];
   FileInfoIterator i = fileInfos.getIterator();
   while(i->hasNext())
   {
      FileInfo& fi = i->next();
      Media& media = fi["media"];
      int sampleLength =
         media["sampleRange"][1]->getUInt32() -
         media["sampleRange"][0]->getUInt32();
      snprintf(temp, 22, "%u", (sampleLength < 0 ? 0 : sampleLength));

      string artist;
      if(media["contributors"]->hasMember("Performer"))
      {
         artist = media["contributors"]["Performer"][0]["name"]->getString();
      }
      else if(media["contributors"]->hasMember("Artist"))
      {
         artist = media["contributors"]["Artist"][0]["name"]->getString();
      }

      content.append("#EXTINF:");
      content.append(temp);
      content.push_back(',');
      content.append(artist);
      content.append(" - ");
      content.append(media["title"]->getString());
      content.push_back('\n');

      // FIXME: get host from configuration or something
      // needs to be public IP that remote side can access
      DynamicObject vars;
      action->getResourceQuery(vars);
      if(!vars->hasMember("nodeuser"))
      {
         BM_ID_SET(vars["nodeuser"], mNode->getDefaultUserId());
      }

      HttpRequestHeader* header = action->getRequest()->getHeader();
      string host = header->getFieldValue("X-Forwarded-Host");
      if(host.length() == 0)
      {
         host = header->getFieldValue("Host");
      }
      content.append("http://");
      content.append(host);
      content.append("/api/3.0/sales/samples/file/");
      content.append(fi["mediaId"]->getString());
      content.push_back('/');
      content.append(fi["id"]->getString());
      content.push_back('\n');
   }

   // set up response header
   HttpResponseHeader* header = action->getResponse()->getHeader();
   header->setField("Content-Type", "audio/x-mpegurl");
   header->setField(
      "Content-Disposition", "attachment; filename=bitmunk-sample.m3u");

   // create content input stream
   ByteBuffer b(content.length());
   b.put(content.c_str(), content.length(), false);
   ByteArrayInputStream bais(&b);

   // send sample
   action->getResponse()->getHeader()->setStatus(200, "OK");
   action->sendResult(&bais);

   return rval;
}
Esempio n. 17
0
/**
 * Build a columnSchema Map out of an ORDER specification.
 *
 * Input:
 * [
 *    {
 *       "name1": order,
 *       ...
 *    },
 *    ...
 * ]
 *
 * Output:
 * {
 *    "name1": {
 *       "value
 *    }
 * }
 */
static void _buildOrderParams(
   SchemaObject& schema,
   DynamicObject& order,
   DynamicObject& params,
   const char* tableAlias)
{
   // create shared table alias object
   DynamicObject taObj(NULL);
   if(tableAlias != NULL)
   {
      taObj = DynamicObject();
      taObj = tableAlias;
   }

   // build map of names
   DynamicObject names(Array);
   {
      DynamicObjectIterator i = order.getIterator();
      while(i->hasNext())
      {
         DynamicObjectIterator ni = i->next().getIterator();
         while(ni->hasNext())
         {
            DynamicObject& next = ni->next();
            names[ni->getName()]["direction"] = next;
         }
      }
   }

   // get column details for each name
   {
      DynamicObjectIterator i = schema["columns"].getIterator();
      while(i->hasNext())
      {
         DynamicObject& next = i->next();
         const char* memberName = next["memberName"]->getString();

         // get details for column if needed
         if(names->hasMember(memberName))
         {
            DynamicObject& nameInfo = names[memberName];
            nameInfo["name"] = next["name"];
            if(tableAlias != NULL)
            {
               nameInfo["tableAlias"] = taObj;
            }
         }
      }
   }

   // setup params in proper order
   {
      DynamicObjectIterator i = order.getIterator();
      while(i->hasNext())
      {
         DynamicObjectIterator ni = i->next().getIterator();
         while(ni->hasNext())
         {
            ni->next();
            params->append(names[ni->getName()]);
         }
      }
   }
}
Esempio n. 18
0
static DynamicObject _compactIri(
   DynamicObject& ctx, DynamicObject& usedCtx,
   const char* predicate, const char* encoded,
   const char* value, char** curie)
{
   DynamicObject rval(NULL);

   // used to store if brackets should be added
   bool addBrackets = true;

   // predicates themselves have no brackets
   if(predicate == NULL)
   {
      addBrackets = false;
   }
   // no brackets for "@" or "a"
   else if(strcmp(predicate, "@") == 0 || strcmp(predicate, "a") == 0)
   {
      addBrackets = false;
   }
   // check type coercion for IRI
   else if(ctx->hasMember("#types") && ctx["#types"]->hasMember(predicate))
   {
      DynamicObject& type = ctx["#types"][predicate];
      usedCtx["#types"][predicate] = type.clone();

      // single type
      if(type->getType() == String)
      {
         string t = _normalizeValue(ctx, type, RDF_TYPE_IRI, NULL, &usedCtx);
         if(strcmp(t.c_str(), XSD_ANY_URI_NORM) == 0)
         {
            addBrackets = false;
         }
      }
      // type coercion info is an ordered list of possible types
      else
      {
         // do not add brackets if URI is a valid type
         DynamicObjectIterator ti = type.getIterator();
         while(ti->hasNext())
         {
            DynamicObject& next = ti->next();
            string t = _normalizeValue(ctx, next, RDF_TYPE_IRI, NULL, &usedCtx);
            if(strcmp(t.c_str(), XSD_ANY_URI_NORM) == 0)
            {
               addBrackets = false;
            }
         }
      }
   }

   // check the context for a prefix that could shorten the IRI to a CURIE
   DynamicObjectIterator i = ctx.getIterator();
   while(rval.isNull() && i->hasNext())
   {
      DynamicObject& next = i->next();

      // skip special context keys (start with '#')
      const char* name = i->getName();
      if(name[0] != '#')
      {
         const char* uri = next;
         const char* ptr = strstr(value, uri);
         if(ptr != NULL && ptr == value)
         {
            size_t ulen = strlen(uri);
            size_t vlen = strlen(value);
            if(vlen > ulen)
            {
               // add 2 to make room for null-terminator and colon
               size_t total = strlen(name) + (vlen - ulen) + 2;
               if(addBrackets)
               {
                  total += 2;
               }
               _realloc(curie, total);
               const char* format = addBrackets ? "<%s:%s>" : "%s:%s";
               snprintf(*curie, total, format, name, ptr + ulen);
               rval = DynamicObject();
               rval = *curie;
               usedCtx[name] = uri;
            }
            else if(vlen == ulen && strcmp(name, "a") == 0)
            {
               rval = DynamicObject();
               rval = "a";
            }
         }
      }
   }

   // if rval still not set, use encoded or value based on addBrackets
   if(rval.isNull())
   {
      rval = DynamicObject();
      rval = addBrackets ? encoded : value;
   }

   return rval;
}
Esempio n. 19
0
bool JsonLd::normalize(DynamicObject& in, DynamicObject& out)
{
   bool rval = true;

   // initialize output
   out->setType(Map);
   out->clear();

   // create map to store subjects
   DynamicObject subjects;
   subjects->setType(Map);

   // initialize context
   DynamicObject ctx(NULL);
   if(in->hasMember("#"))
   {
      ctx = in["#"];
   }

   // put all subjects in an array for single code path
   DynamicObject input;
   input->setType(Array);
   if(in->hasMember("@") && in["@"]->getType() == Array)
   {
      input.merge(in["@"], true);
   }
   else
   {
      input->append(in);
   }

   // do normalization
   int bnodeId = 0;
   DynamicObjectIterator i = input.getIterator();
   while(rval && i->hasNext())
   {
      rval = _normalize(ctx, i->next(), &subjects, NULL, bnodeId);
   }

   // build output
   if(rval)
   {
      // single subject
      if(subjects->length() == 1)
      {
         DynamicObject subject = subjects.first();
         out.merge(subject, false);

         // FIXME: will need to check predicates for blank nodes as well...
         // and fail if they aren't embeds?

         // strip blank node '@'
         if(_isBlankNode(out))
         {
            out->removeMember("@");
         }
      }
      // multiple subjects
      else
      {
         DynamicObject& array = out["@"];
         array->setType(Array);
         i = subjects.getIterator();
         while(i->hasNext())
         {
            DynamicObject& next = i->next();

            // FIXME: will need to check predicates for blank nodes as well...
            // and fail if they aren't embeds?

            // strip blank node '@'
            if(_isBlankNode(next))
            {
               next->removeMember("@");
            }
            array->append(next);
         }
      }
   }

   return rval;
}
Esempio n. 20
0
/**
 * Recursively normalizes the given input object.
 *
 * Input: A subject with predicates and possibly embedded other subjects.
 * Output: Either a map of normalized subjects OR a tree of normalized subjects.
 *
 * Normalization Algorithm:
 *
 * Replace the existing context if the input has '#'.
 *
 * For each key-value:
 * 1. Split the key on a colon and look for prefix in the context. If found,
 *    expand the key to an IRI, else it is already an IRI, add <>, save the
 *    new predicate to add to the output.
 * 2. If value is a Map, then it is a subject, set the predicate to the
 *    subject's '@' IRI value and recurse into it. Else goto #3.
 * 3. Look up the key in the context to find type coercion info. If not found,
 *    goto #4, else goto #5.
 * 4. Check the value for an integer, double, or boolean. If matched, set
 *    type according to xsd types. If not matched, look for <>, if found,
 *    do CURIE vs. IRI check like #1 and create appropriate value.
 * 5. If type coercion entry is a string, encode the value using the specific
 *    type. If it is an array, check the type in order of preference. If an
 *    unrecognized type (non-xsd, non-IRI) is provided, throw an exception.
 *
 * @param ctx the context to use (changes during recursion as necessary).
 * @param in the input object.
 * @param subjects a map of normalized subjects.
 * @param out a tree normalized objects.
 * @param bnodeId the last blank node ID used.
 *
 * @return true on success, false on failure with exception set.
 */
static bool _normalize(
   DynamicObject ctx, DynamicObject& in,
   DynamicObject* subjects, DynamicObject* out, int& bnodeId)
{
   bool rval = true;

   // FIXME: validate context (check for non-xsd types in type coercion arrays)

   if(!in.isNull())
   {
      // update context
      if(in->hasMember("#"))
      {
         ctx = in["#"];
      }

      // vars for normalization state
      DynamicObject subject(NULL);
      if(subjects != NULL)
      {
         subject = DynamicObject();
         subject->setType(Map);

         // assign blank node ID as needed
         if(!in->hasMember("@"))
         {
            string bnodeKey = _createBlankNodeId(++bnodeId);
            subject["@"] = bnodeKey.c_str();
         }
      }
      string nKey;

      // iterate over key-values
      DynamicObjectIterator i = in.getIterator();
      while(rval && i->hasNext())
      {
         DynamicObject& value = i->next();
         const char* key = i->getName();

         // skip context keys
         if(key[0] == '#')
         {
            continue;
         }

         // get normalized key
         nKey = _normalizeValue(ctx, key, RDF_TYPE_IRI, NULL, NULL);

         // put values in an array for single code path
         DynamicObject values;
         values->setType(Array);
         if(value->getType() == Array)
         {
            values.merge(value, true);

            // preserve array structure when not using subjects map
            if(out != NULL)
            {
               (*out)[nKey.c_str()]->setType(Array);
            }
         }
         else
         {
            values->append(value);
         }

         // normalize all values
         DynamicObjectIterator vi = values.getIterator();
         while(rval && vi->hasNext())
         {
            DynamicObject v = vi->next();
            if(v->getType() == Map)
            {
               if(subjects != NULL)
               {
                  // get a normalized subject for the value
                  string vSubject;
                  if(v->hasMember("@"))
                  {
                     // normalize existing subject
                     vSubject = _normalizeValue(
                        ctx, v["@"], RDF_TYPE_IRI, NULL, NULL);
                  }
                  else
                  {
                     // generate the next blank node ID in order to preserve
                     // the blank node embed in the code below
                     vSubject = _createBlankNodeId(bnodeId + 1);
                  }

                  // determine if value is a blank node
                  bool isBNode = _isBlankNode(v);

                  // update non-blank node subject (use value's subject IRI)
                  if(!isBNode)
                  {
                     _setPredicate(subject, nKey.c_str(), vSubject.c_str());
                  }

                  // recurse
                  rval = _normalize(ctx, v, subjects, out, bnodeId);

                  // preserve embedded blank node
                  if(rval && isBNode)
                  {
                     // remove embed from top-level subjects
                     DynamicObject embed = (*subjects)[vSubject.c_str()];
                     (*subjects)->removeMember(vSubject.c_str());
                     embed->removeMember("@");
                     _setEmbed(subject, nKey.c_str(), embed);
                  }
               }
               else
               {
                  // update out and recurse
                  DynamicObject next = (*out)[nKey.c_str()];
                  if(value->getType() == Array)
                  {
                     next = next->append();
                  }
                  else
                  {
                     next->setType(Map);
                  }
                  rval = _normalize(ctx, v, subjects, &next, bnodeId);
               }
            }
            else
            {
               _setPredicate(
                  (subjects != NULL) ? subject : *out, nKey.c_str(),
                  _normalizeValue(ctx, v, RDF_TYPE_UNKNOWN, key, NULL).c_str());
            }
         }
      }

      // add subject to map
      if(subjects != NULL)
      {
         (*subjects)[subject["@"]->getString()] = subject;
      }
   }

   return rval;
}
Esempio n. 21
0
void DatabaseClient::appendWhereSql(
   string& sql, DynamicObject& params, bool useTableAlias)
{
   // FIXME: consider allowing for more complex WHERE clauses other
   // than a bunch of "key=value AND"s concatenated together

   bool first = true;
   DynamicObjectIterator i = params.getIterator();
   while(i->hasNext())
   {
      DynamicObject& param = i->next();
      if(first)
      {
         first = false;
         sql.append(" WHERE ");
      }
      else
      {
         sql.push_back(' ');
         sql.append(param["boolOp"]->getString());
         sql.push_back(' ');
      }

      // append aliased name
      if(useTableAlias)
      {
         sql.append(param["tableAlias"]->getString());
         sql.append(".");
      }
      sql.append(param["name"]->getString());

      // use IN clause
      if(param["value"]->getType() == Array)
      {
         sql.append(" IN (");

         bool aFirst = true;
         DynamicObjectIterator ai = param["value"].getIterator();
         while(ai->hasNext())
         {
            ai->next();
            if(aFirst)
            {
               aFirst = false;
               sql.append("?");
            }
            else
            {
               sql.append(",?");
            }
         }

         sql.append(")");
      }
      // use parameter operator
      else
      {
         sql.append(param["op"]->getString());
         sql.append("?");
      }
   }
}
void DownloadStateEventReactor::reprocessRequired(Event& e)
{
   // get user ID
   UserId userId = BM_USER_ID(e["details"]["userId"]);

   // ensure operation is done as the user to protect against logout
   Operation op = mNode->currentOperation();
   if(mNode->addUserOperation(userId, op, NULL))
   {
      // lock to prevent double-reprocessing download states
      // Note: Reprocessing the download state isn't fatal, it just may fail
      // silently or be annoying by re-assembling already assembled files, etc.
      mReprocessLock.lock();
      {
         // log activity
         MO_CAT_DEBUG(BM_EVENTREACTOR_DS_CAT,
            "Event reactor handling ds 'reprocessRequired' "
            "event for user %" PRIu64 "...", userId);

         // get messenger
         Messenger* messenger = mNode->getMessenger();

         // process all queued directives
         {
            Url url;
            url.format("%s/api/3.0/system/directives?nodeuser=%" PRIu64,
               messenger->getSelfUrl(true).c_str(), userId);

            DynamicObject directives;
            if(messenger->get(&url, directives, userId))
            {
               DynamicObjectIterator i = directives.getIterator();
               while(i->hasNext())
               {
                  DynamicObject& directive = i->next();

                  // process the directive if it is of type "peerbuy":
                  if(strcmp(directive["type"]->getString(), "peerbuy") == 0)
                  {
                     url.format(
                        "%s/api/3.0/system/directives/process/%s?nodeuser=%"
                        PRIu64,
                        messenger->getSelfUrl(true).c_str(),
                        directive["id"]->getString(), userId);

                     DynamicObject in;
                     if(!messenger->post(&url, NULL, &in, userId))
                     {
                        // schedule exception event
                        Event e2;
                        e2["type"] =
                           "bitmunk.eventreactor.EventReactor.exception";
                        e2["details"]["exception"] =
                           Exception::getAsDynamicObject();
                        mNode->getEventController()->schedule(e2);
                     }
                  }
               }
            }
         }

         // create a list of download states to reprocess
         DownloadStateList list;
         list->setType(Array);

         if(e["details"]->hasMember("all") && e["details"]["all"]->getBoolean())
         {
            // get all non-processing download states
            Url url;
            url.format("%s/api/3.0/purchase/contracts/downloadstates"
               "?nodeuser=%" PRIu64 "&incomplete=true&processing=false",
               messenger->getSelfUrl(true).c_str(), userId);
            DynamicObject in;
            if(messenger->get(&url, in, userId))
            {
               // append states to list
               list.merge(in["downloadStates"], true);
            }
            else
            {
               // schedule exception event
               Event e2;
               e2["type"] = "bitmunk.eventreactor.EventReactor.exception";
               e2["details"]["exception"] =
                  Exception::getAsDynamicObject();
               mNode->getEventController()->schedule(e2);
            }
         }
         else if(e["details"]->hasMember("downloadStateId"))
         {
            // reprocess single download state
            DownloadStateId dsId = e["details"]["downloadStateId"]->getUInt64();
            IPurchaseModule* ipm = dynamic_cast<IPurchaseModule*>(
               mNode->getKernel()->getModuleApi(
                  "bitmunk.purchase.Purchase"));
            DownloadState ds;
            ds["id"] = dsId;
            BM_ID_SET(ds["userId"], userId);
            if(ipm->populateDownloadState(ds))
            {
               // append state to list
               list->append(ds);
            }
            else
            {
               // schedule exception event
               Event e2;
               e2["type"] = "bitmunk.eventreactor.EventReactor.exception";
               e2["details"]["exception"] =
                  Exception::getAsDynamicObject();
               mNode->getEventController()->schedule(e2);
            }
         }

         // reprocess all states in the list
         DynamicObjectIterator i = list.getIterator();
         while(i->hasNext())
         {
            DownloadState& ds = i->next();
            DownloadStateId dsId = ds["id"]->getUInt64();

            if(ds["downloadStarted"]->getBoolean())
            {
               // do purchase only if no pieces remain
               if(ds["remainingPieces"]->getUInt32() == 0)
               {
                  if(!ds["licensePurchased"]->getBoolean() ||
                     !ds["dataPurchased"]->getBoolean())
                  {
                     // do purchase
                     postDownloadStateId(userId, dsId, "purchase");
                  }
                  else if(!ds["filesAssembled"]->getBoolean())
                  {
                     // do file assembly
                     postDownloadStateId(userId, dsId, "assemble");
                  }
               }
               else if(!ds["downloadPaused"]->getBoolean())
               {
                  // restart download
                  postDownloadStateId(userId, dsId, "download");
               }
            }
            else if(!ds["initialized"]->getBoolean())
            {
               // initialize download state
               postDownloadStateId(userId, dsId, "initialize");
            }
            else if(!ds["licenseAcquired"]->getBoolean())
            {
               // acquire license
               postDownloadStateId(userId, dsId, "license");
            }
         }
      }
      mReprocessLock.unlock();
   }
}
Esempio n. 23
0
bool JsonWriter::write(DynamicObject& dyno, OutputStream* os, int level)
{
   bool rval = true;

   if(level < 0)
   {
      level = mIndentLevel;
   }

   if(dyno.isNull())
   {
      rval = os->write("null", 4);
   }
   else
   {
      switch(dyno->getType())
      {
         case String:
         {
            const char* temp = dyno->getString();
            size_t length = strlen(temp);

            // Note: UTF-8 has a maximum of 6-bytes per character when
            // encoded in json format ("\u1234")
            string encoded;
            encoded.reserve(length);
            encoded.push_back('"');
            char unicode[6];
            for(size_t i = 0; i < length; ++i)
            {
               unsigned char c = temp[i];
               if((c >= 0x5d /* && c <= 0x10FFFF */) ||
                  (c >= 0x23 && c <= 0x5B) ||
                  (c == 0x21) ||
                  (c == 0x20))
               {
                  // TODO: check this handles UTF-* properly
                  encoded.push_back(c);
               }
               else
               {
                  encoded.push_back('\\');
                  switch(c)
                  {
                     case '"': /* 0x22 */
                     case '\\': /* 0x5C */
                     // '/' is in the RFC but not required to be escaped
                     //case '/': /* 0x2F */
                        encoded.push_back(c);
                        break;
                     case '\b': /* 0x08 */
                        encoded.push_back('b');
                        break;
                     case '\f': /* 0x0C */
                        encoded.push_back('f');
                        break;
                     case '\n': /* 0x0A */
                        encoded.push_back('n');
                        break;
                     case '\r': /* 0x0D */
                        encoded.push_back('r');
                        break;
                     case '\t': /* 0x09 */
                        encoded.push_back('t');
                        break;
                     default:
                        // produces "u01af" (4 digits of 0-filled hex)
                        snprintf(unicode, 6, "u%04x", c);
                        encoded.append(unicode, 5);
                        break;
                  }
               }
            }

            // end string serialization and write encoded string
            encoded.push_back('"');
            rval = os->write(encoded.c_str(), encoded.length());
            break;
         }
         case Boolean:
         case Int32:
         case UInt32:
         case Int64:
         case UInt64:
         case Double:
         {
            const char* temp = dyno->getString();
            rval = os->write(temp, strlen(temp));
            break;
         }
         case Map:
         {
            // start map serialization
            rval = (mCompact || dyno->length() == 0) ?
               os->write("{", 1) : os->write("{\n", 2);

            // serialize each map member
            DynamicObjectIterator i = dyno.getIterator();
            while(rval && i->hasNext())
            {
               DynamicObject& next = i->next();

               // serialize indentation and start serializing member name
               if((rval =
                  writeIndentation(os, level + 1) &&
                  os->write("\"", 1) &&
                  os->write(i->getName(), strlen(i->getName()))))
               {
                  // end serializing member name, serialize member value
                  rval = ((mCompact) ?
                     os->write("\":", 2) : os->write("\": ", 3)) &&
                     write(next, os, level + 1);

                  // serialize delimiter if appropriate
                  if(rval && i->hasNext())
                  {
                     rval = os->write(",", 1);
                  }

                  // add formatting if appropriate
                  if(rval && !mCompact)
                  {
                     rval = os->write("\n", 1);
                  }
               }
            }

            // end map serialization
            if(dyno->length() > 0)
            {
               rval = rval && writeIndentation(os, level);
            }
            rval = rval && os->write("}", 1);
            break;
         }
         case Array:
         {
            // start array serialization
            rval = (mCompact || dyno->length() == 0) ?
               os->write("[", 1) : os->write("[\n", 2);

            // serialize each array element
            DynamicObjectIterator i = dyno.getIterator();
            while(rval && i->hasNext())
            {
               // serialize indentation and array value
               rval =
                  writeIndentation(os, level + 1) &&
                  write(i->next(), os, level + 1);

               // serialize delimiter if appropriate
               if(rval && i->hasNext())
               {
                  rval = os->write(",", 1);
               }

               // add formatting if appropriate
               if(rval && !mCompact)
               {
                  rval = os->write("\n", 1);
               }
            }

            // end array serialization
            if(dyno->length() > 0)
            {
               rval = rval && writeIndentation(os, level);
            }
            rval = rval && os->write("]", 1);
            break;
         }
      }
   }

   return rval;
}