1 /* -*- Mode: C; tab-width: 4 -*-
3 * Copyright (c) 2002-2004 Apple Computer, Inc. All rights reserved.
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
9 * http://www.apache.org/licenses/LICENSE-2.0
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
20 #include "Application.h"
22 #include "DNSServices.h"
24 #include "BrowserDialog.h"
29 static char THIS_FILE
[] = __FILE__
;
32 //===========================================================================================================================
34 //===========================================================================================================================
36 #define WM_USER_SERVICE_ADD ( WM_USER + 0x100 )
37 #define WM_USER_SERVICE_REMOVE ( WM_USER + 0x101 )
39 //===========================================================================================================================
41 //===========================================================================================================================
43 BEGIN_MESSAGE_MAP(BrowserDialog
, CDialog
)
44 //{{AFX_MSG_MAP(BrowserDialog)
45 ON_NOTIFY(NM_CLICK
, IDC_BROWSE_LIST
, OnBrowserListDoubleClick
)
46 ON_MESSAGE( WM_USER_SERVICE_ADD
, OnServiceAdd
)
47 ON_MESSAGE( WM_USER_SERVICE_REMOVE
, OnServiceRemove
)
51 static DWORD
UTF8StringToStringObject( const char *inUTF8
, CString
&inObject
);
53 //===========================================================================================================================
55 //===========================================================================================================================
57 BrowserDialog::BrowserDialog( CWnd
*inParent
)
58 : CDialog( BrowserDialog::IDD
, inParent
)
60 //{{AFX_DATA_INIT(BrowserDialog)
61 // Note: the ClassWizard will add member initialization here
64 // Note that LoadIcon does not require a subsequent DestroyIcon in Win32.
66 mIcon
= AfxGetApp()->LoadIcon( IDR_MAINFRAME
);
70 //===========================================================================================================================
72 //===========================================================================================================================
74 void BrowserDialog::DoDataExchange( CDataExchange
*pDX
)
76 CDialog::DoDataExchange(pDX
);
77 //{{AFX_DATA_MAP(BrowserDialog)
78 DDX_Control(pDX
, IDC_BROWSE_LIST
, mBrowserList
);
82 //===========================================================================================================================
84 //===========================================================================================================================
86 BOOL
BrowserDialog::OnInitDialog()
90 CDialog::OnInitDialog();
92 // Set the icon for this dialog. The framework does this automatically when the application's main window is not a dialog.
94 SetIcon( mIcon
, TRUE
); // Set big icon
95 SetIcon( mIcon
, FALSE
); // Set small icon
97 CenterWindow( GetDesktopWindow() );
103 s
.LoadString( IDS_BROWSER_LIST_COLUMN_NAME
);
104 mBrowserList
.GetWindowRect( rect
);
105 mBrowserList
.InsertColumn( 0, s
, LVCFMT_LEFT
, rect
.Width() - 8 );
107 // Start browsing for services.
111 err
= DNSBrowserCreate( 0, OnBrowserCallBack
, this, &mBrowser
);
114 AfxMessageBox( IDP_SOCKETS_INIT_FAILED
);
118 err
= DNSBrowserStartServiceSearch( mBrowser
, kDNSBrowserFlagAutoResolve
, "_http._tcp", NULL
);
121 AfxMessageBox( IDP_SOCKETS_INIT_FAILED
);
130 //===========================================================================================================================
131 // OnBrowserListDoubleClick
132 //===========================================================================================================================
134 void BrowserDialog::OnBrowserListDoubleClick( NMHDR
*pNMHDR
, LRESULT
*pResult
)
138 (void) pNMHDR
; // Unused
140 selectedItem
= mBrowserList
.GetNextItem( -1, LVNI_SELECTED
);
141 if( selectedItem
>= 0 )
143 BrowserEntry
* entry
;
147 // Build the URL from the IP and optional TXT record.
149 entry
= &mBrowserEntries
[ selectedItem
];
150 url
+= "http://" + entry
->ip
;
152 if( temp
.Find( TEXT( "path=" ) ) == 0 )
156 if( temp
.Find( '/' ) != 0 )
162 // Let the system open the URL in the correct app.
164 SHELLEXECUTEINFO info
;
166 info
.cbSize
= sizeof( info
);
171 info
.lpParameters
= NULL
;
172 info
.lpDirectory
= NULL
;
173 info
.nShow
= SW_SHOWNORMAL
;
174 info
.hInstApp
= NULL
;
176 ShellExecuteEx( &info
);
181 //===========================================================================================================================
182 // OnBrowserCallBack [static]
183 //===========================================================================================================================
186 BrowserDialog::OnBrowserCallBack(
189 DNSStatus inStatusCode
,
190 const DNSBrowserEvent
* inEvent
)
192 BrowserDialog
* dialog
;
193 BrowserEntry
* entry
;
196 DNS_UNUSED( inStatusCode
);
197 dialog
= reinterpret_cast < BrowserDialog
* > ( inContext
);
200 switch( inEvent
->type
)
202 case kDNSBrowserEventTypeResolved
:
203 if( inEvent
->data
.resolved
->address
.addressType
== kDNSNetworkAddressTypeIPv4
)
207 snprintf( ip
, sizeof( ip
), "%u.%u.%u.%u:%u",
208 inEvent
->data
.resolved
->address
.u
.ipv4
.addr
.v8
[ 0 ],
209 inEvent
->data
.resolved
->address
.u
.ipv4
.addr
.v8
[ 1 ],
210 inEvent
->data
.resolved
->address
.u
.ipv4
.addr
.v8
[ 2 ],
211 inEvent
->data
.resolved
->address
.u
.ipv4
.addr
.v8
[ 3 ],
212 ( inEvent
->data
.resolved
->address
.u
.ipv4
.port
.v8
[ 0 ] << 8 ) |
213 inEvent
->data
.resolved
->address
.u
.ipv4
.port
.v8
[ 1 ] );
215 entry
= new BrowserEntry
;
219 UTF8StringToStringObject( inEvent
->data
.resolved
->name
, entry
->name
);
220 UTF8StringToStringObject( ip
, entry
->ip
);
221 UTF8StringToStringObject( inEvent
->data
.resolved
->textRecord
, entry
->text
);
223 posted
= ::PostMessage( dialog
->GetSafeHwnd(), WM_USER_SERVICE_ADD
, 0, (LPARAM
) entry
);
233 case kDNSBrowserEventTypeRemoveService
:
234 entry
= new BrowserEntry
;
238 UTF8StringToStringObject( inEvent
->data
.removeService
.name
, entry
->name
);
240 posted
= ::PostMessage( dialog
->GetSafeHwnd(), WM_USER_SERVICE_REMOVE
, 0, (LPARAM
) entry
);
254 //===========================================================================================================================
256 //===========================================================================================================================
258 LONG
BrowserDialog::OnServiceAdd( WPARAM inWParam
, LPARAM inLParam
)
260 BrowserEntry
* entry
;
266 (void) inWParam
; // Unused
268 entry
= reinterpret_cast < BrowserEntry
* > ( inLParam
);
274 hi
= mBrowserEntries
.GetSize() - 1;
277 mid
= ( lo
+ hi
) / 2;
278 result
= entry
->name
.CompareNoCase( mBrowserEntries
[ mid
].name
);
283 else if( result
< 0 )
294 mBrowserEntries
[ mid
].ip
= entry
->ip
;
295 mBrowserEntries
[ mid
].text
= entry
->text
;
303 mBrowserEntries
.InsertAt( mid
, *entry
);
304 mBrowserList
.InsertItem( mid
, entry
->name
);
310 //===========================================================================================================================
312 //===========================================================================================================================
314 LONG
BrowserDialog::OnServiceRemove( WPARAM inWParam
, LPARAM inLParam
)
316 BrowserEntry
* entry
;
322 (void) inWParam
; // Unused
324 entry
= reinterpret_cast < BrowserEntry
* > ( inLParam
);
330 hi
= mBrowserEntries
.GetSize() - 1;
333 mid
= ( lo
+ hi
) / 2;
334 result
= entry
->name
.CompareNoCase( mBrowserEntries
[ mid
].name
);
339 else if( result
< 0 )
350 mBrowserList
.DeleteItem( mid
);
351 mBrowserEntries
.RemoveAt( mid
);
361 //===========================================================================================================================
362 // UTF8StringToStringObject
363 //===========================================================================================================================
365 static DWORD
UTF8StringToStringObject( const char *inUTF8
, CString
&inObject
)
373 n
= MultiByteToWideChar( CP_UTF8
, 0, inUTF8
, -1, NULL
, 0 );
376 unicode
= (wchar_t *) malloc( (size_t)( n
* sizeof( wchar_t ) ) );
377 if( !unicode
) { err
= ERROR_INSUFFICIENT_BUFFER
; goto exit
; };
379 n
= MultiByteToWideChar( CP_UTF8
, 0, inUTF8
, -1, unicode
, n
);