mirror of https://github.com/sipwise/jitsi.git
parent
c85ca6ca0c
commit
528bdb40d5
Binary file not shown.
Binary file not shown.
@ -0,0 +1,173 @@
|
||||
/*
|
||||
* Jitsi, the OpenSource Java VoIP and Instant Messaging client.
|
||||
*
|
||||
* Distributable under LGPL license.
|
||||
* See terms of license at gnu.org.
|
||||
*/
|
||||
#include "MAPINotification.h"
|
||||
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#include <windows.h>
|
||||
|
||||
#include <stdio.h>
|
||||
#include <Unknwn.h>
|
||||
|
||||
#include <mapidefs.h>
|
||||
#include <mapiutil.h>
|
||||
|
||||
#include "../net_java_sip_communicator_plugin_addrbook_msoutlook_MsOutlookAddrBookContactSourceService.h"
|
||||
#include "../net_java_sip_communicator_plugin_addrbook_msoutlook_MsOutlookAddrBookContactQuery.h"
|
||||
/**
|
||||
* Manages notification for the message data base (used to get the list of
|
||||
* contact).
|
||||
*
|
||||
* @author Vincent Lucas
|
||||
*/
|
||||
|
||||
/**
|
||||
* The List of events we want to retrieve.
|
||||
*/
|
||||
static ULONG EVENT_MASK
|
||||
= fnevObjectCreated
|
||||
| fnevObjectDeleted
|
||||
| fnevObjectModified
|
||||
| fnevObjectMoved;
|
||||
|
||||
/**
|
||||
* Functions called when an event is fired from the message data base.
|
||||
*
|
||||
* @param lpvContext A pointer to the message data base.
|
||||
* @param cNotifications The number of event in this call.
|
||||
* @param lpNotifications The list of notifications.
|
||||
*/
|
||||
LONG STDAPICALLTYPE onNotify(
|
||||
LPVOID lpvContext,
|
||||
ULONG cNotifications,
|
||||
LPNOTIFICATION lpNotifications)
|
||||
{
|
||||
for(unsigned int i = 0; i < cNotifications; ++i)
|
||||
{
|
||||
LPUNKNOWN iUnknown = NULL;
|
||||
if(lpvContext != NULL)
|
||||
{
|
||||
iUnknown = openEntry(
|
||||
lpNotifications[i].info.obj.cbEntryID,
|
||||
lpNotifications[i].info.obj.lpEntryID,
|
||||
lpvContext);
|
||||
}
|
||||
|
||||
// A contact has been created
|
||||
if(lpNotifications[i].ulEventType == fnevObjectCreated)
|
||||
{
|
||||
if(lpNotifications[i].info.obj.ulObjType == MAPI_MESSAGE)
|
||||
{
|
||||
callInsertedCallbackMethod(iUnknown);
|
||||
}
|
||||
}
|
||||
// A contact has been Modified
|
||||
else if(lpNotifications[i].ulEventType == fnevObjectModified)
|
||||
{
|
||||
if(lpNotifications[i].info.obj.ulObjType == MAPI_MESSAGE)
|
||||
{
|
||||
callUpdatedCallbackMethod(iUnknown);
|
||||
}
|
||||
}
|
||||
// A contact has been deleted.
|
||||
else if(lpNotifications[i].ulEventType == fnevObjectDeleted)
|
||||
{
|
||||
if(lpvContext != NULL)
|
||||
{
|
||||
char entryIdStr[lpNotifications[i].info.obj.cbEntryID * 2 + 1];
|
||||
|
||||
HexFromBin(
|
||||
(LPBYTE) lpNotifications[i].info.obj.lpEntryID,
|
||||
lpNotifications[i].info.obj.cbEntryID,
|
||||
entryIdStr);
|
||||
|
||||
if(lpNotifications[i].info.obj.ulObjType == MAPI_MESSAGE)
|
||||
{
|
||||
callDeletedCallbackMethod(entryIdStr);
|
||||
}
|
||||
}
|
||||
}
|
||||
// A contact has been deleted (moved to trash).
|
||||
else if(lpNotifications[i].ulEventType == fnevObjectMoved)
|
||||
{
|
||||
if(lpvContext != NULL)
|
||||
{
|
||||
char entryIdStr[lpNotifications[i].info.obj.cbEntryID * 2 + 1];
|
||||
HexFromBin(
|
||||
(LPBYTE) lpNotifications[i].info.obj.lpEntryID,
|
||||
lpNotifications[i].info.obj.cbEntryID,
|
||||
entryIdStr);
|
||||
char parentEntryIdStr[
|
||||
lpNotifications[i].info.obj.cbParentID * 2 + 1];
|
||||
HexFromBin(
|
||||
(LPBYTE) lpNotifications[i].info.obj.lpParentID,
|
||||
lpNotifications[i].info.obj.cbParentID,
|
||||
parentEntryIdStr);
|
||||
ULONG wasteBasketTags[] = {1, PR_IPM_WASTEBASKET_ENTRYID};
|
||||
ULONG wasteBasketNbValues = 0;
|
||||
LPSPropValue wasteBasketProps = NULL;
|
||||
((LPMDB)lpvContext)->GetProps(
|
||||
(LPSPropTagArray) wasteBasketTags,
|
||||
MAPI_UNICODE,
|
||||
&wasteBasketNbValues,
|
||||
&wasteBasketProps);
|
||||
char wasteBasketEntryIdStr[
|
||||
wasteBasketProps[0].Value.bin.cb * 2 + 1];
|
||||
HexFromBin(
|
||||
(LPBYTE) wasteBasketProps[0].Value.bin.lpb,
|
||||
wasteBasketProps[0].Value.bin.cb,
|
||||
wasteBasketEntryIdStr);
|
||||
|
||||
openEntry(
|
||||
lpNotifications[i].info.obj.cbParentID,
|
||||
lpNotifications[i].info.obj.lpParentID,
|
||||
lpvContext);
|
||||
|
||||
|
||||
if(lpNotifications[i].info.obj.ulObjType == MAPI_MESSAGE
|
||||
&& strcmp(parentEntryIdStr, wasteBasketEntryIdStr) == 0)
|
||||
{
|
||||
callDeletedCallbackMethod(entryIdStr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(iUnknown != NULL)
|
||||
{
|
||||
iUnknown->Release();
|
||||
}
|
||||
}
|
||||
|
||||
// A client must always return a S_OK.
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers to notification for the given message data base.
|
||||
*
|
||||
* @param iUnknown The data base to register to in order to receive events.
|
||||
*
|
||||
* @return A unsigned long which is a token wich must be used to call the
|
||||
* unadvise function for the same message data base.
|
||||
*/
|
||||
ULONG registerNotifyMessageDataBase(
|
||||
LPMDB iUnknown)
|
||||
{
|
||||
LPMAPIADVISESINK adviseSink;
|
||||
HrAllocAdviseSink(
|
||||
&onNotify,
|
||||
iUnknown,
|
||||
&adviseSink);
|
||||
ULONG nbConnection = 0;
|
||||
iUnknown->Advise(
|
||||
0,
|
||||
NULL,
|
||||
EVENT_MASK,
|
||||
adviseSink,
|
||||
&nbConnection);
|
||||
|
||||
return nbConnection;
|
||||
}
|
||||
@ -0,0 +1,30 @@
|
||||
/*
|
||||
* Jitsi, the OpenSource Java VoIP and Instant Messaging client.
|
||||
*
|
||||
* Distributable under LGPL license.
|
||||
* See terms of license at gnu.org.
|
||||
*/
|
||||
|
||||
#ifndef _mapi_notification_h
|
||||
#define _mapi_notification_h
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include <mapidefs.h>
|
||||
#include <mapix.h>
|
||||
|
||||
LONG STDAPICALLTYPE onNotify(
|
||||
LPVOID lpvContext,
|
||||
ULONG cNotifications,
|
||||
LPNOTIFICATION lpNotifications);
|
||||
|
||||
ULONG registerNotifyMessageDataBase(
|
||||
LPMDB iUnknown);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@ -0,0 +1,111 @@
|
||||
/*
|
||||
* Jitsi, the OpenSource Java VoIP and Instant Messaging client.
|
||||
*
|
||||
* Distributable under LGPL license.
|
||||
* See terms of license at gnu.org.
|
||||
*/
|
||||
package net.java.sip.communicator.plugin.addrbook.msoutlook;
|
||||
|
||||
import net.java.sip.communicator.service.contactsource.*;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* Implements a custom <tt>ContactDetail</tt> for the Address Book of Microsoft
|
||||
* Outlook.
|
||||
*
|
||||
* @author Vincent Lucas
|
||||
*/
|
||||
public class MsOutlookAddrBookContactDetail
|
||||
extends EditableContactDetail
|
||||
{
|
||||
/**
|
||||
* The source contact which contains this contact detail.
|
||||
*/
|
||||
private MsOutlookAddrBookSourceContact sourceContact;
|
||||
|
||||
/**
|
||||
* The list of codes used by outlook to identify the property corresponding
|
||||
* to this contact detail.
|
||||
*/
|
||||
private Vector<Long> outlookPropId;
|
||||
|
||||
/**
|
||||
* Initializes a new <tt>ContactDetail</tt> instance which is to represent a
|
||||
* specific contact address and which is to be optionally labeled with a
|
||||
* specific set of labels.
|
||||
*
|
||||
* @param contactDetailValue the contact detail value to be represented by
|
||||
* the new <tt>ContactDetail</tt> instance
|
||||
* @param category The category of this contact detail.
|
||||
* @param subCategories the set of sub categories with which the new
|
||||
* <tt>ContactDetail</tt> instance is to be labeled.
|
||||
* @param outlookPropId The identifier of the outlook property used to
|
||||
* get/set this contact detail.
|
||||
*/
|
||||
public MsOutlookAddrBookContactDetail(
|
||||
String contactDetailValue,
|
||||
Category category,
|
||||
SubCategory[] subCategories,
|
||||
long outlookPropId)
|
||||
{
|
||||
super(contactDetailValue, category, subCategories);
|
||||
|
||||
this.outlookPropId = new Vector<Long>(1, 1);
|
||||
this.outlookPropId.add(new Long(outlookPropId));
|
||||
this.sourceContact = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the source contact that contains this contact detail.
|
||||
*
|
||||
* @param sourceContact The source contact that contains this contact
|
||||
* detail.
|
||||
*/
|
||||
public void setSourceContact(MsOutlookAddrBookSourceContact sourceContact)
|
||||
{
|
||||
this.sourceContact = sourceContact;
|
||||
}
|
||||
|
||||
/**
|
||||
* If the given contact detail is similar to the current one (same category
|
||||
* and same detail value), then return true. False otherwise.
|
||||
*
|
||||
* @param contactDetail The contact detail to compare with.
|
||||
*
|
||||
* @return True, if the given contact detail is similar to the current one
|
||||
* (same category and same detail value). False otherwise.
|
||||
*/
|
||||
public boolean match(ContactDetail contactDetail)
|
||||
{
|
||||
return (this.getCategory() == contactDetail.getCategory()
|
||||
&& this.getDetail().equals(contactDetail.getDetail()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the list of outlook properties corresponding to this contact
|
||||
* detail.
|
||||
*
|
||||
* @return The list of outlook properties corresponding to this contact
|
||||
* detail.
|
||||
*/
|
||||
public Vector<Long> getOutlookPropId()
|
||||
{
|
||||
return this.outlookPropId;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the given detail value.
|
||||
*
|
||||
* @param value the new value of the detail
|
||||
*/
|
||||
public void setDetail(String value)
|
||||
{
|
||||
super.setDetail(value);
|
||||
|
||||
if(this.sourceContact != null)
|
||||
{
|
||||
this.sourceContact.save();
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,195 @@
|
||||
/*
|
||||
* Jitsi, the OpenSource Java VoIP and Instant Messaging client.
|
||||
*
|
||||
* Distributable under LGPL license.
|
||||
* See terms of license at gnu.org.
|
||||
*/
|
||||
package net.java.sip.communicator.plugin.addrbook.msoutlook;
|
||||
|
||||
import net.java.sip.communicator.plugin.addrbook.*;
|
||||
import net.java.sip.communicator.service.contactsource.*;
|
||||
import net.java.sip.communicator.util.*;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* Implements a custom <tt>SourceContact</tt> for the Address Book of Microsoft
|
||||
* Outlook.
|
||||
*
|
||||
* @author Vincent Lucas
|
||||
*/
|
||||
public class MsOutlookAddrBookSourceContact
|
||||
extends GenericSourceContact
|
||||
implements EditableSourceContact
|
||||
{
|
||||
/**
|
||||
* The <tt>Logger</tt> used by the <tt>MsOutlookAddrBookSourceContact</tt>
|
||||
* class and its instances for logging output.
|
||||
*/
|
||||
private static final Logger logger
|
||||
= Logger.getLogger(MsOutlookAddrBookSourceContact.class);
|
||||
|
||||
/**
|
||||
* Initializes a new MsOutlookAddrBookSourceContact instance.
|
||||
*
|
||||
* @param contactSource The ContactSourceService which is creating the new
|
||||
* instance.
|
||||
* @param id The outlook entry identifier for contacts.
|
||||
* @param displayName The display name of the new instance.
|
||||
* @param contactDetails The ContactDetails of the new instance.
|
||||
*/
|
||||
public MsOutlookAddrBookSourceContact(
|
||||
ContactSourceService contactSource,
|
||||
String id,
|
||||
String displayName,
|
||||
List<ContactDetail> contactDetails)
|
||||
{
|
||||
super(contactSource, displayName, contactDetails);
|
||||
|
||||
this.setData(SourceContact.DATA_ID, id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the string identifier for this source contact.
|
||||
*
|
||||
* @return The string identifier for this source contact.
|
||||
*/
|
||||
public String getId()
|
||||
{
|
||||
return (String) this.getData(SourceContact.DATA_ID);
|
||||
}
|
||||
|
||||
/**
|
||||
* Changes the details list with the supplied one. Called when the outlook
|
||||
* database for this source contact has been updated.
|
||||
*
|
||||
* @param details the details.
|
||||
*/
|
||||
public void setDetails(List<ContactDetail> details)
|
||||
{
|
||||
synchronized(this.contactDetails)
|
||||
{
|
||||
contactDetails.clear();
|
||||
contactDetails.addAll(details);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Saves all the properties from this source contact into the outlook
|
||||
* database.
|
||||
*/
|
||||
public void save()
|
||||
{
|
||||
synchronized(this.contactDetails)
|
||||
{
|
||||
MsOutlookAddrBookContactDetail outlookContactDetail;
|
||||
|
||||
for(ContactDetail contactDetail: this.contactDetails)
|
||||
{
|
||||
if(contactDetail instanceof MsOutlookAddrBookContactDetail)
|
||||
{
|
||||
outlookContactDetail
|
||||
= (MsOutlookAddrBookContactDetail) contactDetail;
|
||||
for(Long propId: outlookContactDetail.getOutlookPropId())
|
||||
{
|
||||
MsOutlookAddrBookContactQuery.IMAPIProp_SetPropString(
|
||||
propId.longValue(),
|
||||
contactDetail.getDetail(),
|
||||
this.getId());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes the given <tt>ContactDetail</tt> from the list of details for
|
||||
* this <tt>SourceContact</tt>.
|
||||
*
|
||||
* @param detail the <tt>ContactDetail</tt> to remove
|
||||
*/
|
||||
public void removeContactDetail(ContactDetail detail)
|
||||
{
|
||||
synchronized(this.contactDetails)
|
||||
{
|
||||
int i = 0;
|
||||
while(i < this.contactDetails.size())
|
||||
{
|
||||
MsOutlookAddrBookContactDetail contactDetail
|
||||
= ((MsOutlookAddrBookContactDetail)
|
||||
this.contactDetails.get(i));
|
||||
if(contactDetail.match(detail))
|
||||
{
|
||||
this.removeProperty(contactDetail);
|
||||
this.contactDetails.remove(i);
|
||||
}
|
||||
else
|
||||
{
|
||||
++i;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes the contact detail from the outlook database.
|
||||
*
|
||||
* @param contactDetail The contact detail to remove.
|
||||
*/
|
||||
public void removeProperty(
|
||||
final MsOutlookAddrBookContactDetail contactDetail)
|
||||
{
|
||||
for(Long propId: contactDetail.getOutlookPropId())
|
||||
{
|
||||
MsOutlookAddrBookContactQuery.IMAPIProp_DeleteProp(
|
||||
propId.longValue(),
|
||||
this.getId());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a contact detail to the list of contact details.
|
||||
*
|
||||
* @param detail the <tt>ContactDetail</tt> to add
|
||||
*/
|
||||
public void addContactDetail(ContactDetail detail)
|
||||
{
|
||||
synchronized(this.contactDetails)
|
||||
{
|
||||
MsOutlookAddrBookContactDetail addDetail;
|
||||
if(!(detail instanceof MsOutlookAddrBookContactDetail))
|
||||
{
|
||||
long property = MsOutlookAddrBookContactQuery.getProperty(
|
||||
detail.getCategory(),
|
||||
detail.getSubCategories());
|
||||
Collection<ContactDetail.SubCategory> subCategories
|
||||
= detail.getSubCategories();
|
||||
addDetail = new MsOutlookAddrBookContactDetail(
|
||||
detail.getDetail(),
|
||||
detail.getCategory(),
|
||||
subCategories.toArray(
|
||||
new ContactDetail.SubCategory[
|
||||
subCategories.size()]),
|
||||
property);
|
||||
}
|
||||
else
|
||||
{
|
||||
addDetail = (MsOutlookAddrBookContactDetail) detail;
|
||||
}
|
||||
|
||||
// Checks if this property already exists.
|
||||
for(int i = 0; i < this.contactDetails.size(); ++ i)
|
||||
{
|
||||
MsOutlookAddrBookContactDetail contactDetail
|
||||
= ((MsOutlookAddrBookContactDetail)
|
||||
this.contactDetails.get(i));
|
||||
if(contactDetail.match(addDetail))
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
this.contactDetails.add(addDetail);
|
||||
this.save();
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Reference in new issue