Example #1
0
bool CSettings::Load()
{
	//! Reset default path variables to the right device
	SetDefault();


	std::string filepath = configPath;
	filepath += "/loadiine_gx2.cfg";

	CFile file(filepath, CFile::ReadOnly);
	if (!file.isOpen())
        return false;

    std::string strBuffer;
    strBuffer.resize(file.size());
    file.read((u8 *) &strBuffer[0], strBuffer.size());
    file.close();

    //! remove all windows crap signs
    size_t position;
    while(1)
    {
        position = strBuffer.find('\r');
        if(position == std::string::npos)
            break;

        strBuffer.erase(position, 1);
    }

	std::vector<std::string> lines = stringSplit(strBuffer, "\n");


	if(lines.empty() || !ValidVersion(lines[0]))
		return false;

	for(u32 i = 0; i < lines.size(); ++i)
    {
        std::vector<std::string> valueSplit = stringSplit(lines[i], "=");
        if(valueSplit.size() != 2)
            continue;

        while((valueSplit[0].size() > 0) && valueSplit[0][0] == ' ')
            valueSplit[0].erase(0, 1);

        while((valueSplit[1].size() > 0) && valueSplit[1][ valueSplit[1].size() - 1 ] == ' ')
            valueSplit[1].resize(valueSplit[1].size() - 1);

        for(u32 n = 0; n < settingsNames.size(); n++)
        {
            if(!settingsNames[n])
                continue;

            if(valueSplit[0] == settingsNames[n])
            {
                switch(settingsValues[n].dataType)
                {
                    case TypeBool:
                        settingsValues[n].bValue = atoi(valueSplit[1].c_str());
                        break;
                    case TypeS8:
                        settingsValues[n].cValue = atoi(valueSplit[1].c_str());
                        break;
                    case TypeU8:
                        settingsValues[n].ucValue = atoi(valueSplit[1].c_str());
                        break;
                    case TypeS16:
                        settingsValues[n].sValue = atoi(valueSplit[1].c_str());
                        break;
                    case TypeU16:
                        settingsValues[n].usValue = atoi(valueSplit[1].c_str());
                        break;
                    case TypeS32:
                        settingsValues[n].iValue = atoi(valueSplit[1].c_str());
                        break;
                    case TypeU32:
                        settingsValues[n].uiValue = strtoul(valueSplit[1].c_str(), 0, 10);
                        break;
                    case TypeF32:
                        settingsValues[n].fValue = atof(valueSplit[1].c_str());
                        break;
                    case TypeString:
                        if(settingsValues[n].strValue == NULL)
                            settingsValues[n].strValue = new std::string();

                        *settingsValues[n].strValue = valueSplit[1];
                        break;
                    default:
                        break;
                }
            }
        }
    }

	return true;
}
Example #2
0
bool CSettingsGame::Load()
{
	std::string filepath = configPath;
	filepath += "/" +this->filename;

	CFile file(filepath, CFile::ReadOnly);
	if (!file.isOpen())
        return false;

    std::string strBuffer;
    strBuffer.resize(file.size());
    file.read((u8 *) &strBuffer[0], strBuffer.size());
    file.close();

    //! remove all windows crap signs
    size_t position;
    while(1)
    {
        position = strBuffer.find('\r');
        if(position == std::string::npos)
            break;

        strBuffer.erase(position, 1);
    }

	std::vector<std::string> lines_ = stringSplit(strBuffer, "\n");
	if(lines_.empty() || !ValidVersion(lines_[0]))
		return false;

	for(u32 j = 1; j < lines_.size(); ++j){
		std::vector<std::string> lines = stringSplit(lines_[j], ";");

		if(lines.empty())
			return false;

		std::string ID6 = lines[0];

		std::vector<CSettingsGame::SettingValue> newValues = getSettingValuesFromGameSettings(std::string(COMMON_UPDATE_PATH), false, GAME_SAVES_DEFAULT, LOADIINE_MODE_DEFAULT, SETTING_OFF);

		for(u32 i = 1; i < lines.size(); ++i)
		{
			std::vector<std::string> valueSplit = stringSplit(lines[i], "=");
			if(valueSplit.size() != 2)
				continue;

			while((valueSplit[0].size() > 0) && valueSplit[0][0] == ' ')
				valueSplit[0].erase(0, 1);

			while((valueSplit[1].size() > 0) && valueSplit[1][ valueSplit[1].size() - 1 ] == ' ')
				valueSplit[1].resize(valueSplit[1].size() - 1);

			for(u32 n = 0; n < settingsNames.size(); n++)
			{
				if(!settingsNames[n])
					continue;

				if(valueSplit[0] == settingsNames[n])
				{
					switch(newValues.at(n).dataType)
					{
						case TypeBool:
							newValues.at(n).bValue = atoi(valueSplit[1].c_str());
							break;
						case TypeS8:
							newValues.at(n).cValue = atoi(valueSplit[1].c_str());
							break;
						case TypeU8:
							newValues.at(n).ucValue = atoi(valueSplit[1].c_str());
							break;
						case TypeS16:
							newValues.at(n).sValue = atoi(valueSplit[1].c_str());
							break;
						case TypeU16:
							newValues.at(n).usValue = atoi(valueSplit[1].c_str());
							break;
						case TypeS32:
							newValues.at(n).iValue = atoi(valueSplit[1].c_str());
							break;
						case TypeU32:
							newValues.at(n).uiValue = strtoul(valueSplit[1].c_str(), 0, 10);
							break;
						case TypeF32:
							newValues.at(n).fValue = atof(valueSplit[1].c_str());
							break;
						case TypeString:
							if(newValues.at(n).strValue == NULL)
								newValues.at(n).strValue = new std::string();
							*newValues.at(n).strValue = valueSplit[1];
							break;
						default:
							break;
					}

				}
			}
		}
		GameSettings * set = GetGameSettingsBySettingGameValue(ID6,newValues);

		//Clean pointer
		for(u32 j = 0; j < newValues.size(); j++){
			if(newValues.at(j).dataType == TypeString)
				delete newValues.at(j).strValue;
		}

		settingsGames[ID6] = *set;
		delete set;
	}

	return true;
}
Example #3
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;
}
Example #4
0
/* ****************************************************************************
*
* servicePathCheck - check vector of service paths
*
* This function is called for ALL requests, when a service-path URI-parameter is found.
* So, '#' is considered a valid character at it is valid for discoveries and queries.
* Later on, if the request is a registration or notification, another function is called
* to make sure there is only ONE service path and that there is no '#' present.
*
* FIXME P5: updates should also call the other servicePathCheck (in common lib)
*
* [ Not static just to let unit tests call this function ]
*/
int servicePathCheck(ConnectionInfo* ciP, const char* servicePath)
{
  //
  // 1. Max 10 paths  - ONLY ONE path allowed at this moment
  // 2. Max 10 levels in each path
  // 3. Max 50 characters in each path component
  // 4. Only alphanum and underscore allowed (just like in tenants)
  //    OR: Last component is EXACTLY '#'
  //
  std::vector<std::string> compV;
  int                      components;


  if (ciP->httpHeaders.servicePathReceived == false)
    return 0;

  if (servicePath[0] != '/')
  {
    OrionError e(SccBadRequest, "Only /absolute/ Service Paths allowed [a service path must begin with /]");
    ciP->answer = e.render(ciP->outFormat, "");
    return 1;
  }

  components = stringSplit(servicePath, '/', compV);

  if (components > 10)
  {
    OrionError e(SccBadRequest, "too many components in ServicePath");
    ciP->answer = e.render(ciP->outFormat, "");
    return 2;
  }

  for (int ix = 0; ix < components; ++ix)
  {
    if (strlen(compV[ix].c_str()) > 50)
    {
      OrionError e(SccBadRequest, "component-name too long in ServicePath");
      ciP->answer = e.render(ciP->outFormat, "");
      return 3;
    }

    // Last token in the path is allowed to be *exactly* "#", as in /Madrid/Gardens/#. Note that
    // /Madrid/Gardens/North# is not allowed
    if ((ix == components - 1) && (compV[ix] == "#"))
    {
        continue;
    }

    const char* comp = compV[ix].c_str();      

    for (unsigned int cIx = 0; cIx < strlen(comp); ++cIx)
    {
      if (!isalnum(comp[cIx]) && (comp[cIx] != '_'))
      {
        OrionError e(SccBadRequest, "a component of ServicePath contains an illegal character");
        ciP->answer = e.render(ciP->outFormat, "");
        return 4;
      }
    }
  }

  return 0;
}
/* ****************************************************************************
*
* getEntity -
*
* GET /v2/entities/:id:[?attrs=:list:]
*
* Payload In:  None
* Payload Out: Entity
*
*
* Fill in QueryContextRequest
* Call standard op postQueryContext
* Render Entity response
* Cleanup and return result
*/
std::string getEntity
(
  ConnectionInfo*            ciP,
  int                        components,
  std::vector<std::string>&  compV,
  ParseData*                 parseDataP
)
{
   std::string attrs  = ciP->uriParam["attrs"];
   std::string type   = ciP->uriParam["type"];

   if (forbiddenIdChars(ciP->apiVersion, compV[2].c_str() , NULL))
   {
     OrionError oe(SccBadRequest, INVAL_CHAR_URI);
     return oe.render(ciP, "");
   }

  // Fill in QueryContextRequest
  parseDataP->qcr.res.fill(compV[2], type, "false", EntityTypeEmptyOrNotEmpty, "");

  if (attrs != "")
  {
    std::vector<std::string> attrsV;

    stringSplit(attrs, ',', attrsV);
    for (std::vector<std::string>::const_iterator it = attrsV.begin(); it != attrsV.end(); ++it)
    {
      parseDataP->qcr.res.attributeList.push_back_if_absent(*it);
    }
  }

  // Call standard op postQueryContext
  postQueryContext(ciP, components, compV, parseDataP);


  // Render entity response
  Entity       entity;

  // If request was for /entities/<<id>>/attrs, type and id should not be shown
  if (compV.size() == 4 && compV[3] == "attrs")
  {
    entity.hideIdAndType();
  }

  entity.fill(&parseDataP->qcrs.res);

  std::string answer;
  TIMED_RENDER(answer = entity.render(ciP, EntityResponse));

  if (parseDataP->qcrs.res.errorCode.code == SccOk && parseDataP->qcrs.res.contextElementResponseVector.size() > 1)
  {
      // No problem found, but we expect only one entity
      ciP->httpStatusCode = SccConflict;
  }
  else
  {
      // the same of the wrapped operation
      ciP->httpStatusCode = parseDataP->qcrs.res.errorCode.code;
  }

  // 04. Cleanup and return result
  entity.release();
  parseDataP->qcr.res.release();

  return answer;
}
Example #6
0
SettingsMenu::SettingsMenu(int w, int h)
    : GuiFrame(w, h)
    , categorySelectionFrame(w, h)
    , particleBgImage(w, h, 50)
    , buttonClickSound(Resources::GetSound("settings_click_2.mp3"))
    , quitImageData(Resources::GetImageData("quitButton.png"))
    , categoryImageData(Resources::GetImageData("settingsCategoryButton.png"))
    , categoryBgImageData(Resources::GetImageData("settingsCategoryBg.png"))
    , quitImage(quitImageData)
    , quitButton(quitImage.getWidth(), quitImage.getHeight())
    , touchTrigger(GuiTrigger::CHANNEL_1, GuiTrigger::VPAD_TOUCH)
    , wpadTouchTrigger(GuiTrigger::CHANNEL_2 | GuiTrigger::CHANNEL_3 | GuiTrigger::CHANNEL_4 | GuiTrigger::CHANNEL_5, GuiTrigger::BUTTON_A)
    , buttonATrigger(GuiTrigger::CHANNEL_ALL, GuiTrigger::BUTTON_A, true)
    , buttonBTrigger(GuiTrigger::CHANNEL_ALL, GuiTrigger::BUTTON_B, true)
    , buttonLTrigger(GuiTrigger::CHANNEL_ALL, GuiTrigger::BUTTON_L, true)
    , buttonRTrigger(GuiTrigger::CHANNEL_ALL, GuiTrigger::BUTTON_R, true)
    , buttonLeftTrigger(GuiTrigger::CHANNEL_ALL, GuiTrigger::BUTTON_LEFT | GuiTrigger::STICK_L_LEFT, true)
    , buttonRightTrigger(GuiTrigger::CHANNEL_ALL, GuiTrigger::BUTTON_RIGHT | GuiTrigger::STICK_L_RIGHT, true)
    , leftArrowImageData(Resources::GetImageData("leftArrow.png"))
    , rightArrowImageData(Resources::GetImageData("rightArrow.png"))
    , leftArrowImage(leftArrowImageData)
    , rightArrowImage(rightArrowImageData)
    , leftArrowButton(leftArrowImage.getWidth(), leftArrowImage.getHeight())
    , rightArrowButton(rightArrowImage.getWidth(), rightArrowImage.getHeight())
    , DPADButtons(w,h)
{
    currentPosition = 0;
    targetPosition = 0;
    selectedCategory = 0;
    animationSpeed = 25;
    bUpdatePositions = true;

    quitButton.setImage(&quitImage);
    quitButton.setAlignment(ALIGN_BOTTOM | ALIGN_LEFT);
    quitButton.clicked.connect(this, &SettingsMenu::OnQuitButtonClick);
    quitButton.setTrigger(&touchTrigger);
    quitButton.setTrigger(&wpadTouchTrigger);
    quitButton.setEffectGrow();
    quitButton.setSoundClick(buttonClickSound);
    categorySelectionFrame.append(&quitButton);

    versionText.setColor(glm::vec4(0.6f, 0.6f, 0.6f, 1.0f));
    versionText.setFontSize(42);
    versionText.setAlignment(ALIGN_TOP | ALIGN_RIGHT);
    versionText.setPosition(-50, -80);
    versionText.setText("Loadiine GX2 " LOADIINE_VERSION);
    categorySelectionFrame.append(&versionText);

    const u32 cuCategoriesCount = sizeof(stSettingsCategories) / sizeof(stSettingsCategories[0]);

    if(cuCategoriesCount > 0) selectedCategory = 0;

    for(u32 idx = 0; idx < cuCategoriesCount; idx++)
    {
        settingsCategories.resize(idx + 1);
        GuiSettingsCategory & category = settingsCategories[idx];

        std::vector<std::string> splitDescriptions = stringSplit(stSettingsCategories[idx].descriptions, "\n");

        category.categoryIconData = Resources::GetImageData(stSettingsCategories[idx].icon);
        category.categoryIconGlowData = Resources::GetImageData(stSettingsCategories[idx].iconGlow);

        category.categoryLabel = new GuiText(tr(stSettingsCategories[idx].name), 46, glm::vec4(0.8f, 0.8f, 0.8f, 1.0f));
        category.categoryLabel->setPosition(0, -120);

        category.categoryBgImage = new GuiImage(categoryBgImageData);
        category.categoryImages = new GuiImage(categoryImageData);
        category.categoryIcon = new GuiImage(category.categoryIconData);
        category.categoryIconGlow = new GuiImage(category.categoryIconGlowData);
        category.categoryButton = new GuiButton(category.categoryImages->getWidth(), category.categoryImages->getHeight());

        category.categoryIcon->setPosition(0, 40);
        category.categoryIconGlow->setPosition(0, 40);

        category.categoryButton->setLabel(category.categoryLabel);
        category.categoryButton->setImage(category.categoryImages);
        category.categoryButton->setPosition(-300, 0);
        category.categoryButton->setIcon(category.categoryIcon);
        category.categoryButton->setIconOver(category.categoryIconGlow);
        category.categoryButton->setTrigger(&touchTrigger);
        category.categoryButton->setTrigger(&wpadTouchTrigger);
        category.categoryButton->setSoundClick(buttonClickSound);
        category.categoryButton->setEffectGrow();
        category.categoryButton->clicked.connect(this, &SettingsMenu::OnCategoryClick);

        categorySelectionFrame.append(category.categoryBgImage);
        categorySelectionFrame.append(category.categoryButton);

        category.categoryButton->setParent(category.categoryBgImage);
        category.categoryBgImage->setPosition(currentPosition + (category.categoryBgImage->getWidth() + 40) * idx, 0);

        for(u32 n = 0; n < splitDescriptions.size(); n++)
        {
            GuiText * descr = new GuiText(tr(splitDescriptions[n].c_str()), 46, glm::vec4(0.8f, 0.8f, 0.8f, 1.0f));
            descr->setAlignment(ALIGN_MIDDLE | ALIGN_LEFT);
            descr->setPosition(category.categoryBgImage->getWidth() * 0.5f - 50.0f, category.categoryBgImage->getHeight() * 0.5f - 100.0f - n * 60.0f);
            categorySelectionFrame.append(descr);
            descr->setParent(category.categoryBgImage);
            category.descriptions.push_back(descr);
        }

        GuiImage *smallIconOver = new GuiImage(category.categoryIconGlowData);
        GuiImage *smallIcon = new GuiImage(category.categoryIconData);
        GuiButton *smallIconButton = new GuiButton(smallIcon->getWidth() * smallIconScale, smallIcon->getHeight() * smallIconScale);
        smallIcon->setScale(smallIconScale);
        smallIconOver->setScale(smallIconScale);
        smallIconButton->setImage(smallIcon);
        smallIconButton->setEffectGrow();
        smallIconButton->setTrigger(&touchTrigger);
        smallIconButton->setTrigger(&wpadTouchTrigger);
        smallIconButton->setSoundClick(buttonClickSound);
        smallIconButton->clicked.connect(this, &SettingsMenu::OnSmallIconClick);
        categorySelectionFrame.append(smallIconButton);

        categorySmallImages.push_back(smallIcon);
        categorySmallImagesOver.push_back(smallIconOver);
        categorySmallButtons.push_back(smallIconButton);
    }

    leftArrowButton.setImage(&leftArrowImage);
    leftArrowButton.setEffectGrow();
    leftArrowButton.setPosition(40, 0);
    leftArrowButton.setAlignment(ALIGN_LEFT | ALIGN_MIDDLE);
    leftArrowButton.setTrigger(&touchTrigger);
    leftArrowButton.setTrigger(&wpadTouchTrigger);

    leftArrowButton.setSoundClick(buttonClickSound);
    leftArrowButton.clicked.connect(this, &SettingsMenu::OnCategoryLeftClick);
    categorySelectionFrame.append(&leftArrowButton);

    rightArrowButton.setImage(&rightArrowImage);
    rightArrowButton.setEffectGrow();
    rightArrowButton.setPosition(-40, 0);
    rightArrowButton.setAlignment(ALIGN_RIGHT | ALIGN_MIDDLE);
    rightArrowButton.setTrigger(&touchTrigger);
    rightArrowButton.setTrigger(&wpadTouchTrigger);
    rightArrowButton.setSoundClick(buttonClickSound);
    rightArrowButton.clicked.connect(this, &SettingsMenu::OnCategoryRightClick);
    categorySelectionFrame.append(&rightArrowButton);

    DPADButtons.setTrigger(&buttonATrigger);
    DPADButtons.setTrigger(&buttonBTrigger);
    DPADButtons.setTrigger(&buttonLTrigger);
    DPADButtons.setTrigger(&buttonRTrigger);
    DPADButtons.setTrigger(&buttonLeftTrigger);
    DPADButtons.setTrigger(&buttonRightTrigger);
    DPADButtons.clicked.connect(this, &SettingsMenu::OnDPADClick);
    append(&DPADButtons);
	categorySelectionFrame.append(&DPADButtons);
    setTargetPosition(0);
    moving = false;

    //! the particle BG is always appended in all sub menus
    append(&particleBgImage);
    append(&categorySelectionFrame);
}
call_stack::call_stack(const size_t /*num_discard = 0*/) {
    // getting a stack trace on Windows / MinGW is loads of fun (not)
    std::vector<void*> traceVector;
    HANDLE process = GetCurrentProcess();
    HANDLE thread = GetCurrentThread();

    void* fakeStackPtr = stacktrace::getFakeCallStackPointer();
    if (fakeStackPtr) {
        // set up fake stack for partial trace
        LPEXCEPTION_POINTERS exceptionInfo = (LPEXCEPTION_POINTERS) fakeStackPtr;
        if (exceptionInfo->ExceptionRecord->ExceptionCode == EXCEPTION_STACK_OVERFLOW) {
            // can't do stack walking in Windows when a stack overflow happens :-/
            traceVector.push_back((void*) exceptionInfo->ContextRecord->Eip);
        } else {
            SymInitialize(GetCurrentProcess(), 0, TRUE);
            STACKFRAME frame = {0};
            frame.AddrPC.Offset    = exceptionInfo->ContextRecord->Eip;
            frame.AddrPC.Mode      = AddrModeFlat;
            frame.AddrStack.Offset = exceptionInfo->ContextRecord->Esp;
            frame.AddrStack.Mode   = AddrModeFlat;
            frame.AddrFrame.Offset = exceptionInfo->ContextRecord->Ebp;
            frame.AddrFrame.Mode   = AddrModeFlat;
            while ((int) traceVector.size() < WIN_STACK_FRAMES_MAX &&
                   StackWalk(IMAGE_FILE_MACHINE_I386,
                             process,
                             thread,
                             &frame,
                             exceptionInfo->ContextRecord,
                             0,
                             SymFunctionTableAccess,
                             SymGetModuleBase,
                             0)) {
                traceVector.push_back((void*) frame.AddrPC.Offset);
            }
        }
    } else {
        if (!::SymSetOptions(
                             // ::SymGetOptions()
                               SYMOPT_DEBUG
                             | SYMOPT_DEFERRED_LOADS
                             | SYMOPT_INCLUDE_32BIT_MODULES
                             // | SYMOPT_UNDNAME
                             | SYMOPT_CASE_INSENSITIVE
                             | SYMOPT_LOAD_LINES)) {
            // std::cout << "SymSetOptions failed!" << std::endl;
            // return;
        }
        if (!::SymInitialize(
                /* process */ process,
                /* user-defined search path */ NULL,
                /* include current process */ TRUE)) {
            // std::cout << "SymInitialize failed!" << std::endl;
            // return;
        }

        void* trace[WIN_STACK_FRAMES_MAX];
        USHORT frameCount = ::CaptureStackBackTrace(
                    /* framesToSkip */ WIN_STACK_FRAMES_TO_SKIP,
                    /* framesToCapture; must be < 63 */ WIN_STACK_FRAMES_MAX,
                    trace,
                    /* hash */ NULL
                    );
        for (int i = 0; i < frameCount; i++) {
            traceVector.push_back(trace[i]);
        }

        // try to load module symbol information; this always fails for me  :-/
        DWORD64 BaseAddr = 0;
        DWORD   FileSize = 0;
        const char* progFileC = exceptions::getProgramNameForStackTrace().c_str();
        char* progFile = (char*) progFileC;
        if (!::SymLoadModule(
                process,      // Process handle of the current process
                NULL,         // Handle to the module's image file (not needed)
                progFile,     // Path/name of the file
                NULL,         // User-defined short name of the module (it can be NULL)
                BaseAddr,     // Base address of the module (cannot be NULL if .PDB file is used, otherwise it can be NULL)
                FileSize)) {      // Size of the file (cannot be NULL if .PDB file is used, otherwise it can be NULL)
            // std::cout << "Error: SymLoadModule() failed: " << pp->os_getLastError() << std::endl;
            // return;
        }
    }

    // let's also try to get the line numbers via an external command-line process 'addr2line'
    // (ought to be able to get this information through C function 'backtrace', but for some
    // reason, Qt Creator's shipped version of MinGW does not include this functionality, argh)
    std::string addr2lineOutput;
    std::vector<std::string> addr2lineLines;
    if (!traceVector.empty()) {
        int result = addr2line_all(traceVector, addr2lineOutput);
        if (result == 0) {
            addr2lineLines = stringSplit(addr2lineOutput, "\n");
        }
    }

    SYMBOL_INFO* symbol = (SYMBOL_INFO*) calloc(sizeof(SYMBOL_INFO) + 1024 * sizeof(char), 1);
    symbol->MaxNameLen   = 1020;
    symbol->SizeOfStruct = sizeof(SYMBOL_INFO);
    for (int i = 0; i < (int) traceVector.size(); ++i) {
        entry ent;
        ent.address = traceVector[i];
        if (process && ::SymFromAddr(process, (DWORD64) traceVector[i], 0, symbol)) {
            ent.function = symbol->Name;
        }
        // internal stuff failed, so load from external process
        if (i < addr2lineLines.size()) {
            injectAddr2lineInfo(ent, addr2line_clean(addr2lineLines[i]));
        } else {
            injectAddr2lineInfo(ent, "");
        }

        if (!ent.function.empty() || ent.line > 0) {
            stack.push_back(ent);
        }
    }
    free(symbol);
}
/* ****************************************************************************
*
* mongoConnect -
*
* Default value for writeConcern == 1 (0: unacknowledged, 1: acknowledged)
*/
static DBClientBase* mongoConnect
(
    const char*  host,
    const char*  db,
    const char*  rplSet,
    const char*  username,
    const char*  passwd,
    bool         multitenant,
    int          writeConcern,
    double       timeout
)
{
    std::string   err;
    DBClientBase* connection = NULL;

    LM_T(LmtMongo, ("Connection info: dbName='%s', rplSet='%s', timeout=%f", db, rplSet, timeout));

    bool connected     = false;
    int  retries       = RECONNECT_RETRIES;

    if (strlen(rplSet) == 0)
    {
        /* Setting the first argument to true is to use autoreconnect */
        connection = new DBClientConnection(true);

        /* Not sure of how to generalize the following code, given that DBClientBase class doesn't have a common connect() method (surprisingly) */
        for (int tryNo = 0; tryNo < retries; ++tryNo)
        {
            if ( ((DBClientConnection*)connection)->connect(host, err))
            {
                connected = true;
                break;
            }

            if (tryNo == 0)
            {
                LM_E(("Database Startup Error (cannot connect to mongo - doing %d retries with a %d microsecond interval)", retries, RECONNECT_DELAY));
            }
            else
            {
                LM_T(LmtMongo, ("Try %d connecting to mongo failed", tryNo));
            }

            usleep(RECONNECT_DELAY * 1000); // usleep accepts microseconds
        }
    }
    else
    {
        LM_T(LmtMongo, ("Using replica set %s", rplSet));

        // autoReconnect is always on for DBClientReplicaSet connections.
        std::vector<std::string>  hostTokens;
        int components = stringSplit(host, ',', hostTokens);

        std::vector<HostAndPort> rplSetHosts;
        for (int ix = 0; ix < components; ix++)
        {
            LM_T(LmtMongo, ("rplSet host <%s>", hostTokens[ix].c_str()));
            rplSetHosts.push_back(HostAndPort(hostTokens[ix]));
        }

        connection = new DBClientReplicaSet(rplSet, rplSetHosts, timeout);

        /* Not sure of to generalize the following code, given that DBClientBase class hasn't a common connect() method (surprisingly) */
        for (int tryNo = 0; tryNo < retries; ++tryNo)
        {
            if ( ((DBClientReplicaSet*)connection)->connect())
            {
                connected = true;
                break;
            }

            if (tryNo == 0)
            {
                LM_E(("Database Startup Error (cannot connect to mongo - doing %d retries with a %d microsecond interval)", retries, RECONNECT_DELAY));
            }
            else
            {
                LM_T(LmtMongo, ("Try %d connecting to mongo failed", tryNo));
            }

            usleep(RECONNECT_DELAY * 1000); // usleep accepts microseconds
        }
    }

    if (connected == false)
    {
        LM_E(("Database Error (connection failed, after %d retries: '%s')", retries, err.c_str()));
        return NULL;
    }

    LM_I(("Successful connection to database"));

    //
    // WriteConcern
    //
    mongo::WriteConcern writeConcernCheck;

    // In legacy driver writeConcern is no longer an int, but a class. We need a small
    // conversion step here
    mongo::WriteConcern wc = writeConcern == 1 ? mongo::WriteConcern::acknowledged : mongo::WriteConcern::unacknowledged;

    connection->setWriteConcern((mongo::WriteConcern) wc);
    writeConcernCheck = (mongo::WriteConcern) connection->getWriteConcern();

    if (writeConcernCheck.nodes() != wc.nodes())
    {
        LM_E(("Database Error (Write Concern not set as desired)"));
        return NULL;
    }
    LM_T(LmtMongo, ("Active DB Write Concern mode: %d", writeConcern));

    /* Authentication is different depending if multiservice is used or not. In the case of not
     * using multiservice, we authenticate in the single-service database. In the case of using
     * multiservice, it isn't a default database that we know at contextBroker start time (when
     * this connection function is invoked) so we authenticate on the admin database, which provides
     * access to any database */
    if (multitenant)
    {
        if (strlen(username) != 0 && strlen(passwd) != 0)
        {
            if (!connection->auth("admin", std::string(username), std::string(passwd), err))
            {
                LM_E(("Database Startup Error (authentication: db='admin', username='******', password='******': %s)", username, err.c_str()));
                return NULL;
            }
        }
    }
    else
    {
        if (strlen(db) != 0 && strlen(username) != 0 && strlen(passwd) != 0)
        {
            if (!connection->auth(std::string(db), std::string(username), std::string(passwd), err))
            {
                LM_E(("Database Startup Error (authentication: db='%s', username='******', password='******': %s)", db, username, err.c_str()));
                return NULL;
            }
        }
    }

    /* Get mongo version with the 'buildinfo' command */
    BSONObj result;
    std::string extra;
    connection->runCommand("admin", BSON("buildinfo" << 1), result);
    std::string versionString = std::string(result.getStringField("version"));
    if (!versionParse(versionString, mongoVersionMayor, mongoVersionMinor, extra))
    {
        LM_E(("Database Startup Error (invalid version format: %s)", versionString.c_str()));
        return NULL;
    }
    LM_T(LmtMongo, ("mongo version server: %s (mayor: %d, minor: %d, extra: %s)", versionString.c_str(), mongoVersionMayor, mongoVersionMinor, extra.c_str()));

    return connection;
}
Example #9
0
/* ****************************************************************************
*
* parseUrl -
*
* Breaks an URL into pieces. It returns false if the string passed as first
* argument is not a valid URL. Otherwise, it returns true.
*
*/
bool parseUrl(std::string url, std::string& host, int& port, std::string& path)
{

    /* Sanity check */
    if (url == "") {
        return false;
    }

    /* First: split by the first '/' to get host:ip and path */
    std::vector<std::string>  urlTokens;
    int                       components = stringSplit(url, '/', urlTokens);

    /* http://some.host.com/my/path
     *      ^^             ^  ^
     *      ||             |  |
     * -----  ------------- -- ----
     *   0          2       3    4  position in urlTokens vector
     *   1  23             4  5     coponentes
     */

    if ((components < 3) || (components == 3 && urlTokens[2].length() == 0)) {
        return false;
    }

    path = "";
    /* Note that components could be 3, in which case we don't enter in the for. This is
     * the case of URL without '/' like eg. "http://www.google.com" */
    for (int ix = 3; ix < components; ++ix ) {
        path += "/" + urlTokens[ix];
    }
    if (path == "") {
        /* Minimum path is always "/" */
        path = "/";
    }

    /* Second: split third token for host and port */

    std::string  auxIp;
    std::string  auxPort;

    // First we check if it is IPv6
    if (getIPv6Port(urlTokens[2], auxIp, auxPort))  
    {
      // IPv6
      host = auxIp;
      port = atoi(auxPort.c_str());
      LM_VVV(("Parsed IPv6: '%s' and port: '%d'", host.c_str(), port));
    }
    else
    {
      // IPv4
      std::vector<std::string>  hostTokens;
      components = stringSplit(urlTokens[2], ':', hostTokens);

      /* some.host.com:8080
       *              ^
       *              |
       * ------------- ----
       *   0             1  position in urlTokens vector
       * 1            2     components
       */

      /* Sanity check */
      if (components > 2) {
          return false;
      }

      host = hostTokens[0];

      if (components == 2) {
          port = atoi(hostTokens[1].c_str());
      }
      else {
        port = DEFAULT_HTTP_PORT;
      }
    }

    return true;

}
 CompletionType evaluate()
 {
     Register<Value> value;
     switch (method)
     {
     case ToString:
     case ValueOf:
         if (!getThis()->isObject())
         {
             throw getErrorInstance("TypeError");
         }
         value = static_cast<ObjectValue*>(getThis())->getValueProperty();
         if (!value->isString())
         {
             throw getErrorInstance("TypeError");
         }
         break;
     case CharAt:
         value = charAt();
         break;
     case CharCodeAt:
         value = charCodeAt();
         break;
     case Concat:
         value = concat(getThis());
         break;
     case IndexOf:
         value = indexOf(getThis());
         break;
     case LastIndexOf:
         value = lastIndexOf(getThis());
         break;
     case LocaleCompare:
         value = localeCompare(getThis());
         break;
     case Match:
         value = stringMatch();
         break;
     case Replace:
         value = stringReplace();
         break;
     case Search:
         value = stringSearch();
         break;
     case Slice:
         value = slice(getThis());
         break;
     case Split:
         value = stringSplit();
         break;
     case Substring:
         value = substring(getThis());
         break;
     case Substr:
         value = substr(getThis());
         break;
     case ToLowerCase:
     case ToLocaleLowerCase:
         value = toLowerCase(getThis());
         break;
     case ToUpperCase:
     case ToLocaleUpperCase:
         value = toUpperCase(getThis());
         break;
     }
     return CompletionType(CompletionType::Return, value, "");
 }
/* ****************************************************************************
*
* getEntities - 
*
* GET /v2/entities
*
* Payload In:  None
* Payload Out: Entities
*
* URI parameters:
*   - limit=NUMBER
*   - offset=NUMBER
*   - count=true/false
*   - id
*   - idPattern
*   - q
*   - geometry
*   - coords
*
* 01. Fill in QueryContextRequest
* 02. Call standard op postQueryContext
* 03. Render Entities response
* 04. Cleanup and return result
*/
std::string getEntities
(
  ConnectionInfo*            ciP,
  int                        components,
  std::vector<std::string>&  compV,
  ParseData*                 parseDataP
)
{
  Entities     entities;
  std::string  answer;
  std::string  pattern    = ".*"; // all entities, default value
  std::string  id         = ciP->uriParam["id"];
  std::string  idPattern  = ciP->uriParam["idPattern"];
  std::string  q          = ciP->uriParam["q"];
  std::string  geometry   = ciP->uriParam["geometry"];
  std::string  coords     = ciP->uriParam["coords"];
  std::string  out;

  if ((idPattern != "") && (id != ""))
  {
    OrionError oe(SccBadRequest, "Incompatible parameters: id, IdPattern");

    TIMED_RENDER(answer = oe.render(ciP, ""));
    return answer;
  }
  else if (id != "")
  {
    // FIXME: a more efficient query could be possible ...
    std::vector<std::string> idsV;

    stringSplit(id, ',', idsV);

    for (unsigned int ix = 0; ix != idsV.size(); ++ix)
    {
      if (ix != 0)
      {
        pattern += "|";
      }

      pattern += idsV[ix];
    }
  }
  else if (idPattern != "")
  {
    pattern = idPattern;
  }


  // Making sure geometry and coords are not used individually
  if ((coords != "") && (geometry == ""))
  {
    OrionError   oe(SccBadRequest, "URI param /coords/ used without /geometry/");

    TIMED_RENDER(out = oe.render(ciP, ""));
    return out;
  }
  else if ((geometry != "") && (coords == ""))
  {
    OrionError oe(SccBadRequest, "URI param /geometry/ used without /coords/");

    TIMED_RENDER(out = oe.render(ciP, ""));

    return out;
  }

  // Making sure geometry is valid (if present)
  orion::Geometry           geo;
  std::vector<std::string>  coordsV;

  if (geometry != "")
  {
    std::string  errorString;

    if (geo.parse(geometry.c_str(), &errorString) != 0)
    {
      OrionError oe(SccBadRequest, std::string("error parsing geometry: ") + errorString);

      TIMED_RENDER(out = oe.render(ciP, ""));

      return out;
    }

    if ((geo.areaType != "polygon") && (geo.areaType != "circle"))
    {
      OrionError oe(SccBadRequest, "URI param /geometry/ must be either /polygon/ or /circle/");

      TIMED_RENDER(out = oe.render(ciP, ""));

      return out;
    }

    //
    // As 'geometry' is present, so is 'coords' - checking coords
    //
    int noOfCoords = stringSplit(coords, ';', coordsV);

    if (noOfCoords == 0)
    {
      OrionError oe(SccBadRequest, "URI param /coords/ has no coordinates");

      TIMED_RENDER(out = oe.render(ciP, ""));

      return out;
    }

    if ((geo.areaType == "circle") && (noOfCoords != 1))
    {
      OrionError oe(SccBadRequest, "Too many coordinates for circle");

      TIMED_RENDER(out = oe.render(ciP, ""));

      return out;
    }

    if ((geo.areaType == "polygon") && (noOfCoords < 3))
    {
      OrionError oe(SccBadRequest, "Too few coordinates for polygon");

      TIMED_RENDER(out = oe.render(ciP, ""));

      return out;
    }
  }


  //
  // 01. Fill in QueryContextRequest - type "" is valid for all types
  //
  parseDataP->qcr.res.fill(pattern, ciP->uriParam["type"], "true", EntityTypeEmptyOrNotEmpty, "");

  // If URI param 'q' is given, its value must be put in a scope
  if (q != "")
  {
    Scope* scopeP = new Scope(SCOPE_TYPE_SIMPLE_QUERY, q);

    parseDataP->qcr.res.restriction.scopeVector.push_back(scopeP);
  }


  // If URI params 'geometry' and 'coords' are given, another scope is to be created for this
  if ((coords != "") && (geometry != ""))
  {
    Scope*       scopeP = new Scope(SCOPE_TYPE_LOCATION, "");
    std::string  errorString;

    if (scopeP->fill(&geo, coordsV, &errorString) != 0)
    {
      OrionError oe(SccBadRequest, errorString);

      TIMED_RENDER(out = oe.render(ciP, ""));

      return out;
    }

    parseDataP->qcr.res.restriction.scopeVector.push_back(scopeP);
  }


  // 02. Call standard op postQueryContext
  answer = postQueryContext(ciP, components, compV, parseDataP);

  if (ciP->httpStatusCode != SccOk)
  {
    // Something went wrong in the query, an invalid pattern for example

    parseDataP->qcr.res.release();

    return answer;
  }

  // 03. Render Entities response
  if (parseDataP->qcrs.res.contextElementResponseVector.size() == 0)
  {
    ciP->httpStatusCode = SccOk;
    answer = "[]";
  }
  else
  {
    entities.fill(&parseDataP->qcrs.res);

    TIMED_RENDER(answer = entities.render(ciP, EntitiesResponse));
  }

  // 04. Cleanup and return result
  entities.release();
  parseDataP->qcr.res.release();

  return answer;
}
Example #12
0
/* ****************************************************************************
*
* Entity::render - 
*
* The rendering of JSON in APIv2 depends on the URI param 'options'
* Rendering methods:
*   o 'normalized' (default)
*   o 'keyValues'  (less verbose, only name and values shown for attributes - no type, no metadatas)
*   o 'values'     (only the values of the attributes are printed, in a vector)
*/
std::string Entity::render(ConnectionInfo* ciP, RequestType requestType, bool comma)
{
  RenderFormat  renderFormat = NGSI_V2_NORMALIZED;

  if      (ciP->uriParamOptions[OPT_KEY_VALUES]    == true)  { renderFormat = NGSI_V2_KEYVALUES;     }
  else if (ciP->uriParamOptions[OPT_VALUES]        == true)  { renderFormat = NGSI_V2_VALUES;        }
  else if (ciP->uriParamOptions[OPT_UNIQUE_VALUES] == true)  { renderFormat = NGSI_V2_UNIQUE_VALUES; }

  if ((oe.details == "") && ((oe.reasonPhrase == "OK") || (oe.reasonPhrase == "")))
  {
    std::string out;
    std::vector<std::string> metadataFilter;
    std::vector<std::string> attrsFilter;

    if (ciP->uriParam[URI_PARAM_METADATA] != "")
    {
      stringSplit(ciP->uriParam[URI_PARAM_METADATA], ',', metadataFilter);
    }

    if (ciP->uriParam[URI_PARAM_ATTRIBUTES] != "")
    {
      stringSplit(ciP->uriParam[URI_PARAM_ATTRIBUTES], ',', attrsFilter);
    }

    // Add special attributes representing entity dates
    if ((creDate != 0) && (ciP->uriParamOptions[DATE_CREATED] || (std::find(attrsFilter.begin(), attrsFilter.end(), DATE_CREATED) != attrsFilter.end())))
    {
      ContextAttribute* caP = new ContextAttribute(DATE_CREATED, DATE_TYPE, creDate);
      attributeVector.push_back(caP);
    }
    if ((modDate != 0) && (ciP->uriParamOptions[DATE_MODIFIED] || (std::find(attrsFilter.begin(), attrsFilter.end(), DATE_MODIFIED) != attrsFilter.end())))
    {
      ContextAttribute* caP = new ContextAttribute(DATE_MODIFIED, DATE_TYPE, modDate);
      attributeVector.push_back(caP);
    }

    if ((renderFormat == NGSI_V2_VALUES) || (renderFormat == NGSI_V2_UNIQUE_VALUES))
    {
      out = "[";
      if (attributeVector.size() != 0)
      {
        out += attributeVector.toJson(renderFormat, attrsFilter, metadataFilter, false);
      }
      out += "]";        
    }
    else
    {
      out = "{";

      if (renderId)
      {
        out += JSON_VALUE("id", id);
        out += ",";

        /* This is needed for entities coming from NGSIv1 (which allows empty or missing types) */
        out += JSON_STR("type") + ":" + ((type != "")? JSON_STR(type) : JSON_STR(DEFAULT_ENTITY_TYPE));
      }

      std::string attrsOut;
      if (attributeVector.size() != 0)
      {
        attrsOut += attributeVector.toJson(renderFormat, attrsFilter, metadataFilter, false);
      }

      //
      // Note that just attributeVector.size() != 0 (used in previous versions) cannot be used
      // as ciP->uriParam["attrs"] filter could remove all the attributes
      //
      if (attrsOut != "")
      {
        if (renderId)
        {
          out +=  "," + attrsOut;
        }
        else
        {
          out += attrsOut;
        }
      }

      out += "}";
    }

    if (comma)
    {
      out += ",";
    }

    return out;
  }

  return oe.toJson();
}