mirror of
https://repo.dactyloidae.xyz/Dactyloidae/UXP.git
synced 2026-09-20 23:37:33 +09:00
1132 lines
28 KiB
C++
1132 lines
28 KiB
C++
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
|
/* This Source Code Form is subject to the terms of the Mozilla Public
|
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
|
|
|
#include <tchar.h>
|
|
#include "nscore.h"
|
|
#include "nsOE5File.h"
|
|
#include "wabobject.h"
|
|
#include <algorithm>
|
|
|
|
enum {
|
|
ieidPR_DISPLAY_NAME = 0,
|
|
ieidPR_ENTRYID,
|
|
ieidPR_OBJECT_TYPE,
|
|
ieidMax
|
|
};
|
|
|
|
static const SizedSPropTagArray(ieidMax, ptaEid)=
|
|
{
|
|
ieidMax,
|
|
{
|
|
PR_DISPLAY_NAME,
|
|
PR_ENTRYID,
|
|
PR_OBJECT_TYPE,
|
|
}
|
|
};
|
|
|
|
|
|
enum {
|
|
iemailPR_DISPLAY_NAME = 0,
|
|
iemailPR_ENTRYID,
|
|
iemailPR_EMAIL_ADDRESS,
|
|
iemailPR_OBJECT_TYPE,
|
|
iemailMax
|
|
};
|
|
static const SizedSPropTagArray(iemailMax, ptaEmail)=
|
|
{
|
|
iemailMax,
|
|
{
|
|
PR_DISPLAY_NAME,
|
|
PR_ENTRYID,
|
|
PR_EMAIL_ADDRESS,
|
|
PR_OBJECT_TYPE
|
|
}
|
|
};
|
|
|
|
typedef struct {
|
|
bool multiLine;
|
|
ULONG tag;
|
|
char * pLDIF;
|
|
} AddrImportField;
|
|
|
|
#define kExtraUserFields 10
|
|
AddrImportField extraUserFields[kExtraUserFields] = {
|
|
{true, PR_COMMENT, "description:"},
|
|
{false, PR_BUSINESS_TELEPHONE_NUMBER, "telephonenumber:"},
|
|
{false, PR_HOME_TELEPHONE_NUMBER, "homephone:"},
|
|
{false, PR_COMPANY_NAME, "o:"},
|
|
{false, PR_TITLE, "title:"},
|
|
{false, PR_BUSINESS_FAX_NUMBER, "facsimiletelephonenumber:"},
|
|
{false, PR_LOCALITY, "locality:"},
|
|
{false, PR_STATE_OR_PROVINCE, "st:"},
|
|
{true, PR_STREET_ADDRESS, "streetaddress:"},
|
|
{false, PR_POSTAL_CODE, "postalcode:"}
|
|
};
|
|
|
|
#define kWhitespace " \t\b\r\n"
|
|
|
|
#define TR_OUTPUT_EOL "\r\n"
|
|
|
|
#define kLDIFPerson "objectclass: top" TR_OUTPUT_EOL "objectclass: person" TR_OUTPUT_EOL
|
|
#define kLDIFGroup "objectclass: top" TR_OUTPUT_EOL "objectclass: groupOfNames" TR_OUTPUT_EOL
|
|
|
|
/*********************************************************************************/
|
|
|
|
|
|
// contructor for CWAB object
|
|
//
|
|
// pszFileName - FileName of WAB file to open
|
|
// if no file name is specified, opens the default
|
|
//
|
|
CWAB::CWAB(nsIFile *file)
|
|
{
|
|
// Here we load the WAB Object and initialize it
|
|
m_pUniBuff = NULL;
|
|
m_uniBuffLen = 0;
|
|
|
|
m_bInitialized = false;
|
|
m_lpAdrBook = NULL;
|
|
m_lpWABObject = NULL;
|
|
m_hinstWAB = NULL;
|
|
|
|
{
|
|
TCHAR szWABDllPath[MAX_PATH];
|
|
DWORD dwType = 0;
|
|
ULONG cbData = sizeof(szWABDllPath);
|
|
HKEY hKey = NULL;
|
|
|
|
*szWABDllPath = '\0';
|
|
|
|
// First we look under the default WAB DLL path location in the
|
|
// Registry.
|
|
// WAB_DLL_PATH_KEY is defined in wabapi.h
|
|
//
|
|
if (ERROR_SUCCESS == RegOpenKeyEx(HKEY_LOCAL_MACHINE, WAB_DLL_PATH_KEY, 0, KEY_READ, &hKey)) {
|
|
RegQueryValueEx(hKey, "", NULL, &dwType, (LPBYTE) szWABDllPath, &cbData);
|
|
if (dwType == REG_EXPAND_SZ) {
|
|
// Expand the environment variables
|
|
DWORD bufferSize = ExpandEnvironmentStrings(szWABDllPath, NULL, 0);
|
|
if (bufferSize && bufferSize < MAX_PATH) {
|
|
TCHAR tmp[MAX_PATH];
|
|
ExpandEnvironmentStrings(szWABDllPath, tmp, bufferSize);
|
|
_tcscpy(szWABDllPath, tmp);
|
|
}
|
|
else {
|
|
// This is an error condition. Nothing else is initialized yet, so simply return.
|
|
return;
|
|
}
|
|
|
|
}
|
|
}
|
|
else {
|
|
if (GetSystemDirectory(szWABDllPath, MAX_PATH)) {
|
|
_tcsncat(szWABDllPath, WAB_DLL_NAME,
|
|
std::min(_tcslen(WAB_DLL_NAME), MAX_PATH - _tcslen(szWABDllPath) - 1));
|
|
}
|
|
else {
|
|
// Yet another error condition.
|
|
return;
|
|
}
|
|
}
|
|
|
|
if(hKey) RegCloseKey(hKey);
|
|
|
|
// if the Registry came up blank, we do a loadlibrary on the wab32.dll
|
|
// WAB_DLL_NAME is defined in wabapi.h
|
|
//
|
|
m_hinstWAB = LoadLibrary((lstrlen(szWABDllPath)) ? szWABDllPath : WAB_DLL_NAME);
|
|
}
|
|
|
|
if(m_hinstWAB)
|
|
{
|
|
// if we loaded the dll, get the entry point
|
|
//
|
|
m_lpfnWABOpen = (LPWABOPEN) GetProcAddress(m_hinstWAB, "WABOpen");
|
|
|
|
if(m_lpfnWABOpen)
|
|
{
|
|
char fName[2] = {0, 0};
|
|
HRESULT hr = E_FAIL;
|
|
WAB_PARAM wp = {0};
|
|
wp.cbSize = sizeof(WAB_PARAM);
|
|
if (file != nullptr) {
|
|
nsCString path;
|
|
file->GetNativePath(path);
|
|
wp.szFileName = (LPTSTR) ToNewCString(path);
|
|
}
|
|
else
|
|
wp.szFileName = (LPTSTR) fName;
|
|
|
|
// if we choose not to pass in a WAB_PARAM object,
|
|
// the default WAB file will be opened up
|
|
//
|
|
hr = m_lpfnWABOpen(&m_lpAdrBook,&m_lpWABObject,&wp,0);
|
|
|
|
if(!hr)
|
|
m_bInitialized = TRUE;
|
|
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
|
|
// Destructor
|
|
//
|
|
CWAB::~CWAB()
|
|
{
|
|
if (m_pUniBuff)
|
|
delete [] m_pUniBuff;
|
|
|
|
if(m_bInitialized)
|
|
{
|
|
if(m_lpAdrBook)
|
|
m_lpAdrBook->Release();
|
|
|
|
if(m_lpWABObject)
|
|
m_lpWABObject->Release();
|
|
|
|
if(m_hinstWAB)
|
|
FreeLibrary(m_hinstWAB);
|
|
}
|
|
}
|
|
|
|
|
|
HRESULT CWAB::IterateWABContents(CWabIterator *pIter, int *pDone)
|
|
{
|
|
if (!m_bInitialized || !m_lpAdrBook)
|
|
return E_FAIL;
|
|
|
|
ULONG ulObjType = 0;
|
|
LPMAPITABLE lpAB = NULL;
|
|
ULONG cRows = 0;
|
|
LPSRowSet lpRowAB = NULL;
|
|
LPABCONT lpContainer = NULL;
|
|
int cNumRows = 0;
|
|
nsresult keepGoing;
|
|
|
|
HRESULT hr = E_FAIL;
|
|
|
|
ULONG lpcbEID = 0;
|
|
LPENTRYID lpEID = NULL;
|
|
ULONG rowCount = 0;
|
|
ULONG curCount = 0;
|
|
|
|
nsString uniStr;
|
|
|
|
// Get the entryid of the root PAB container
|
|
//
|
|
hr = m_lpAdrBook->GetPAB(&lpcbEID, &lpEID);
|
|
|
|
if (HR_FAILED(hr))
|
|
goto exit;
|
|
|
|
ulObjType = 0;
|
|
|
|
// Open the root PAB container
|
|
// This is where all the WAB contents reside
|
|
//
|
|
hr = m_lpAdrBook->OpenEntry(lpcbEID,
|
|
(LPENTRYID)lpEID,
|
|
NULL,
|
|
0,
|
|
&ulObjType,
|
|
(LPUNKNOWN *)&lpContainer);
|
|
|
|
m_lpWABObject->FreeBuffer(lpEID);
|
|
|
|
lpEID = NULL;
|
|
|
|
if(HR_FAILED(hr))
|
|
goto exit;
|
|
|
|
// Get a contents table of all the contents in the
|
|
// WABs root container
|
|
//
|
|
hr = lpContainer->GetContentsTable(0, &lpAB);
|
|
|
|
if(HR_FAILED(hr))
|
|
goto exit;
|
|
|
|
hr = lpAB->GetRowCount(0, &rowCount);
|
|
if (HR_FAILED(hr))
|
|
rowCount = 100;
|
|
if (rowCount == 0)
|
|
rowCount = 1;
|
|
|
|
// Order the columns in the ContentsTable to conform to the
|
|
// ones we want - which are mainly DisplayName, EntryID and
|
|
// ObjectType
|
|
// The table is gauranteed to set the columns in the order
|
|
// requested
|
|
//
|
|
hr =lpAB->SetColumns((LPSPropTagArray)&ptaEid, 0);
|
|
|
|
if(HR_FAILED(hr))
|
|
goto exit;
|
|
|
|
|
|
// Reset to the beginning of the table
|
|
//
|
|
hr = lpAB->SeekRow(BOOKMARK_BEGINNING, 0, NULL);
|
|
|
|
if(HR_FAILED(hr))
|
|
goto exit;
|
|
|
|
// Read all the rows of the table one by one
|
|
//
|
|
|
|
do {
|
|
|
|
hr = lpAB->QueryRows(1, 0, &lpRowAB);
|
|
|
|
if(HR_FAILED(hr))
|
|
break;
|
|
|
|
if(lpRowAB)
|
|
{
|
|
cNumRows = lpRowAB->cRows;
|
|
|
|
if (cNumRows)
|
|
{
|
|
LPTSTR lpsz = lpRowAB->aRow[0].lpProps[ieidPR_DISPLAY_NAME].Value.lpszA;
|
|
LPENTRYID lpEID = (LPENTRYID) lpRowAB->aRow[0].lpProps[ieidPR_ENTRYID].Value.bin.lpb;
|
|
ULONG cbEID = lpRowAB->aRow[0].lpProps[ieidPR_ENTRYID].Value.bin.cb;
|
|
|
|
// There are 2 kinds of objects - the MAPI_MAILUSER contact object
|
|
// and the MAPI_DISTLIST contact object
|
|
// For the purposes of this sample, we will only consider MAILUSER
|
|
// objects
|
|
//
|
|
if(lpRowAB->aRow[0].lpProps[ieidPR_OBJECT_TYPE].Value.l == MAPI_MAILUSER)
|
|
{
|
|
// We will now take the entry-id of each object and cache it
|
|
// on the listview item representing that object. This enables
|
|
// us to uniquely identify the object later if we need to
|
|
//
|
|
CStrToUnicode(lpsz, uniStr);
|
|
keepGoing = pIter->EnumUser(uniStr.get(), lpEID, cbEID);
|
|
curCount++;
|
|
if (pDone) {
|
|
*pDone = (curCount * 100) / rowCount;
|
|
if (*pDone > 100)
|
|
*pDone = 100;
|
|
}
|
|
}
|
|
}
|
|
FreeProws(lpRowAB);
|
|
}
|
|
|
|
|
|
} while (SUCCEEDED(hr) && cNumRows && lpRowAB && NS_SUCCEEDED(keepGoing)) ;
|
|
|
|
hr = lpAB->SeekRow(BOOKMARK_BEGINNING, 0, NULL);
|
|
|
|
if(HR_FAILED(hr))
|
|
goto exit;
|
|
|
|
// Read all the rows of the table one by one
|
|
//
|
|
keepGoing = NS_OK;
|
|
do {
|
|
|
|
hr = lpAB->QueryRows(1, 0, &lpRowAB);
|
|
|
|
if(HR_FAILED(hr))
|
|
break;
|
|
|
|
if(lpRowAB)
|
|
{
|
|
cNumRows = lpRowAB->cRows;
|
|
|
|
if (cNumRows)
|
|
{
|
|
LPTSTR lpsz = lpRowAB->aRow[0].lpProps[ieidPR_DISPLAY_NAME].Value.lpszA;
|
|
LPENTRYID lpEID = (LPENTRYID) lpRowAB->aRow[0].lpProps[ieidPR_ENTRYID].Value.bin.lpb;
|
|
ULONG cbEID = lpRowAB->aRow[0].lpProps[ieidPR_ENTRYID].Value.bin.cb;
|
|
|
|
// There are 2 kinds of objects - the MAPI_MAILUSER contact object
|
|
// and the MAPI_DISTLIST contact object
|
|
// For the purposes of this sample, we will only consider MAILUSER
|
|
// objects
|
|
//
|
|
if(lpRowAB->aRow[0].lpProps[ieidPR_OBJECT_TYPE].Value.l == MAPI_DISTLIST)
|
|
{
|
|
LPABCONT distListContainer = NULL;
|
|
// We will now take the entry-id of each object and cache it
|
|
// on the listview item representing that object. This enables
|
|
// us to uniquely identify the object later if we need to
|
|
//
|
|
hr = m_lpAdrBook->OpenEntry(cbEID, lpEID, NULL,
|
|
0,&ulObjType,(LPUNKNOWN *)&distListContainer);
|
|
|
|
LPMAPITABLE distListTable = NULL;
|
|
|
|
|
|
// Get a contents table of the dist list
|
|
//
|
|
hr = distListContainer->GetContentsTable(0, &distListTable);
|
|
if (lpAB)
|
|
{
|
|
hr = distListTable->GetRowCount(0, &rowCount);
|
|
if (HR_FAILED(hr))
|
|
rowCount = 100;
|
|
if (rowCount == 0)
|
|
rowCount = 1;
|
|
|
|
// Order the columns in the ContentsTable to conform to the
|
|
// ones we want - which are mainly DisplayName, EntryID and
|
|
// ObjectType
|
|
// The table is gauranteed to set the columns in the order
|
|
// requested
|
|
//
|
|
hr = distListTable->SetColumns((LPSPropTagArray)&ptaEid, 0);
|
|
CStrToUnicode(lpsz, uniStr);
|
|
keepGoing = pIter->EnumList(uniStr.get(), lpEID, cbEID, distListTable);
|
|
curCount++;
|
|
if (pDone) {
|
|
*pDone = (curCount * 100) / rowCount;
|
|
if (*pDone > 100)
|
|
*pDone = 100;
|
|
}
|
|
}
|
|
if (distListContainer)
|
|
distListContainer->Release();
|
|
if (distListTable)
|
|
distListTable->Release();
|
|
}
|
|
}
|
|
FreeProws(lpRowAB);
|
|
}
|
|
|
|
} while (SUCCEEDED(hr) && cNumRows && lpRowAB && NS_SUCCEEDED(keepGoing)) ;
|
|
|
|
|
|
exit:
|
|
|
|
if (lpContainer)
|
|
lpContainer->Release();
|
|
|
|
if (lpAB)
|
|
lpAB->Release();
|
|
|
|
return hr;
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void CWAB::FreeProws(LPSRowSet prows)
|
|
{
|
|
ULONG irow;
|
|
if (!prows)
|
|
return;
|
|
for (irow = 0; irow < prows->cRows; ++irow)
|
|
m_lpWABObject->FreeBuffer(prows->aRow[irow].lpProps);
|
|
m_lpWABObject->FreeBuffer(prows);
|
|
}
|
|
|
|
|
|
LPDISTLIST CWAB::GetDistList(ULONG cbEid, LPENTRYID pEid)
|
|
{
|
|
if (!m_bInitialized || !m_lpAdrBook)
|
|
return NULL;
|
|
|
|
LPDISTLIST lpDistList = NULL;
|
|
ULONG ulObjType;
|
|
|
|
m_lpAdrBook->OpenEntry(cbEid, pEid, NULL, 0, &ulObjType, (LPUNKNOWN *)&lpDistList);
|
|
return lpDistList;
|
|
}
|
|
|
|
LPSPropValue CWAB::GetListProperty(LPDISTLIST pUser, ULONG tag)
|
|
{
|
|
if (!pUser)
|
|
return NULL;
|
|
|
|
int sz = CbNewSPropTagArray(1);
|
|
SPropTagArray *pTag = (SPropTagArray *) new char[sz];
|
|
pTag->cValues = 1;
|
|
pTag->aulPropTag[0] = tag;
|
|
LPSPropValue lpProp = NULL;
|
|
ULONG cValues = 0;
|
|
HRESULT hr = pUser->GetProps(pTag, 0, &cValues, &lpProp);
|
|
delete [] pTag;
|
|
if (HR_FAILED(hr) || (cValues != 1)) {
|
|
if (lpProp)
|
|
m_lpWABObject->FreeBuffer(lpProp);
|
|
return NULL;
|
|
}
|
|
return lpProp;
|
|
}
|
|
|
|
LPMAILUSER CWAB::GetUser(ULONG cbEid, LPENTRYID pEid)
|
|
{
|
|
if (!m_bInitialized || !m_lpAdrBook)
|
|
return NULL;
|
|
|
|
LPMAILUSER lpMailUser = NULL;
|
|
ULONG ulObjType;
|
|
|
|
m_lpAdrBook->OpenEntry(cbEid, pEid, NULL, 0, &ulObjType, (LPUNKNOWN *)&lpMailUser);
|
|
return lpMailUser;
|
|
}
|
|
|
|
LPSPropValue CWAB::GetUserProperty(LPMAILUSER pUser, ULONG tag)
|
|
{
|
|
if (!pUser)
|
|
return NULL;
|
|
|
|
ULONG uTag = tag;
|
|
/*
|
|
Getting Unicode does not help with getting the right
|
|
international charset. Windoze bloze.
|
|
*/
|
|
/*
|
|
if (PROP_TYPE(uTag) == PT_STRING8) {
|
|
uTag = CHANGE_PROP_TYPE(tag, PT_UNICODE);
|
|
}
|
|
*/
|
|
|
|
int sz = CbNewSPropTagArray(1);
|
|
SPropTagArray *pTag = (SPropTagArray *) new char[sz];
|
|
pTag->cValues = 1;
|
|
pTag->aulPropTag[0] = uTag;
|
|
LPSPropValue lpProp = NULL;
|
|
ULONG cValues = 0;
|
|
HRESULT hr = pUser->GetProps(pTag, 0, &cValues, &lpProp);
|
|
if (HR_FAILED(hr) || (cValues != 1)) {
|
|
if (lpProp)
|
|
m_lpWABObject->FreeBuffer(lpProp);
|
|
lpProp = NULL;
|
|
if (uTag != tag) {
|
|
pTag->cValues = 1;
|
|
pTag->aulPropTag[0] = tag;
|
|
cValues = 0;
|
|
hr = pUser->GetProps(pTag, 0, &cValues, &lpProp);
|
|
if (HR_FAILED(hr) || (cValues != 1)) {
|
|
if (lpProp)
|
|
m_lpWABObject->FreeBuffer(lpProp);
|
|
lpProp = NULL;
|
|
}
|
|
}
|
|
}
|
|
delete [] pTag;
|
|
return lpProp;
|
|
}
|
|
|
|
void CWAB::CStrToUnicode(const char *pStr, nsString& result)
|
|
{
|
|
result.Truncate();
|
|
int wLen = MultiByteToWideChar(CP_ACP, 0, pStr, -1, wwc(m_pUniBuff), 0);
|
|
if (wLen >= m_uniBuffLen) {
|
|
if (m_pUniBuff)
|
|
delete [] m_pUniBuff;
|
|
m_pUniBuff = new char16_t[wLen + 64];
|
|
m_uniBuffLen = wLen + 64;
|
|
}
|
|
if (wLen) {
|
|
MultiByteToWideChar(CP_ACP, 0, pStr, -1, wwc(m_pUniBuff), m_uniBuffLen);
|
|
result = m_pUniBuff;
|
|
}
|
|
}
|
|
|
|
// If the value is a string, get it...
|
|
void CWAB::GetValueString(LPSPropValue pVal, nsString& val)
|
|
{
|
|
val.Truncate();
|
|
|
|
if (!pVal)
|
|
return;
|
|
|
|
switch(PROP_TYPE(pVal->ulPropTag)) {
|
|
case PT_STRING8:
|
|
CStrToUnicode((const char *) (pVal->Value.lpszA), val);
|
|
break;
|
|
case PT_UNICODE:
|
|
val = (char16_t *) (pVal->Value.lpszW);
|
|
break;
|
|
case PT_MV_STRING8: {
|
|
nsString tmp;
|
|
ULONG j;
|
|
for(j = 0; j < pVal->Value.MVszA.cValues; j++) {
|
|
CStrToUnicode((const char *) (pVal->Value.MVszA.lppszA[j]), tmp);
|
|
val += tmp;
|
|
val.Append(NS_ConvertASCIItoUTF16(TR_OUTPUT_EOL));
|
|
}
|
|
break;
|
|
}
|
|
case PT_MV_UNICODE: {
|
|
ULONG j;
|
|
for(j = 0; j < pVal->Value.MVszW.cValues; j++) {
|
|
val += (char16_t *) (pVal->Value.MVszW.lppszW[j]);
|
|
val.Append(NS_ConvertASCIItoUTF16(TR_OUTPUT_EOL));
|
|
}
|
|
break;
|
|
}
|
|
case PT_I2:
|
|
case PT_LONG:
|
|
case PT_R4:
|
|
case PT_DOUBLE:
|
|
case PT_BOOLEAN: {
|
|
/*
|
|
TCHAR sz[256];
|
|
wsprintf(sz,"%d", pVal->Value.l);
|
|
val = sz;
|
|
*/
|
|
break;
|
|
}
|
|
|
|
case PT_BINARY:
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
|
|
val.Trim(kWhitespace, true, true);
|
|
}
|
|
|
|
|
|
void CWAB::GetValueTime(LPSPropValue pVal, PRTime& val)
|
|
{
|
|
if (!pVal)
|
|
return;
|
|
|
|
if (PROP_TYPE(pVal->ulPropTag) != PT_SYSTIME)
|
|
return;
|
|
|
|
nsOE5File::FileTimeToPRTime(&pVal->Value.ft, &val);
|
|
}
|
|
|
|
bool CWAB::IsAvailable()
|
|
{
|
|
if (!m_bInitialized || !m_lpAdrBook)
|
|
return false;
|
|
|
|
ULONG lpcbEID = 0;
|
|
LPENTRYID lpEID = NULL;
|
|
HRESULT hr = m_lpAdrBook->GetPAB(&lpcbEID, &lpEID);
|
|
if (HR_FAILED(hr))
|
|
return false;
|
|
|
|
ULONG ulObjType = 0;
|
|
LPABCONT lpContainer = NULL;
|
|
hr = m_lpAdrBook->OpenEntry(lpcbEID,
|
|
(LPENTRYID)lpEID,
|
|
NULL,
|
|
0,
|
|
&ulObjType,
|
|
(LPUNKNOWN *)&lpContainer);
|
|
m_lpWABObject->FreeBuffer(lpEID);
|
|
|
|
LPMAPITABLE lpAB = NULL;
|
|
hr = lpContainer->GetContentsTable(0, &lpAB);
|
|
if(HR_FAILED(hr)) {
|
|
lpContainer->Release();
|
|
return false;
|
|
}
|
|
|
|
ULONG rowCount = 0;
|
|
hr = lpAB->GetRowCount(0, &rowCount);
|
|
lpContainer->Release();
|
|
lpAB->Release();
|
|
return (rowCount != 0);
|
|
}
|
|
|
|
/*
|
|
BOOL CWabIterateProcess::SanitizeMultiLine(CString& val)
|
|
{
|
|
val.TrimLeft();
|
|
val.TrimRight();
|
|
int idx = val.FindOneOf("\x0D\x0A");
|
|
if (idx == -1)
|
|
return FALSE;
|
|
|
|
// needs encoding
|
|
U32 bufSz = UMimeEncode::GetBufferSize(val.GetLength());
|
|
P_U8 pBuf = new U8[bufSz];
|
|
U32 len = UMimeEncode::ConvertBuffer((PC_U8)((PC_S8)val), val.GetLength(), pBuf, 66, 52, "\x0D\x0A ");
|
|
pBuf[len] = 0;
|
|
val = pBuf;
|
|
delete pBuf;
|
|
return TRUE;
|
|
}
|
|
|
|
BOOL CWabIterateProcess::EnumUser(LPCTSTR pName, LPENTRYID pEid, ULONG cbEid)
|
|
{
|
|
TRACE1("User: %s\n", pName);
|
|
|
|
LPMAILUSER pUser = m_pWab->GetUser(cbEid, pEid);
|
|
|
|
// Get the "required" strings first
|
|
CString lastName;
|
|
CString firstName;
|
|
CString eMail;
|
|
CString nickName;
|
|
CString middleName;
|
|
|
|
if (!pUser) {
|
|
UDialogs::ErrMessage1(IDS_ENTRY_ERROR, pName);
|
|
return FALSE;
|
|
}
|
|
|
|
LPSPropValue pProp = m_pWab->GetUserProperty(pUser, PR_EMAIL_ADDRESS);
|
|
if (pProp) {
|
|
m_pWab->GetValueString(pProp, eMail);
|
|
SanitizeValue(eMail);
|
|
m_pWab->FreeProperty(pProp);
|
|
}
|
|
pProp = m_pWab->GetUserProperty(pUser, PR_GIVEN_NAME);
|
|
if (pProp) {
|
|
m_pWab->GetValueString(pProp, firstName);
|
|
SanitizeValue(firstName);
|
|
m_pWab->FreeProperty(pProp);
|
|
}
|
|
pProp = m_pWab->GetUserProperty(pUser, PR_SURNAME);
|
|
if (pProp) {
|
|
m_pWab->GetValueString(pProp, lastName);
|
|
SanitizeValue(lastName);
|
|
m_pWab->FreeProperty(pProp);
|
|
}
|
|
pProp = m_pWab->GetUserProperty(pUser, PR_MIDDLE_NAME);
|
|
if (pProp) {
|
|
m_pWab->GetValueString(pProp, middleName);
|
|
SanitizeValue(middleName);
|
|
m_pWab->FreeProperty(pProp);
|
|
}
|
|
pProp = m_pWab->GetUserProperty(pUser, PR_NICKNAME);
|
|
if (pProp) {
|
|
m_pWab->GetValueString(pProp, nickName);
|
|
SanitizeValue(nickName);
|
|
m_pWab->FreeProperty(pProp);
|
|
}
|
|
if (nickName.IsEmpty())
|
|
nickName = pName;
|
|
if (firstName.IsEmpty()) {
|
|
firstName = nickName;
|
|
middleName.Empty();
|
|
lastName.Empty();
|
|
}
|
|
if (lastName.IsEmpty())
|
|
middleName.Empty();
|
|
|
|
if (eMail.IsEmpty())
|
|
eMail = nickName;
|
|
|
|
|
|
// We now have the required fields
|
|
// write them out followed by any optional fields!
|
|
BOOL result = TRUE;
|
|
|
|
if (m_recordsDone)
|
|
result = m_out.WriteEol();
|
|
|
|
CString line;
|
|
CString header;
|
|
line.LoadString(IDS_LDIF_DN_START);
|
|
line += firstName;
|
|
if (!middleName.IsEmpty()) {
|
|
line += ' ';
|
|
line += middleName;
|
|
}
|
|
if (!lastName.IsEmpty()) {
|
|
line += ' ';
|
|
line += lastName;
|
|
}
|
|
header.LoadString(IDS_LDIF_DN_MIDDLE);
|
|
line += header;
|
|
line += eMail;
|
|
result = result && m_out.WriteStr(line);
|
|
result = result && m_out.WriteEol();
|
|
|
|
line.LoadString(IDS_FIELD_LDIF_FULLNAME);
|
|
line += ' ';
|
|
line += firstName;
|
|
if (!middleName.IsEmpty()) {
|
|
line += ' ';
|
|
line += middleName;
|
|
}
|
|
if (!lastName.IsEmpty()) {
|
|
line += ' ';
|
|
line += lastName;
|
|
}
|
|
result = result && m_out.WriteStr(line);
|
|
result = result && m_out.WriteEol();
|
|
|
|
|
|
line.LoadString(IDS_FIELD_LDIF_GIVENNAME);
|
|
line += ' ';
|
|
line += firstName;
|
|
result = result && m_out.WriteStr(line);
|
|
result = result && m_out.WriteEol();
|
|
|
|
if (!lastName.IsEmpty()) {
|
|
line.LoadString(IDS_FIELD_LDIF_LASTNAME);
|
|
if (!middleName.IsEmpty()) {
|
|
line += ' ';
|
|
line += middleName;
|
|
}
|
|
line += ' ';
|
|
line += lastName;
|
|
result = result && m_out.WriteStr(line);
|
|
result = result && m_out.WriteEol();
|
|
}
|
|
|
|
result = result && m_out.WriteStr(kLDIFPerson);
|
|
|
|
line.LoadString(IDS_FIELD_LDIF_EMAIL);
|
|
line += ' ';
|
|
line += eMail;
|
|
result = result && m_out.WriteStr(line);
|
|
result = result && m_out.WriteEol();
|
|
|
|
line.LoadString(IDS_FIELD_LDIF_NICKNAME);
|
|
line += ' ';
|
|
line += nickName;
|
|
result = result && m_out.WriteStr(line);
|
|
result = result && m_out.WriteEol();
|
|
|
|
// Do all of the extra fields!
|
|
CString value;
|
|
BOOL encoded = FALSE;
|
|
for (int i = 0; i < kExtraUserFields; i++) {
|
|
value.Empty();
|
|
pProp = m_pWab->GetUserProperty(pUser, extraUserFields[i].tag);
|
|
if (pProp) {
|
|
m_pWab->GetValueString(pProp, value);
|
|
m_pWab->FreeProperty(pProp);
|
|
}
|
|
if (extraUserFields[i].multiLine) {
|
|
encoded = SanitizeMultiLine(value);
|
|
}
|
|
else
|
|
SanitizeValue(value);
|
|
if (!value.IsEmpty()) {
|
|
line = extraUserFields[i].pLDIF;
|
|
if (encoded) {
|
|
line += ": ";
|
|
encoded = FALSE;
|
|
}
|
|
else
|
|
line += ' ';
|
|
line += value;
|
|
result = result && m_out.WriteStr(line);
|
|
result = result && m_out.WriteEol();
|
|
}
|
|
}
|
|
|
|
m_pWab->ReleaseUser(pUser);
|
|
|
|
if (!result) {
|
|
UDialogs::ErrMessage0(IDS_ADDRESS_SAVE_ERROR);
|
|
}
|
|
|
|
m_totalDone += kValuePerUser;
|
|
m_recordsDone++;
|
|
|
|
return result;
|
|
}
|
|
*/
|
|
|
|
|
|
|
|
|
|
/*
|
|
BOOL CWabIterateProcess::EnumList(LPCTSTR pName, LPENTRYID pEid, ULONG cbEid)
|
|
{
|
|
TRACE1("List: %s\n", pName);
|
|
|
|
LPDISTLIST pList = m_pWab->GetDistList(cbEid, pEid);
|
|
if (!pList) {
|
|
UDialogs::ErrMessage1(IDS_ENTRY_ERROR, pName);
|
|
return FALSE;
|
|
}
|
|
|
|
// Find out if this is just a regular entry or a true list...
|
|
CString eMail;
|
|
LPSPropValue pProp = m_pWab->GetListProperty(pList, PR_EMAIL_ADDRESS);
|
|
if (pProp) {
|
|
m_pWab->GetValueString(pProp, eMail);
|
|
SanitizeValue(eMail);
|
|
m_pWab->FreeProperty(pProp);
|
|
// Treat this like a regular entry...
|
|
if (!eMail.IsEmpty()) {
|
|
m_pWab->ReleaseDistList(pList);
|
|
return WriteListUserEntry(pName, eMail);
|
|
}
|
|
}
|
|
|
|
// This may very well be a list, find the entries...
|
|
m_pListTable = OpenDistList(pList);
|
|
if (m_pListTable) {
|
|
m_pList = pList;
|
|
m_listName = pName;
|
|
m_listDone = 0;
|
|
m_listHeaderDone = FALSE;
|
|
m_state = kEnumListState;
|
|
}
|
|
else {
|
|
m_pWab->ReleaseDistList(pList);
|
|
m_recordsDone++;
|
|
m_totalDone += kValuePerUser;
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
BOOL CWabIterateProcess::EnumNextListUser(BOOL *pDone)
|
|
{
|
|
HRESULT hr;
|
|
int cNumRows = 0;
|
|
LPSRowSet lpRowAB = NULL;
|
|
BOOL keepGoing = TRUE;
|
|
|
|
if (!m_pListTable)
|
|
return FALSE;
|
|
|
|
hr = m_pListTable->QueryRows(1, 0, &lpRowAB);
|
|
|
|
if(HR_FAILED(hr)) {
|
|
UDialogs::ErrMessage0(IDS_ERROR_READING_WAB);
|
|
return FALSE;
|
|
}
|
|
|
|
if(lpRowAB) {
|
|
cNumRows = lpRowAB->cRows;
|
|
|
|
if (cNumRows) {
|
|
LPTSTR lpsz = lpRowAB->aRow[0].lpProps[ieidPR_DISPLAY_NAME].Value.lpszA;
|
|
LPENTRYID lpEID = (LPENTRYID) lpRowAB->aRow[0].lpProps[ieidPR_ENTRYID].Value.bin.lpb;
|
|
ULONG cbEID = lpRowAB->aRow[0].lpProps[ieidPR_ENTRYID].Value.bin.cb;
|
|
if(lpRowAB->aRow[0].lpProps[ieidPR_OBJECT_TYPE].Value.l == MAPI_DISTLIST) {
|
|
keepGoing = HandleListList(lpsz, lpEID, cbEID);
|
|
}
|
|
else if (lpRowAB->aRow[0].lpProps[ieidPR_OBJECT_TYPE].Value.l == MAPI_MAILUSER) {
|
|
keepGoing = HandleListUser(lpsz, lpEID, cbEID);
|
|
}
|
|
}
|
|
m_pWab->FreeProws(lpRowAB);
|
|
}
|
|
|
|
if (!cNumRows || !lpRowAB) {
|
|
*pDone = TRUE;
|
|
m_pListTable->Release();
|
|
m_pListTable = NULL;
|
|
if (m_pList)
|
|
m_pWab->ReleaseDistList(m_pList);
|
|
m_pList = NULL;
|
|
if (m_listDone < kValuePerUser)
|
|
m_totalDone += (kValuePerUser - m_listDone);
|
|
m_recordsDone++;
|
|
return keepGoing;
|
|
}
|
|
|
|
if (!keepGoing)
|
|
return FALSE;
|
|
|
|
if (m_listDone < kValuePerUser) {
|
|
m_listDone++;
|
|
m_totalDone++;
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
BOOL CWabIterateProcess::HandleListList(LPCTSTR pName, LPENTRYID lpEid, ULONG cbEid)
|
|
{
|
|
BOOL result;
|
|
LPDISTLIST pList = m_pWab->GetDistList(cbEid, lpEid);
|
|
if (!pList) {
|
|
UDialogs::ErrMessage1(IDS_ENTRY_ERROR, pName);
|
|
return FALSE;
|
|
}
|
|
|
|
CString eMail;
|
|
LPSPropValue pProp = m_pWab->GetListProperty(pList, PR_EMAIL_ADDRESS);
|
|
if (pProp) {
|
|
m_pWab->GetValueString(pProp, eMail);
|
|
SanitizeValue(eMail);
|
|
m_pWab->FreeProperty(pProp);
|
|
// Treat this like a regular entry...
|
|
if (!eMail.IsEmpty()) {
|
|
// write out a member based on pName and eMail
|
|
result = WriteGroupMember(pName, eMail);
|
|
m_pWab->ReleaseDistList(pList);
|
|
return result;
|
|
}
|
|
}
|
|
|
|
// iterate the list and add each member to the top level list
|
|
LPMAPITABLE pTable = OpenDistList(pList);
|
|
if (!pTable) {
|
|
TRACE0("Error opening table for list\n");
|
|
m_pWab->ReleaseDistList(pList);
|
|
UDialogs::ErrMessage1(IDS_ENTRY_ERROR, pName);
|
|
return FALSE;
|
|
}
|
|
|
|
int cNumRows = 0;
|
|
LPSRowSet lpRowAB = NULL;
|
|
HRESULT hr;
|
|
BOOL keepGoing = TRUE;
|
|
|
|
do {
|
|
hr = pTable->QueryRows(1, 0, &lpRowAB);
|
|
|
|
if(HR_FAILED(hr)) {
|
|
UDialogs::ErrMessage0(IDS_ERROR_READING_WAB);
|
|
pTable->Release();
|
|
m_pWab->ReleaseDistList(pList);
|
|
return FALSE;
|
|
}
|
|
|
|
if(lpRowAB) {
|
|
cNumRows = lpRowAB->cRows;
|
|
|
|
if (cNumRows) {
|
|
LPTSTR lpsz = lpRowAB->aRow[0].lpProps[ieidPR_DISPLAY_NAME].Value.lpszA;
|
|
LPENTRYID lpEID = (LPENTRYID) lpRowAB->aRow[0].lpProps[ieidPR_ENTRYID].Value.bin.lpb;
|
|
ULONG cbEID = lpRowAB->aRow[0].lpProps[ieidPR_ENTRYID].Value.bin.cb;
|
|
if(lpRowAB->aRow[0].lpProps[ieidPR_OBJECT_TYPE].Value.l == MAPI_DISTLIST) {
|
|
keepGoing = HandleListList(lpsz, lpEID, cbEID);
|
|
}
|
|
else if (lpRowAB->aRow[0].lpProps[ieidPR_OBJECT_TYPE].Value.l == MAPI_MAILUSER) {
|
|
keepGoing = HandleListUser(lpsz, lpEID, cbEID);
|
|
}
|
|
}
|
|
m_pWab->FreeProws(lpRowAB);
|
|
}
|
|
}
|
|
while (keepGoing && cNumRows && lpRowAB);
|
|
|
|
pTable->Release();
|
|
m_pWab->ReleaseDistList(pList);
|
|
return keepGoing;
|
|
}
|
|
|
|
BOOL CWabIterateProcess::HandleListUser(LPCTSTR pName, LPENTRYID lpEid, ULONG cbEid)
|
|
{
|
|
// Get the basic properties for building the member line
|
|
LPMAILUSER pUser = m_pWab->GetUser(cbEid, lpEid);
|
|
|
|
// Get the "required" strings first
|
|
CString lastName;
|
|
CString firstName;
|
|
CString eMail;
|
|
CString nickName;
|
|
CString middleName;
|
|
|
|
if (!pUser) {
|
|
UDialogs::ErrMessage1(IDS_ENTRY_ERROR, pName);
|
|
return FALSE;
|
|
}
|
|
|
|
LPSPropValue pProp = m_pWab->GetUserProperty(pUser, PR_EMAIL_ADDRESS);
|
|
if (pProp) {
|
|
m_pWab->GetValueString(pProp, eMail);
|
|
SanitizeValue(eMail);
|
|
m_pWab->FreeProperty(pProp);
|
|
}
|
|
pProp = m_pWab->GetUserProperty(pUser, PR_GIVEN_NAME);
|
|
if (pProp) {
|
|
m_pWab->GetValueString(pProp, firstName);
|
|
SanitizeValue(firstName);
|
|
m_pWab->FreeProperty(pProp);
|
|
}
|
|
pProp = m_pWab->GetUserProperty(pUser, PR_SURNAME);
|
|
if (pProp) {
|
|
m_pWab->GetValueString(pProp, lastName);
|
|
SanitizeValue(lastName);
|
|
m_pWab->FreeProperty(pProp);
|
|
}
|
|
pProp = m_pWab->GetUserProperty(pUser, PR_MIDDLE_NAME);
|
|
if (pProp) {
|
|
m_pWab->GetValueString(pProp, middleName);
|
|
SanitizeValue(middleName);
|
|
m_pWab->FreeProperty(pProp);
|
|
}
|
|
pProp = m_pWab->GetUserProperty(pUser, PR_NICKNAME);
|
|
if (pProp) {
|
|
m_pWab->GetValueString(pProp, nickName);
|
|
SanitizeValue(nickName);
|
|
m_pWab->FreeProperty(pProp);
|
|
}
|
|
if (nickName.IsEmpty())
|
|
nickName = pName;
|
|
if (firstName.IsEmpty()) {
|
|
firstName = nickName;
|
|
middleName.Empty();
|
|
lastName.Empty();
|
|
}
|
|
if (lastName.IsEmpty())
|
|
middleName.Empty();
|
|
|
|
if (eMail.IsEmpty())
|
|
eMail = nickName;
|
|
|
|
m_pWab->ReleaseUser(pUser);
|
|
|
|
CString name = firstName;
|
|
if (!middleName.IsEmpty()) {
|
|
name += ' ';
|
|
name += middleName;
|
|
}
|
|
if (!lastName.IsEmpty()) {
|
|
name += ' ';
|
|
name += lastName;
|
|
}
|
|
return WriteGroupMember(name, eMail);
|
|
}
|
|
|
|
BOOL CWabIterateProcess::WriteGroupMember(const char *pName, const char *pEmail)
|
|
{
|
|
CString middle;
|
|
CString line;
|
|
BOOL result;
|
|
|
|
// Check for the header first
|
|
if (!m_listHeaderDone) {
|
|
if (m_recordsDone)
|
|
result = m_out.WriteEol();
|
|
else
|
|
result = TRUE;
|
|
line.LoadString(IDS_LDIF_DN_START);
|
|
line += m_listName;
|
|
line += TR_OUTPUT_EOL;
|
|
middle.LoadString(IDS_FIELD_LDIF_FULLNAME);
|
|
line += middle;
|
|
line += m_listName;
|
|
line += TR_OUTPUT_EOL;
|
|
if (!result || !m_out.WriteStr(line) || !m_out.WriteStr(kLDIFGroup)) {
|
|
UDialogs::ErrMessage0(IDS_ADDRESS_SAVE_ERROR);
|
|
return FALSE;
|
|
}
|
|
m_listHeaderDone = TRUE;
|
|
}
|
|
|
|
|
|
line.LoadString(IDS_FIELD_LDIF_MEMBER_START);
|
|
line += pName;
|
|
middle.LoadString(IDS_LDIF_DN_MIDDLE);
|
|
line += middle;
|
|
line += pEmail;
|
|
line += TR_OUTPUT_EOL;
|
|
if (!m_out.WriteStr(line)) {
|
|
UDialogs::ErrMessage0(IDS_ADDRESS_SAVE_ERROR);
|
|
return FALSE;
|
|
}
|
|
|
|
if (m_listDone < kValuePerUser) {
|
|
m_listDone++;
|
|
m_totalDone++;
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
*/
|
|
|