void MojoDatabase::UpdateAccountFolders(Signal::SlotRef slot, const MojObject& accountId, const MojObject& inboxFolderId, const MojObject& draftsFolderId, const MojObject& sentFolderId, const MojObject& outboxFolderId, const MojObject& trashFolderId) { MojDbQuery q; MojErr err = q.from(PopAccountAdapter::POP_ACCOUNT_KIND); ErrorToException(err); err = q.where(PopAccountAdapter::ACCOUNT_ID, MojDbQuery::OpEq, accountId); ErrorToException(err); MojObject props; if (!inboxFolderId.undefined()) { err = props.put(EmailAccountAdapter::INBOX_FOLDERID, inboxFolderId); ErrorToException(err); } if (!draftsFolderId.undefined()) { err = props.put(EmailAccountAdapter::DRAFTS_FOLDERID, draftsFolderId); ErrorToException(err); } if (!sentFolderId.undefined()) { err = props.put(EmailAccountAdapter::SENT_FOLDERID, sentFolderId); ErrorToException(err); } if (!outboxFolderId.undefined()) { err = props.put(EmailAccountAdapter::OUTBOX_FOLDERID, outboxFolderId); ErrorToException(err); } if (!trashFolderId.undefined()) { err = props.put(EmailAccountAdapter::TRASH_FOLDERID, trashFolderId); ErrorToException(err); } err = m_dbClient.merge(slot, q, props); ErrorToException(err); }
void PopClient::SetAccount(MojObject& accountId) { MojLogTrace(s_log); assert(m_state == State_None); assert(!accountId.null()); assert(!accountId.undefined()); m_accountId = accountId; m_builderFactory->SetAccountId(m_accountId); }
MojErr MojDb::get(const MojObject& id, MojObject& objOut, bool& foundOut, MojDbReqRef req) { MojLogTrace(s_log); objOut.clear(); foundOut = false; MojObjectBuilder builder; MojErr err = get(&id, &id + 1, builder, req); MojErrCheck(err); objOut = builder.object(); foundOut = !objOut.undefined(); return MojErrNone; }
void MojoDatabase::UpdateEmailParts(Signal::SlotRef slot, const MojObject& emailId, const MojObject& parts, bool autoDownload) { MojObject email; MojErr err = email.put(PopEmailAdapter::ID, emailId); ErrorToException(err); err = email.put(EmailSchema::PARTS, parts); ErrorToException(err); if ((!parts.undefined() && !parts.null() && parts.size() > 0) || !autoDownload) { err = email.put(PopEmailAdapter::DOWNLOADED, true); ErrorToException(err); } MojLogDebug(PopClient::s_log, "Updating email '%s' with parts: '%s'", AsJsonString(emailId).c_str(), AsJsonString(parts).c_str()); err = m_dbClient.merge(slot, email); ErrorToException(err); }
MojErr MojDbSearchTest::initQuery(MojDbQuery& query, const MojChar* queryStr, const MojChar* orderBy, const MojObject& barVal, bool desc) { query.clear(); MojErr err = query.from(_T("SearchTest:1")); MojTestErrCheck(err); MojString val; err = val.assign(queryStr); MojTestErrCheck(err); err = query.where(_T("foo"), MojDbQuery::OpSearch, val, MojDbCollationPrimary); MojTestErrCheck(err); query.desc(desc); if (!barVal.undefined()) { err = query.where(_T("bar"), MojDbQuery::OpEq, barVal); MojTestErrCheck(err); } if (orderBy) { err = query.order(orderBy); MojTestErrCheck(err); } return MojErrNone; }
MojErr PopBusDispatcher::DownloadAttachment(MojServiceMessage* msg, MojObject& payload) { // cancel shut down if it is in shut down state CancelShutdown(); MojLogTrace(s_log); MojLogInfo(s_log, "Downloading parts from client"); try { MojObject accountId; MojErr err = payload.getRequired("accountId", accountId); ErrorToException(err); ClientPtr client = GetOrCreateClient(accountId, false); MojObject folderId; err = payload.getRequired("folderId", folderId); ErrorToException(err); if(folderId.undefined() || folderId.null()) MojErrThrowMsg(MojErrInternal, "Invalid folder ID"); MojObject emailId; err = payload.getRequired("emailId", emailId); ErrorToException(err); MojObject partId; err = payload.getRequired("partId", partId); ErrorToException(err); boost::shared_ptr<DownloadListener> listener(new DownloadListener(msg, emailId, partId)); client->DownloadPart(folderId, emailId, partId, listener); return MojErrNone; } catch (const std::exception& e) { MojErrThrowMsg(MojErrInternal, "exception: %s", e.what()); } return MojErrNone; }
void EmailAdapter::ParseDatabaseObject(const MojObject& obj, Email& email) { MojErr err; MojObject folderId; err = obj.getRequired(FOLDER_ID, folderId); ErrorToException(err); email.SetFolderId(folderId); MojString subject; err = obj.getRequired(SUBJECT, subject); ErrorToException(err); email.SetSubject( std::string(subject) ); MojObject fromAddress; err = obj.getRequired(FROM, fromAddress); ErrorToException(err); email.SetFrom( ParseAddress(fromAddress) ); // Optional replyTo address MojObject replyTo; if(obj.get(REPLY_TO, replyTo) && !replyTo.null()) { email.SetReplyTo( ParseAddress(replyTo) ); } MojInt64 timestamp; err = obj.getRequired(TIMESTAMP, timestamp); ErrorToException(err); email.SetDateReceived(timestamp); // Parse recipients MojObject recipients; err = obj.getRequired(RECIPIENTS, recipients); ErrorToException(err); ParseRecipients(recipients, email); // Parse flags MojObject flags; if (obj.get(FLAGS, flags)) { ParseFlags(flags, email); } // Parse parts MojObject parts; err = obj.getRequired(PARTS, parts); ErrorToException(err); EmailPartList partList; ParseParts(parts, partList); email.SetPartList(partList); MojObject originalMsgId; if (obj.get(ORIGINAL_MSG_ID, originalMsgId)) { email.SetOriginalMsgId(originalMsgId); } MojString draftType; bool hasDraftType = false; err = obj.get(DRAFT_TYPE, draftType, hasDraftType); ErrorToException(err); if (hasDraftType) { email.SetDraftType( ParseDraftType(draftType) ); } MojString priority; bool hasPriority = false; err = obj.get(PRIORITY, priority, hasPriority); ErrorToException(err); // If no priority exists, this will default to normal email.SetPriority(ParsePriority(priority)); email.SetMessageId( DatabaseAdapter::GetOptionalString(obj, MESSAGE_ID) ); email.SetInReplyTo( DatabaseAdapter::GetOptionalString(obj, IN_REPLY_TO) ); // SendStatus // NOTE: This is not being serialized back to the database in SerializeToDatabaseObject MojObject sendStatus; if (obj.get(SEND_STATUS, sendStatus)) { bool isSent = false; if (sendStatus.get(SendStatus::SENT, isSent)) { email.SetSent(isSent); } bool hasFatalError = false; if (sendStatus.get(SendStatus::FATAL_ERROR, hasFatalError)) { email.SetHasFatalError(hasFatalError); } MojInt64 retryCount; if (sendStatus.get(SendStatus::RETRY_COUNT, retryCount)) { email.SetRetryCount(retryCount); } MojObject sendError; if (sendStatus.get(SendStatus::ERROR, sendError)) { MojObject errorCode; if (sendError.get(SendStatusError::ERROR_CODE, errorCode) && !errorCode.null() && !errorCode.undefined()) { email.SetSendError(static_cast<MailError::ErrorCode>(errorCode.intValue())); } } } }
MojErr MojDb::putObj(const MojObject& id, MojObject& obj, const MojObject* oldObj, MojDbStorageItem* oldItem, MojDbReq& req, MojDbOp op, bool checkSchema) { MojLogTrace(s_log); // if nothing changed, don't do the update if (oldObj != NULL && obj == *oldObj) return MojErrNone; // update revision MojInt64 rev; MojErr err = nextId(rev); MojErrCheck(err); err = obj.put(RevKey, rev); MojErrCheck(err); // assign id MojObject putId = id; if (putId.undefined()) { err = m_idGenerator.id(putId); MojErrCheck(err); err = obj.put(IdKey, putId); MojErrCheck(err); } // assign ids to subobjects in arrays - only for regular objects MojString kindName; bool found = false; err = obj.get(MojDb::KindKey, kindName, found); MojErrCheck(err); if (!found) MojErrThrow(MojErrDbKindNotSpecified); if (!kindName.startsWith(MojDbKindEngine::KindKindIdPrefix)) { err = assignIds(obj); MojErrCheck(err); } // validate, update indexes, etc. MojTokenSet tokenSet; err = m_kindEngine.update(&obj, oldObj, req, op, tokenSet, checkSchema); MojErrCheck(err); // serialize object MojDbObjectHeader header(putId); err = header.extractFrom(obj); MojErrCheck(err); MojBuffer buf; err = header.write(buf, m_kindEngine); MojErrCheck(err); MojObjectWriter writer(buf, &tokenSet); err = obj.visit(writer); MojErrCheck(err); // store it in the db if (oldItem) { err = m_objDb->update(putId, buf, oldItem, req.txn()); MojErrCheck(err); } else { err = m_objDb->insert(putId, buf, req.txn()); MojErrCheck(err); } // put header back in the object for response purposes err = header.addTo(obj); MojErrCheck(err); return MojErrNone; }
MojErr MojDb::dumpImpl(MojFile& file, bool backup, bool incDel, const MojObject& revParam, const MojObject& delRevParam, bool skipKinds, MojUInt32& countOut, MojDbReq& req, MojObject* response, const MojChar* keyName, MojSize& bytesWritten, MojSize& warns, MojUInt32 maxBytes) { // query for objects, adding the backup key and rev key if necessary MojDbQuery query; MojErr err = query.from(MojDbKindEngine::RootKindId); MojErrCheck(err); err = query.where(MojDb::DelKey, MojDbQuery::OpEq, incDel); MojErrCheck(err); if (backup) { err = query.where(MojDb::SyncKey, MojDbQuery::OpEq, true); MojErrCheck(err); if (incDel) { err = query.where(MojDb::RevKey, MojDbQuery::OpGreaterThan, delRevParam); MojErrCheck(err); } else { err = query.where(MojDb::RevKey, MojDbQuery::OpGreaterThan, revParam); MojErrCheck(err); } } MojDbCursor cursor; err = findImpl(query, cursor, NULL, req, OpRead); MojErrCheck(err); warns = 0; MojObject curRev; for(;;) { bool found = false; MojObject obj; err = cursor.get(obj, found); // So that we can get as much data as possible from a corrupt database // We simply skip ghost keys and continue if (err == MojErrInternalIndexOnFind) { warns++; continue; } MojErrCheck(err); if (!found) break; if (skipKinds) { MojString kind; err = obj.getRequired(KindKey, kind); MojErrCheck(err); if (kind == MojDbKindEngine::KindKindId) { continue; } } // write out each object, if the backup is full, insert the appropriate incremental key err = dumpObj(file, obj, bytesWritten, maxBytes); MojErrCatch(err, MojErrDbBackupFull) { if (response) { MojErr errBackup = MojErrNone; if (!curRev.undefined()) { errBackup = insertIncrementalKey(*response, keyName, curRev); MojErrCheck(errBackup); } else { errBackup = insertIncrementalKey(*response, keyName, incDel ? delRevParam: revParam); MojErrCheck(errBackup); } errBackup = handleBackupFull(revParam, delRevParam, *response, keyName); MojErrCheck(errBackup); } return MojErrNone; } MojErrCheck(err); err = obj.getRequired(MojDb::RevKey, curRev); MojErrCheck(err); countOut++; } err = cursor.close(); MojErrCheck(err); if (warns > 0) { MojLogWarning(s_log, _T("Finished Backup with %d warnings \n"), (int)warns); } else { MojLogDebug(s_log, _T("Finished Backup with no warnings \n")); } // construct the next incremental key if (response && !curRev.undefined()) { err = insertIncrementalKey(*response, keyName, curRev); MojErrCheck(err); } return MojErrNone; }