123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330 |
- /*
- * Copyright 2005 - 2016 Zarafa and its licensors
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
- */
- #include <new>
- #include <kopano/platform.h>
- #include "ECDatabase.h"
- #include <mapidefs.h>
- #include <edkmdb.h>
- #include "ECSecurity.h"
- #include "ECSessionManager.h"
- #include "ECUserStoreTable.h"
- #include "ECGenProps.h"
- #include "ECSession.h"
- #include <kopano/stringutil.h>
- namespace KC {
- // 1 == MAPI_STORE.. does it even matter?
- ECUserStoreTable::ECUserStoreTable(ECSession *lpSession, unsigned int ulFlags, const ECLocale &locale) :
- ECGenericObjectTable(lpSession, 1, ulFlags, locale)
- {
- // Set callback function for queryrowdata (again?)
- m_lpfnQueryRowData = QueryRowData;
- }
- ECRESULT ECUserStoreTable::Create(ECSession *lpSession, unsigned int ulFlags, const ECLocale &locale, ECUserStoreTable **lppTable)
- {
- *lppTable = new(std::nothrow) ECUserStoreTable(lpSession, ulFlags, locale);
- if (*lppTable == nullptr)
- return KCERR_NOT_ENOUGH_MEMORY;
- (*lppTable)->AddRef();
- return erSuccess;
- }
- ECRESULT ECUserStoreTable::QueryRowData(ECGenericObjectTable *lpThis, struct soap *soap, ECSession *lpSession, ECObjectTableList* lpRowList, struct propTagArray *lpsPropTagArray, void* lpObjectData, struct rowSet **lppRowSet, bool bCacheTableData, bool bTableLimit)
- {
- auto pThis = dynamic_cast<ECUserStoreTable *>(lpThis);
- if (pThis == nullptr)
- return KCERR_INVALID_PARAMETER;
- struct rowSet *lpsRowSet = NULL;
- gsoap_size_t i;
- GUID sZeroGuid = {0};
- lpsRowSet = s_alloc<rowSet>(soap);
- lpsRowSet->__size = 0;
- lpsRowSet->__ptr = NULL;
- if(lpRowList->empty()) {
- *lppRowSet = lpsRowSet;
- return erSuccess;
- }
- // We return a square array with all the values
- lpsRowSet->__size = lpRowList->size();
- lpsRowSet->__ptr = s_alloc<propValArray>(soap, lpsRowSet->__size);
- memset(lpsRowSet->__ptr, 0, sizeof(propValArray) * lpsRowSet->__size);
- // Allocate memory for all rows
- for (i = 0; i < lpsRowSet->__size; ++i) {
- lpsRowSet->__ptr[i].__size = lpsPropTagArray->__size;
- lpsRowSet->__ptr[i].__ptr = s_alloc<propVal>(soap, lpsPropTagArray->__size);
- memset(lpsRowSet->__ptr[i].__ptr, 0, sizeof(propVal) * lpsPropTagArray->__size);
- }
- i = 0;
- for (const auto &row : *lpRowList) {
- for (gsoap_size_t k = 0; k < lpsPropTagArray->__size; ++k) {
- lpsRowSet->__ptr[i].__ptr[k].ulPropTag = PROP_TAG(PT_ERROR, lpsPropTagArray->__ptr[k]);
- lpsRowSet->__ptr[i].__ptr[k].__union = SOAP_UNION_propValData_ul;
- lpsRowSet->__ptr[i].__ptr[k].Value.ul = KCERR_NOT_FOUND;
- switch (PROP_ID(lpsPropTagArray->__ptr[k])) {
- case PROP_ID(PR_INSTANCE_KEY):
- // generate key
- lpsRowSet->__ptr[i].__ptr[k].__union = SOAP_UNION_propValData_bin;
- lpsRowSet->__ptr[i].__ptr[k].ulPropTag = PR_INSTANCE_KEY;
- lpsRowSet->__ptr[i].__ptr[k].Value.bin = s_alloc<xsd__base64Binary>(soap);
- lpsRowSet->__ptr[i].__ptr[k].Value.bin->__size = sizeof(sObjectTableKey);
- lpsRowSet->__ptr[i].__ptr[k].Value.bin->__ptr = s_alloc<unsigned char>(soap, sizeof(sObjectTableKey));
- memcpy(lpsRowSet->__ptr[i].__ptr[k].Value.bin->__ptr, &row, sizeof(sObjectTableKey));
- break;
- case PROP_ID(PR_EC_USERNAME):
- if (!pThis->m_mapUserStoreData[row.ulObjId].strUsername.empty()) {
- lpsRowSet->__ptr[i].__ptr[k].ulPropTag = lpsPropTagArray->__ptr[k];
- lpsRowSet->__ptr[i].__ptr[k].__union = SOAP_UNION_propValData_lpszA;
- lpsRowSet->__ptr[i].__ptr[k].Value.lpszA = s_strcpy(soap, const_cast<char *>(pThis->m_mapUserStoreData[row.ulObjId].strUsername.c_str()));
- }
- break;
- case PROP_ID(PR_DISPLAY_NAME):
- if (!pThis->m_mapUserStoreData[row.ulObjId].strGuessname.empty()) {
- lpsRowSet->__ptr[i].__ptr[k].ulPropTag = lpsPropTagArray->__ptr[k];
- lpsRowSet->__ptr[i].__ptr[k].__union = SOAP_UNION_propValData_lpszA;
- lpsRowSet->__ptr[i].__ptr[k].Value.lpszA = s_strcpy(soap, const_cast<char *>(pThis->m_mapUserStoreData[row.ulObjId].strGuessname.c_str()));
- }
- break;
- case PROP_ID(PR_EC_STOREGUID):
- if (pThis->m_mapUserStoreData[row.ulObjId].sGuid != sZeroGuid) {
- lpsRowSet->__ptr[i].__ptr[k].ulPropTag = lpsPropTagArray->__ptr[k];
- lpsRowSet->__ptr[i].__ptr[k].__union = SOAP_UNION_propValData_bin;
- lpsRowSet->__ptr[i].__ptr[k].Value.bin = s_alloc<xsd__base64Binary>(soap);
- lpsRowSet->__ptr[i].__ptr[k].Value.bin->__size = sizeof(GUID);
- lpsRowSet->__ptr[i].__ptr[k].Value.bin->__ptr = s_alloc<unsigned char>(soap, sizeof(GUID));
- memcpy(lpsRowSet->__ptr[i].__ptr[k].Value.bin->__ptr, &pThis->m_mapUserStoreData[row.ulObjId].sGuid, sizeof(GUID));
- }
- break;
- case PROP_ID(PR_EC_STORETYPE):
- lpsRowSet->__ptr[i].__ptr[k].ulPropTag = lpsPropTagArray->__ptr[k];
- lpsRowSet->__ptr[i].__ptr[k].__union = SOAP_UNION_propValData_ul;
- lpsRowSet->__ptr[i].__ptr[k].Value.ul = pThis->m_mapUserStoreData[row.ulObjId].ulStoreType;
- break;
- case PROP_ID(PR_EC_COMPANYID):
- if (pThis->m_mapUserStoreData[row.ulObjId].ulCompanyId != 0) {
- lpsRowSet->__ptr[i].__ptr[k].ulPropTag = lpsPropTagArray->__ptr[k];
- lpsRowSet->__ptr[i].__ptr[k].__union = SOAP_UNION_propValData_ul;
- lpsRowSet->__ptr[i].__ptr[k].Value.ul = pThis->m_mapUserStoreData[row.ulObjId].ulCompanyId;
- }
- break;
- case PROP_ID(PR_EC_COMPANY_NAME):
- if (!pThis->m_mapUserStoreData[row.ulObjId].strCompanyName.empty()) {
- lpsRowSet->__ptr[i].__ptr[k].ulPropTag = lpsPropTagArray->__ptr[k];
- lpsRowSet->__ptr[i].__ptr[k].__union = SOAP_UNION_propValData_lpszA;
- lpsRowSet->__ptr[i].__ptr[k].Value.lpszA = s_strcpy(soap, const_cast<char *>(pThis->m_mapUserStoreData[row.ulObjId].strCompanyName.c_str()));
- }
- break;
- case PROP_ID(PR_STORE_ENTRYID):
- // ignore errors
- ECGenProps::GetPropComputedUncached(soap, NULL,
- lpSession, PR_STORE_ENTRYID,
- pThis->m_mapUserStoreData[row.ulObjId].ulObjId,
- 0, pThis->m_mapUserStoreData[row.ulObjId].ulObjId,
- 0, MAPI_STORE, &lpsRowSet->__ptr[i].__ptr[k]);
- break;
- case PROP_ID(PR_LAST_MODIFICATION_TIME):
- if (pThis->m_mapUserStoreData[row.ulObjId].tModTime != 0) {
- FILETIME ftTmp;
- UnixTimeToFileTime(pThis->m_mapUserStoreData[row.ulObjId].tModTime, &ftTmp);
- lpsRowSet->__ptr[i].__ptr[k].ulPropTag = lpsPropTagArray->__ptr[k];
- lpsRowSet->__ptr[i].__ptr[k].__union = SOAP_UNION_propValData_hilo;
- lpsRowSet->__ptr[i].__ptr[k].Value.hilo = s_alloc<struct hiloLong>(soap);
- lpsRowSet->__ptr[i].__ptr[k].Value.hilo->hi = ftTmp.dwHighDateTime;
- lpsRowSet->__ptr[i].__ptr[k].Value.hilo->lo = ftTmp.dwLowDateTime;
- }
- break;
- case PROP_ID(PR_MESSAGE_SIZE_EXTENDED):
- lpsRowSet->__ptr[i].__ptr[k].ulPropTag = lpsPropTagArray->__ptr[k];
- lpsRowSet->__ptr[i].__ptr[k].__union = SOAP_UNION_propValData_li;
- lpsRowSet->__ptr[i].__ptr[k].Value.li = pThis->m_mapUserStoreData[row.ulObjId].ullStoreSize;
- break;
- default:
- lpsRowSet->__ptr[i].__ptr[k].ulPropTag = PROP_TAG(PT_ERROR, lpsPropTagArray->__ptr[k]);
- lpsRowSet->__ptr[i].__ptr[k].__union = SOAP_UNION_propValData_ul;
- lpsRowSet->__ptr[i].__ptr[k].Value.ul = KCERR_NOT_FOUND;
- break;
- };
- }
- ++i;
- }
- *lppRowSet = lpsRowSet;
- return erSuccess;
- }
- ECRESULT ECUserStoreTable::Load() {
- ECRESULT er = erSuccess;
- ECListIntIterator i;
- ECDatabase *lpDatabase = NULL;
- DB_RESULT lpDBResult;
- DB_ROW lpDBRow = NULL;
- DB_LENGTHS lpDBLength = NULL;
- std::string strQuery;
- std::list<unsigned int> lstObjIds;
- ECUserStore sUserStore;
- int iRowId;
- ECUserManagement *lpUserManagement = lpSession->GetUserManagement();
- ECSecurity *lpSecurity = lpSession->GetSecurity();
- objectdetails_t sUserDetails;
- GUID sZeroGuid = {0};
- objectclass_t objclass = OBJECTCLASS_UNKNOWN;
- objectdetails_t sDetails;
- enum cols { USERID = 0, EXTERNID, OBJCLASS, UCOMPANY, STOREGUID, STORETYPE, USERNAME, SCOMPANY, HIERARCHYID, STORESIZE, MODTIME_HI, MODTIME_LO };
- er = lpSession->GetDatabase(&lpDatabase);
- if (er != erSuccess)
- return er;
- Clear();
- /*
- * The next query will first get the list of all users with their primary store details or NULL if
- * no primary store was found. Secondly it will get the list of all stores with their owner or NULL
- * if they're detached.
- * The most important difference id that the first query will return no store for users without a
- * primary store, even if they do have an archive store attached, while the second query will
- * return all stores types.
- */
- strQuery =
- " SELECT u.id, u.externid, u.objectclass, u.company, s.guid, s.type, s.user_name, s.company, s.hierarchy_id, p.val_longint, m.val_hi, m.val_lo FROM users AS u"
- " LEFT JOIN stores AS s ON s.user_id=u.id AND s.type=" + stringify(ECSTORE_TYPE_PRIVATE) + " LEFT JOIN hierarchy AS h ON h.id=s.hierarchy_id"
- " LEFT JOIN properties AS p ON p.hierarchyid=s.hierarchy_id and p.tag=0x0E08 and p.type=0x14"
- " LEFT JOIN properties AS m ON m.hierarchyid=s.hierarchy_id and m.tag=0x66A2 and m.type=0x40"
- " UNION"
- " SELECT u.id, u.externid, u.objectclass, u.company, s.guid, s.type, s.user_name, s.company, s.hierarchy_id, p.val_longint, m.val_hi, m.val_lo FROM users AS u"
- " RIGHT JOIN stores AS s ON s.user_id=u.id LEFT JOIN hierarchy AS h ON h.id=s.hierarchy_id"
- " LEFT JOIN properties AS p ON p.hierarchyid=s.hierarchy_id and p.tag=0x0E08 and p.type=0x14"
- " LEFT JOIN properties AS m ON m.hierarchyid=s.hierarchy_id and m.tag=0x66A2 and m.type=0x40";
- er = lpDatabase->DoSelect(strQuery, &lpDBResult);
- if(er != erSuccess)
- return er;
- iRowId = 0;
- while(1) {
- lpDBRow = lpDatabase->FetchRow(lpDBResult);
- if(lpDBRow == NULL)
- break;
- lpDBLength = lpDatabase->FetchRowLengths(lpDBResult);
- if (lpDBRow[OBJCLASS])
- objclass = (objectclass_t)atoi(lpDBRow[OBJCLASS]);
- if (lpDBRow[USERID]) {
- sUserStore.ulUserId = atoi(lpDBRow[USERID]);
- if (sUserStore.ulUserId == KOPANO_UID_SYSTEM) // everyone already filtered by object type
- continue;
- } else {
- sUserStore.ulUserId = -1;
- }
- sUserStore.ulCompanyId = 0;
- if (lpDBRow[UCOMPANY])
- sUserStore.ulCompanyId = atoi(lpDBRow[UCOMPANY]);
- if (lpDBRow[SCOMPANY])
- sUserStore.ulCompanyId = atoi(lpDBRow[SCOMPANY]); // might override from user.company
- // check if we're admin over this company
- if (lpSecurity->IsAdminOverUserObject(sUserStore.ulCompanyId) != erSuccess)
- continue;
- if (lpDBRow[EXTERNID]) {
- sUserStore.sExternId.id.assign(lpDBRow[EXTERNID], lpDBLength[EXTERNID]);
- sUserStore.sExternId.objclass = objclass;
- } else {
- sUserStore.sExternId.id.clear();
- sUserStore.sExternId.objclass = OBJECTCLASS_UNKNOWN;
- }
- sUserStore.strUsername.clear();
- // find and override real username if possible
- if (sUserStore.ulUserId != -1 && lpUserManagement->GetObjectDetails(sUserStore.ulUserId, &sUserDetails) == erSuccess) {
- if (lpSession->GetSessionManager()->IsDistributedSupported() &&
- sUserDetails.GetPropString(OB_PROP_S_SERVERNAME).compare(lpSession->GetSessionManager()->GetConfig()->GetSetting("server_name")) != 0)
- continue; // user not on this server
- sUserStore.strUsername = sUserDetails.GetPropString(OB_PROP_S_LOGIN);
- }
- sUserStore.sGuid = sZeroGuid;
- if (lpDBRow[STOREGUID])
- memcpy(&sUserStore.sGuid, lpDBRow[STOREGUID], lpDBLength[STOREGUID]);
- if (lpDBRow[STORETYPE])
- sUserStore.ulStoreType = atoi(lpDBRow[STORETYPE]);
- else
- sUserStore.ulStoreType = ECSTORE_TYPE_PRIVATE; // or invalid value?
-
- if (lpDBRow[USERNAME])
- sUserStore.strGuessname = lpDBRow[USERNAME];
- else
- sUserStore.strGuessname.clear();
- if (sUserStore.ulCompanyId > 0 && lpUserManagement->GetObjectDetails(sUserStore.ulCompanyId, &sDetails) == erSuccess)
- sUserStore.strCompanyName = sDetails.GetPropString(OB_PROP_S_LOGIN);
- if(lpDBRow[HIERARCHYID])
- sUserStore.ulObjId = atoui(lpDBRow[HIERARCHYID]);
- else
- sUserStore.ulObjId = 0;
- sUserStore.tModTime = 0;
- if(lpDBRow[MODTIME_HI] && lpDBRow[MODTIME_LO]) {
- FILETIME ft;
- ft.dwHighDateTime = atoui(lpDBRow[MODTIME_HI]);
- ft.dwLowDateTime = atoui(lpDBRow[MODTIME_LO]);
- sUserStore.tModTime = 0;
- FileTimeToUnixTime(ft, &sUserStore.tModTime);
- }
- if(lpDBRow[STORESIZE])
- sUserStore.ullStoreSize = atoll(lpDBRow[STORESIZE]);
- else
- sUserStore.ullStoreSize = 0;
- // add to table
- lstObjIds.push_back(iRowId);
- // remember details
- m_mapUserStoreData.insert(std::pair<unsigned int, ECUserStore>(iRowId++, sUserStore));
- }
- LoadRows(&lstObjIds, 0);
- return erSuccess;
- }
- } /* namespace KC */
|