X-Git-Url: https://git.saurik.com/apple/mdnsresponder.git/blobdiff_plain/8e92c31c9a45a66732f5bc7afbc9f5596c17e91d..7f0064bd55e3fa98568d2c359429ff8a38b23a6c:/mDNSWindows/Applications/ExplorerPlugin/ExplorerBarWindow.cpp diff --git a/mDNSWindows/Applications/ExplorerPlugin/ExplorerBarWindow.cpp b/mDNSWindows/Applications/ExplorerPlugin/ExplorerBarWindow.cpp deleted file mode 100644 index 7ca9f2a..0000000 --- a/mDNSWindows/Applications/ExplorerPlugin/ExplorerBarWindow.cpp +++ /dev/null @@ -1,751 +0,0 @@ -/* - * Copyright (c) 2003-2004 Apple Computer, Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved. - * - * This file contains Original Code and/or Modifications of Original Code - * as defined in and that are subject to the Apple Public Source License - * Version 2.0 (the 'License'). You may not use this file except in - * compliance with the License. Please obtain a copy of the License at - * http://www.opensource.apple.com/apsl/ and read it before using this - * file. - * - * The Original Code and all software distributed under the License are - * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. - * Please see the License for the specific language governing rights and - * limitations under the License. - * - * @APPLE_LICENSE_HEADER_END@ - - Change History (most recent first): - -$Log: ExplorerBarWindow.cpp,v $ -Revision 1.5 2004/04/15 01:00:05 bradley -Removed support for automatically querying for A/AAAA records when resolving names. Platforms -without .local name resolving support will need to manually query for A/AAAA records as needed. - -Revision 1.4 2004/04/09 21:03:15 bradley -Changed port numbers to use network byte order for consistency with other platforms. - -Revision 1.3 2004/04/08 09:43:43 bradley -Changed callback calling conventions to __stdcall so they can be used with C# delegates. - -Revision 1.2 2004/02/21 04:36:19 bradley -Enable dot local name lookups now that the NSP is being installed. - -Revision 1.1 2004/01/30 03:01:56 bradley -Explorer Plugin to browse for Rendezvous-enabled Web and FTP servers from within Internet Explorer. - -*/ - -#include "StdAfx.h" - -#include "CommonServices.h" -#include "DebugServices.h" -#include "DNSSD.h" - -#include "ExplorerBar.h" -#include "LoginDialog.h" -#include "Resource.h" - -#include "ExplorerBarWindow.h" - -// MFC Debugging - -#ifdef _DEBUG -#define new DEBUG_NEW -#undef THIS_FILE -static char THIS_FILE[] = __FILE__; -#endif - -#if 0 -#pragma mark == Constants == -#endif - -//=========================================================================================================================== -// Constants -//=========================================================================================================================== - -// Control IDs - -#define IDC_EXPLORER_TREE 1234 - -// Private Messages - -#define WM_PRIVATE_SERVICE_ADD ( WM_USER + 0x100 ) -#define WM_PRIVATE_SERVICE_REMOVE ( WM_USER + 0x101 ) -#define WM_PRIVATE_RESOLVE ( WM_USER + 0x102 ) - -// TXT records - -#define kTXTRecordKeyPath "path=" -#define kTXTRecordKeyPathSize sizeof_string( kTXTRecordKeyPath ) - -#if 0 -#pragma mark == Prototypes == -#endif - -//=========================================================================================================================== -// Prototypes -//=========================================================================================================================== - -DEBUG_LOCAL int FindServiceArrayIndex( const ServiceInfoArray &inArray, const ServiceInfo &inService, int &outIndex ); -DEBUG_LOCAL OSStatus UTF8StringToStringObject( const char *inUTF8, CString &inObject ); - -#if 0 -#pragma mark == Message Map == -#endif - -//=========================================================================================================================== -// Message Map -//=========================================================================================================================== - -BEGIN_MESSAGE_MAP( ExplorerBarWindow, CWnd ) - ON_WM_CREATE() - ON_WM_DESTROY() - ON_WM_SIZE() - ON_NOTIFY( NM_DBLCLK, IDC_EXPLORER_TREE, OnDoubleClick ) - ON_MESSAGE( WM_PRIVATE_SERVICE_ADD, OnServiceAdd ) - ON_MESSAGE( WM_PRIVATE_SERVICE_REMOVE, OnServiceRemove ) - ON_MESSAGE( WM_PRIVATE_RESOLVE, OnResolve ) -END_MESSAGE_MAP() - -#if 0 -#pragma mark - -#endif - -//=========================================================================================================================== -// ExplorerBarWindow -//=========================================================================================================================== - -ExplorerBarWindow::ExplorerBarWindow( void ) -{ - mOwner = NULL; - mResolveServiceRef = NULL; -} - -//=========================================================================================================================== -// ~ExplorerBarWindow -//=========================================================================================================================== - -ExplorerBarWindow::~ExplorerBarWindow( void ) -{ - // -} - -#if 0 -#pragma mark - -#endif - -//=========================================================================================================================== -// OnCreate -//=========================================================================================================================== - -int ExplorerBarWindow::OnCreate( LPCREATESTRUCT inCreateStruct ) -{ - AFX_MANAGE_STATE( AfxGetStaticModuleState() ); - - OSStatus err; - CRect rect; - CString s; - - err = CWnd::OnCreate( inCreateStruct ); - require_noerr( err, exit ); - - GetClientRect( rect ); - mTree.Create( WS_TABSTOP | WS_VISIBLE | WS_CHILD | TVS_HASBUTTONS | TVS_LINESATROOT | TVS_HASLINES, rect, this, - IDC_EXPLORER_TREE ); - - err = DNSServiceInitialize( kDNSServiceInitializeFlagsNone, 0 ); - if( err != kNoErr ) - { - // Cannot talk to the mDNSResponder service. Show the error message and exit (with kNoErr so they can see it). - - s.LoadString( IDS_RENDEZVOUS_NOT_AVAILABLE ); - mTree.InsertItem( s, 0, 0, TVI_ROOT, TVI_LAST ); - err = kNoErr; - goto exit; - } - - ServiceHandlerEntry * e; - - // Web Site Handler - - e = new ServiceHandlerEntry; - check( e ); - e->type = "_http._tcp"; - e->urlScheme = "http://"; - e->ref = NULL; - e->treeItem = NULL; - e->treeFirst = true; - e->obj = this; - e->needsLogin = false; - mServiceHandlers.Add( e ); - - s.LoadString( IDS_WEB_SITES ); - e->treeItem = mTree.InsertItem( s, 0, 0 ); - mTree.Expand( e->treeItem, TVE_EXPAND ); - - err = DNSServiceBrowse( &e->ref, 0, 0, e->type, NULL, BrowseCallBack, e ); - require_noerr( err, exit ); - - // FTP Site Handler - - e = new ServiceHandlerEntry; - check( e ); - e->type = "_ftp._tcp"; - e->urlScheme = "ftp://"; - e->ref = NULL; - e->treeItem = NULL; - e->treeFirst = true; - e->obj = this; - e->needsLogin = true; - mServiceHandlers.Add( e ); - - s.LoadString( IDS_FTP_SITES ); - e->treeItem = mTree.InsertItem( s, 0, 0 ); - mTree.Expand( e->treeItem, TVE_EXPAND ); - - err = DNSServiceBrowse( &e->ref, 0, 0, e->type, NULL, BrowseCallBack, e ); - require_noerr( err, exit ); - -exit: - return( err ); -} - -//=========================================================================================================================== -// OnDestroy -//=========================================================================================================================== - -void ExplorerBarWindow::OnDestroy( void ) -{ - // Stop any resolves that may still be pending (shouldn't be any). - - StopResolve(); - - // Clean up the service handlers. - - int i; - int n; - - n = (int) mServiceHandlers.GetSize(); - for( i = 0; i < n; ++i ) - { - delete mServiceHandlers[ i ]; - } - - DNSServiceFinalize(); - CWnd::OnDestroy(); -} - -//=========================================================================================================================== -// OnSize -//=========================================================================================================================== - -void ExplorerBarWindow::OnSize( UINT inType, int inX, int inY ) -{ - CWnd::OnSize( inType, inX, inY ); - mTree.MoveWindow( 0, 0, inX, inY ); -} - -//=========================================================================================================================== -// OnDoubleClick -//=========================================================================================================================== - -void ExplorerBarWindow::OnDoubleClick( NMHDR *inNMHDR, LRESULT *outResult ) -{ - HTREEITEM item; - ServiceInfo * service; - OSStatus err; - - DEBUG_UNUSED( inNMHDR ); - - item = mTree.GetSelectedItem(); - require( item, exit ); - - service = reinterpret_cast < ServiceInfo * > ( mTree.GetItemData( item ) ); - require_quiet( service, exit ); - - err = StartResolve( service ); - require_noerr( err, exit ); - -exit: - *outResult = 0; -} - -#if 0 -#pragma mark - -#endif - -//=========================================================================================================================== -// BrowseCallBack -//=========================================================================================================================== - -void CALLBACK_COMPAT - ExplorerBarWindow::BrowseCallBack( - DNSServiceRef inRef, - DNSServiceFlags inFlags, - uint32_t inInterfaceIndex, - DNSServiceErrorType inErrorCode, - const char * inName, - const char * inType, - const char * inDomain, - void * inContext ) -{ - ServiceHandlerEntry * obj; - ServiceInfo * service; - OSStatus err; - - DEBUG_UNUSED( inRef ); - - service = NULL; - - require_noerr( inErrorCode, exit ); - obj = reinterpret_cast < ServiceHandlerEntry * > ( inContext ); - check( obj ); - check( obj->obj ); - - try - { - // Post a message to the main thread so it can handle it since MFC is not thread safe. - - service = new ServiceInfo; - require_action( service, exit, err = kNoMemoryErr ); - - err = UTF8StringToStringObject( inName, service->displayName ); - check_noerr( err ); - - service->name = strdup( inName ); - require_action( service->name, exit, err = kNoMemoryErr ); - - service->type = strdup( inType ); - require_action( service->type, exit, err = kNoMemoryErr ); - - service->domain = strdup( inDomain ); - require_action( service->domain, exit, err = kNoMemoryErr ); - - service->ifi = inInterfaceIndex; - service->handler = obj; - - DWORD message; - BOOL ok; - - message = ( inFlags & kDNSServiceFlagsAdd ) ? WM_PRIVATE_SERVICE_ADD : WM_PRIVATE_SERVICE_REMOVE; - ok = ::PostMessage( obj->obj->GetSafeHwnd(), message, 0, (LPARAM) service ); - check( ok ); - if( ok ) - { - service = NULL; - } - } - catch( ... ) - { - dlog( kDebugLevelError, "BrowseCallBack: exception thrown\n" ); - } - -exit: - if( service ) - { - delete service; - } -} - -//=========================================================================================================================== -// OnServiceAdd -//=========================================================================================================================== - -LONG ExplorerBarWindow::OnServiceAdd( WPARAM inWParam, LPARAM inLParam ) -{ - ServiceInfo * service; - ServiceHandlerEntry * handler; - int cmp; - int index; - - DEBUG_UNUSED( inWParam ); - - service = reinterpret_cast < ServiceInfo * > ( inLParam ); - check( service ); - handler = service->handler; - check( handler ); - - cmp = FindServiceArrayIndex( handler->array, *service, index ); - if( cmp == 0 ) - { - // Found a match so update the item. The index is index + 1 so subtract 1. - - index -= 1; - check( index < handler->array.GetSize() ); - - service->item = handler->array[ index ]->item; - delete handler->array[ index ]; - handler->array[ index ] = service; - mTree.SetItemText( service->item, service->displayName ); - mTree.SetItemData( service->item, (DWORD_PTR) service ); - } - else - { - HTREEITEM afterItem; - - // Insert the new item in sorted order. - - afterItem = ( index > 0 ) ? handler->array[ index - 1 ]->item : TVI_FIRST; - handler->array.InsertAt( index, service ); - service->item = mTree.InsertItem( service->displayName, handler->treeItem, afterItem ); - mTree.SetItemData( service->item, (DWORD_PTR) service ); - - // Make sure the item is visible if this is the first time a service was added. - - if( handler->treeFirst ) - { - handler->treeFirst = false; - mTree.EnsureVisible( service->item ); - } - } - return( 0 ); -} - -//=========================================================================================================================== -// OnServiceRemove -//=========================================================================================================================== - -LONG ExplorerBarWindow::OnServiceRemove( WPARAM inWParam, LPARAM inLParam ) -{ - ServiceInfo * service; - ServiceHandlerEntry * handler; - int cmp; - int index; - - DEBUG_UNUSED( inWParam ); - - service = reinterpret_cast < ServiceInfo * > ( inLParam ); - check( service ); - handler = service->handler; - check( handler ); - - // Search to see if we know about this service instance. If so, remove it from the list. - - cmp = FindServiceArrayIndex( handler->array, *service, index ); - check( cmp == 0 ); - if( cmp == 0 ) - { - // Found a match remove the item. The index is index + 1 so subtract 1. - - index -= 1; - check( index < handler->array.GetSize() ); - - mTree.DeleteItem( handler->array[ index ]->item ); - delete handler->array[ index ]; - handler->array.RemoveAt( index ); - } - delete service; - return( 0 ); -} - -#if 0 -#pragma mark - -#endif - -//=========================================================================================================================== -// StartResolve -//=========================================================================================================================== - -OSStatus ExplorerBarWindow::StartResolve( ServiceInfo *inService ) -{ - OSStatus err; - - check( inService ); - - // Stop any current resolve that may be in progress. - - StopResolve(); - - // Resolve the service. - - err = DNSServiceResolve( &mResolveServiceRef, kDNSServiceFlagsNone, inService->ifi, - inService->name, inService->type, inService->domain, ResolveCallBack, inService->handler ); - require_noerr( err, exit ); - -exit: - return( err ); -} - -//=========================================================================================================================== -// StopResolve -//=========================================================================================================================== - -void ExplorerBarWindow::StopResolve( void ) -{ - if( mResolveServiceRef ) - { - DNSServiceRefDeallocate( mResolveServiceRef ); - mResolveServiceRef = NULL; - } -} - -//=========================================================================================================================== -// ResolveCallBack -//=========================================================================================================================== - -void CALLBACK_COMPAT - ExplorerBarWindow::ResolveCallBack( - DNSServiceRef inRef, - DNSServiceFlags inFlags, - uint32_t inInterfaceIndex, - DNSServiceErrorType inErrorCode, - const char * inFullName, - const char * inHostName, - uint16_t inPort, - uint16_t inTXTSize, - const char * inTXT, - void * inContext ) -{ - ExplorerBarWindow * obj; - ServiceHandlerEntry * handler; - OSStatus err; - - DEBUG_UNUSED( inRef ); - DEBUG_UNUSED( inFlags ); - DEBUG_UNUSED( inErrorCode ); - DEBUG_UNUSED( inFullName ); - - require_noerr( inErrorCode, exit ); - handler = (ServiceHandlerEntry *) inContext; - check( handler ); - obj = handler->obj; - check( obj ); - - try - { - ResolveInfo * resolve; - BOOL ok; - - dlog( kDebugLevelNotice, "resolved %s on ifi %d to %s\n", inFullName, inInterfaceIndex, inHostName ); - - // Stop resolving after the first good result. - - obj->StopResolve(); - - // Post a message to the main thread so it can handle it since MFC is not thread safe. - - resolve = new ResolveInfo; - require_action( resolve, exit, err = kNoMemoryErr ); - - UTF8StringToStringObject( inHostName, resolve->host ); - resolve->port = ntohs( inPort ); - resolve->ifi = inInterfaceIndex; - resolve->handler = handler; - - err = resolve->txt.SetData( inTXT, inTXTSize ); - check_noerr( err ); - - ok = ::PostMessage( obj->GetSafeHwnd(), WM_PRIVATE_RESOLVE, 0, (LPARAM) resolve ); - check( ok ); - if( !ok ) - { - delete resolve; - } - } - catch( ... ) - { - dlog( kDebugLevelError, "ResolveCallBack: exception thrown\n" ); - } - -exit: - return; -} - -//=========================================================================================================================== -// OnResolve -//=========================================================================================================================== - -LONG ExplorerBarWindow::OnResolve( WPARAM inWParam, LPARAM inLParam ) -{ - ResolveInfo * resolve; - CString url; - uint8_t * path; - size_t pathSize; - char * pathPrefix; - CString username; - CString password; - - DEBUG_UNUSED( inWParam ); - - resolve = reinterpret_cast < ResolveInfo * > ( inLParam ); - check( resolve ); - - // Get login info if needed. - - if( resolve->handler->needsLogin ) - { - LoginDialog dialog; - - if( !dialog.GetLogin( username, password ) ) - { - goto exit; - } - } - - // If the HTTP TXT record is a "path=" entry, use it as the resource path. Otherwise, use "/". - - pathPrefix = ""; - if( strcmp( resolve->handler->type, "_http._tcp" ) == 0 ) - { - resolve->txt.GetData( &path, &pathSize ); - if( pathSize > 0 ) - { - pathSize = *path++; - } - if( ( pathSize > kTXTRecordKeyPathSize ) && ( memicmp( path, kTXTRecordKeyPath, kTXTRecordKeyPathSize ) == 0 ) ) - { - path += kTXTRecordKeyPathSize; - pathSize -= kTXTRecordKeyPathSize; - } - else if( pathSize == 0 ) - { - path = (uint8_t *) "/"; - pathSize = 1; - } - if( *path != '/' ) - { - pathPrefix = "/"; - } - } - else - { - path = (uint8_t *) ""; - pathSize = 1; - } - - // Build the URL in the following format: - // - // [[:]@][] - - url.AppendFormat( TEXT( "%S" ), resolve->handler->urlScheme ); // URL Scheme - if( username.GetLength() > 0 ) - { - url.AppendFormat( TEXT( "%s" ), username ); // Username - if( password.GetLength() > 0 ) - { - url.AppendFormat( TEXT( ":%s" ), password ); // Password - } - url.AppendFormat( TEXT( "@" ) ); - } - - url += resolve->host; // Host - url.AppendFormat( TEXT( ":%d" ), resolve->port ); // :Port - url.AppendFormat( TEXT( "%S" ), pathPrefix ); // Path Prefix ("/" or empty). - url.AppendFormat( TEXT( "%.*S" ), (int) pathSize, (char *) path ); // Path (possibly empty). - - // Tell Internet Explorer to go to the URL. - - check( mOwner ); - mOwner->GoToURL( url ); - -exit: - delete resolve; - return( 0 ); -} - -#if 0 -#pragma mark - -#endif - -//=========================================================================================================================== -// FindServiceArrayIndex -//=========================================================================================================================== - -DEBUG_LOCAL int FindServiceArrayIndex( const ServiceInfoArray &inArray, const ServiceInfo &inService, int &outIndex ) -{ - int result; - int lo; - int hi; - int mid; - - result = -1; - mid = 0; - lo = 0; - hi = (int)( inArray.GetSize() - 1 ); - while( lo <= hi ) - { - mid = ( lo + hi ) / 2; - result = inService.displayName.CompareNoCase( inArray[ mid ]->displayName ); - if( result == 0 ) - { - result = ( (int) inService.ifi ) - ( (int) inArray[ mid ]->ifi ); - } - if( result == 0 ) - { - break; - } - else if( result < 0 ) - { - hi = mid - 1; - } - else - { - lo = mid + 1; - } - } - if( result == 0 ) - { - mid += 1; // Bump index so new item is inserted after matching item. - } - else if( result > 0 ) - { - mid += 1; - } - outIndex = mid; - return( result ); -} - -//=========================================================================================================================== -// UTF8StringToStringObject -//=========================================================================================================================== - -DEBUG_LOCAL OSStatus UTF8StringToStringObject( const char *inUTF8, CString &inObject ) -{ - OSStatus err; - int n; - BSTR unicode; - - unicode = NULL; - - n = MultiByteToWideChar( CP_UTF8, 0, inUTF8, -1, NULL, 0 ); - if( n > 0 ) - { - unicode = (BSTR) malloc( (size_t)( n * sizeof( wchar_t ) ) ); - if( !unicode ) - { - err = ERROR_INSUFFICIENT_BUFFER; - goto exit; - } - - n = MultiByteToWideChar( CP_UTF8, 0, inUTF8, -1, unicode, n ); - try - { - inObject = unicode; - } - catch( ... ) - { - err = ERROR_NO_UNICODE_TRANSLATION; - goto exit; - } - } - else - { - inObject = ""; - } - err = ERROR_SUCCESS; - -exit: - if( unicode ) - { - free( unicode ); - } - return( err ); -}