/*----------------------------------------------------------------------------*/
void XmlServer :: methodRegister(XmlRequest& request, XmlResponse& response)
{
  if(database->isKsefError() || database->ksefDatabase() == NULL)
  {
    response.setStatus(XmlResponse::InternalError, database->ksefMessage());
    return;
  }

  User user = database->userStorage()->user(request.userName(), request.password());
  if(!user.ksef.write)
  {
    response.setStatus(XmlResponse::accessDenied, QString("Access denied for user '%1'").arg(user.name));
    return;
  }

  KsefDocument doc;

  QDomElement data = request.data();
  QDomElement e = data.firstChildElement("RQ");
  e = e.firstChildElement("DAT");

  if(e.isNull() || !doc.assign(e))
  {
    response.setStatus(XmlResponse::InvalidQuery, "Invalid query");
    return;
  }



  if(!database->ksefDatabase()->cashRegister(doc, response))
    response.setStatus(XmlResponse::InternalError, database->ksefDatabase()->message());
}
/*----------------------------------------------------------------------------*/
void XmlServer :: methodUpdate(XmlRequest& request, XmlResponse& response)
{
  if(database->isStoreError() || database->storeDatabase() == NULL)
  {
    response.setStatus(XmlResponse::InternalError, database->storeMessage());
    return;
  }

  User user = database->userStorage()->user(request.userName(), request.password());
  if(!user.store.write)
  {
    response.setStatus(XmlResponse::accessDenied, QString("Access denied for user '%1'").arg(user.name));
    return;
  }
  if(!database->storeDatabase()->update(request, response))
    response.setStatus(XmlResponse::InternalError, database->storeDatabase()->message());
}
/*----------------------------------------------------------------------------*/
void XmlServer :: methodKsefGet(XmlRequest& request, XmlResponse& response)
{
  if(database->isKsefError() || database->ksefDatabase() == NULL)
  {
    response.setStatus(XmlResponse::InternalError, database->ksefMessage());
    return;
  }

  User user = database->userStorage()->user(request.userName(), request.password());
  if(!user.ksef.read)
  {
    response.setStatus(XmlResponse::accessDenied, QString("Access denied for user '%1'").arg(user.name));
    return;
  }

  if(!database->ksefDatabase()->query(request, response))
    response.setStatus(XmlResponse::InternalError, database->ksefDatabase()->message());
}
/* ****************************************************************************
*
* invalidEntityIdAttribute_xml - 
*
* FIXME P5: invalid attributes in EntityId are found but not reported
*/
TEST(SubscribeContextRequest, invalidEntityIdAttribute_xml)
{
  ParseData       parseData;
  ConnectionInfo  ci("", "POST", "1.1");
  const char*     infile = "ngsi10.subscribeContextRequest.entityIdAttribute.invalid.xml";
  const char*     expected = "OK";
  XmlRequest*     reqP;

  utInit();

  EXPECT_EQ("OK", testDataFromFile(testBuf, sizeof(testBuf), infile)) << "Error getting test data from '" << infile << "'";

  std::string result = xmlTreat(testBuf, &ci, &parseData, SubscribeContext, "subscribeContextRequest", &reqP);

  reqP->release(&parseData);
  EXPECT_STREQ(expected, result.c_str());

  utExit();
}
/* ****************************************************************************
*
* invalidDuration_xml - 
*/
TEST(SubscribeContextRequest, invalidDuration_xml)
{
  ParseData       parseData;
  ConnectionInfo  ci("", "POST", "1.1");
  const char*     infile  = "ngsi10.subscribeContextRequest.duration.invalid.xml";
  const char*     outfile = "ngsi10.subscribeContextResponse.invalidDuration.valid.xml";
  XmlRequest*     reqP;

  utInit();

  EXPECT_EQ("OK", testDataFromFile(testBuf, sizeof(testBuf), infile)) << "Error getting test data from '" << infile << "'";
  EXPECT_EQ("OK", testDataFromFile(expectedBuf, sizeof(expectedBuf), outfile)) << "Error getting test data from '" << outfile << "'";

  lmTraceLevelSet(LmtDump, true);
  std::string out = xmlTreat(testBuf, &ci, &parseData, SubscribeContext, "subscribeContextRequest", &reqP);
  lmTraceLevelSet(LmtDump, false);

  reqP->release(&parseData);
  EXPECT_STREQ(expectedBuf, out.c_str());

  utExit();
}
/*----------------------------------------------------------------------------*/
void XmlServer :: service(XmlRequest& request, XmlResponse& response)
{
  if(request.method() == "register")
  {
    methodRegister(request, response);
  }
  else
  if(request.method() == "upload")
  {
    methodUpload(request, response);
  }
  else
  if(request.method() == "download")
  {
    methodDownload(request, response);
  }
  else
  if(request.method() == "sync")
  {
    methodUpload(request, response);
    if(response.isOk())
      methodDownload(request, response);
  }
  else
  if(request.method() == "update")
  {
    methodUpdate(request, response);
  }
  else
  if(request.method() == "ksef_get")
  {
    methodKsefGet(request, response);
  }
  else
  {
    response.setStatus(XmlResponse::InvalidMethod, QString("Invalid method '%1'").arg(request.method()) );
  }
}
Beispiel #7
0
/* ****************************************************************************
*
* xmlTreat -
*/
std::string xmlTreat
(
  const char*      content,
  ConnectionInfo*  ciP,
  ParseData*       parseDataP,
  RequestType      request,
  std::string      payloadWord,
  XmlRequest**     reqPP,
  std::string*     errorMsgP
)
{
  xml_document<>  doc;
  char*           xmlPayload = (char*) content;

  //
  // If the payload is empty, the XML parsing library does an assert
  // and the broker dies.
  // Therefore, this check here is important, to avoid death.
  // 
  // 'OK' is returned as there is no error to send a request without payload.
  //
  if ((content == NULL) || (*content == 0))
  {
    return "OK";
  }

  try
  {
    doc.parse<0>(xmlPayload);
  }
  catch (parse_error& e)
  {
    std::string errorReply = restErrorReplyGet(ciP, ciP->outFormat, "", "unknown", SccBadRequest, "XML Parse Error");
    LM_W(("Bad Input ('%s', '%s')", content, e.what()));

    if (errorMsgP)
    {
      *errorMsgP = std::string("XML parse error exception: ") + e.what();
    }

    return errorReply;
  }
  catch (...)
  {
    std::string errorReply = restErrorReplyGet(ciP, ciP->outFormat, "", "unknown", SccBadRequest, "XML Parse Error");
    LM_W(("Bad Input (%s)", content));

    if (errorMsgP)
    {
      *errorMsgP = std::string("XML parse generic exception");
    }

    return errorReply;
  }

  xml_node<>*   father = doc.first_node();
  XmlRequest*   reqP   = xmlRequestGet(request, ciP->method);

  ciP->parseDataP = parseDataP;

  if (father == NULL)
  {
    std::string errorReply = restErrorReplyGet(ciP, ciP->outFormat, "", "unknown", SccBadRequest, "XML Parse Error");
    LM_W(("Bad Input (XML parse error)"));
    if (errorMsgP)
    {
      *errorMsgP = std::string("XML parse error: invalid XML input");
    }

    return errorReply;
  }

  if (reqP == NULL)
  {
    std::string errorReply =
      restErrorReplyGet(
        ciP,
        ciP->outFormat,
        "",
        requestType(request),
        SccBadRequest,
        std::string("Sorry, no request treating object found for RequestType /") +
        requestType(request) + "/, method /" + ciP->method + "/");

    LM_W(("Bad Input (no request treating object found for RequestType %d (%s), method %s)",
          request,
          requestType(request),
          ciP->method.c_str()));

    LM_W(("Bad Input (no request treating object found for RequestType %d (%s), method %s)",
          request, requestType(request), ciP->method.c_str()));

    if (errorMsgP)
    {
      *errorMsgP = std::string("Unable to treat ") + requestType(request) + " requests";
    }

    return errorReply;
  }


  if (reqPP != NULL)
  {
    *reqPP = reqP;
  }

  //
  // Checking that the payload matches the URL
  //
  if (((ciP->verb == POST) || (ciP->verb == PUT)) && (payloadWord.length() != 0))
  {
    std::string  errorReply;
    char*        payloadStart = (char*) content;

    // Skip '<?xml version="1.0" encoding="UTF-8"?> ' ?
    if (strncmp(payloadStart, "<?xml", 5) == 0)
    {
      ++payloadStart;
      payloadStart = strstr(payloadStart, "<");
    }

    // Skip '<'
    if (*payloadStart == '<')
    {
       ++payloadStart;
    }

    if (strncasecmp(payloadWord.c_str(), payloadStart, payloadWord.length()) != 0)
    {
      errorReply  = restErrorReplyGet(ciP,
                                      ciP->outFormat,
                                      "",
                                      reqP->keyword,
                                      SccBadRequest,
                                      std::string("Expected /") + payloadWord +
                                        "/ payload, got /" + payloadStart + "/");

      LM_W(("Bad Input (invalid  payload: wanted: '%s', got '%s')", payloadWord.c_str(), payloadStart));

      if (errorMsgP)
      {
        *errorMsgP = std::string("Bad Input (invalid payload, expecting '") +
          payloadWord + "', got '" + payloadStart + "')";
      }

      return errorReply;
    }
  }

  if (reqP->init == NULL)  // No payload treating function
  {
    return "OK";
  }

  reqP->init(parseDataP);
  ciP->httpStatusCode = SccOk;
  xmlParse(ciP, NULL, father, "", "", reqP->parseVector, parseDataP, errorMsgP);
  if (ciP->httpStatusCode != SccOk)
  {
    LM_W(("Bad Input (XML parse error)"));

    return restErrorReplyGet(ciP, ciP->outFormat, "", payloadWord, ciP->httpStatusCode, ciP->answer);
  }

  LM_T(LmtParseCheck, ("Calling check for XML parsed tree (%s)", ciP->payloadWord));
  std::string check = reqP->check(parseDataP, ciP);
  if (check != "OK")
  {
    LM_W(("Bad Input (%s: %s)", reqP->keyword.c_str(), check.c_str()));

    if (errorMsgP)
    {
      *errorMsgP = std::string("Bad Input: ") + check;
    }
  }

  reqP->present(parseDataP);

  if (check != "OK")
  {
    if (errorMsgP)
    {
      *errorMsgP = std::string("Bad Input: ") + check;
    }
  }

  return check;
}
Beispiel #8
0
/* ****************************************************************************
*
* restService -
*/
std::string restService(ConnectionInfo* ciP, RestService* serviceV)
{
    std::vector<std::string>  compV;
    int                       components;
    XmlRequest*               reqP       = NULL;
    JsonRequest*              jsonReqP   = NULL;
    ParseData                 parseData;

    if ((ciP->url.length() == 0) || ((ciP->url.length() == 1) && (ciP->url.c_str()[0] == '/')))
    {
        OrionError  error(SccBadRequest, "The Orion Context Broker is a REST service, not a 'web page'");
        std::string response = error.render(ciP->outFormat, "");

        LM_W(("Bad Input (The Orion Context Broker is a REST service, not a 'web page')"));
        restReply(ciP, response);

        return std::string("Empty URL");
    }

    ciP->httpStatusCode = SccOk;

    components = stringSplit(ciP->url, '/', compV);

    for (unsigned int ix = 0; serviceV[ix].treat != NULL; ++ix)
    {
        if ((serviceV[ix].components != 0) && (serviceV[ix].components != components))
        {
            continue;
        }

        if ((ciP->method != serviceV[ix].verb) && (serviceV[ix].verb != "*"))
        {
            continue;
        }

        strncpy(ciP->payloadWord, serviceV[ix].payloadWord.c_str(), sizeof(ciP->payloadWord));
        bool match = true;
        for (int compNo = 0; compNo < components; ++compNo)
        {
            if (serviceV[ix].compV[compNo] == "*")
            {
                continue;
            }

            if (strcasecmp(serviceV[ix].compV[compNo].c_str(), compV[compNo].c_str()) != 0)
            {
                match = false;
                break;
            }
        }

        if (match == false)
        {
            continue;
        }

        if ((ciP->payload != NULL) && (ciP->payloadSize != 0) && (ciP->payload[0] != 0) && (serviceV[ix].verb != "*"))
        {
            std::string response;

            LM_T(LmtParsedPayload, ("Parsing payload for URL '%s', method '%s', service vector index: %d", ciP->url.c_str(), ciP->method.c_str(), ix));
            ciP->parseDataP = &parseData;
            response = payloadParse(ciP, &parseData, &serviceV[ix], &reqP, &jsonReqP);
            LM_T(LmtParsedPayload, ("payloadParse returns '%s'", response.c_str()));

            if (response != "OK")
            {
                restReply(ciP, response);

                if (reqP != NULL)
                {
                    reqP->release(&parseData);
                }
                if (jsonReqP != NULL)
                {
                    jsonReqP->release(&parseData);
                }

                compV.clear();
                return response;
            }
        }

        LM_T(LmtService, ("Treating service %s %s", serviceV[ix].verb.c_str(), ciP->url.c_str())); // Sacred - used in 'heavyTest'
        statisticsUpdate(serviceV[ix].request, ciP->inFormat);

        // Tenant to connectionInfo
        ciP->tenant = ciP->tenantFromHttpHeader;

        //
        // A tenant string must not be longer than 50 characters and may only contain
        // underscores and alphanumeric characters.
        //
        std::string result;
        if ((ciP->tenant != "") && ((result = tenantCheck(ciP->tenant)) != "OK"))
        {
            OrionError  error(SccBadRequest,
                              "tenant name not accepted - a tenant string must not be longer than " MAX_TENANT_NAME_LEN_STRING " characters"
                              " and may only contain underscores and alphanumeric characters");

            std::string  response = error.render(ciP->outFormat, "");

            LM_W(("Bad Input (%s)", error.details.c_str()));
            restReply(ciP, response);

            if (reqP != NULL)
            {
                reqP->release(&parseData);
            }

            if (jsonReqP != NULL)
            {
                jsonReqP->release(&parseData);
            }

            compV.clear();

            return response;
        }

        LM_T(LmtTenant, ("tenant: '%s'", ciP->tenant.c_str()));
        commonFilters(ciP, &parseData, &serviceV[ix]);
        scopeFilter(ciP, &parseData, &serviceV[ix]);
        std::string response = serviceV[ix].treat(ciP, components, compV, &parseData);
        filterRelease(&parseData, serviceV[ix].request);

        if (reqP != NULL)
        {
            reqP->release(&parseData);
        }

        if (jsonReqP != NULL)
        {
            jsonReqP->release(&parseData);
        }

        compV.clear();

        if (response == "DIE")
        {
            orionExitFunction(0, "Received a 'DIE' request on REST interface");
        }

        restReply(ciP, response);
        return response;
    }

    LM_W(("Bad Input (service '%s' not recognized)", ciP->url.c_str()));
    ciP->httpStatusCode = SccBadRequest;
    std::string answer = restErrorReplyGet(ciP, ciP->outFormat, "", ciP->payloadWord, SccBadRequest, std::string("unrecognized request"));
    restReply(ciP, answer);

    compV.clear();
    return answer;
}