diff --git a/lib/native/windows-64/jmsofficecomm.dll b/lib/native/windows-64/jmsofficecomm.dll index 8205f5970..af28cc97c 100755 Binary files a/lib/native/windows-64/jmsofficecomm.dll and b/lib/native/windows-64/jmsofficecomm.dll differ diff --git a/lib/native/windows/jmsofficecomm.dll b/lib/native/windows/jmsofficecomm.dll index 69d4f0a6e..968465a20 100755 Binary files a/lib/native/windows/jmsofficecomm.dll and b/lib/native/windows/jmsofficecomm.dll differ diff --git a/src/native/windows/msofficecomm/Messenger.cxx b/src/native/windows/msofficecomm/Messenger.cxx index 41f42ba71..a24eb498d 100644 --- a/src/native/windows/msofficecomm/Messenger.cxx +++ b/src/native/windows/msofficecomm/Messenger.cxx @@ -705,7 +705,7 @@ HRESULT Messenger::start(JNIEnv *env) = env->GetMethodID( clazz, "startConversation", - "(I[Ljava/lang/String;)V"); + "(I[Ljava/lang/String;Ljava/lang/String;)V"); if (startConversationMethodID) { @@ -744,11 +744,119 @@ Messenger::StartConversation VARIANT vConversationData, VARIANT *pvWndHnd) { + JavaVM *vm = OutOfProcessServer::getJavaVM(); + JNIEnv *env; + HRESULT hr; + + if (vm && !(vm->AttachCurrentThreadAsDaemon((void **) &env, NULL))) + { + jobjectArray participants; + + hr = toStringArray(env, vParticipants, &participants); + if (SUCCEEDED(hr)) + { + jstring conversationData; + + hr = toString(env, vConversationData, &conversationData); + /* + * The MSDN is pretty scarce on the subject of vConversationData + * thus we can hardly rely on getting it right. + */ + if (hr == E_INVALIDARG) + { + conversationData = NULL; + hr = S_OK; + } + if (SUCCEEDED(hr)) + { + if (_jobject) + { + env->CallVoidMethod( + _jobject, + _jstartConversationMethodID, + (jint) ConversationType, + participants, + conversationData); + } + else + hr = E_FAIL; + } + } + if (env->ExceptionCheck()) + { + env->ExceptionClear(); + hr = E_FAIL; + } + } + else + hr = E_UNEXPECTED; + return hr; +} + +STDMETHODIMP Messenger::StartVideo(VARIANT vContact, IDispatch **ppMWindow) + STDMETHODIMP_E_NOTIMPL_STUB + +STDMETHODIMP Messenger::StartVoice(VARIANT vContact, IDispatch **ppMWindow) + STDMETHODIMP_E_NOTIMPL_STUB + +HRESULT Messenger::stop(JNIEnv *env) +{ + jclass clazz = _jclass; + + _jclass = NULL; + _jctorMethodID = NULL; + _jstartConversationMethodID = NULL; + if (clazz) + env->DeleteGlobalRef(clazz); + + return S_OK; +} + +HRESULT Messenger::toString(JNIEnv *env, VARIANT &v, jstring *string) +{ + BSTR bstr; HRESULT hr; - if (VT_ARRAY == (vParticipants.vt & VT_ARRAY)) + if (VT_BSTR == v.vt) { - SAFEARRAY *sa = vParticipants.parray; + bstr = v.bstrVal; + hr = S_OK; + } + else if ((VT_BSTR | VT_BYREF) == v.vt) + { + bstr = *(v.pbstrVal); + hr = S_OK; + } + else + hr = E_INVALIDARG; + + if (SUCCEEDED(hr)) + { + if (bstr) + { + jstring _string + = env->NewString((const jchar *) bstr, ::SysStringLen(bstr)); + + if (_string) + *string = _string; + else + hr = E_OUTOFMEMORY; + } + else + *string = NULL; + } + + return hr; +} + +HRESULT +Messenger::toStringArray(JNIEnv *env, VARIANT &v, jobjectArray *stringArray) +{ + HRESULT hr; + + if (VT_ARRAY == (v.vt & VT_ARRAY)) + { + SAFEARRAY *sa = v.parray; if (sa && (1 == sa->cDims) @@ -759,86 +867,41 @@ Messenger::StartConversation hr = ::SafeArrayAccessData(sa, (PVOID *) &data); if (SUCCEEDED(hr)) { - JavaVM *vm = OutOfProcessServer::getJavaVM(); - JNIEnv *env; + jclass stringClass = env->FindClass("java/lang/String"); - if (vm - && !(vm->AttachCurrentThreadAsDaemon( - (void **) &env, - NULL))) + if (stringClass) { - jclass stringClass = env->FindClass("java/lang/String"); + SAFEARRAYBOUND *bound = sa->rgsabound; + ULONG length = bound->cElements; + jobjectArray _stringArray + = env->NewObjectArray(length, stringClass, NULL); - if (stringClass) + if (_stringArray) { - SAFEARRAYBOUND *bound = sa->rgsabound; - ULONG length = bound->cElements; - jobjectArray participants - = env->NewObjectArray(length, stringClass, NULL); + ULONG elemsize = sa->cbElements; - if (participants) + data += bound->lLbound; + for (ULONG i = 0; i < length; i++, data += elemsize) { - ULONG elemsize = sa->cbElements; - - data += bound->lLbound; - for (ULONG i = 0; i < length; i++, data += elemsize) - { - VARIANT *v = (VARIANT *) data; - BSTR bstr; - - if (VT_BSTR == v->vt) - bstr = v->bstrVal; - else if ((VT_BSTR | VT_BYREF) == v->vt) - bstr = *(v->pbstrVal); - else - { - hr = E_INVALIDARG; - break; - } - - jstring participant - = env->NewString( - (const jchar *) bstr, - ::SysStringLen(bstr)); - - if (participant) - { - env->SetObjectArrayElement( - participants, - i, - participant); - } - else - { - hr = E_OUTOFMEMORY; - break; - } - } + jstring _string; + hr = toString(env, *((VARIANT *) data), &_string); if (SUCCEEDED(hr)) { - if (_jobject) - { - env->CallVoidMethod( - _jobject, - _jstartConversationMethodID, - (jint) ConversationType, - participants); - if (env->ExceptionCheck()) - { - env->ExceptionClear(); - hr = E_FAIL; - } - } - else - hr = E_FAIL; + env->SetObjectArrayElement( + _stringArray, + i, + _string); } + else + break; } - else - hr = E_OUTOFMEMORY; + + if (SUCCEEDED(hr)) + *stringArray = _stringArray; } else - hr = E_UNEXPECTED; + hr = E_OUTOFMEMORY; } else hr = E_UNEXPECTED; @@ -853,24 +916,5 @@ Messenger::StartConversation return hr; } -STDMETHODIMP Messenger::StartVideo(VARIANT vContact, IDispatch **ppMWindow) - STDMETHODIMP_E_NOTIMPL_STUB - -STDMETHODIMP Messenger::StartVoice(VARIANT vContact, IDispatch **ppMWindow) - STDMETHODIMP_E_NOTIMPL_STUB - -HRESULT Messenger::stop(JNIEnv *env) -{ - jclass clazz = _jclass; - - _jclass = NULL; - _jctorMethodID = NULL; - _jstartConversationMethodID = NULL; - if (clazz) - env->DeleteGlobalRef(clazz); - - return S_OK; -} - STDMETHODIMP Messenger::ViewProfile(VARIANT vContact) STDMETHODIMP_E_NOTIMPL_STUB diff --git a/src/native/windows/msofficecomm/Messenger.h b/src/native/windows/msofficecomm/Messenger.h index 7a8051c6a..5eca3e885 100644 --- a/src/native/windows/msofficecomm/Messenger.h +++ b/src/native/windows/msofficecomm/Messenger.h @@ -113,6 +113,8 @@ private: HRESULT createMessengerContact(BSTR signinName, REFIID iid, PVOID *obj); HRESULT destructJobject(); HRESULT getMessengerContact(BSTR signinName, REFIID iid, PVOID *obj); + HRESULT toString(JNIEnv *env, VARIANT &v, jstring *string); + HRESULT toStringArray(JNIEnv *env, VARIANT &v, jobjectArray *stringArray); DMessengerEventsConnectionPoint *_dMessengerEventsConnectionPoint; jobject _jobject; diff --git a/src/net/java/sip/communicator/plugin/msofficecomm/Messenger.java b/src/net/java/sip/communicator/plugin/msofficecomm/Messenger.java index 21319d1e8..831b3724d 100644 --- a/src/net/java/sip/communicator/plugin/msofficecomm/Messenger.java +++ b/src/net/java/sip/communicator/plugin/msofficecomm/Messenger.java @@ -21,7 +21,9 @@ import net.java.sip.communicator.service.protocol.yahooconstants.*; import net.java.sip.communicator.util.*; +import org.jitsi.util.xml.*; import org.osgi.framework.*; +import org.w3c.dom.*; /** * Represents the Java counterpart of a native IMessenger @@ -31,6 +33,12 @@ */ public class Messenger { + /** + * The Logger used by the Messenger class and its + * instances for logging output. + */ + private static final Logger logger = Logger.getLogger(Messenger.class); + static final int CONVERSATION_TYPE_AUDIO = 8; static final int CONVERSATION_TYPE_IM = 1; @@ -653,10 +661,13 @@ public Messenger() * type of the conversation to be started * @param participants an array of String values specifying the * other users to start a conversation with + * @param conversationData an XML BLOB specifying the phone numbers to be + * dialed in order to start the conversation */ public void startConversation( final int conversationType, - String[] participants) + String[] participants, + String conversationData) { /* * Firstly, resolve the participants into Contacts which may include @@ -670,10 +681,103 @@ public void startConversation( case CONVERSATION_TYPE_PHONE: case CONVERSATION_TYPE_PSTN: opSetClass = OperationSetBasicTelephony.class; + + if ((conversationData != null) && (conversationData.length() != 0)) + { + if (logger.isTraceEnabled()) + { + logger.trace( + "conversationData = \"" + conversationData + "\""); + } + + // According to MSDN, vConversationData could be an XML BLOB. + if (conversationData.startsWith("<")) + { + try + { + Document document + = XMLUtils.createDocument(conversationData); + Element documentElement = document.getDocumentElement(); + + if ("TelURIs".equalsIgnoreCase( + documentElement.getTagName())) + { + NodeList childNodes + = documentElement.getChildNodes(); + + if (childNodes != null) + { + int childNodeCount = childNodes.getLength(); + List phoneNumbers + = new ArrayList(childNodeCount); + + for (int childNodeIndex = 0; + childNodeIndex < childNodeCount; + childNodeIndex++) + { + Node childNode + = childNodes.item(childNodeIndex); + + if (childNode.getNodeType() + == Node.ELEMENT_NODE) + { + phoneNumbers.add( + childNode.getTextContent()); + } + } + + int count = participants.length; + + if (phoneNumbers.size() == count) + { + for (int i = 0; i < count; i++) + { + String phoneNumber + = phoneNumbers.get(i); + + if ((phoneNumber != null) + && (phoneNumber.length() != 0)) + { + if (phoneNumber + .toLowerCase() + .startsWith("tel:")) + { + phoneNumber + = phoneNumber.substring(4); + } + participants[i] = phoneNumber; + } + } + } + } + } + } + catch (Exception e) + { + logger.error( + "Failed to parse" + + " IMessengerAdvanced::StartConversation" + + " vConversationData: " + + conversationData, + e); + } + } + else + { + /* + * Practice/testing shows that vConversationData is the + * phone number in the case of a single participant. + */ + if (participants.length == 1) + participants[0] = conversationData; + } + } + break; case CONVERSATION_TYPE_IM: opSetClass = OperationSetBasicInstantMessaging.class; break; + default: throw new UnsupportedOperationException(); }