+++ /dev/null
-/*
- * Copyright (c) 2002-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: ChooserDialog.cpp,v $
-Revision 1.10 2004/04/23 01:19:41 bradley
-Changed TXT record new line delimiter from \n to \r\n so it works now that it is an edit text.
-
-Revision 1.9 2004/03/07 05:51:04 bradley
-Updated service type list table to include all service types from dns-sd.org as of 2004-03-06.
-Added separate Service Type and Service Description columns so both are show in the window.
-
-Revision 1.8 2004/01/30 02:56:32 bradley
-Updated to support full Unicode display. Added support for all services on www.dns-sd.org.
-
-Revision 1.7 2003/12/25 03:42:04 bradley
-Added login dialog to get username/password when going to FTP sites. Added more services.
-
-Revision 1.6 2003/10/31 12:18:30 bradley
-Added display of the resolved host name. Show separate TXT record entries on separate lines.
-
-Revision 1.5 2003/10/16 09:21:56 bradley
-Ignore non-IPv4 resolves until mDNS on Windows supports IPv6.
-
-Revision 1.4 2003/10/10 03:41:29 bradley
-Changed HTTP double-click handling to work with or without the path= prefix in the TXT record.
-
-Revision 1.3 2003/10/09 19:50:40 bradley
-Sort service type list by description.
-
-Revision 1.2 2003/10/09 19:41:29 bradley
-Changed quit handling to go through normal close path so dialog is freed on quit. Integrated changes
-from Andrew van der Stock for the addition of an _rfb._tcp service type for a VNC Remote Framebuffer
-Server for KDE support. Widened service type list to handle larger service type descriptions.
-
-Revision 1.1 2003/08/21 02:06:47 bradley
-Moved Rendezvous Browser for non-Windows CE into Windows sub-folder.
-
-Revision 1.7 2003/08/20 06:45:56 bradley
-Updated for IP address changes in DNSServices. Added support for browsing for Xserve RAID.
-
-Revision 1.6 2003/08/12 19:56:28 cheshire
-Update to APSL 2.0
-
-Revision 1.5 2003/07/13 01:03:55 cheshire
-Diffs provided by Bob Bradley to provide provide proper display of Unicode names
-
-Revision 1.4 2003/07/02 21:20:06 cheshire
-<rdar://problem/3313413> Update copyright notices, etc., in source code comments
-
-Revision 1.3 2002/09/21 20:44:55 zarzycki
-Added APSL info
-
-Revision 1.2 2002/09/20 08:39:21 bradley
-Make sure each resolved item matches the selected service type to handle resolved that may have
-been queued up on the Windows Message Loop. Reduce column to fit when scrollbar is present.
-
-Revision 1.1 2002/09/20 06:12:52 bradley
-Rendezvous Browser for Windows
-
-*/
-
-#include <assert.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <time.h>
-
-#include <algorithm>
-#include <memory>
-
-#include "stdafx.h"
-
-#include "DNSServices.h"
-
-#include "Application.h"
-#include "AboutDialog.h"
-#include "LoginDialog.h"
-#include "Resource.h"
-
-#include "ChooserDialog.h"
-
-#ifdef _DEBUG
-#define new DEBUG_NEW
-#undef THIS_FILE
-static char THIS_FILE[] = __FILE__;
-#endif
-
-#if 0
-#pragma mark == Constants ==
-#endif
-
-//===========================================================================================================================
-// Constants
-//===========================================================================================================================
-
-// Menus
-
-enum
-{
- kChooserMenuIndexFile = 0,
- kChooserMenuIndexHelp = 1
-};
-
-// Domain List
-
-#define kDomainListDefaultDomainColumnWidth 164
-
-// Service List
-
-#define kServiceListDefaultServiceColumnTypeWidth 146
-#define kServiceListDefaultServiceColumnDescWidth 230
-
-// Chooser List
-
-#define kChooserListDefaultNameColumnWidth 190
-#define kChooserListDefaultIPColumnWidth 120
-
-// Windows User Messages
-
-#define WM_USER_DOMAIN_ADD ( WM_USER + 0x100 )
-#define WM_USER_DOMAIN_REMOVE ( WM_USER + 0x101 )
-#define WM_USER_SERVICE_ADD ( WM_USER + 0x102 )
-#define WM_USER_SERVICE_REMOVE ( WM_USER + 0x103 )
-#define WM_USER_RESOLVE ( WM_USER + 0x104 )
-
-#if 0
-#pragma mark == Constants - Service Table ==
-#endif
-
-//===========================================================================================================================
-// Constants - Service Table
-//===========================================================================================================================
-
-struct KnownServiceEntry
-{
- const char * serviceType;
- const char * description;
- const char * urlScheme;
- bool useText;
-};
-
-static const KnownServiceEntry kKnownServiceTable[] =
-{
- { "_accountedge._tcp.", "MYOB AccountEdge", "", false },
- { "_aecoretech._tcp.", "Apple Application Engineering Services", "", false },
- { "_afpovertcp._tcp.", "Apple File Sharing (AFP)", "afp://", false },
- { "_airport._tcp.", "AirPort Base Station", "", false },
- { "_apple-sasl._tcp.", "Apple Password Server", "", false },
- { "_aquamon._tcp.", "AquaMon", "", false },
- { "_async._tcp", "address-o-sync", "", false },
- { "_auth._tcp.", "Authentication Service", "", false },
- { "_bootps._tcp.", "Bootstrap Protocol Server", "", false },
- { "_bousg._tcp.", "Bag Of Unusual Strategy Games", "", false },
- { "_browse._udp.", "DNS Service Discovery", "", false },
- { "_cheat._tcp.", "The Cheat", "", false },
- { "_chess._tcp", "Project Gridlock", "", false },
- { "_chfts._tcp", "Fluid Theme Server", "", false },
- { "_clipboard._tcp", "Clipboard Sharing", "", false },
- { "_contactserver._tcp.", "Now Up-to-Date & Contact", "", false },
- { "_cvspserver._tcp", "CVS PServer", "", false },
- { "_cytv._tcp.", "CyTV Network streaming for Elgato EyeTV", "", false },
- { "_daap._tcp.", "Digital Audio Access Protocol (iTunes)", "daap://", false },
- { "_distcc._tcp", "Distributed Compiler", "", false },
- { "_dns-sd._udp", "DNS Service Discovery", "", false },
- { "_dpap._tcp.", "Digital Picture Access Protocol (iPhoto)", "", false },
- { "_earphoria._tcp.", "Earphoria", "", false },
- { "_ecbyesfsgksc._tcp.", "Net Monitor Anti-Piracy Service", "", false },
- { "_eheap._tcp.", "Interactive Room Software", "", false },
- { "_embrace._tcp.", "DataEnvoy", "", false },
- { "_eppc._tcp.", "Remote AppleEvents", "eppc://", false },
- { "_exec._tcp.", "Remote Process Execution", "", false },
- { "_facespan._tcp.", "FaceSpan", "", false },
- { "_fjork._tcp.", "Fjork", "", false },
- { "_ftp._tcp.", "File Transfer (FTP)", "ftp://", false },
- { "_ftpcroco._tcp.", "Crocodile FTP Server", "", false },
- { "_gbs-smp._tcp.", "SnapMail", "", false },
- { "_gbs-stp._tcp.", "SnapTalk", "", false },
- { "_grillezvous._tcp.", "Roxio ToastAnywhere(tm) Recorder Sharing", "", false },
- { "_h323._tcp.", "H.323", "", false },
- { "_hotwayd._tcp", "Hotwayd", "", false },
- { "_http._tcp.", "Web Server (HTTP)", "http://", true },
- { "_hydra._tcp", "SubEthaEdit", "", false },
- { "_ica-networking._tcp.", "Image Capture Networking", "", false },
- { "_ichalkboard._tcp.", "iChalk", "", false },
- { "_ichat._tcp.", "iChat", "ichat://", false },
- { "_iconquer._tcp.", "iConquer", "", false },
- { "_imap._tcp.", "Internet Message Access Protocol", "", false },
- { "_imidi._tcp.", "iMidi", "", false },
- { "_ipp._tcp.", "Printer (IPP)", "ipp://", false },
- { "_ishare._tcp.", "iShare", "", false },
- { "_isparx._tcp.", "iSparx", "", false },
- { "_istorm._tcp", "iStorm", "", false },
- { "_iwork._tcp.", "iWork Server", "", false },
- { "_liaison._tcp.", "Liaison", "", false },
- { "_login._tcp.", "Remote Login a la Telnet", "", false },
- { "_lontalk._tcp.", "LonTalk over IP (ANSI 852)", "", false },
- { "_lonworks._tcp.", "Echelon LNS Remote Client", "", false },
- { "_macfoh-remote._tcp.", "MacFOH Remote", "", false },
- { "_moneyworks._tcp.", "MoneyWorks", "", false },
- { "_mp3sushi._tcp", "MP3 Sushi", "", false },
- { "_mttp._tcp.", "MenuTunes Sharing", "", false },
- { "_ncbroadcast._tcp.", "Network Clipboard Broadcasts", "", false },
- { "_ncdirect._tcp.", "Network Clipboard Direct Transfers", "", false },
- { "_ncsyncserver._tcp.", "Network Clipboard Sync Server", "", false },
- { "_newton-dock._tcp.", "Escale", "", false },
- { "_nfs._tcp", "NFS", "", false },
- { "_nssocketport._tcp.", "DO over NSSocketPort", "", false },
- { "_omni-bookmark._tcp.", "OmniWeb", "", false },
- { "_openbase._tcp.", "OpenBase SQL", "", false },
- { "_p2pchat._tcp.", "Peer-to-Peer Chat", "", false },
- { "_pdl-datastream._tcp.", "Printer (PDL)", "pdl://", false },
- { "_poch._tcp.", "Parallel OperatiOn and Control Heuristic", "", false },
- { "_pop_2_ambrosia._tcp.", "Pop-Pop", "", false },
- { "_pop3._tcp", "POP3 Server", "", false },
- { "_postgresql._tcp", "PostgreSQL Server", "", false },
- { "_presence._tcp", "iChat AV", "", false },
- { "_printer._tcp.", "Printer (LPR)", "lpr://", false },
- { "_ptp._tcp.", "Picture Transfer (PTP)", "ptp://", false },
- { "_register._tcp", "DNS Service Discovery", "", false },
- { "_rendezvouspong._tcp", "RendezvousPong", "", false },
- { "_rfb._tcp.", "Remote Frame Buffer", "", false },
- { "_riousbprint._tcp.", "Remote I/O USB Printer Protocol", "", false },
- { "_rtsp._tcp.", "Real Time Stream Control Protocol", "", false },
- { "_safarimenu._tcp", "Safari Menu", "", false },
- { "_scone._tcp", "Scone", "", false },
- { "_sdsharing._tcp.", "Speed Download", "", false },
- { "_seeCard._tcp.", "seeCard", "", false },
- { "_services._udp.", "DNS Service Discovery", "", false },
- { "_shell._tcp.", "like exec, but automatic authentication", "", false },
- { "_shout._tcp.", "Shout", "", false },
- { "_shoutcast._tcp", "Nicecast", "", false },
- { "_smb._tcp.", "Windows File Sharing (SMB)", "smb://", false },
- { "_soap._tcp.", "Simple Object Access Protocol", "", false },
- { "_spincrisis._tcp.", "Spin Crisis", "", false },
- { "_spl-itunes._tcp.", "launchTunes", "", false },
- { "_spr-itunes._tcp.", "netTunes", "", false },
- { "_ssh._tcp.", "Secure Shell (SSH)", "ssh://", false },
- { "_ssscreenshare._tcp", "Screen Sharing", "", false },
- { "_sge-exec._tcp", "Sun Grid Engine (Execution Host)", "", false },
- { "_sge-qmaster._tcp", "Sun Grid Engine (Master)", "", false },
- { "_stickynotes._tcp", "Sticky Notes", "", false },
- { "_strateges._tcp", "Strateges", "", false },
- { "_sxqdea._tcp", "Synchronize! Pro X", "", false },
- { "_sybase-tds._tcp", "Sybase Server", "", false },
- { "_tce._tcp", "Power Card", "", false },
- { "_teamlist._tcp", "ARTIS Team Task", "", false },
- { "_teleport._tcp", "teleport", "", false },
- { "_telnet._tcp.", "Telnet", "telnet://", false },
- { "_tftp._tcp.", "Trivial File Transfer (TFTP)", "tftp://", false },
- { "_tinavigator._tcp.", "TI Navigator", "", false },
- { "_tivo_servemedia._tcp", "TiVo", "", false },
- { "_upnp._tcp.", "Universal Plug and Play", "", false },
- { "_utest._tcp.", "uTest", "", false },
- { "_vue4rendercow._tcp", "VueProRenderCow", "", false },
- { "_webdav._tcp.", "WebDAV", "webdav://", false },
- { "_whamb._tcp.", "Whamb", "", false },
- { "_workstation._tcp", "Macintosh Manager", "", false },
- { "_ws._tcp", "Web Services", "", false },
- { "_xserveraid._tcp.", "Xserve RAID", "xsr://", false },
- { "_xsync._tcp.", "Xserve RAID Synchronization", "", false },
-
- { "", "", "", false },
-
- // Unofficial and invalid service types that will be phased out:
-
- { "_clipboardsharing._tcp.", "ClipboardSharing", "", false },
- { "_MacOSXDupSuppress._tcp.", "Mac OS X Duplicate Suppression", "", false },
- { "_netmonitorserver._tcp.", "Net Monitor Server", "", false },
- { "_networkclipboard._tcp.", "Network Clipboard", "", false },
- { "_slimdevices_slimp3_cli._tcp.", "SliMP3 Server Command-Line Interface", "", false },
- { "_slimdevices_slimp3_http._tcp.", "SliMP3 Server Web Interface", "", false },
- { "_tieducationalhandhelddevice._tcp.", "TI Connect Manager", "", false },
- { "_tivo_servemedia._tcp.", "TiVo", "", false },
-
- { NULL, NULL, NULL, false },
-};
-
-#if 0
-#pragma mark == Structures ==
-#endif
-
-//===========================================================================================================================
-// Structures
-//===========================================================================================================================
-
-struct DomainEventInfo
-{
- DNSBrowserEventType eventType;
- CString domain;
- DNSNetworkAddress ifIP;
-};
-
-struct ServiceEventInfo
-{
- DNSBrowserEventType eventType;
- std::string name;
- std::string type;
- std::string domain;
- DNSNetworkAddress ifIP;
-};
-
-#if 0
-#pragma mark == Prototypes ==
-#endif
-
-//===========================================================================================================================
-// Prototypes
-//===========================================================================================================================
-
-static void
- BrowserCallBack(
- void * inContext,
- DNSBrowserRef inRef,
- DNSStatus inStatusCode,
- const DNSBrowserEvent * inEvent );
-
-static char * DNSNetworkAddressToString( const DNSNetworkAddress *inAddr, char *outString );
-
-static DWORD UTF8StringToStringObject( const char *inUTF8, CString &inObject );
-static DWORD StringObjectToUTF8String( CString &inObject, std::string &outUTF8 );
-
-#if 0
-#pragma mark == Message Map ==
-#endif
-
-//===========================================================================================================================
-// Message Map
-//===========================================================================================================================
-
-BEGIN_MESSAGE_MAP(ChooserDialog, CDialog)
- //{{AFX_MSG_MAP(ChooserDialog)
- ON_WM_SYSCOMMAND()
- ON_NOTIFY(LVN_ITEMCHANGED, IDC_DOMAIN_LIST, OnDomainListChanged)
- ON_NOTIFY(LVN_ITEMCHANGED, IDC_SERVICE_LIST, OnServiceListChanged)
- ON_NOTIFY(LVN_ITEMCHANGED, IDC_CHOOSER_LIST, OnChooserListChanged)
- ON_NOTIFY(NM_DBLCLK, IDC_CHOOSER_LIST, OnChooserListDoubleClick)
- ON_COMMAND(ID_HELP_ABOUT, OnAbout)
- ON_WM_INITMENUPOPUP()
- ON_WM_ACTIVATE()
- ON_COMMAND(ID_FILE_CLOSE, OnFileClose)
- ON_COMMAND(ID_FILE_EXIT, OnExit)
- ON_WM_CLOSE()
- ON_WM_NCDESTROY()
- //}}AFX_MSG_MAP
- ON_MESSAGE( WM_USER_DOMAIN_ADD, OnDomainAdd )
- ON_MESSAGE( WM_USER_DOMAIN_REMOVE, OnDomainRemove )
- ON_MESSAGE( WM_USER_SERVICE_ADD, OnServiceAdd )
- ON_MESSAGE( WM_USER_SERVICE_REMOVE, OnServiceRemove )
- ON_MESSAGE( WM_USER_RESOLVE, OnResolve )
-END_MESSAGE_MAP()
-
-#if 0
-#pragma mark == Routines ==
-#endif
-
-//===========================================================================================================================
-// ChooserDialog
-//===========================================================================================================================
-
-ChooserDialog::ChooserDialog( CWnd *inParent )
- : CDialog( ChooserDialog::IDD, inParent)
-{
- //{{AFX_DATA_INIT(ChooserDialog)
- // NOTE: the ClassWizard will add member initialization here
- //}}AFX_DATA_INIT
-
- // Load menu accelerator table.
-
- mMenuAcceleratorTable = ::LoadAccelerators( AfxGetInstanceHandle(), MAKEINTRESOURCE( IDR_CHOOSER_DIALOG_MENU_ACCELERATORS ) );
- assert( mMenuAcceleratorTable );
-
- mBrowser = NULL;
- mIsServiceBrowsing = false;
-}
-
-//===========================================================================================================================
-// ~ChooserDialog
-//===========================================================================================================================
-
-ChooserDialog::~ChooserDialog( void )
-{
- if( mBrowser )
- {
- DNSStatus err;
-
- err = DNSBrowserRelease( mBrowser, 0 );
- assert( err == kDNSNoErr );
- }
-}
-
-//===========================================================================================================================
-// DoDataExchange
-//===========================================================================================================================
-
-void ChooserDialog::DoDataExchange( CDataExchange *pDX )
-{
- CDialog::DoDataExchange(pDX);
-
- //{{AFX_DATA_MAP(ChooserDialog)
- DDX_Control(pDX, IDC_SERVICE_LIST, mServiceList);
- DDX_Control(pDX, IDC_DOMAIN_LIST, mDomainList);
- DDX_Control(pDX, IDC_CHOOSER_LIST, mChooserList);
- //}}AFX_DATA_MAP
-}
-
-//===========================================================================================================================
-// OnInitDialog
-//===========================================================================================================================
-
-BOOL ChooserDialog::OnInitDialog( void )
-{
- HICON icon;
- BOOL result;
- CString tempString;
- DNSStatus err;
-
- // Initialize our parent.
-
- CDialog::OnInitDialog();
-
- // Set up the window icon.
-
- icon = AfxGetApp()->LoadIcon( IDR_MAIN_ICON );
- assert( icon );
- if( icon )
- {
- SetIcon( icon, TRUE ); // Set big icon
- SetIcon( icon, FALSE ); // Set small icon
- }
-
- // Set up the Domain List.
-
- result = tempString.LoadString( IDS_CHOOSER_DOMAIN_COLUMN_NAME );
- assert( result );
- mDomainList.InsertColumn( 0, tempString, LVCFMT_LEFT, kDomainListDefaultDomainColumnWidth );
-
- // Set up the Service List.
-
- result = tempString.LoadString( IDS_CHOOSER_SERVICE_COLUMN_TYPE );
- assert( result );
- mServiceList.InsertColumn( 0, tempString, LVCFMT_LEFT, kServiceListDefaultServiceColumnTypeWidth );
-
- result = tempString.LoadString( IDS_CHOOSER_SERVICE_COLUMN_DESC );
- assert( result );
- mServiceList.InsertColumn( 1, tempString, LVCFMT_LEFT, kServiceListDefaultServiceColumnDescWidth );
-
- PopulateServicesList();
-
- // Set up the Chooser List.
-
- result = tempString.LoadString( IDS_CHOOSER_CHOOSER_NAME_COLUMN_NAME );
- assert( result );
- mChooserList.InsertColumn( 0, tempString, LVCFMT_LEFT, kChooserListDefaultNameColumnWidth );
-
- result = tempString.LoadString( IDS_CHOOSER_CHOOSER_IP_COLUMN_NAME );
- assert( result );
- mChooserList.InsertColumn( 1, tempString, LVCFMT_LEFT, kChooserListDefaultIPColumnWidth );
-
- // Set up the other controls.
-
- UpdateInfoDisplay();
-
- // Start browsing for domains.
-
- err = DNSBrowserCreate( 0, BrowserCallBack, this, &mBrowser );
- assert( err == kDNSNoErr );
-
- err = DNSBrowserStartDomainSearch( mBrowser, 0 );
- assert( err == kDNSNoErr );
-
- return( true );
-}
-
-//===========================================================================================================================
-// OnFileClose
-//===========================================================================================================================
-
-void ChooserDialog::OnFileClose()
-{
- OnClose();
-}
-
-//===========================================================================================================================
-// OnActivate
-//===========================================================================================================================
-
-void ChooserDialog::OnActivate( UINT nState, CWnd* pWndOther, BOOL bMinimized )
-{
- // Always make the active window the "main" window so modal dialogs work better and the app quits after closing
- // the last window.
-
- gApp.m_pMainWnd = this;
-
- CDialog::OnActivate(nState, pWndOther, bMinimized);
-}
-
-//===========================================================================================================================
-// PostNcDestroy
-//===========================================================================================================================
-
-void ChooserDialog::PostNcDestroy()
-{
- // Call the base class to do the normal cleanup.
-
- delete this;
-}
-
-//===========================================================================================================================
-// PreTranslateMessage
-//===========================================================================================================================
-
-BOOL ChooserDialog::PreTranslateMessage(MSG* pMsg)
-{
- BOOL result;
-
- result = false;
- assert( mMenuAcceleratorTable );
- if( mMenuAcceleratorTable )
- {
- result = ::TranslateAccelerator( m_hWnd, mMenuAcceleratorTable, pMsg );
- }
- if( !result )
- {
- result = CDialog::PreTranslateMessage( pMsg );
- }
- return( result );
-}
-
-//===========================================================================================================================
-// OnInitMenuPopup
-//===========================================================================================================================
-
-void ChooserDialog::OnInitMenuPopup( CMenu *pPopupMenu, UINT nIndex, BOOL bSysMenu )
-{
- CDialog::OnInitMenuPopup( pPopupMenu, nIndex, bSysMenu );
-
- switch( nIndex )
- {
- case kChooserMenuIndexFile:
- break;
-
- case kChooserMenuIndexHelp:
- break;
-
- default:
- break;
- }
-}
-
-//===========================================================================================================================
-// OnExit
-//===========================================================================================================================
-
-void ChooserDialog::OnExit()
-{
- OnClose();
-}
-
-//===========================================================================================================================
-// OnAbout
-//===========================================================================================================================
-
-void ChooserDialog::OnAbout()
-{
- AboutDialog dialog;
-
- dialog.DoModal();
-}
-
-//===========================================================================================================================
-// OnSysCommand
-//===========================================================================================================================
-
-void ChooserDialog::OnSysCommand( UINT inID, LPARAM inParam )
-{
- CDialog::OnSysCommand( inID, inParam );
-}
-
-//===========================================================================================================================
-// OnClose
-//===========================================================================================================================
-
-void ChooserDialog::OnClose()
-{
- StopBrowsing();
-
- gApp.m_pMainWnd = this;
- DestroyWindow();
-}
-
-//===========================================================================================================================
-// OnNcDestroy
-//===========================================================================================================================
-
-void ChooserDialog::OnNcDestroy()
-{
- gApp.m_pMainWnd = this;
-
- CDialog::OnNcDestroy();
-}
-
-//===========================================================================================================================
-// OnDomainListChanged
-//===========================================================================================================================
-
-void ChooserDialog::OnDomainListChanged( NMHDR *pNMHDR, LRESULT *pResult )
-{
- UNUSED_ALWAYS( pNMHDR );
-
- // Domain list changes have similar effects to service list changes so reuse that code path by calling it here.
-
- OnServiceListChanged( NULL, NULL );
-
- *pResult = 0;
-}
-
-//===========================================================================================================================
-// OnServiceListChanged
-//===========================================================================================================================
-
-void ChooserDialog::OnServiceListChanged( NMHDR *pNMHDR, LRESULT *pResult )
-{
- int selectedType;
- int selectedDomain;
-
- UNUSED_ALWAYS( pNMHDR );
-
- // Stop any existing service search.
-
- StopBrowsing();
-
- // If a domain and service type are selected, start searching for the service type on the domain.
-
- selectedType = mServiceList.GetNextItem( -1, LVNI_SELECTED );
- selectedDomain = mDomainList.GetNextItem( -1, LVNI_SELECTED );
-
- if( ( selectedType >= 0 ) && ( selectedDomain >= 0 ) )
- {
- CString s;
- std::string utf8;
- const char * type;
-
- s = mDomainList.GetItemText( selectedDomain, 0 );
- StringObjectToUTF8String( s, utf8 );
- type = mServiceTypes[ selectedType ].serviceType.c_str();
- if( *type != '\0' )
- {
- StartBrowsing( type, utf8.c_str() );
- }
- }
-
- if( pResult )
- {
- *pResult = 0;
- }
-}
-
-//===========================================================================================================================
-// OnChooserListChanged
-//===========================================================================================================================
-
-void ChooserDialog::OnChooserListChanged( NMHDR *pNMHDR, LRESULT *pResult )
-{
- UNUSED_ALWAYS( pNMHDR );
-
- UpdateInfoDisplay();
- *pResult = 0;
-}
-
-//===========================================================================================================================
-// OnChooserListDoubleClick
-//===========================================================================================================================
-
-void ChooserDialog::OnChooserListDoubleClick( NMHDR *pNMHDR, LRESULT *pResult )
-{
- int selectedItem;
-
- UNUSED_ALWAYS( pNMHDR );
-
- // Display the service instance if it is selected. Otherwise, clear all the info.
-
- selectedItem = mChooserList.GetNextItem( -1, LVNI_SELECTED );
- if( selectedItem >= 0 )
- {
- ServiceInstanceInfo * p;
- CString url;
- const KnownServiceEntry * service;
-
- assert( selectedItem < (int) mServiceInstances.size() );
- p = &mServiceInstances[ selectedItem ];
-
- // Search for a known service type entry that matches.
-
- for( service = kKnownServiceTable; service->serviceType; ++service )
- {
- if( p->type == service->serviceType )
- {
- break;
- }
- }
- if( service->serviceType )
- {
- const char * text;
-
- // Create a URL representing the service instance.
-
- if( strcmp( service->serviceType, "_smb._tcp." ) == 0 )
- {
- // Special case for SMB (no port number).
-
- url.Format( TEXT( "%s%s/" ), service->urlScheme, (const char *) p->ip.c_str() );
- }
- else if( strcmp( service->serviceType, "_ftp._tcp." ) == 0 )
- {
- // Special case for FTP to get login info.
-
- LoginDialog dialog;
- CString username;
- CString password;
-
- if( !dialog.GetLogin( username, password ) )
- {
- goto exit;
- }
-
- // Build URL in the following format:
- //
- // ftp://[username[:password]@]<ip>
-
- url += service->urlScheme;
- if( username.GetLength() > 0 )
- {
- url += username;
- if( password.GetLength() > 0 )
- {
- url += ':';
- url += password;
- }
- url += '@';
- }
- url += p->ip.c_str();
- }
- else if( strcmp( service->serviceType, "_http._tcp." ) == 0 )
- {
- // Special case for HTTP to exclude "path=" if present.
-
- text = service->useText ? p->text.c_str() : "";
- if( strncmp( text, "path=", 5 ) == 0 )
- {
- text += 5;
- }
- if( *text != '/' )
- {
- url.Format( TEXT( "%s%s/%s" ), service->urlScheme, (const char *) p->ip.c_str(), text );
- }
- else
- {
- url.Format( TEXT( "%s%s%s" ), service->urlScheme, (const char *) p->ip.c_str(), text );
- }
- }
- else
- {
- text = service->useText ? p->text.c_str() : "";
- url.Format( TEXT( "%s%s/%s" ), service->urlScheme, (const char *) p->ip.c_str(), text );
- }
-
- // Let the system open the URL in the correct app.
-
- {
- CWaitCursor waitCursor;
-
- ShellExecute( NULL, TEXT( "open" ), url, TEXT( "" ), TEXT( "c:\\" ), SW_SHOWNORMAL );
- }
- }
- }
-
-exit:
- *pResult = 0;
-}
-
-//===========================================================================================================================
-// OnCancel
-//===========================================================================================================================
-
-void ChooserDialog::OnCancel()
-{
- // Do nothing.
-}
-
-//===========================================================================================================================
-// PopulateServicesList
-//===========================================================================================================================
-
-void ChooserDialog::PopulateServicesList( void )
-{
- ServiceTypeVector::iterator i;
- CString type;
- CString desc;
- std::string tmp;
-
- // Add a fixed list of known services.
-
- if( mServiceTypes.empty() )
- {
- const KnownServiceEntry * service;
-
- for( service = kKnownServiceTable; service->serviceType; ++service )
- {
- ServiceTypeInfo info;
-
- info.serviceType = service->serviceType;
- info.description = service->description;
- info.urlScheme = service->urlScheme;
- mServiceTypes.push_back( info );
- }
- }
-
- // Add each service to the list.
-
- for( i = mServiceTypes.begin(); i != mServiceTypes.end(); ++i )
- {
- const char * p;
- const char * q;
-
- p = ( *i ).serviceType.c_str();
- if( *p == '_' ) ++p; // Skip leading '_'.
- q = strchr( p, '.' ); // Find first '.'.
- if( q ) tmp.assign( p, (size_t)( q - p ) ); // Use only up to the first '.'.
- else tmp.assign( p ); // No '.' so use the entire string.
- UTF8StringToStringObject( tmp.c_str(), type );
- UTF8StringToStringObject( ( *i ).description.c_str(), desc );
-
- int n;
-
- n = mServiceList.GetItemCount();
- mServiceList.InsertItem( n, type );
- mServiceList.SetItemText( n, 1, desc );
- }
-
- // Select the first service type by default.
-
- if( !mServiceTypes.empty() )
- {
- mServiceList.SetItemState( 0, LVIS_SELECTED | LVIS_FOCUSED, LVIS_SELECTED | LVIS_FOCUSED );
- }
-}
-
-//===========================================================================================================================
-// UpdateInfoDisplay
-//===========================================================================================================================
-
-void ChooserDialog::UpdateInfoDisplay( void )
-{
- int selectedItem;
- std::string name;
- CString s;
- std::string ip;
- std::string ifIP;
- std::string text;
- std::string textNewLines;
- std::string hostName;
- CWnd * item;
- std::string::iterator i;
-
- // Display the service instance if it is selected. Otherwise, clear all the info.
-
- selectedItem = mChooserList.GetNextItem( -1, LVNI_SELECTED );
- if( selectedItem >= 0 )
- {
- ServiceInstanceInfo * p;
-
- assert( selectedItem < (int) mServiceInstances.size() );
- p = &mServiceInstances[ selectedItem ];
-
- name = p->name;
- ip = p->ip;
- ifIP = p->ifIP;
- text = p->text;
- hostName = p->hostName;
-
- // Sync up the list items with the actual data (IP address may change).
-
- UTF8StringToStringObject( ip.c_str(), s );
- mChooserList.SetItemText( selectedItem, 1, s );
- }
-
- // Name
-
- item = (CWnd *) this->GetDlgItem( IDC_INFO_NAME_TEXT );
- assert( item );
- UTF8StringToStringObject( name.c_str(), s );
- item->SetWindowText( s );
-
- // IP
-
- item = (CWnd *) this->GetDlgItem( IDC_INFO_IP_TEXT );
- assert( item );
- UTF8StringToStringObject( ip.c_str(), s );
- item->SetWindowText( s );
-
- // Interface
-
- item = (CWnd *) this->GetDlgItem( IDC_INFO_INTERFACE_TEXT );
- assert( item );
- UTF8StringToStringObject( ifIP.c_str(), s );
- item->SetWindowText( s );
-
-
- item = (CWnd *) this->GetDlgItem( IDC_INFO_HOST_NAME_TEXT );
- assert( item );
- UTF8StringToStringObject( hostName.c_str(), s );
- item->SetWindowText( s );
-
- // Text
-
- item = (CWnd *) this->GetDlgItem( IDC_INFO_TEXT_TEXT );
- assert( item );
- for( i = text.begin(); i != text.end(); ++i )
- {
- if( *i == '\1' )
- {
- textNewLines += "\r\n";
- }
- else
- {
- textNewLines += *i;
- }
- }
- UTF8StringToStringObject( textNewLines.c_str(), s );
- item->SetWindowText( s );
-}
-
-#if 0
-#pragma mark -
-#endif
-
-//===========================================================================================================================
-// OnDomainAdd
-//===========================================================================================================================
-
-LONG ChooserDialog::OnDomainAdd( WPARAM inWParam, LPARAM inLParam )
-{
- DomainEventInfo * p;
- std::auto_ptr < DomainEventInfo > pAutoPtr;
- int n;
- int i;
- CString domain;
- CString s;
- bool found;
-
- UNUSED_ALWAYS( inWParam );
-
- assert( inLParam );
- p = reinterpret_cast <DomainEventInfo *> ( inLParam );
- pAutoPtr.reset( p );
-
- // Search to see if we already know about this domain. If not, add it to the list.
-
- found = false;
- domain = p->domain;
- n = mDomainList.GetItemCount();
- for( i = 0; i < n; ++i )
- {
- s = mDomainList.GetItemText( i, 0 );
- if( s == domain )
- {
- found = true;
- break;
- }
- }
- if( !found )
- {
- int selectedItem;
-
- mDomainList.InsertItem( n, domain );
-
- // If no domains are selected and the domain being added is a default domain, select it.
-
- selectedItem = mDomainList.GetNextItem( -1, LVNI_SELECTED );
- if( ( selectedItem < 0 ) && ( p->eventType == kDNSBrowserEventTypeAddDefaultDomain ) )
- {
- mDomainList.SetItemState( n, LVIS_SELECTED | LVIS_FOCUSED, LVIS_SELECTED | LVIS_FOCUSED );
- }
- }
- return( 0 );
-}
-
-//===========================================================================================================================
-// OnDomainRemove
-//===========================================================================================================================
-
-LONG ChooserDialog::OnDomainRemove( WPARAM inWParam, LPARAM inLParam )
-{
- DomainEventInfo * p;
- std::auto_ptr < DomainEventInfo > pAutoPtr;
- int n;
- int i;
- CString domain;
- CString s;
- bool found;
-
- UNUSED_ALWAYS( inWParam );
-
- assert( inLParam );
- p = reinterpret_cast <DomainEventInfo *> ( inLParam );
- pAutoPtr.reset( p );
-
- // Search to see if we know about this domain. If so, remove it from the list.
-
- found = false;
- domain = p->domain;
- n = mDomainList.GetItemCount();
- for( i = 0; i < n; ++i )
- {
- s = mDomainList.GetItemText( i, 0 );
- if( s == domain )
- {
- found = true;
- break;
- }
- }
- if( found )
- {
- mDomainList.DeleteItem( i );
- }
- return( 0 );
-}
-
-//===========================================================================================================================
-// OnServiceAdd
-//===========================================================================================================================
-
-LONG ChooserDialog::OnServiceAdd( WPARAM inWParam, LPARAM inLParam )
-{
- ServiceEventInfo * p;
- std::auto_ptr < ServiceEventInfo > pAutoPtr;
-
- UNUSED_ALWAYS( inWParam );
-
- assert( inLParam );
- p = reinterpret_cast <ServiceEventInfo *> ( inLParam );
- pAutoPtr.reset( p );
-
- return( 0 );
-}
-
-//===========================================================================================================================
-// OnServiceRemove
-//===========================================================================================================================
-
-LONG ChooserDialog::OnServiceRemove( WPARAM inWParam, LPARAM inLParam )
-{
- ServiceEventInfo * p;
- std::auto_ptr < ServiceEventInfo > pAutoPtr;
- bool found;
- int n;
- int i;
-
- UNUSED_ALWAYS( inWParam );
-
- assert( inLParam );
- p = reinterpret_cast <ServiceEventInfo *> ( inLParam );
- pAutoPtr.reset( p );
-
- // Search to see if we know about this service instance. If so, remove it from the list.
-
- found = false;
- n = (int) mServiceInstances.size();
- for( i = 0; i < n; ++i )
- {
- ServiceInstanceInfo * q;
-
- // If the name, type, domain, and interface match, treat it as the same service instance.
-
- q = &mServiceInstances[ i ];
- if( ( p->name == q->name ) &&
- ( p->type == q->type ) &&
- ( p->domain == q->domain ) )
- {
- found = true;
- break;
- }
- }
- if( found )
- {
- mChooserList.DeleteItem( i );
- assert( i < (int) mServiceInstances.size() );
- mServiceInstances.erase( mServiceInstances.begin() + i );
- }
- return( 0 );
-}
-
-//===========================================================================================================================
-// OnResolve
-//===========================================================================================================================
-
-LONG ChooserDialog::OnResolve( WPARAM inWParam, LPARAM inLParam )
-{
- ServiceInstanceInfo * p;
- std::auto_ptr < ServiceInstanceInfo > pAutoPtr;
- int selectedType;
- int n;
- int i;
- bool found;
-
- UNUSED_ALWAYS( inWParam );
-
- assert( inLParam );
- p = reinterpret_cast <ServiceInstanceInfo *> ( inLParam );
- pAutoPtr.reset( p );
-
- // Make sure it is for an item of the correct type. This handles any resolves that may have been queued up.
-
- selectedType = mServiceList.GetNextItem( -1, LVNI_SELECTED );
- assert( selectedType >= 0 );
- if( selectedType >= 0 )
- {
- assert( selectedType <= (int) mServiceTypes.size() );
- if( p->type != mServiceTypes[ selectedType ].serviceType )
- {
- goto exit;
- }
- }
-
- // Search to see if we know about this service instance. If so, update its info. Otherwise, add it to the list.
-
- found = false;
- n = (int) mServiceInstances.size();
- for( i = 0; i < n; ++i )
- {
- ServiceInstanceInfo * q;
-
- // If the name, type, domain, and interface matches, treat it as the same service instance.
-
- q = &mServiceInstances[ i ];
- if( ( p->name == q->name ) &&
- ( p->type == q->type ) &&
- ( p->domain == q->domain ) &&
- ( p->ifIP == q->ifIP ) )
- {
- found = true;
- break;
- }
- }
- if( found )
- {
- mServiceInstances[ i ] = *p;
- }
- else
- {
- CString s;
-
- mServiceInstances.push_back( *p );
- UTF8StringToStringObject( p->name.c_str(), s );
- mChooserList.InsertItem( n, s );
-
- UTF8StringToStringObject( p->ip.c_str(), s );
- mChooserList.SetItemText( n, 1, s );
-
- // If this is the only item, select it.
-
- if( n == 0 )
- {
- mChooserList.SetItemState( n, LVIS_SELECTED | LVIS_FOCUSED, LVIS_SELECTED | LVIS_FOCUSED );
- }
- }
- UpdateInfoDisplay();
-
-exit:
- return( 0 );
-}
-
-//===========================================================================================================================
-// StartBrowsing
-//===========================================================================================================================
-
-void ChooserDialog::StartBrowsing( const char *inType, const char *inDomain )
-{
- DNSStatus err;
-
- assert( mServiceInstances.empty() );
- assert( mChooserList.GetItemCount() == 0 );
- assert( !mIsServiceBrowsing );
-
- mChooserList.DeleteAllItems();
- mServiceInstances.clear();
-
- mIsServiceBrowsing = true;
- err = DNSBrowserStartServiceSearch( mBrowser, kDNSBrowserFlagAutoResolve, inType, inDomain );
- assert( err == kDNSNoErr );
-}
-
-//===========================================================================================================================
-// StopBrowsing
-//===========================================================================================================================
-
-void ChooserDialog::StopBrowsing( void )
-{
- // If searching, stop.
-
- if( mIsServiceBrowsing )
- {
- DNSStatus err;
-
- mIsServiceBrowsing = false;
- err = DNSBrowserStopServiceSearch( mBrowser, 0 );
- assert( err == kDNSNoErr );
- }
-
- // Remove all service instances.
-
- mChooserList.DeleteAllItems();
- assert( mChooserList.GetItemCount() == 0 );
- mServiceInstances.clear();
- assert( mServiceInstances.empty() );
- UpdateInfoDisplay();
-}
-
-#if 0
-#pragma mark -
-#endif
-
-//===========================================================================================================================
-// BrowserCallBack
-//===========================================================================================================================
-
-static void
- BrowserCallBack(
- void * inContext,
- DNSBrowserRef inRef,
- DNSStatus inStatusCode,
- const DNSBrowserEvent * inEvent )
-{
- ChooserDialog * dialog;
- UINT message;
- BOOL posted;
-
- UNUSED_ALWAYS( inStatusCode );
- UNUSED_ALWAYS( inRef );
-
- // Check parameters.
-
- assert( inContext );
- dialog = reinterpret_cast <ChooserDialog *> ( inContext );
-
- try
- {
- switch( inEvent->type )
- {
- case kDNSBrowserEventTypeRelease:
- break;
-
- // Domains
-
- case kDNSBrowserEventTypeAddDomain:
- case kDNSBrowserEventTypeAddDefaultDomain:
- case kDNSBrowserEventTypeRemoveDomain:
- {
- DomainEventInfo * domain;
- std::auto_ptr < DomainEventInfo > domainAutoPtr;
-
- domain = new DomainEventInfo;
- domainAutoPtr.reset( domain );
-
- domain->eventType = inEvent->type;
- domain->domain = inEvent->data.addDomain.domain;
- domain->ifIP = inEvent->data.addDomain.interfaceIP;
-
- message = ( inEvent->type == kDNSBrowserEventTypeRemoveDomain ) ? WM_USER_DOMAIN_REMOVE : WM_USER_DOMAIN_ADD;
- posted = ::PostMessage( dialog->GetSafeHwnd(), message, 0, (LPARAM) domain );
- assert( posted );
- if( posted )
- {
- domainAutoPtr.release();
- }
- break;
- }
-
- // Services
-
- case kDNSBrowserEventTypeAddService:
- case kDNSBrowserEventTypeRemoveService:
- {
- ServiceEventInfo * service;
- std::auto_ptr < ServiceEventInfo > serviceAutoPtr;
-
- service = new ServiceEventInfo;
- serviceAutoPtr.reset( service );
-
- service->eventType = inEvent->type;
- service->name = inEvent->data.addService.name;
- service->type = inEvent->data.addService.type;
- service->domain = inEvent->data.addService.domain;
- service->ifIP = inEvent->data.addService.interfaceIP;
-
- message = ( inEvent->type == kDNSBrowserEventTypeAddService ) ? WM_USER_SERVICE_ADD : WM_USER_SERVICE_REMOVE;
- posted = ::PostMessage( dialog->GetSafeHwnd(), message, 0, (LPARAM) service );
- assert( posted );
- if( posted )
- {
- serviceAutoPtr.release();
- }
- break;
- }
-
- // Resolves
-
- case kDNSBrowserEventTypeResolved:
- if( inEvent->data.resolved->address.addressType == kDNSNetworkAddressTypeIPv4 )
- {
- ServiceInstanceInfo * serviceInstance;
- std::auto_ptr < ServiceInstanceInfo > serviceInstanceAutoPtr;
- char s[ 32 ];
-
- serviceInstance = new ServiceInstanceInfo;
- serviceInstanceAutoPtr.reset( serviceInstance );
-
- serviceInstance->name = inEvent->data.resolved->name;
- serviceInstance->type = inEvent->data.resolved->type;
- serviceInstance->domain = inEvent->data.resolved->domain;
- serviceInstance->ip = DNSNetworkAddressToString( &inEvent->data.resolved->address, s );
- serviceInstance->ifIP = DNSNetworkAddressToString( &inEvent->data.resolved->interfaceIP, s );
- serviceInstance->text = inEvent->data.resolved->textRecord;
- serviceInstance->hostName = inEvent->data.resolved->hostName;
-
- posted = ::PostMessage( dialog->GetSafeHwnd(), WM_USER_RESOLVE, 0, (LPARAM) serviceInstance );
- assert( posted );
- if( posted )
- {
- serviceInstanceAutoPtr.release();
- }
- }
- break;
-
- default:
- break;
- }
- }
- catch( ... )
- {
- // Don't let exceptions escape.
- }
-}
-
-//===========================================================================================================================
-// DNSNetworkAddressToString
-//
-// Note: Currently only supports IPv4 network addresses.
-//===========================================================================================================================
-
-static char * DNSNetworkAddressToString( const DNSNetworkAddress *inAddr, char *outString )
-{
- const DNSUInt8 * p;
- DNSUInt16 port;
-
- p = inAddr->u.ipv4.addr.v8;
- port = ntohs( inAddr->u.ipv4.port.v16 );
- if( port != kDNSPortInvalid )
- {
- sprintf( outString, "%u.%u.%u.%u:%u", p[ 0 ], p[ 1 ], p[ 2 ], p[ 3 ], port );
- }
- else
- {
- sprintf( outString, "%u.%u.%u.%u", p[ 0 ], p[ 1 ], p[ 2 ], p[ 3 ] );
- }
- return( outString );
-}
-
-//===========================================================================================================================
-// UTF8StringToStringObject
-//===========================================================================================================================
-
-static DWORD UTF8StringToStringObject( const char *inUTF8, CString &inObject )
-{
- DWORD 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 = 0;
-
-exit:
- if( unicode )
- {
- free( unicode );
- }
- return( err );
-}
-
-//===========================================================================================================================
-// StringObjectToUTF8String
-//===========================================================================================================================
-
-static DWORD StringObjectToUTF8String( CString &inObject, std::string &outUTF8 )
-{
- DWORD err;
- BSTR unicode;
- int nUnicode;
- int n;
- char * utf8;
-
- unicode = NULL;
- utf8 = NULL;
-
- nUnicode = inObject.GetLength();
- if( nUnicode > 0 )
- {
- unicode = inObject.AllocSysString();
- n = WideCharToMultiByte( CP_UTF8, 0, unicode, nUnicode, NULL, 0, NULL, NULL );
- assert( n > 0 );
-
- utf8 = (char *) malloc( (size_t) n );
- assert( utf8 );
- if( !utf8 ) { err = ERROR_INSUFFICIENT_BUFFER; goto exit; }
-
- n = WideCharToMultiByte( CP_UTF8, 0, unicode, nUnicode, utf8, n, NULL, NULL );
- assert( n > 0 );
-
- try
- {
- outUTF8.assign( utf8, n );
- }
- catch( ... )
- {
- err = ERROR_NO_UNICODE_TRANSLATION;
- goto exit;
- }
- }
- else
- {
- outUTF8.clear();
- }
- err = 0;
-
-exit:
- if( unicode )
- {
- SysFreeString( unicode );
- }
- if( utf8 )
- {
- free( utf8 );
- }
- return( err );
-}