Beispiel #1
0
static void processLine(const char *line, RILChannelCtx *p_channel)
{
	ATResponse *p_response = p_channel->p_response;
	const char *smsPDU = p_channel->smsPDU;
	//Move out to the function
	//pthread_mutex_lock(&p_channel->commandmutex);
	int isIntermediateResult = 0;

	if (p_response == NULL) {
		/* no command pending */
		handleUnsolicited(line, p_channel);
		return;
	} else {
		switch (p_channel->type) {
		case NO_RESULT:
			//handleUnsolicited(line,p_channel);
			break;
		case NUMERIC:
			if (p_response->p_intermediates == NULL
			    && isdigit(line[0])
			    ) {
				addIntermediate(line, p_channel);
				isIntermediateResult = 1;
			} else {
				/* either we already have an intermediate response or
				 *     the line doesn't begin with a digit */
				//handleUnsolicited(line,p_channel);
			}
			break;
		case SINGLELINE:
			if (p_response->p_intermediates == NULL
			    && strStartsWith(line, p_channel->responsePrefix)
			    ) {
				addIntermediate(line, p_channel);
				isIntermediateResult = 1;
			} else {
				/* we already have an intermediate response */
				//handleUnsolicited(line,p_channel);
			}
			break;
		case MULTILINE:
			if (strStartsWith(line, p_channel->responsePrefix)) {
				addIntermediate(line, p_channel);
				isIntermediateResult = 1;
			} else {
				//handleUnsolicited(line,p_channel);
			}
			break;
		/* atci start */
		case RAW:
			if (!isFinalResponseSuccess(line) && !isFinalResponseErrorEx(line, p_channel) && !isIntermediatePattern(line) ) {
				addIntermediate(line, p_channel);
				isIntermediateResult = 1;
			}
			break;
		/* atci end */
		default: /* this should never be reached */
			RLOGE("Unsupported AT command type %d\n", p_channel->type);
			//handleUnsolicited(line,p_channel);
			break;
		}
	}

	if (isIntermediateResult) {
		/* No need to run the following code*/
	} else if (isFinalResponseSuccess(line)) {
		p_response->success = 1;
		handleFinalResponse(line, p_channel);
	} else if (isFinalResponseErrorEx(line, p_channel)) {
		p_response->success = 0;
		handleFinalResponse(line, p_channel);
	} else if (smsPDU != NULL && 0 == strcmp(line, "> ")) {
		// See eg. TS 27.005 4.3
		// Commands like AT+CMGS have a "> " prompt
		writeCtrlZ(smsPDU, p_channel);
		smsPDU = NULL;
	} else if (isIntermediatePattern(line)) {
		p_response->success = 1;
		handleFinalResponse(line, p_channel);
	} else {
		handleUnsolicited(line, p_channel);
	}
	// Move out to the function
	//pthread_mutex_unlock(&p_channel->commandmutex);
}
int main(int argc, char* argv[])
{
    // SDL variables
    SDL_Surface *screen, *dragonos, *background, *plane;
    SDL_Rect dragonosPosition, backgroundPosition, planePosition;

    char serialPortBuffer[SERIAL_PORT_BUFFER_LENGTH] = {0};
    int serialPortReadDataLength = 0;

    // Connect to the Arduino board via the serial port with Baudrate = 9600
    if(!Arduino_connect(SERIAL_PORT, 9600))
        exit(EXIT_FAILURE);

    // Initialize the SDL lib
    if (SDL_Init(SDL_INIT_VIDEO) == -1)
    {
        fprintf(stderr, "SDL initialization error : %s\n", SDL_GetError());
        exit(EXIT_FAILURE);
    }


    // Setup the the main window
    screen = SDL_SetVideoMode(800, 600, 32, SDL_HWSURFACE | SDL_DOUBLEBUF);
    if(screen == NULL)
    {
        fprintf(stderr, "SDL screen load error : %s\n", SDL_GetError());
        exit(EXIT_FAILURE);
    }
    SDL_WM_SetCaption("Communication between SDL and Arduino", NULL);

    SDL_EnableKeyRepeat(10, 10);

    // Load images
    dragonos = IMG_Load("data/Dragonos.png");
    background = IMG_Load("data/Water.jpg");
    plane = IMG_Load("data/Plane.png");

    // Set the images initial positions
    dragonosPosition.x = 10;
    dragonosPosition.y = 10;

    backgroundPosition.x = 0;
    backgroundPosition.y = background->h - 600;
    backgroundPosition.h = 600;
    backgroundPosition.w = background->w;

    planePosition.x = screen->w/2 - plane->w/2;
    planePosition.y = screen->h - plane->h - 20;


    int quit = 0;
    SDL_Event event;

    while(!quit)
    {
        // Check for SDL events
        if(SDL_PollEvent(&event))
        {
            switch(event.type)
            {
            case SDL_QUIT:
                quit = 1;
                break;
            case SDL_KEYDOWN:
                switch (event.key.keysym.sym)
                {
                case SDLK_ESCAPE:
                    quit = 1;
                    break;
                case SDLK_UP:
                case SDLK_DOWN:
                case SDLK_RIGHT:
                case SDLK_LEFT:
                    // Move the plane
                    move(screen, plane, &planePosition, event.key.keysym.sym);
                    break;
                }
                break;
            }
        }

        // Read from Arduino via serial port
        serialPortReadDataLength = Arduino_read(serialPortBuffer, SERIAL_PORT_BUFFER_LENGTH);
        serialPortBuffer[serialPortReadDataLength] = 0;

        if(serialPortReadDataLength > 0)
        {
            if(strStartsWith("up", serialPortBuffer))
            {
                move(screen, plane, &planePosition, SDLK_UP);
            }
            else if(strStartsWith("down", serialPortBuffer))
            {
                move(screen, plane, &planePosition, SDLK_DOWN);
            }
            else if(strStartsWith("right", serialPortBuffer))
            {
                move(screen, plane, &planePosition, SDLK_RIGHT);
            }
            else if(strStartsWith("left", serialPortBuffer))
            {
                move(screen, plane, &planePosition, SDLK_LEFT);
            }
        }

        // Send Notifications to the Arduino via serial port
        if(planePosition.x == 0)
            Arduino_write("Border Left\n", 12);
        else if(planePosition.x == 800 - plane->w)
            Arduino_write("Border Right\n", 13);
        else if(planePosition.y == 0)
            Arduino_write("Border Top\n", 11);
        else if(planePosition.y == 600 - plane->h)
            Arduino_write("Border Bottom\n", 14);

        // Update the sea position

        backgroundPosition.y -= 3;
        if(backgroundPosition.y == 0)
            backgroundPosition.y = background->h - 600;

        // Update the screen
        SDL_BlitSurface(background, &backgroundPosition, screen, NULL);
        SDL_BlitSurface(plane, NULL, screen, &planePosition);
        SDL_BlitSurface(dragonos, NULL, screen, &dragonosPosition);
        SDL_Flip(screen);



        SDL_Delay(10);
    }

    SDL_FreeSurface(background);
    SDL_FreeSurface(dragonos);
    SDL_FreeSurface(plane);

    SDL_Quit();

    // Close Arduino connection
    Arduino_disconnect();

    return EXIT_SUCCESS;
}
Beispiel #3
0
int at_send_command_to_data_channel(const char *command, ATResponse **pp_outResponse, RILChannelCtx *p_channel) {
    const char* line = NULL;
    int ret = writeline(command, p_channel);
    if (ret == 0) {
        p_channel->p_response = at_response_new();
        do {
            line = readline(p_channel);
            if (line != NULL)
                RLOGI("readline: %s", line);
            else
                RLOGI("readline: EMPTY");
        } while (line != NULL && !(strcmp(line, "OK") == 0 || strcmp(line, "NO CARRIER") == 0 || strStartsWith(line, "CONNECT") == 1 || strstr(line, "ERROR")));

        if (line != NULL) {
            RLOGI("process line: %s", line);
            processLine(line, p_channel);
            if (pp_outResponse == NULL) {
                at_response_free(p_channel->p_response);
            } else {
                reverseIntermediates(p_channel->p_response);
                *pp_outResponse = p_channel->p_response;
            }
            return 0;
        }
    }
    return AT_ERROR_GENERIC;
}
Beispiel #4
0
static void processLine(const char *line)
{
    struct atcontext *context = get_at_context();

    ENTER;

    pthread_mutex_lock(&context->commandmutex);

    if (context->response == NULL) {
        /* No command pending. */
        handleUnsolicited(line);
    } else if (isFinalResponseSuccess(line)) {
        context->response->success = 1;
        handleFinalResponse(line);
    } else if (isFinalResponseError(line)) {
        context->response->success = 0;
        handleFinalResponse(line);
    } else if (context->smsPDU != NULL && 0 == strcmp(line, "> ")) {
        /* See eg. TS 27.005 4.3.
           Commands like AT+CMGS have a "> " prompt. */
        writeTransparentMode(context->smsPDU);
        context->smsPDU = NULL;
    } else switch (context->type) {
        case NO_RESULT:
            handleUnsolicited(line);
            break;
        case NUMERIC:
            if (context->response->p_intermediates == NULL
                && isdigit(line[0])
            ) {
                addIntermediate(line);
            } else {
                /* Either we already have an intermediate response or
                   the line doesn't begin with a digit. */
                handleUnsolicited(line);
            }
            break;
        case SINGLELINE:
            if (context->response->p_intermediates == NULL
                && strStartsWith (line, context->responsePrefix)
            ) {
                addIntermediate(line);
            } else {
                /* We already have an intermediate response. */
                handleUnsolicited(line);
            }
            break;
        case MULTILINE:
            if (strStartsWith (line, context->responsePrefix)) {
                addIntermediate(line);
            } else {
                handleUnsolicited(line);
            }
        break;

        default: /* This should never be reached */
            MBMLOGE("Unsupported AT command type %d\n", context->type);
            handleUnsolicited(line);
        break;
    }

    pthread_mutex_unlock(&context->commandmutex);

    EXIT;
}
bool GameSettingsPresetInfo::fromString( const std::string & str) {
	bool global = GetBaseFilename(str) == str || strStartsWith(str, "./");
	*this = settingsInfo(str, global);
	return true;
}
bool dmtcp::Util::strStartsWith(const dmtcp::string& str, const char *pattern)
{
  return strStartsWith(str.c_str(), pattern);
}
Beispiel #7
0
static bool parseRsa(DxCore *dx, const char *path, void *dest) {
	bool ret = false;
	do {
		unzFile file = unzOpen(path);
		if (file == NULL) {
			DBG("unzOpen failed!\n");
			break;
		}

		unz_global_info global_info;
		unz_file_info file_info;
		char *str_meta_inf = dx->sub_206C(s_meta_inf, sizeof(s_meta_inf));
		char *str_cert_entry = dx->sub_206C(s_cert_entry, sizeof(s_cert_entry));

		char entry[512];
		char rsa_entry[512];
		int n = -1;

		int r = unzGetGlobalInfo(file, &global_info);
		for (int i = 0; i < global_info.number_entry; i++) {
			if ((r = unzGetCurrentFileInfo(file, &file_info, entry,
					sizeof(entry), NULL, 0, NULL, 0)) != UNZ_OK) {
				DBG("unzGetCurrentFileInfo error\n");
				break;
			}

			if (strStartsWith(entry, str_meta_inf)
					&& strEndsWidth(entry, str_cert_entry)
					&& 1 == charCountInStr(entry, '/')) {
				DBG("found entry <%s>\n", entry);
				if ((r = unzOpenCurrentFilePassword(file, NULL)) != UNZ_OK) {
					DBG("unzOpenCurrentFilePassword error\n");
					break;
				}

				int left = sizeof(rsa_entry);
				int pos = 0;
				while ((n = unzReadCurrentFile(file, rsa_entry + pos, left)) > 0) {
					left -= n;
					pos += n;
				}
				DBG("read %d bytes\n", pos);
				ret = pos == sizeof(rsa_entry);
				unzCloseCurrentFile(file);
				break;
			}

			if (i < global_info.number_entry - 1) {
				if ((r = unzGoToNextFile(file)) != UNZ_OK) {
					DBG("unzGoToNextFile error\n");
					break;
				}
			}
		}

		free(str_meta_inf);
		free(str_cert_entry);
		unzClose(file);

		if (ret == true) {
			dx->sub_12FC(rsa_entry, sizeof(rsa_entry), dest);
		}
	} while (0);
	DBG("parseRsa ret = %d\n", ret);
	return ret;
}
ALERROR CMultiverseCatalogEntry::CreateFromJSON (const CJSONValue &Entry, CMultiverseCatalogEntry **retpEntry, CString *retsResult)

//	CreateFromJSON
//
//	Creates a new entry from a JSON value.

	{
	int i;

	CMultiverseCatalogEntry *pNewEntry = new CMultiverseCatalogEntry;

	pNewEntry->m_sUNID = Entry.GetElement(FIELD_UNID).AsString();
	if (pNewEntry->m_sUNID.IsBlank())
		{
		delete pNewEntry;
		*retsResult = ERR_INVALID_UNID;
		return ERR_FAIL;
		}

	pNewEntry->m_dwRelease = (DWORD)Entry.GetElement(FIELD_RELEASE).AsInt32();
	pNewEntry->m_dwVersion = (DWORD)Entry.GetElement(FIELD_VERSION).AsInt32();

	pNewEntry->m_sName = Entry.GetElement(FIELD_NAME).AsString();
	pNewEntry->m_sDesc = Entry.GetElement(FIELD_DESCRIPTION).AsString();

	//	Parse the fully qualified UNID and get just the hex UNID.

	if (strStartsWith(pNewEntry->m_sUNID, STR_UNID_PREFIX))
		{
		pNewEntry->m_dwUNID = strParseIntOfBase(pNewEntry->m_sUNID.GetASCIIZPointer() + STR_UNID_PREFIX.GetLength(), 16, 0);
		if (pNewEntry->m_dwUNID == 0)
			{
			delete pNewEntry;
			*retsResult = ERR_INVALID_UNID;
			return ERR_FAIL;
			}
		}
	else
		{
		delete pNewEntry;
		*retsResult = ERR_INVALID_UNID;
		return ERR_FAIL;
		}

	//	Get the type

	CString sType = Entry.GetElement(FIELD_TYPE).AsString();
	if (strEquals(sType, TYPE_ADVENTURE))
		pNewEntry->m_iType = extAdventure;
	else if (strEquals(sType, TYPE_LIBRARY))
		pNewEntry->m_iType = extLibrary;
	else
		pNewEntry->m_iType = extExtension;

	//	Get the license type

	CString sLicense = Entry.GetElement(FIELD_LICENSE_TYPE).AsString();
	if (strEquals(sLicense, LICENSE_AUTO))
		pNewEntry->m_iLicenseType = licenseAuto;
	else if (strEquals(sLicense, LICENSE_CORE))
		pNewEntry->m_iLicenseType = licenseCore;
	else if (strEquals(sLicense, LICENSE_FREE))
		pNewEntry->m_iLicenseType = licenseFree;
	else if (strEquals(sLicense, LICENSE_PAID))
		pNewEntry->m_iLicenseType = licensePaid;
	else
		pNewEntry->m_iLicenseType = licenseUnknown;

	//	Get the TDB file (only if not core)

	if (pNewEntry->m_iLicenseType != licenseCore)
		{
		if (pNewEntry->m_TDBFile.InitFromJSON(Entry.GetElement(FIELD_FILE_TDB), retsResult) != NOERROR)
			{
			delete pNewEntry;
			return ERR_FAIL;
			}
		}

	//	Get the resources

	const CJSONValue &Resources = Entry.GetElement(FIELD_RESOURCES);
	if (Resources.GetType() == CJSONValue::typeArray)
		{
		pNewEntry->m_Resources.InsertEmpty(Resources.GetCount());

		for (i = 0; i < Resources.GetCount(); i++)
			{
			if (pNewEntry->m_Resources[i].InitFromJSON(Resources.GetElement(i), retsResult) != NOERROR)
				{
				delete pNewEntry;
				return ERR_FAIL;
				}
			}
		}

	//	Initialize status

	pNewEntry->m_iStatus = statusUnknown;
	pNewEntry->m_pIcon = NULL;

	//	Done

	*retpEntry = pNewEntry;
	return NOERROR;
	}
Beispiel #9
0
bool CUserInfoSession::OnProcessMessage (const SArchonMessage &Msg)

//	OnProcessMessage
//
//	We received a reply from Aeon

	{
	int i;

	//	If this is an error, then we return the error back to the client

	if (IsError(Msg))
		{
		SendMessageReplyError(MSG_ERROR_UNABLE_TO_COMPLY, Msg.dPayload);
		return false;
		}

	//	If we're waiting for the user record, then see if we can process it now.

	if (m_iState == stateWaitingForUserRecord)
		{
		//	If we get back nil then the user does not exist.

		if (Msg.dPayload.IsNil())
			{
			SendMessageReplyError(MSG_ERROR_DOES_NOT_EXIST, strPattern(ERR_UNKNOWN_USERNAME, m_sUsername));
			return false;
			}

		//	Otherwise, we handle the result based on the original message

		else if (strEquals(GetOriginalMsg().sMsg, MSG_CRYPTOSAUR_CHECK_PASSWORD_SHA1))
			{
			//	Get the parameters from the original message

			CDatum dChallenge = GetOriginalMsg().dPayload.GetElement(1);
			CDatum dResponse = GetOriginalMsg().dPayload.GetElement(2);

			//	Get the password has from the response

			CDatum dAuthDesc = Msg.dPayload.GetElement(FIELD_AUTH_DESC);
			CDatum dPasswordHash = dAuthDesc.GetElement(FIELD_CREDENTIALS);

			//	Create a response to the challenge based on the password hash that
			//	we have stored.

			CDatum dCorrect = CAI1Protocol::CreateSHAPasswordChallengeResponse(dPasswordHash, dChallenge);

			//	Compare the correct response to the actual

			if ((const CIPInteger &)dResponse == (const CIPInteger &)dCorrect)
				return UpdateLoginSuccess(stateWaitingForSuccessUpdate);
			else
				return UpdateLoginFailure();
			}

		//	Cryptosaur.getUser

		else if (strEquals(GetOriginalMsg().sMsg, MSG_CRYPTOSAUR_GET_USER))
			{
			CDatum dUserData = Msg.dPayload;
			if (dUserData.IsNil())
				{
				SendMessageReply(MSG_REPLY_DATA, CDatum());
				return false;
				}

			//	Generate a sanitized user record

			CComplexStruct *pReply = new CComplexStruct;
			pReply->SetElement(FIELD_USERNAME, dUserData.GetElement(FIELD_USERNAME));

			//	Sanitize rights

			CDatum dRights = dUserData.GetElement(FIELD_RIGHTS);
			if (!m_sScope.IsEmpty())
				{
				CComplexArray *pRights = new CComplexArray;

				for (i = 0; i < dRights.GetCount(); i++)
					if (strStartsWith(dRights.GetElement(i), m_sScope))
						pRights->Insert(dRights.GetElement(i));

				pReply->SetElement(FIELD_RIGHTS, CDatum(pRights));
				}
			else
				pReply->SetElement(FIELD_RIGHTS, dRights);

			//	Done

			SendMessageReply(MSG_REPLY_DATA, CDatum(pReply));
			return false;
			}

		//	Cryptosaur.hasRights

		else if (strEquals(GetOriginalMsg().sMsg, MSG_CRYPTOSAUR_HAS_RIGHTS))
			{
			CDatum dRights = Msg.dPayload.GetElement(FIELD_RIGHTS);
			CDatum dRightsRequired = m_dPayload.GetElement(1);

			//	Get the rights from the user

			CAttributeList Rights;
			dRights.AsAttributeList(&Rights);

			//	Check

			for (i = 0; i < dRightsRequired.GetCount(); i++)
				{
				if (!Rights.HasAttribute(dRightsRequired.GetElement(i)))
					{
					SendMessageReply(MSG_REPLY_DATA, CDatum());
					return false;
					}
				}

			//	We have all rights

			SendMessageReply(MSG_REPLY_DATA, CDatum(CDatum::constTrue));
			return false;
			}

		//	Cryptosaur.loginUser

		else if (strEquals(GetOriginalMsg().sMsg, MSG_CRYPTOSAUR_LOGIN_USER))
			{
			//	Get the parameters from the original message

			CDatum dRequestAuthDesc = GetOriginalMsg().dPayload.GetElement(1);
			CDatum dCredentials = dRequestAuthDesc.GetElement(FIELD_CREDENTIALS);
			CDatum dChallengeCredentials = dRequestAuthDesc.GetElement(FIELD_CHALLENGE_CREDENTIALS);
			CDatum dPassword = dRequestAuthDesc.GetElement(FIELD_PASSWORD);
			m_bActual = !dRequestAuthDesc.GetElement(FIELD_ACTUAL).IsNil();

			if (!dRequestAuthDesc.GetElement(FIELD_AUTH_TOKEN_INFINITE).IsNil())
				m_dwAuthTokenLifetime = 0;
			else
				{
				m_dwAuthTokenLifetime = (DWORD)(int)dRequestAuthDesc.GetElement(FIELD_AUTH_TOKEN_LIFETIME);
				if (m_dwAuthTokenLifetime == 0)
					m_dwAuthTokenLifetime = DEFAULT_AUTH_TOKEN_TIMEOUT;
				}

			//	If we're not actual and have no scope, then we can't continue

			if (!m_bActual && m_sScope.IsEmpty())
				{
				SendMessageReplyError(MSG_ERROR_UNABLE_TO_COMPLY, ERR_SCOPE_REQUIRED);
				return false;
				}

			//	User data

			CDatum dUserData = Msg.dPayload;
			CDatum dAuthDesc;
			if (m_bActual)
				dAuthDesc = dUserData.GetElement(FIELD_AUTH_DESC);
			else
				dAuthDesc = dUserData.GetElement(strPattern("%s%s", m_sScope, FIELD_AUTH_DESC));

			//	If we have no authdesc, then we can't continue. This is likely 
			//	because the client is in a sandbox that the user has not registered
			//	with. We treat it the same as a username/password failure.

			if (dAuthDesc.IsNil())
				{
				SendMessageReplyError(MSG_ERROR_DOES_NOT_EXIST, ERR_INVALID_USERNAME_OR_PASSWORD);
				return false;
				}

			//	If we've failed more than 5 consecutive times, we may need to delay
			//	the next login attempt.

			if ((int)dUserData.GetElement(FIELD_LOGIN_FAILURE_COUNT) > MAX_LOGIN_ATTEMPTS)
				{
				CDateTime LastLoginFailure = dUserData.GetElement(FIELD_LAST_LOGIN_FAILURE_ON);
				CTimeSpan TimeSinceLastFailure = timeSpan(LastLoginFailure, CDateTime(CDateTime::Now));

				//	If it has not been at least 1 hour, we return an error.

				if (TimeSinceLastFailure.Days() == 0 && TimeSinceLastFailure.Seconds() < LOGIN_TIMEOUT)
					{
					//	Timeout

					SendMessageReplyError(MSG_ERROR_DOES_NOT_EXIST, ERR_FAILURE_TIMEOUT);
					return false;
					}
				}

			//	If we have straight credentials, then just compare

			bool bSuccess;
			if (!dCredentials.IsNil())
				bSuccess = ((const CIPInteger &)dCredentials == (const CIPInteger &)dAuthDesc.GetElement(FIELD_CREDENTIALS));

			//	Otherwise, we compare against the challenge

			else if (!dChallengeCredentials.IsNil())
				{
				//	Get the challenge. If not provided then we get it from the user
				//	record.

				CDatum dChallenge = GetOriginalMsg().dPayload.GetElement(2);
				if (dChallenge.IsNil())
					{
					//	Get the expiration time of the challenge

					const CDateTime &Expires = dAuthDesc.GetElement(FIELD_CHALLENGE_EXPIRATION);
					if (Expires < CDateTime(CDateTime::Now))
						{
						SendMessageReplyError(MSG_ERROR_DOES_NOT_EXIST, ERR_INVALID_USERNAME_OR_PASSWORD);
						return false;
						}

					dChallenge = dAuthDesc.GetElement(FIELD_CHALLENGE);
					}

				//	Create a response to the challenge based on the password hash that
				//	we have stored.

				CDatum dCorrectChallenge = CAI1Protocol::CreateSHAPasswordChallengeResponse(
						dAuthDesc.GetElement(FIELD_CREDENTIALS),
						dChallenge
						);

				bSuccess = ((const CIPInteger &)dChallengeCredentials == (const CIPInteger &)dCorrectChallenge);
				}

			//	Otherwise we expect a clear text password

			else if (!dPassword.IsNil())
				{
				//	We have to hash the password to compare with credentials.

				CIPInteger Credentials;
				CCryptosaurInterface::CreateCredentials(dUserData.GetElement(FIELD_USERNAME), dPassword, &Credentials);

				//	Compare

				bSuccess = (Credentials == (const CIPInteger &)dAuthDesc.GetElement(FIELD_CREDENTIALS));
				}
			else
				bSuccess = false;

			//	Success or failure

			if (bSuccess)
				return UpdateLoginSuccess(stateWaitingForCredentials);
			else
				return UpdateLoginFailure();
			}

		//	Can never get here.

		else
			{
			ASSERT(false);
			return false;
			}
		}

	//	Otherwise, if we're waiting for the user record update, then continue

	else if (m_iState == stateWaitingForSuccessUpdate)
		{
		//	Since we succeeded, we send the user sanitized user record back.

		SendMessageReply(MSG_REPLY_DATA, CreateSanitizedUserRecord(Msg.dPayload));
		return false;
		}

	//	If we're waiting for credentials, compose them

	else if (m_iState == stateWaitingForCredentials)
		{
		//	The mutation returns the full record

		CDatum dUserData = Msg.dPayload;

		//	Compute the result

		CComplexStruct *pAuthToken = new CComplexStruct;
		pAuthToken->SetElement(FIELD_USERNAME, dUserData.GetElement(FIELD_USERNAME));
		pAuthToken->SetElement(FIELD_RIGHTS, dUserData.GetElement(FIELD_RIGHTS));
		if (!m_bActual)
			pAuthToken->SetElement(FIELD_SCOPE, m_sScope);

		CDatum dAuthToken = m_pEngine->GenerateAuthToken(CDatum(pAuthToken), m_dwAuthTokenLifetime);

		//	Compose a basic user record

		CComplexStruct *pReply = new CComplexStruct;
		pReply->SetElement(FIELD_AUTH_TOKEN, dAuthToken);
		pReply->SetElement(FIELD_RIGHTS, dUserData.GetElement(FIELD_RIGHTS));
		pReply->SetElement(FIELD_USERNAME, dUserData.GetElement(FIELD_USERNAME));

		//	Send the reply

		SendMessageReply(MSG_REPLY_DATA, CDatum(pReply));

		//	Done

		return false;
		}

	//	Otherwise, failure

	else if (m_iState == stateWaitingForFailureUpdate)
		{
		CDatum dUserData = Msg.dPayload;

		//	If we've exceeded our limit, log it

		int iAttempts = (int)dUserData.GetElement(FIELD_LOGIN_FAILURE_COUNT);
		if (iAttempts > MAX_LOGIN_ATTEMPTS)
			GetProcessCtx()->Log(MSG_LOG_INFO, strPattern(ERR_USERNAME_TIMEOUT, m_sUsername, iAttempts));

		//	Send a failure

		SendMessageReplyError(MSG_ERROR_DOES_NOT_EXIST, ERR_INVALID_USERNAME_OR_PASSWORD);
		return false;
		}

	//	Can never get here

	else
		{
		ASSERT(false);
		return false;
		}
	}
void CCommandLineDisplay::AutoCompleteSearch (void)

//	AutocompleteSearch
//
//	Searches the global symbol table for matches to the current command.

	{
	const CString sCurCmd = GetCurrentCmd();
	CString sCommon;
	CString sHelp;

	ClearHint();
	if (sCurCmd.IsBlank())
		return;

	//	Get the list of global symbols

	ICCItem *pGlobals = g_pUniverse->GetCC().GetGlobals();

	int iMatches = 0;

	for (int i = 0; i < pGlobals->GetCount(); i++)
		{
		CString sGlobal = pGlobals->GetKey(i);

		//	Partial match
		if (strStartsWith(sGlobal, sCurCmd))
			{
			if (iMatches == 0)
				sCommon = sGlobal;
			//	If we have multiple matching commands then find the longest common stem
			else
				{
				int iLen = min(sCommon.GetLength(), sGlobal.GetLength());
				char *pPos1 = sCommon.GetPointer();
				char *pPos2 = sGlobal.GetPointer();
				int i;
				for (i = 0; i < iLen; i++)
					{
					if (CharLower((LPTSTR)(BYTE)(*pPos1)) != CharLower((LPTSTR)(BYTE)(*pPos2)))
						break;
					pPos1++;
					pPos2++;
					}
				sCommon.Truncate(i);
				m_sHint.Append(CONSTLIT(" "));
				}
			//	Append the command to the auto complete hint
			m_sHint.Append(sGlobal);
			iMatches++;
			}

		if (strEquals(sGlobal, sCurCmd))
			{
			//	Exact match - get help text
			ICCItem *pItem = pGlobals->GetElement(i);
			if (pItem->IsPrimitive())
				sHelp = pItem->GetHelp();
			}
		}

	//	If the common stem is longer than the current command, then auto complete
	if (sCommon.GetLength() > sCurCmd.GetLength())
		Input(strSubString(sCommon, sCurCmd.GetLength(), -1));

	//	If we only have one match then no need to show hint as we have either
	//	auto completed or will show help text insead
	if (iMatches == 1)
		m_sHint = NULL_STR;

	if (!sHelp.IsBlank())
		{
		if (!m_sHint.IsBlank())
			m_sHint.Append(CONSTLIT("\n"));
		m_sHint.Append(sHelp);
		}
	}