Exemple #1
0
bool SmtpClient::sendMessage(Connection* c, Mail* mail)
{
   bool rval = true;

   // send headers
   Message msg = mail->getMessage();
   DynamicObjectIterator i = msg["headers"].getIterator();
   while(rval && i->hasNext())
   {
      // iterate over each header
      DynamicObjectIterator hi = i->next().getIterator();
      bool comma = false;
      while(rval && hi->hasNext())
      {
         DynamicObject header = hi->next();

         if(rval && !comma)
         {
            // send header name and colon
            rval =
               c->getOutputStream()->write(
                  i->getName(), strlen(i->getName())) &&
               c->getOutputStream()->write(": ", 2);
         }

         if(rval && comma)
         {
            // send comma
            rval = c->getOutputStream()->write(", ", 2);
         }
         else
         {
            comma = true;
         }

         if(rval)
         {
            // send smtp-encoded header value
            string value = header->getString();
            Mail::smtpMessageEncode(value);
            rval = c->getOutputStream()->write(value.c_str(), value.length());
         }
      }

      // send CRLF
      if(rval)
      {
         rval = sendCrlf(c);
      }
   }

   if(rval)
   {
      // send encoded body
      string body = mail->getTransferEncodedBody();
      rval = c->getOutputStream()->write(body.c_str(), body.length());
   }

   return rval;
}
Exemple #2
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);
      }
   }
}
Exemple #3
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());
   }
Exemple #4
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();
   }
}
Exemple #5
0
/**
 * Normalizes a value using the given context.
 *
 * @param ctx the context.
 * @param value the value to normalize.
 * @param type the expected RDF type, use RDF_TYPE_UNKNOWN if not known.
 * @param predicate an optional predicate for the value (used to look up
 *           type coercion info).
 * @param usedCtx a context to update if a value was used from "ctx".
 *
 * @return the normalized string.
 */
static string _normalizeValue(
   DynamicObject& ctx, DynamicObject value,
   RdfType type, const char* predicate, DynamicObject* usedCtx)
{
   string rval;

   // "@" or "a"/RDF_TYPE predicates have values that are IRIs or CURIEs
   if(predicate != NULL &&
      (strcmp(predicate, "@") == 0 || strcmp(predicate, "a") == 0 ||
       strcmp(predicate, RDF_TYPE_NORM) == 0))
   {
      type = RDF_TYPE_IRI;
   }

   // IRI "@" is already normalized
   if(type == RDF_TYPE_IRI && strcmp(value, "@") == 0)
   {
      rval.assign(value);
   }
   // IRI "a" is special rdf type
   else if(type == RDF_TYPE_IRI && strcmp(value, "a") == 0)
   {
      rval.assign(RDF_TYPE_NORM);
   }
   else
   {
      string datatype;

      // look for type coercion info
      if(type == RDF_TYPE_UNKNOWN && predicate != NULL &&
         !ctx.isNull() && ctx->hasMember("#types") &&
         ctx["#types"]->hasMember(predicate))
      {
         DynamicObject& tci = ctx["#types"][predicate];
         if(usedCtx != NULL)
         {
            (*usedCtx)["#types"][predicate] = tci.clone();
         }

         // handle specific type
         if(tci->getType() == String)
         {
            rval = value->getString();
            datatype = _normalizeValue(ctx, tci, RDF_TYPE_IRI, NULL, usedCtx);
            type = (strcmp(datatype.c_str(), XSD_ANY_URI_NORM) == 0) ?
               RDF_TYPE_IRI : RDF_TYPE_TYPED_LITERAL;
         }
         // handle type preferences in order
         else
         {
            DynamicObjectIterator ti = tci.getIterator();
            while(type == RDF_TYPE_UNKNOWN && ti->hasNext())
            {
               // FIXME: if value works w/type, set value, datatype, type
               //type = RDF_TYPE_TYPED_LITERAL;
            }
         }
      }
      // determine type from DynamicObjectType
      else if(type == RDF_TYPE_UNKNOWN && value->getType() != String)
      {
         type = RDF_TYPE_TYPED_LITERAL;
         rval = value->getString();

         // handle native xsd types
         if(value->isNumber())
         {
            datatype = value->isInteger() ? XSD_INTEGER : XSD_DOUBLE;
         }
         else if(value->getType() == Boolean)
         {
            datatype = XSD_BOOLEAN;
         }
         else
         {
            // FIXME: this should never happen?
            datatype = XSD_ANY_TYPE;
         }
      }
      else
      {
         // JSON-LD decode
         RdfType t = type;
         _decode(value, type, rval, datatype);
         if(type == RDF_TYPE_TYPED_LITERAL)
         {
            _expandCurie(ctx, datatype.c_str(), datatype, usedCtx);
         }

         // preserve expected type
         if(t != RDF_TYPE_UNKNOWN)
         {
            type = t;
         }
      }

      // expand CURIE
      if(type == RDF_TYPE_IRI)
      {
         _expandCurie(ctx, rval.c_str(), rval, usedCtx);
      }

      // JSON-LD encode
      rval = _encode(type, rval.c_str(), datatype.c_str());
   }

   return rval;
}
Exemple #6
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;
}
Exemple #7
0
bool Int::isValid(
   DynamicObject& obj,
   ValidatorContext* context)
{
   bool rval;
   DynamicObjectType objType;

   rval = !obj.isNull();

   if(rval)
   {
      objType = obj->getType();
      if(objType == String)
      {
         objType = DynamicObject::determineType(obj->getString());
      }

      // type check
      rval =
         objType == Int32 ||
         objType == UInt32 ||
         objType == Int64 ||
         objType == UInt64;
   }

   if(!rval)
   {
      DynamicObject detail =
         context->addError("monarch.validation.ValueError", &obj);
      detail["validator"] = "monarch.validator.Int";
      detail["message"] =
         mErrorMessage ? mErrorMessage :
            "The given value type is required to be an integer.";
   }

   // absolute value of dyno value
   uint64_t val = 0;
   // flag if val is negative
   bool valneg = false;

   // get value for min/max check
   if(rval)
   {
      // get value and sign
      switch(objType)
      {
         case Int32:
         case Int64:
         {
            int64_t raw = obj->getInt64();
            valneg = (raw < 0);
            val = (uint64_t)(valneg ? -raw : raw);
            break;
         }
         case UInt32:
         case UInt64:
         {
            valneg = false;
            val = obj->getUInt64();
            break;
         }
         default:
            // never get here
            break;
      }
   }

   // min check
   if(rval)
   {
      if(mMinNegative != valneg)
      {
         // signs are different
         // val meets the minimum unless val is negative
         rval = !valneg;
      }
      else
      {
         // signs are the same
         // val meets the minimum if:
         // 1. val is positive and larger than mMin
         // 2. val is negative and smaller than mMin
         rval = (!valneg ? val >= mMin : val <= mMin);
      }

      // set exception on failure
      if(!rval)
      {
         DynamicObject detail =
            context->addError("monarch.validation.ValueError", &obj);
         detail["validator"] = "monarch.validator.Int";
         detail["message"] = mErrorMessage ? mErrorMessage :
            "The given integer value is less than the required minimum "
            "integer value.";
         detail["expectedMin"] = mMin;
      }
   }

   // max check
   if(rval)
   {
      if(mMaxNegative != valneg)
      {
         // signs are different
         // val meets the maximum unless val is positive
         rval = valneg;
      }
      else
      {
         // signs are the same
         // val meets the maximum if:
         // 1. val is positive and smaller than mMax
         // 2. val is negative and larger than mMax
         rval = (valneg ? val >= mMax : val <= mMax);
      }

      // set exception on failure
      if(!rval)
      {
         DynamicObject detail =
            context->addError("monarch.validation.ValueError", &obj);
         detail["validator"] = "monarch.validator.Int";
         detail["message"] = mErrorMessage ? mErrorMessage :
            "The given integer value is greater than the allowable maximum "
            "integer value.";
         detail["expectedMax"] = mMax;
      }
   }

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

   return rval;
}
Exemple #8
0
bool ControlPoint::getServiceDescription(Service& service)
{
   bool rval = false;

   // get the description url for the service
   Url url;
   url.format("%s%s",
      service["rootURL"]->getString(),
      service["SCPDURL"]->getString());

   // get description
   string description;
   rval = getDescription(&url, description);
   if(rval)
   {
      //  parse result
      Element root;
      DomReader reader;
      ByteArrayInputStream bais(description.c_str(), description.length());
      reader.start(root);
      if((rval = reader.read(&bais) && reader.finish()))
      {
         MO_CAT_DEBUG(MO_UPNP_CAT, "Parsing service from xml: %s",
            JsonWriter::writeToString(root).c_str());

         // parse out actions
         service["actions"]->setType(Map);
         if(root["children"]->hasMember("actionList"))
         {
            Element& actionList = root["children"]["actionList"][0];
            if(actionList["children"]->hasMember("action"))
            {
               DynamicObjectIterator ai =
                  actionList["children"]["action"].getIterator();
               while(ai->hasNext())
               {
                  DynamicObject& action = ai->next();

                  // get action basics
                  Action a;
                  a["name"] =
                     action["children"]["name"][0]["data"]->getString();
                  a["arguments"]->setType(Map);
                  a["arguments"]["in"]->setType(Array);
                  a["arguments"]["out"]->setType(Array);

                  // add action arguments
                  if(action["children"]->hasMember("argumentList"))
                  {
                     Element& argList = action["children"]["argumentList"][0];
                     DynamicObjectIterator argi =
                        argList["children"]["argument"].getIterator();
                     while(argi->hasNext())
                     {
                        DynamicObject& argument = argi->next();

                        // build argument
                        DynamicObject name;
                        name =
                           argument["children"]["name"]
                           [0]["data"]->getString();
                        const char* direction =
                           argument["children"]["direction"]
                           [0]["data"]->getString();
                        if(strcmp(direction, "in") == 0)
                        {
                           a["arguments"]["in"]->append(name);
                        }
                        else
                        {
                           a["arguments"]["out"]->append(name);
                        }

                        if(argument["children"]->hasMember("retval"))
                        {
                           a["retval"][name->getString()] =
                              argument["children"]["retval"]
                              [0]["data"]->getString();
                        }
                     }

                     // add action to service
                     service["actions"][a["name"]->getString()] = a;
                  }
               }
            }
         }
      }
   }

   if(rval)
   {
      MO_CAT_DEBUG(MO_UPNP_CAT, "Parsed service: %s",
         JsonWriter::writeToString(service).c_str());
   }

   return rval;
}