/* * Result of query for buddy with given username and serviceName * * If the buddy is found, we can send no matter what. If buddy is not found, we need to check if this service allows sending IM messages * to non buddies (gtalk does not allow this, aol does) */ MojErr SendOneMessageHandler::findBuddyResult(MojObject& result, MojErr findErr) { if (findErr) { MojString error; MojErrToString(findErr, error); MojLogError(IMServiceApp::s_log, _T("findBuddyResult: error %d - %s"), findErr, error.data()); // not much we can do here... failMessage(ERROR_SEND_GENERIC_ERROR); } else { // log the results MojString mojStringJson; result.toJson(mojStringJson); MojLogDebug(IMServiceApp::s_log, _T("findBuddyResult result: %s"), mojStringJson.data()); // "results" in result MojObject results; result.get(_T("results"), results); // check to see if array is empty - there should really always be 0 or 1 item here if (!results.empty()){ // buddy is on the list - send to the transport MojLogInfo(IMServiceApp::s_log, _T("findBuddyResult - user is on buddy list. No need to check account template.")); sendToTransport(); } else { MojLogInfo(IMServiceApp::s_log, _T("findBuddyResult - no buddy found. Need to check account template if this is allowed")); // check palm://com.palm.service.accounts/listAccountTemplates {"capability":"MESSAGING"} to get a list of account templates that support messaging. // If the account template includes "chatWithNonBuddies":false, it should fail to send. MojLogInfo(IMServiceApp::s_log, "Issuing listAccountTemplates request to com.palm.service.accounts"); // parameters: {“capability”:”MESSAGING”} MojObject params; params.putString("capability", "MESSAGING"); // Get a request object from the service MojRefCountedPtr<MojServiceRequest> req; MojErr err = m_service->createRequest(req); if (!err) { err = req->send(m_listAccountSlot, "com.palm.service.accounts", "listAccountTemplates", params); } if (err) { MojString error; MojErrToString(err, error); MojLogError(IMServiceApp::s_log, _T("findBuddyResult failed to send request to accounts: error %d - %s"), err, error.data()); // not much we can do here...don't leave message still pending failMessage(ERROR_SEND_GENERIC_ERROR); } } } return MojErrNone; }
// Expected responses // {"activityId":78,"returnValue":true} // {"activityId":78,"event":"start","returnValue":true} <-- this occurs when the timeout fires // Error in case there is already an activity for the given serviceName // {"errorCode":17,"errorText":"Activity with that name already exists","returnValue":false} MojErr ConnectionState::ConnectionChangedScheduler::scheduleActivityResult(MojObject& result, MojErr err) { // log the parameters IMServiceHandler::logMojObjectJsonString(_T("ConnectionChangedScheduler::scheduleActivityResult: %s"), result); if (MojErrNone != err) { MojString error; MojErrToString(err, error); MojLogError(IMServiceApp::s_log, _T("ConnectionChangedScheduler::scheduleActivityResult failed: error %d - %s"), err, error.data()); // we created this slot with unlimited responses, so we have to explicitly cancel it, unless there is another activity of this name already, in which case // we get here again if (MojErrExists != err) { // err 17 = "Activity with that name already exists" m_scheduleActivitySlot.cancel(); } } else { MojString event; if (result.getRequired(_T("event"), event) == MojErrNone) { MojLogInfo(IMServiceApp::s_log, _T("ConnectionChangedScheduler::scheduleActivityResult event=%s"), event.data()); if (event == "start") { MojInt64 activityId = 0; MojObject dummy; m_loginState->handleConnectionChanged(dummy); bool found = result.get("activityId", activityId); if (found && activityId > 0) { MojRefCountedPtr<MojServiceRequest> req; err = m_service->createRequest(req); MojObject completeParams; completeParams.put(_T("activityId"), activityId); err = req->send(m_activityCompleteSlot, "com.palm.activitymanager", "complete", completeParams, 1); } else { MojLogError(IMServiceApp::s_log,_T("ConnectionChangedScheduler::scheduleActivityResult - missing activityId")); } if (activityId <= 0 || err) { MojString error; MojErrToString(err, error); MojLogError(IMServiceApp::s_log, _T("ConnectionChangedScheduler::scheduleActivityResult send request failed: error %d - %s"), err, error.data()); // we created this slot with unlimited responses, so we have to explicitly cancel m_scheduleActivitySlot.cancel(); } } } // if there is no event we get here again } return MojErrNone; }
/* * New incoming IM message */ bool IMServiceHandler::incomingIM(const char* serviceName, const char* username, const char* usernameFrom, const char* message) { MojLogTrace(IMServiceApp::s_log); // log the parameters // don't log the message text MojLogInfo (IMServiceApp::s_log, _T("incomingIM - IM received. serviceName: %s username: %s usernameFrom: %s"), serviceName, username, usernameFrom); // no error - process the IM MojRefCountedPtr<IMMessage> imMessage(new IMMessage); // set the message fields based on the incoming parameters MojErr err = imMessage->initFromCallback(serviceName, username, usernameFrom, message); if (!err) { // handle the message MojRefCountedPtr<IncomingIMHandler> incomingIMHandler(new IncomingIMHandler(m_service)); err = incomingIMHandler->saveNewIMMessage(imMessage); } if (err) { MojString error; MojErrToString(err, error); MojLogError(IMServiceApp::s_log, _T("incomingIM failed: %d - %s"), err, error.data()); MojErrCheck(err); return false; } return true; }
MojErr OnEnabledHandler::getAccountConfigResult(MojObject& payload, MojErr err) { MojLogTrace(IMServiceApp::s_log); if (err != MojErrNone) { MojString error; MojErrToString(err, error); MojLogCritical(IMServiceApp::s_log, "getAccountConfig failed: error %d - %s", err, error.data()); } else { MojObject results; payload.get("results", results); if (!results.empty()) { m_config = *results.arrayBegin(); } } if (m_enable) { err = accountEnabled(); } else { err = accountDisabled(); } return err; }
/* * Result of query for loginState entry with given username and serviceName when removing a buddy * * Remove buddy from buddyStatus and contact DB */ MojErr SendOneMessageHandler::findAccountIdResult(MojObject& result, MojErr findErr) { if (findErr) { MojString error; MojErrToString(findErr, error); MojLogError(IMServiceApp::s_log, _T("findAccountIdResult failed: error %d - %s"), findErr, error.data()); // not much we can do here... failMessage(ERROR_SEND_GENERIC_ERROR); } else { // parse out the accountId readAccountIdFromResults(result); if (!m_accountId.empty()){ // construct our where clause - find by username, accountId and servicename MojDbQuery query; query.where("username", MojDbQuery::OpEq, m_usernameTo); query.where("accountId", MojDbQuery::OpEq, m_accountId); query.from(IM_BUDDYSTATUS_KIND); MojObject queryObject; query.toObject(queryObject); IMServiceHandler::logMojObjectJsonString(_T("findAccountIdResult - buddyStatus query: %s"), queryObject); // call find //virtual MojErr find(Signal::SlotRef handler, const MojDbQuery& query, // bool watch = false, bool returnCount = false) = 0; MojErr err = m_tempdbClient.find(this->m_findBuddySlot, query, /* watch */ false ); if (err) { MojString error; MojErrToString(err, error); MojLogError(IMServiceApp::s_log, _T("findAccountIdResult dbClient.find() failed: error %d - %s"), err, error.data()); failMessage(ERROR_SEND_GENERIC_ERROR); } } else { MojLogError(IMServiceApp::s_log, _T("findAccountIdResult: no matching loginState record found for %s"), m_serviceName.data()); // tell the outgoing Command handler we are done failMessage(ERROR_SEND_GENERIC_ERROR); } } return MojErrNone; }
/* * Result of query for loginState entry with given username and serviceName when adding a buddy * * Save buddy in buddyStatus and contact DB */ MojErr SendOneCommandHandler::findAccountIdForAddResult(MojObject& result, MojErr findErr) { if (findErr) { MojString error; MojErrToString(findErr, error); MojLogError(IMServiceApp::s_log, _T("findAccountIdResult failed: error %d - %s"), findErr, error.data()); } else { // parse out the accountId readAccountIdFromResults(result); if (!m_accountId.empty()){ MojObject buddyStatus; buddyStatus.putString("_kind", IM_BUDDYSTATUS_KIND); buddyStatus.put("accountId", m_accountId); buddyStatus.put("username", m_buddyName); buddyStatus.put("serviceName", m_serviceName); // log it MojString json; buddyStatus.toJson(json); MojLogInfo(IMServiceApp::s_log, _T("saving buddy status to db: %s"), json.data()); // save it // the save generates a call to the save result handler MojErr err = m_tempdbClient.put(m_addBuddySlot, buddyStatus); if (err) { MojString error; MojErrToString(err, error); MojLogError(IMServiceApp::s_log, _T("findAccountIdResult: dbClient.put() failed: error %d - %s"), err, error.data()); // tell the outgoing Command handler we are done m_outgoingIMHandler->messageFinished(); } } else { MojLogError(IMServiceApp::s_log, _T("findAccountIdResult: no matching loginState record found for %s %s"), m_username.data(), m_serviceName.data()); // tell the outgoing Command handler we are done m_outgoingIMHandler->messageFinished(); } } return MojErrNone; }
MojErr MojServiceMessage::replyError(MojErr code) { MojString str; MojErr err = MojErrToString(code, str); MojErrCheck(err); err = replyError(code, str); MojErrCheck(err); return MojErrNone; }
/* * Result of query for loginState entry with given username and serviceName when removing a buddy * * Remove buddy from buddyStatus and contact DB */ MojErr SendOneCommandHandler::findAccountIdForRemoveResult(MojObject& result, MojErr findErr) { if (findErr) { MojString error; MojErrToString(findErr, error); MojLogError(IMServiceApp::s_log, _T("findAccountIdResult failed: error %d - %s"), findErr, error.data()); } else { // parse out the accountId readAccountIdFromResults(result); if (!m_accountId.empty()){ // construct our where clause - find by username, accountId and servicename MojDbQuery query; query.where("username", MojDbQuery::OpEq, m_buddyName); query.where("accountId", MojDbQuery::OpEq, m_accountId); query.from(IM_BUDDYSTATUS_KIND); // call del // virtual MojErr del(Signal::SlotRef handler, const MojDbQuery& query, // MojUInt32 flags = MojDb::FlagNone); MojErr err = m_tempdbClient.del(m_removeBuddySlot, query); if (err) { MojString error; MojErrToString(err, error); MojLogError(IMServiceApp::s_log, _T("removeBuddy: dbClient.del() failed: error %d - %s"), err, error.data()); // tell the outgoing Command handler we are done m_outgoingIMHandler->messageFinished(); } } else { MojLogError(IMServiceApp::s_log, _T("findAccountIdResult: no matching loginState record found for %s %s"), m_username.data(), m_serviceName.data()); // tell the outgoing Command handler we are done m_outgoingIMHandler->messageFinished(); } } return MojErrNone; }
MojErr OnEnabledHandler::deleteImBuddyStatusResult(MojObject& payload, MojErr err) { MojLogTrace(IMServiceApp::s_log); if (err != MojErrNone) { MojString error; MojErrToString(err, error); MojLogCritical(IMServiceApp::s_log, _T("deleteImBuddyStatusResult failed: error %d - %s"), err, error.data()); } return err; }
/* * Callback for DB delete results * deleted buddyStatus record */ MojErr SendOneCommandHandler::removeBuddyResult(MojObject& result, MojErr delErr) { MojLogTrace(IMServiceApp::s_log); if (delErr) { MojString error; MojErrToString(delErr, error); MojLogError(IMServiceApp::s_log, _T("removeBuddyResult failed. error %d - %s"), delErr, error.data()); } else { MojString json; result.toJson(json); MojLogInfo(IMServiceApp::s_log, _T("removeBuddyResult response: %s"), json.data()); } // now delete from contacts DB //construct our where clause - find by username and servicename MojDbQuery query; MojErr err; err = createContactQuery(query); if (err) { MojString error; MojErrToString(err, error); MojLogError(IMServiceApp::s_log, _T("removeBuddyResult: createContactsQuery failed: error %d - %s"), err, error.data()); } // call del // virtual MojErr del(Signal::SlotRef handler, const MojDbQuery& query, // MojUInt32 flags = MojDb::FlagNone); err = m_dbClient.del(this->m_removeContactSlot, query); if (err) { MojString error; MojErrToString(err, error); MojLogError(IMServiceApp::s_log, _T("removeBuddyResult: dbClient.del() failed: error %d - %s"), err, error.data()); // tell the outgoing Command handler we are done m_outgoingIMHandler->messageFinished(); } return MojErrNone; }
MojErr OnEnabledHandler::addImLoginStateResult(MojObject& payload, MojErr err) { MojLogTrace(IMServiceApp::s_log); if (err != MojErrNone) { MojString error; MojErrToString(err, error); MojLogCritical(IMServiceApp::s_log, _T("addLoginStateResult failed: error %d - %s"), err, error.data()); //TODO retry adding the record. Not worrying about this for now because the add would only fail in // extreme conditions. } return err; }
/** * callback from the save message call. */ MojErr IncomingIMHandler::IMSaveMessageResult(MojObject& result, MojErr saveErr) { MojLogTrace(IMServiceApp::s_log); if (saveErr) { MojString error; MojErrToString(saveErr, error); MojLogError(IMServiceApp::s_log, _T("database put failed. error %d - %s"), saveErr, error.data()); } else { IMServiceHandler::logMojObjectJsonString(_T("database put success: %s"), result); } return MojErrNone; }
MojErr formatErrResponse(MojErr errExpected, MojObject& objOut) { MojString errTxt; MojErr err = MojErrToString(errExpected, errTxt); MojTestErrCheck(err); // format expected error return err = objOut.putBool(MojServiceMessage::ReturnValueKey, false); MojErrCheck(err); err = objOut.putInt(MojServiceMessage::ErrorCodeKey, (MojInt64)errExpected); MojErrCheck(err); err = objOut.putString(MojServiceMessage::ErrorTextKey, errTxt); MojErrCheck(err); return MojErrNone; }
MojErr IMServiceHandler::onEnabled(MojServiceMessage* serviceMsg, const MojObject payload) { MojRefCountedPtr<OnEnabledHandler> handler(new OnEnabledHandler(m_service)); MojErr err = handler->start(payload); if (err == MojErrNone) { serviceMsg->replySuccess(); } else { MojString error; MojString msg; MojErrToString(err, error); msg.format(_T("OnEnabledHandler.start() failed: error %d - %s"), err, error.data()); MojLogError(IMServiceApp::s_log, _T("%s"), msg.data()); serviceMsg->replyError(err); } return MojErrNone; }
/* * Callback for DB save results * * Status change to "waiting-for-connection" */ MojErr SendOneCommandHandler::imSaveCommandResult(MojObject& result, MojErr saveErr) { MojLogTrace(IMServiceApp::s_log); if (saveErr) { MojString error; MojErrToString(saveErr, error); MojLogError(IMServiceApp::s_log, _T("save imcommand failed. error %d - %s"), saveErr, error.data()); } else { MojString json; result.toJson(json); MojLogInfo(IMServiceApp::s_log, _T("save imcommand %s. response: %s"), this->m_currentCmdDbId.data(), json.data()); } return MojErrNone; }
/** * Callback from the save buddy in contact DB call. */ MojErr SendOneCommandHandler::addContactResult(MojObject& result, MojErr saveErr) { MojLogTrace(IMServiceApp::s_log); if (saveErr) { MojString error; MojErrToString(saveErr, error); MojLogError(IMServiceApp::s_log, _T("addContactResult failed. error %d - %s"), saveErr, error.data()); } else { IMServiceHandler::logMojObjectJsonString(_T("addContactResult success: %s"), result); } // last callback - tell the outgoing Command handler we are finally done m_outgoingIMHandler->messageFinished(); return MojErrNone; }
/* * Receive a request for authorization (accept/deny) from another user to add us to their buddy list */ bool IMServiceHandler::receivedBuddyInvite(const char* serviceName, const char* username, const char* usernameFrom, const char* customMessage) { // log the parameters MojLogInfo (IMServiceApp::s_log, _T("receivedBuddyInvite - serviceName: %s username: %s usernameFrom: %s message: %s"), serviceName, username, usernameFrom, customMessage); // Create an imcommand for the application to prompt user for acceptance MojRefCountedPtr<BuddyStatusHandler> buddyStatusHandler(new BuddyStatusHandler(m_service)); MojErr err = buddyStatusHandler->receivedBuddyInvite(serviceName, username, usernameFrom, customMessage); if (err) { MojString error; MojErrToString(err, error); MojLogError(IMServiceApp::s_log, _T("receivedBuddyInvite failed: %d - %s"), err, error.data()); return false; } return true; }
/* * Callback for DB save results * Status changes */ MojErr SendOneMessageHandler::imSaveMessageResult(MojObject& result, MojErr saveErr) { MojLogTrace(IMServiceApp::s_log); if (saveErr) { MojString error; MojErrToString(saveErr, error); MojLogError(IMServiceApp::s_log, _T("save sent im failed. error %d - %s"), saveErr, error.data()); } else { MojString json; result.toJson(json); MojLogInfo(IMServiceApp::s_log, _T("save sent message %s. response: %s"), this->m_currentMsgdbId.data(), json.data()); } // tell the outgoing message handler we are done m_outgoingIMHandler->messageFinished(); return MojErrNone; }
/* * Callback for DB delete results * deleted buddyStatus record */ MojErr SendOneCommandHandler::removeContactResult(MojObject& result, MojErr delErr) { MojLogTrace(IMServiceApp::s_log); if (delErr) { MojString error; MojErrToString(delErr, error); MojLogError(IMServiceApp::s_log, _T("removeContactResult failed. error %d - %s"), delErr, error.data()); } else { MojString json; result.toJson(json); MojLogInfo(IMServiceApp::s_log, _T("removeContactResult response: %s"), json.data()); } // last callback - tell the outgoing Command handler we are finally done m_outgoingIMHandler->messageFinished(); return MojErrNone; }
/* * Enabling an IM account requires the following * add com.palm.imloginstate.libpurple record */ MojErr OnEnabledHandler::accountEnabled() { MojLogTrace(IMServiceApp::s_log); MojLogInfo(IMServiceApp::s_log, _T("accountEnabled id=%s, serviceName=%s"), m_accountId.data(), m_serviceName.data()); // first see if an imloginstate record already exists for this account. This can happen on an OTA update or restore // construct our where clause - find by username and servicename MojDbQuery query; query.where("serviceName", MojDbQuery::OpEq, m_serviceName); query.where("username", MojDbQuery::OpEq, m_username); query.from(IM_LOGINSTATE_KIND); MojErr err = m_dbClient.find(this->m_findImLoginStateSlot, query); if (err) { MojString error; MojErrToString(err, error); MojLogError(IMServiceApp::s_log, _T("accountEnabled: dbClient.find() failed: error %d - %s"), err, error.data()); // query failed - not much we can do here... } return err; }
/* * Enabling an IM account requires the following * add com.palm.imloginstate.libpurple record */ MojErr OnEnabledHandler::accountEnabled(const MojString& accountId, const MojString& serviceName, const MojString& username) { //TODO: first issue a merge in case the account already exists? MojLogTrace(IMServiceApp::s_log); MojLogInfo(IMServiceApp::s_log, _T("accountEnabled id=%s, serviceName=%s"), accountId.data(), serviceName.data()); MojObject imLoginState; imLoginState.putString(_T("_kind"), IM_LOGINSTATE_KIND); imLoginState.put(_T("accountId"), accountId); imLoginState.put(_T("serviceName"), serviceName); imLoginState.put(_T("username"), username); imLoginState.putString(_T("state"), LOGIN_STATE_OFFLINE); imLoginState.putInt(_T("availability"), PalmAvailability::ONLINE); //default to online so we automatically login at first MojErr err = m_dbClient.put(m_addImLoginStateSlot, imLoginState); if (err != MojErrNone) { MojString error; MojErrToString(err, error); MojLogError(IMServiceApp::s_log, _T("OnEnabledHandler db.put() failed: error %d - %s"), err, error.data()); } return err; }
MojErr MojDbLunaServiceDb::recoverDb(MojDbEnv* env, const MojChar* dir, const MojObject& conf) { MojErr err; if (m_recoveryScriptPath.empty()) { LOG_ERROR(MSGID_LUNA_SERVICE_DB_OPEN,0, "No recovery script, close database"); return MojErrDbFatal; } int recoveryResult = system(m_recoveryScriptPath.data()); if (recoveryResult != 0) { LOG_ERROR(MSGID_LUNA_SERVICE_DB_OPEN, 3, PMLOGKS("recoveryScript", m_recoveryScriptPath.data()), PMLOGKFV("scriptExecResult", "%i", recoveryResult), PMLOGKS("dbdir", dir), "Can't recovery database with help of recovery script"); return MojErrDbFatal; // close database and stop process } LOG_INFO(MSGID_LUNA_SERVICE_DB_OPEN, 0, "Recovery database success, reopen database" ); err = openDb(env, dir, conf); if (err != MojErrNone) { MojString msg; MojErrToString(err, msg); LOG_ERROR(MSGID_LUNA_SERVICE_DB_OPEN, 3, PMLOGKS("dbdir", dir), PMLOGKS("dbdata", msg.data()), PMLOGKFV("dberror", "%d", err), "Error re-opening database after recovery"); return err; } return MojErrNone; }
/* * Change in buddy status */ bool IMServiceHandler::updateBuddyStatus(const char* accountId, const char* serviceName, const char* username, int availability, const char* customMessage, const char* groupName, const char* buddyAvatarLoc) { MojLogTrace(IMServiceApp::s_log); // log the parameters MojLogInfo (IMServiceApp::s_log, _T("updateBuddyStatus - accountId: %s, serviceName: %s, username: %s, availability: %i, customMessage: %s, groupName: %s, buddyAvatarLoc: %s"), accountId, serviceName, username, availability, customMessage, groupName, buddyAvatarLoc); // handle the message MojRefCountedPtr<BuddyStatusHandler> buddyStatusHandler(new BuddyStatusHandler(m_service)); MojErr err = buddyStatusHandler->updateBuddyStatus(accountId, serviceName, username, availability, customMessage, groupName, buddyAvatarLoc); if (err) { MojString error; MojErrToString(err, error); MojLogError(IMServiceApp::s_log, _T("updateBuddyStatus failed: %d - %s"), err, error.data()); return false; } return true; }
MojErr MojDbKindEngine::loadKinds(MojDbReq& req) { MojAssert(isOpen()); MojAssertWriteLocked(m_db->m_schemaLock); MojLogTrace(s_log); MojDbQuery query; MojErr err = query.from(KindKindId); MojErrCheck(err); MojDbCursor cursor; err = m_db->find(query, cursor, req); MojErrCheck(err); for (;;) { MojObject obj; bool found = false; err = cursor.get(obj, found); MojErrCheck(err); if (!found) break; // load kind MojErr loadErr = err = putKind(obj, req); MojErrCatchAll(err) { MojString id; bool found = false; MojErr err = obj.get(MojDbServiceDefs::IdKey, id, found); MojErrCheck(err); MojString errStr; MojErrToString(loadErr, errStr); MojLogError(s_log, _T("error loading kind '%s' - %s"), id.data(), errStr.data()); } } err = cursor.close(); MojErrCheck(err); return MojErrNone; }
MojErr MojService::dispatchRequest(MojServiceMessage* msg) { MojAssert(msg); MojAssertMutexUnlocked(m_mutex); MojLogTrace(s_log); // get payload MojObject payload; MojErr reqErr; MojErr err = reqErr = msg->payload(payload); MojErrCatchAll(err) { return msg->replyError(reqErr); } // get callback Category* category = msg->serviceCategory(); MojAssert(category); MojAssert(category && category->m_service == this); // invoke err = reqErr = category->m_handler->invoke(msg->method(), msg, payload); MojErrCatchAll(err) { MojString payloadStr; (void) payload.toJson(payloadStr); MojString errStr; (void) MojErrToString(reqErr, errStr); MojLogError(s_log, _T("%s (%d) - sender='%s' method='%s' payload='%s'"), errStr.data(), (int) reqErr, msg->senderName(), msg->method(), payloadStr.data()); if (msg->numReplies() == 0) { return msg->replyError(reqErr); } } if (msg->numReplies() == 0 && msg->hasData()) { return msg->reply(); } return MojErrNone; }
MojErr MojDbLunaServiceDb::open(MojGmainReactor& reactor, MojDbEnv* env, const MojChar* serviceName, const MojChar* dir, const MojObject& conf) { LOG_TRACE("Entering function %s", __FUNCTION__); // open service MojErr err = m_service.open(serviceName); MojErrCheck(err); err = m_service.attach(reactor.impl()); MojErrCheck(err); // open handler err = m_handler->open(); MojErrCheck(err); err = m_service.addCategory(MojDbServiceDefs::Category, m_handler.get()); MojErrCheck(err); LOG_DEBUG("[MojDb] service name: %s", serviceName); // open db err = openDb(env, dir, conf); if (err != MojErrNone) { MojString msg; MojErrToString(err, msg); LOG_WARNING(MSGID_LUNA_SERVICE_DB_OPEN, 3, PMLOGKS("dbdir", dir), PMLOGKS("dbdata", msg.data()), PMLOGKFV("dberror", "%d", err), "Can't open database"); err = recoverDb(env, dir, conf); MojErrCheck(err); } return err; }
/* * Add buddy record to the buddyStatus and contact DB */ MojErr SendOneCommandHandler::addBuddyToDb() { // first we have to figure out the accountId - query ImLoginState //construct our where clause - find by username and servicename MojDbQuery query; query.where("serviceName", MojDbQuery::OpEq, m_serviceName); query.where("username", MojDbQuery::OpEq, m_username); query.from(IM_LOGINSTATE_KIND); // call del // virtual MojErr del(Signal::SlotRef handler, const MojDbQuery& query, // MojUInt32 flags = MojDb::FlagNone); MojErr err = m_dbClient.find(this->m_findAccountIdForAddSlot, query); if (err) { MojString error; MojErrToString(err, error); MojLogError(IMServiceApp::s_log, _T("addBuddy: dbClient.find() failed: error %d - %s"), err, error.data()); // query failed - not much we can do here... m_outgoingIMHandler->messageFinished(); } return MojErrNone; }
/* * Send one IMMessage that was in the outbox. See java code in TransportCallbackThread.sendImHelper() * Change the message status from pending to either successful or failed in the DB when done * Set timestamp on the message and save it. * * errors returned up to OutgoingIMHandler * * send payload format: * im.libpurple.palm //sendMessage string=“{"serviceName":"gmail","usernameTo":"*****@*****.**","messageText":"Test send from phone","username":"******"}” * luna://im.libpurple.palm/sendMessage '{"serviceName":"aol","usernameTo":"palm","messageText":"test send IM","username":"******"}' * * @param imMsg - imMessage that was read out of the DB with status pending and folder set to outbox */ MojErr SendOneMessageHandler::doSend(const MojObject imMsg) { MojErr err = MojErrNone; // body // text should be saved unescaped in the DB bool found = false; err = imMsg.get(MOJDB_MSG_TEXT, m_messageText, found); MojErrCheck(err); // userNameTo - use "to" address MojObject addrArray; // array found = imMsg.get(MOJDB_TO, addrArray); // now read the address out of the object MojObject toAddrObject; if (found) { found = addrArray.at(0, toAddrObject); err = toAddrObject.get(MOJDB_ADDRESS, m_usernameTo, found); MojErrCheck(err); } // user = "******" address MojObject fromAddrObject; found = imMsg.get(MOJDB_FROM, fromAddrObject); if (found) { err = fromAddrObject.get(MOJDB_ADDRESS, m_username, found); MojErrCheck(err); } // serviceName err = imMsg.get(MOJDB_SERVICENAME, m_serviceName, found); MojErrCheck(err); // get the id so we can update the status in the DB after sending err = imMsg.getRequired("_id", m_currentMsgdbId); MojErrCheck(err); // need to search buddy list to see if this user is on it. // first we have to figure out the accountId - query ImLoginState // construct our where clause - find by username and servicename MojDbQuery query; query.where("serviceName", MojDbQuery::OpEq, m_serviceName); query.where("username", MojDbQuery::OpEq, m_username); query.from(IM_LOGINSTATE_KIND); // call del // virtual MojErr del(Signal::SlotRef handler, const MojDbQuery& query, // MojUInt32 flags = MojDb::FlagNone); err = m_dbClient.find(this->m_findAccountIdSlot, query); if (err) { MojString error; MojErrToString(err, error); MojLogError(IMServiceApp::s_log, _T("doSend: dbClient.find() failed: error %d - %s"), err, error.data()); // tell the outgoing Command handler we are done failMessage(ERROR_SEND_GENERIC_ERROR); } return MojErrNone; }
/* * Result callback for the listAccountsTemplate * * result list form: * { "templateId": "com.palm.aol", "loc_name": "AOL", "validator": "palm://com.palm.imaccountvalidator/checkCredentials", "capabilityProviders": [ { "capability": "MESSAGING", "capabilitySubtype": "IM", "id": "com.palm.aol.aim", "loc_name": "AIM", "loc_shortName": "AIM", "icon": { "loc_32x32": "/usr/palm/public/accounts/com.palm.aol/images/aim32x32.png", "loc_48x48": "/usr/palm/public/accounts/com.palm.aol/images/aim48x48.png", "splitter": "/usr/palm/public/accounts/com.palm.aol/images/aim_transport_splitter.png" }, "implementation": "palm://com.palm.imlibpurple/", "onEnabled": "palm://com.palm.imlibpurple/onEnabled", "serviceName": "type_aim", "dbkinds": { "immessage": "com.palm.immessage.libpurple", "imcommand": "com.palm.imcommand.libpurple" } } ] }, */ MojErr SendOneMessageHandler::listAccountResult(MojObject& result, MojErr err) { if (err) { MojString error; MojErrToString(err, error); MojLogError(IMServiceApp::s_log, _T("listAccountTemplates failed. error %d - %s"), err, error.data()); // not much we can do here...don't leave message pending failMessage(ERROR_SEND_GENERIC_ERROR); } else { IMServiceHandler::logMojObjectJsonString(_T("listAccountTemplates success: %s"), result); // if the flag is not there, assume we can send to a non buddy // if we got here, the message is going to a non buddy bool nonBuddyChatOK = true; // find the template and provider for our service and look for "chatWithNonBuddies":false // "results" in result MojObject results; result.get(_T("results"), results); // check to see if array is empty - should not be... if (!results.empty()){ // find the messaging capability object MojObject capability; MojObject accountTemplate; MojString serviceName; bool found = false; bool foundService = false; MojObject::ConstArrayIterator templItr = results.arrayBegin(); while (templItr != results.arrayEnd()) { accountTemplate = *templItr; IMServiceHandler::logMojObjectJsonString(_T("listAccountTemplates template: %s"), accountTemplate); // now find the capabilityProviders array MojObject providersArray; found = accountTemplate.get(XPORT_CAPABILITY_PROVIDERS, providersArray); if (found) { MojObject::ConstArrayIterator capItr = providersArray.arrayBegin(); while (capItr != providersArray.arrayEnd()) { capability = *capItr; IMServiceHandler::logMojObjectJsonString(_T("listAccountTemplates capability: %s"), capability); // find the one for our service capability.get(XPORT_SERVICE_TYPE, serviceName, found); if (found) { MojLogInfo(IMServiceApp::s_log, _T("listAccountTemplates - capability service %s. "), serviceName.data()); if (0 == serviceName.compare(m_serviceName)) { foundService = true; found = capability.get("chatWithNonBuddies", nonBuddyChatOK); MojLogInfo(IMServiceApp::s_log, _T("listAccountTemplates - found service %s. found %d, chatWithNonBuddies %d"), m_serviceName.data(), found, nonBuddyChatOK); break; } } else MojLogError(IMServiceApp::s_log, _T("error: no service name in capability provider")); capItr++; } } else MojLogError(IMServiceApp::s_log, _T("error: no provider array in templateId")); if (foundService) break; templItr++; } } if (nonBuddyChatOK){ // send to the transport sendToTransport(); } else { // permanent error - no retry option MojLogError(IMServiceApp::s_log, _T("error: Trying to send to user that is not on buddy list")); failMessage(ERROR_SEND_TO_NON_BUDDY); } } return MojErrNone; }
MojErr OnEnabledHandler::findImLoginStateResult(MojObject& payload, MojErr err) { MojLogTrace(IMServiceApp::s_log); if (err != MojErrNone) { MojString error; MojErrToString(err, error); MojLogCritical(IMServiceApp::s_log, _T("findImLoginStateResult failed: error %d - %s"), err, error.data()); } else { // "results" in result MojObject results; payload.get(_T("results"), results); // check to see if array is empty - normally it will be if this is a newly created account. There should never be more than 1 item here if (!results.empty()){ IMServiceHandler::logMojObjectJsonString(_T("findImLoginStateResult found existing imLoginState record: %s"), payload); // if there is a record already, make sure the account id matches. MojObject loginState; MojObject::ConstArrayIterator itr = results.arrayBegin(); bool foundOne = false; while (itr != results.arrayEnd()) { if (foundOne) { MojLogError(IMServiceApp::s_log, _T("findImLoginStateResult: found more than one ImLoginState with same username/serviceName - using the first one")); break; } loginState = *itr; foundOne = true; itr++; } MojString accountId; MojErr err = loginState.getRequired("accountId", accountId); if (err) { MojLogError(IMServiceApp::s_log, _T("findImLoginStateResult: missing accountId in loginState entry")); } if (0 != accountId.compare(m_accountId)) { MojLogError(IMServiceApp::s_log, _T("findImLoginStateResult: existing loginState record does not have matching account id. accountId = %s"), accountId.data()); // delete this record MojObject idsToDelete; MojString dbId; err = loginState.getRequired("_id", dbId); if (err) { MojLogError(IMServiceApp::s_log, _T("findImLoginStateResult: missing dbId in loginState entry")); } else { idsToDelete.push(dbId); // luna://com.palm.db/del '{"ids":[2]}' MojLogInfo(IMServiceApp::s_log, _T("findImLoginStateResult: deleting loginState entry id: %s"), dbId.data()); err = m_dbClient.del(this->m_deleteImLoginStateSlot, idsToDelete.arrayBegin(), idsToDelete.arrayEnd()); if (err != MojErrNone) { MojString error; MojErrToString(err, error); MojLogError(IMServiceApp::s_log, _T("findImLoginStateResult: db.del() failed: error %d - %s"), err, error.data()); } } } // if the account id matches, leave the old record and we are done else return MojErrNone; } // no existing record found or the old one was deleted - create a new one MojLogInfo(IMServiceApp::s_log, _T("findImLoginStateResult: no matching loginState record found for %s, %s. creating a new one"), m_username.data(), m_serviceName.data()); MojObject imLoginState; imLoginState.putString(_T("_kind"), IM_LOGINSTATE_KIND); imLoginState.put(_T("accountId"), m_accountId); imLoginState.put(_T("serviceName"), m_serviceName); imLoginState.put(_T("username"), m_username); imLoginState.put(_T("capabilityId"), m_capabilityProviderId); imLoginState.putString(_T("state"), LOGIN_STATE_OFFLINE); imLoginState.putInt(_T("availability"), PalmAvailability::ONLINE); //default to online so we automatically login at first imLoginState.put(_T("config"), m_config); MojErr err = m_dbClient.put(m_addImLoginStateSlot, imLoginState); if (err != MojErrNone) { MojString error; MojErrToString(err, error); MojLogError(IMServiceApp::s_log, _T("findImLoginStateResult: db.put() failed: error %d - %s"), err, error.data()); } } return err; }