-
Notifications
You must be signed in to change notification settings - Fork 3
/
listing62.html
executable file
·342 lines (320 loc) · 36.8 KB
/
listing62.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"http://www.w3.org/TR/1999/REC-html401-19991224/loose.dtd">
<html>
<head>
<!-- BEGIN META TAG INFO -->
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
<link rel="home" href="http://developer.apple.com/">
<link rel="find" href="http://developer.apple.com/search/">
<link rel="stylesheet" type="text/css" href="../../documentation/css/adcstyle.css" title="fonts">
<script language="JavaScript" src="../../documentation/js/adc.js" type="text/javascript"></script>
<!-- END META TAG INFO -->
<!-- BEGIN TITLE -->
<title>QISA - /ReadMeAboutQISA.html</title>
<!-- END TITLE -->
<script language="JavaScript">
function JumpToNewPage() {
window.location=document.scpopupmenu.gotop.value;
return true;
}
</script>
</head>
<!-- BEGIN BODY OPEN -->
<body>
<!--END BODY OPEN -->
<!-- START CENTER OPEN -->
<center>
<!-- END CENTER OPEN -->
<!-- BEGIN LOGO AND SEARCH -->
<!--#include virtual="/includes/adcnavbar"-->
<!-- END LOGO AND SEARCH -->
<!-- START BREADCRUMB -->
<div id="breadcrumb">
<table width="680" border="0" cellpadding="0" cellspacing="0">
<tr>
<td scope="row"><img width="340" height="10" src="images/1dot.gif" alt=""></td>
<td><img width="340" height="10" src="images/1dot.gif" alt=""></td>
</tr>
<tr valign="middle">
<td align="left" colspan="2">
<a href="http://developer.apple.com/">ADC Home</a> > <a href="../../referencelibrary/index.html">Reference Library</a> > <a href="../../samplecode/index.html">Sample Code</a> > <a href="../../samplecode/Networking/index.html">Networking</a> > <a href="../../samplecode/Networking/idxDarwin-date.html">Darwin</a> > <A HREF="javascript:location.replace('index.html');">QISA</A> >
</td>
</tr>
<tr>
<td colspan="2" scope="row"><img width="680" height="35" src="images/1dot.gif" alt=""></td>
</tr>
</table>
</div>
<!-- END BREADCRUMB -->
<!-- START MAIN CONTENT -->
<!-- START TITLE GRAPHIC AND INTRO-->
<table width="680" border="0" cellpadding="0" cellspacing="0">
<tr align="left" valign="top">
<td><h1><div id="pagehead">QISA</div></h1></td>
</tr>
</table>
<!-- END TITLE GRAPHIC AND INTRO -->
<!-- START WIDE COLUMN -->
<table width="680" border="0" cellpadding="0" cellspacing="0">
<tr align="left" valign="top">
<td id="scdetails">
<h2>/ReadMeAboutQISA.html</h2>
<form name="scpopupmenu" onSubmit="return false;" method=post>
<p><strong>View Source Code:</strong>
<select name="gotop" onChange="JumpToNewPage();" style="width:340px"><option selected value="ingnore">Select File</option>
<option value="listing1.html">/MoreIsBetter Bits/MoreIsBetter/MIB-Libraries/MoreAppearance/MoreAppearance.cp</option>
<option value="listing2.html">/MoreIsBetter Bits/MoreIsBetter/MIB-Libraries/MoreAppearance/MoreAppearance.h</option>
<option value="listing3.html">/MoreIsBetter Bits/MoreIsBetter/MIB-Libraries/MoreAppleEvents/MoreAEDataModel.c</option>
<option value="listing4.html">/MoreIsBetter Bits/MoreIsBetter/MIB-Libraries/MoreAppleEvents/MoreAEDataModel.h</option>
<option value="listing5.html">/MoreIsBetter Bits/MoreIsBetter/MIB-Libraries/MoreAppleEvents/MoreAEObjects.c</option>
<option value="listing6.html">/MoreIsBetter Bits/MoreIsBetter/MIB-Libraries/MoreAppleEvents/MoreAEObjects.h</option>
<option value="listing7.html">/MoreIsBetter Bits/MoreIsBetter/MIB-Libraries/MoreAppleEvents/MoreAppleEvents.cp</option>
<option value="listing8.html">/MoreIsBetter Bits/MoreIsBetter/MIB-Libraries/MoreAppleEvents/MoreAppleEvents.h</option>
<option value="listing9.html">/MoreIsBetter Bits/MoreIsBetter/MIB-Libraries/MoreCarbonEvents/MoreCarbonEvents.c</option>
<option value="listing10.html">/MoreIsBetter Bits/MoreIsBetter/MIB-Libraries/MoreCarbonEvents/MoreCarbonEvents.h</option>
<option value="listing11.html">/MoreIsBetter Bits/MoreIsBetter/MIB-Libraries/MoreCFQ/MoreCFQ.c</option>
<option value="listing12.html">/MoreIsBetter Bits/MoreIsBetter/MIB-Libraries/MoreCFQ/MoreCFQ.h</option>
<option value="listing13.html">/MoreIsBetter Bits/MoreIsBetter/MIB-Libraries/MoreControls/MoreControls.cp</option>
<option value="listing14.html">/MoreIsBetter Bits/MoreIsBetter/MIB-Libraries/MoreControls/MoreControls.h</option>
<option value="listing15.html">/MoreIsBetter Bits/MoreIsBetter/MIB-Libraries/MoreDialogs/MoreDialogs.cp</option>
<option value="listing16.html">/MoreIsBetter Bits/MoreIsBetter/MIB-Libraries/MoreDialogs/MoreDialogs.h</option>
<option value="listing17.html">/MoreIsBetter Bits/MoreIsBetter/MIB-Libraries/MoreInterfaceLib/MoreInterfaceLib.c</option>
<option value="listing18.html">/MoreIsBetter Bits/MoreIsBetter/MIB-Libraries/MoreInterfaceLib/MoreInterfaceLib.h</option>
<option value="listing19.html">/MoreIsBetter Bits/MoreIsBetter/MIB-Libraries/MoreInterfaceLib/RemoteAccessInterface.h</option>
<option value="listing20.html">/MoreIsBetter Bits/MoreIsBetter/MIB-Libraries/MoreMemory/MoreMemory.c</option>
<option value="listing21.html">/MoreIsBetter Bits/MoreIsBetter/MIB-Libraries/MoreMemory/MoreMemory.h</option>
<option value="listing22.html">/MoreIsBetter Bits/MoreIsBetter/MIB-Libraries/MoreOSUtils/MoreOSUtils.c</option>
<option value="listing23.html">/MoreIsBetter Bits/MoreIsBetter/MIB-Libraries/MoreOSUtils/MoreOSUtils.h</option>
<option value="listing24.html">/MoreIsBetter Bits/MoreIsBetter/MIB-Libraries/MoreProcesses/MoreProcesses.cp</option>
<option value="listing25.html">/MoreIsBetter Bits/MoreIsBetter/MIB-Libraries/MoreProcesses/MoreProcesses.h</option>
<option value="listing26.html">/MoreIsBetter Bits/MoreIsBetter/MIB-Libraries/MoreQuickDraw/MoreQuickDraw.cp</option>
<option value="listing27.html">/MoreIsBetter Bits/MoreIsBetter/MIB-Libraries/MoreQuickDraw/MoreQuickDraw.h</option>
<option value="listing28.html">/MoreIsBetter Bits/MoreIsBetter/MIB-Libraries/MoreSCF/MoreSCF.c</option>
<option value="listing29.html">/MoreIsBetter Bits/MoreIsBetter/MIB-Libraries/MoreSCF/MoreSCF.h</option>
<option value="listing30.html">/MoreIsBetter Bits/MoreIsBetter/MIB-Libraries/MoreSCF/MoreSCFCCLScanner.c</option>
<option value="listing31.html">/MoreIsBetter Bits/MoreIsBetter/MIB-Libraries/MoreSCF/MoreSCFCCLScanner.h</option>
<option value="listing32.html">/MoreIsBetter Bits/MoreIsBetter/MIB-Libraries/MoreSCF/MoreSCFDigest.c</option>
<option value="listing33.html">/MoreIsBetter Bits/MoreIsBetter/MIB-Libraries/MoreSCF/MoreSCFDigest.h</option>
<option value="listing34.html">/MoreIsBetter Bits/MoreIsBetter/MIB-Libraries/MoreSCF/MoreSCFHelpers.c</option>
<option value="listing35.html">/MoreIsBetter Bits/MoreIsBetter/MIB-Libraries/MoreSCF/MoreSCFHelpers.h</option>
<option value="listing36.html">/MoreIsBetter Bits/MoreIsBetter/MIB-Libraries/MoreSCF/MoreSCFPortScanner.c</option>
<option value="listing37.html">/MoreIsBetter Bits/MoreIsBetter/MIB-Libraries/MoreSCF/MoreSCFPortScanner.h</option>
<option value="listing38.html">/MoreIsBetter Bits/MoreIsBetter/MIB-Libraries/MoreSecurity/MoreSecurity.c</option>
<option value="listing39.html">/MoreIsBetter Bits/MoreIsBetter/MIB-Libraries/MoreSecurity/MoreSecurity.h</option>
<option value="listing40.html">/MoreIsBetter Bits/MoreIsBetter/MIB-Libraries/MoreSetup.h</option>
<option value="listing41.html">/MoreIsBetter Bits/MoreIsBetter/MIB-Libraries/MoreTextUtils/MoreTextUtils.cp</option>
<option value="listing42.html">/MoreIsBetter Bits/MoreIsBetter/MIB-Libraries/MoreTextUtils/MoreTextUtils.h</option>
<option value="listing43.html">/MoreIsBetter Bits/MoreIsBetter/MIB-Libraries/MoreUNIX/MoreUNIX.c</option>
<option value="listing44.html">/MoreIsBetter Bits/MoreIsBetter/MIB-Libraries/MoreUNIX/MoreUNIX.h</option>
<option value="listing45.html">/MoreIsBetter Bits/MoreIsBetter/MIB-Libraries/MoreWindows/MoreWindows.cp</option>
<option value="listing46.html">/MoreIsBetter Bits/MoreIsBetter/MIB-Libraries/MoreWindows/MoreWindows.h</option>
<option value="listing47.html">/MoreIsBetter Bits/MoreIsBetter/MIB-Libraries/NetworkSetup/MoreNetworkSetup.c</option>
<option value="listing48.html">/MoreIsBetter Bits/MoreIsBetter/MIB-Libraries/NetworkSetup/MoreNetworkSetup.h</option>
<option value="listing49.html">/MoreIsBetter Bits/MoreIsBetter/MIB-Libraries/NetworkSetup/NetworkSetupHelpers.c</option>
<option value="listing50.html">/MoreIsBetter Bits/MoreIsBetter/MIB-Libraries/NetworkSetup/NetworkSetupHelpers.h</option>
<option value="listing51.html">/MoreIsBetter Bits/MoreIsBetter/MIB-Libraries/NetworkSetup/OldStyleAPI/OldOTConfigLib.h</option>
<option value="listing52.html">/QISA.c</option>
<option value="listing53.html">/QISA.h</option>
<option value="listing54.html">/QISAPanels.c</option>
<option value="listing55.html">/QISAPanels.h</option>
<option value="listing56.html">/QISAPlatform.c</option>
<option value="listing57.html">/QISAPlatform.h</option>
<option value="listing58.html">/QISAPlatformCFM/QISAPlatformCFM.c</option>
<option value="listing59.html">/QISAPlatformCFM/QISAPlatformCFMPrefix.h</option>
<option value="listing60.html">/QISAPlatformMach-O/QISAPlatformMach-O.c</option>
<option value="listing61.html">/QISAPlatformMach-O/QISASetupTool.c</option>
<option value="listing62.html">/ReadMeAboutQISA.html</option></select>
</p>
</form>
<p><strong><a href="QISA.zip">Download Sample</a></strong> (“QISA.zip”, 610.6K)<BR>
<strong><a href="QISA.dmg">Download Sample</a></strong> (“QISA.dmg”, 903.9K)</p>
<!--
<p><strong><a href="#">Download Sample</a></strong> (“filename.sit”, 500K)</p>
-->
</td>
</tr>
<tr>
<td scope="row"><img width="680" height="10" src="images/1dot.gif" alt=""><br>
<img height="1" width="680" src="images/1dot_919699.gif" alt=""><br>
<img width="680" height="20" src="images/1dot.gif" alt=""></td>
</tr>
<tr>
<td scope="row">
<!--googleon: index -->
<pre class="sourcecodebox"><!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"><html> <head> <meta http-equiv="content-type" content="text/html;charset=ISO-8859-1"> <meta name="generator" content="Adobe GoLive 6"> <title>Welcome to Adobe GoLive 6</title> </head> <body bgcolor="#ffffff"> <h1>Read Me About QISA</h1> <p>1.0a3</p> <p>QISA, or the Q Internet Setup Assistant, is a sample that demonstrates the basics of writing an Internet Setup Assistant for Mac OS. The sample is a Carbon application that runs on both Mac OS 9 and Mac OS X. It uses platform-specific technologies to configure the network for the appropriate platform. On Mac OS 9, it uses the Network Setup library for this, and on Mac OS X it uses the System Configuration framework. Platform-specific code is compiled into distinct bundles, which are then loaded and called at runtime via CFBundle.</p> <p>QISA makes extensive use of the MoreIsBetter DTS sample code library. The Mac OS 9 platform support bundle uses the MoreNetworkSetup module as a high-level interface to the Network Setup library. The Mac OS X platform support bundle uses MoreSCF as a high-level interface to System Configuration framework, and MoreSecurity to execute that code in a privileged helper tool.</p> <p>QISA runs on Mac OS 9 and higher (excluding Mac OS X 10.0.x, which did not support a public System Configuration framework API). On traditional Mac OS, it requires CarbonLib 1.6 or higher.</p> <h2>Packing List</h2> <p>The sample contains the following items.</p> <ul> <li>ReadMeAboutQISA.html &#151; This document. <li>QISA.pbproj &#151; A Project Builder project to build the application. <li>QISA.mcp &#151; A CodeWarrior project to build the application. <li>QISAPlatformMach-O &#151; Source and data for the Mach-O platform plug-in. <li>QISAPlatformCFM &#151; Source and data for the CFM platform plug-in. <li>Resources &#151; Resources for the application. <li>QISA.h &#151; Interface to the main application. <li>QISA.c &#151; The main application source code. <li>QISAPlatform.h &#151; Interface to the platform abstraction layer. <li>QISAPlatform.c &#151; Implementation of the above. <li>QISAPanels.h &#151; Interface to the application's panel abstraction layer. <li>QISAPanels.c &#151; Implementation of the above. <li>MoreIsBetter Bits &#151; This sample makes extensive use of the DTS sample code library MoreIsBetter. The required components of MoreIsBetter are included in this folder. <li>QISA-Mach-O.pch &#151; The source for the pre-compiled header used by the CodeWarrior Mach-O build. <li>QISA-Carbon-CFM.prefix &#151; A prefix file used by the CodeWarrior CFM build. <li>QISA &#151; A pre-built application. </ul> <h2>Using the Sample</h2> <p>To try out the sample for yourself, launch the QISA application. The application will create a new setup window which is made up of a number of panels. When you've finished entering information in a panel, click Next. In the &quot;Config&quot; panel, click the &quot;Do It&quot; button to apply your changes. QISA will create a new network location (on Mac OS X, or a set of configurations on traditional Mac OS) named &quot;QISA Test&quot; and make those settings active.</p> <h2>Building the Sample</h2> <p>You can build the sample using Project Builder 2.1 from the December 2002 Mac OS X developer tools release. Open the project file (QISA.pbproj), make sure that the &quot;QISA&quot; target is selected, and choose Build from the Build menu. This will automatically build the application and the platform-support bundle.</p> <p>The project also builds with CodeWarrior Pro 8.3 on Mac OS X 10.2. Open the project file (QISA.mcp), choose either the CFM or Mach-O target, and then choose Make from the Project menu. This will automatically build the application and the platform-support bundles.</p> <p>The Mach-O target builds are provided to keep me honest and to allow easier debugging on Mac OS X. If you want to deploy a product, like QISA, that runs on Mac OS 9 and X, you would ship a CFM build.</p> <h2>How it Works</h2> <p>QISA is a modern Carbon-based application, packaged to support both Mac OS 9 and Mac OS X. The application is modern in the sense that it's entirely Carbon-event based and creates its user interface using NIBs. The application is divided into three main layers.</p> <ul> <li>Application &#151; The actual application is a very simple shell that provides a way to host panels. <li>Panels &#151; Each of the panels in the application window is managed by its own panel 'plug-in'. These plug-ins are not dynamically linked (they are statically linked into the application) but are instead an object-oriented abstraction layer for displaying and managing panels. <li>Platform Support &#151; The panels communicate with the target platform (Mac OS 9 or X) via a platform support layer that isolates them from the details of that particular platform. Each platform is implemented as a CFBundle. The platform support layer loads the appropriate bundle and routes requests through to the implementation within the bundle. </ul> <p><a name="BasicProcess"></a>These layers share one key data structure, a dictionary of global values. The set of keys for this dictionary and their semantics are defined in &quot;QISA.h&quot;. The accessor routines for this dictionary are all implemented in &quot;QISA.c&quot;. There is one such dictionary per setup window. The application layer initialises the dictionary to its default value based on a property list file within the application bundle (&quot;SetupInfo.plist&quot;, read by <code>CopyGlobalValuesFromFile</code>) supplemented by a property list from the platform plug-in (&quot;PlatformProperties.plist&quot;, read by <code>QISACopyPlatformProperties</code> which is called by <code>CopyGlobalValuesFromFile</code>). Each panel reads values from the dictionary (using <code>QISAGetGlobalValue</code>) to display the current user settings and writes values to the dictionary (using <code>QISASetGlobalValue</code>) when those settings change. Finally, when the &quot;Config&quot; panel wants to create a new network location, it makes a copy of the global values dictionary (by calling <code>QISACopyGlobalsDict</code>) and passes that to the platform support layer, which creates the network location based on the information in the dictionary.</p> <h3>Application Layer</h3> <p>The application layer is surprisingly simple. It consists of just two source files &quot;QISA.h&quot; and &quot;QISA.c&quot;. The first contains definitions and entry points that are used by the other two layers, for example, the global value dictionary routines described above. The file &quot;QISA.c&quot; contains the implementation of these routines and some application infrastructure. This infrastructure is surprisingly small due to the miracle of Carbon events.</p> <p>The highlights of &quot;QISA.c&quot; are:</p> <ul> <li>global value dictionary &#151; Three exported routines (<code>QISAGetGlobalValue</code>, <code>QISASetGlobalValue</code>, and <code>QISACopyGlobalsDict</code>) represent the API to the global values dictionary. The dictionary itself is stored in a mutable CFDictionary within the per-window state (see below). <li>error handling &#151; The routine <code>QISADisplayError</code> is used by both the application layer and the panels to display error dialogs. <li>panel switching &#151; The exported routines, <code>QISAIsButtonEnabled</code> and <code>QISASetButtonEnable</code>, allow the panels to control the state of the Next and Previous buttons. The internal routines <code>SwitchFromPanel</code>, <code>SwitchToPanel</code>, and <code>ChangeToNewPanel</code> implement the panel switching behaviour. <code>SwitchToPanel</code> and <code>SwitchFromPanel</code> are split from <code>ChangeToNewPanel</code> because they're called to switch to the initial panel when the document is created and to switch from the current panel when the document is closed. The panel architecture is described in more detail in the next section. <li>default panel &#151; The application contains default implementation of all of the panel entry points. These are described in the next section. <li>command handling &#151; The application only implements two HI commands: <code>QISACommandNew</code> and <code>QISACommandAbout</code>. There is also an &quot;open application&quot; Apple event handler (<code>NewAppleEventHandler</code>), which just calls through to <code>QISACommandNew</code>. <li>initialisation &#151; The main function checks for system requirements, initialises the platform support layer, initialises the application layer (calling another routine, <code>SetupMenus</code>, to set up the menu bar), and then calls <code>RunApplicationEventLoop</code> to run the main loop. </ul> <p>The application layer maintains per-window storage, in the form of the <code>QISAState</code> structure. A pointer to this state is held in the window's refCon. This state, in turn, holds a <code>WindowRef</code> for the window, along with all the other state needed to manage the window. This includes an array of panel state structures that holds the state for each panel within the window (the <code>panels</code> field), and a mutable CFDictionary that holds the global values (the <code>globalValues</code> field).</p> <h3>Panels Layer</h3> <p>The interface between the application and the panel layers is declared in &quot;QISAPanels.h&quot; (application to panel) and &quot;QISA.h&quot; (panel to application). The interface is object oriented in design, although implemented in C. The application maintains a per-panel data structure, <code>QISAPanel</code>, for each panel in the window. Every time it calls the panel or the panel calls it, a pointer to this data structure is passed. This data structure contains the state needed by the application layer to manage the panel, including a number of panel entry point function pointers. Each pointer is initialised to point to a default implementation (within &quot;QISA.c&quot;). When the panel is initialised it can override one or more of these default implementations by overwriting the entry point function pointers.</p> <p>The entry points currently defined are:</p> <ul> <li><code>Initialise</code> &#151; The application layer calls this entry point before calling any other. If this returns an error, the panel is not displayed, an error dialog is shown, and no other entry points are called. Typcially the panel uses this entry point to initialise its instance data. The default implementation does nothing and returns <code>noErr</code>. <li><code>Terminate</code> &#151; The application layer calls this for each panel that has been successfully initialised when the window is closed. Typically the panel uses this opportunity to clean up its instance data. The default implementation does nothing. <li><code>SwitchTo</code> &#151; The application layer calls this entry point when the user switches to the panel. If it returns an error, the panel is not switched to (the old panel remains current) and an error dialog is shown. Typically the implementation sets up its controls to reflect the current state of the window, as stored in the global values dictionary. The default implementation does nothing. <li><code>SwitchFrom</code> &#151; This application layer calls this entry point when the user switches away from the panel to another panel in the same window (activating a different window is not considered a switch). The panel is required to return a &quot;next panel to activate&quot;. All current panels do this by calling through to the default implementation (which returns the next panel in the sequence) but a future panel could implement some clever branching mechanism. Typically the implementation also stores the current value of its controls in the window's global values. In addition, the panel can use this as an opportunity to cancel any pending activities, interacting with the user if required. If the panel returns an error, the switch does not happen; the panel can utilitise this to present a confirmation dialog to the user and return <code>userCanceledErr</code> if the user hits the cancel button. </ul> <p>The panel state also contains a <code>refCon</code> field that the panel can use to store a pointer to its own per-panel instance data structure.</p> <p>There are three panels implemented in &quot;QISAPanels.c&quot;.</p> <ul> <li>PortCCL &#151; This is the first panel displayed. It populates two popup menus with the list of available ports and CCLs (modem scripts). It gets this information by calling the platform support layer. The panel will not let the user advance until they have selected a port and a CCL (for example, if are no available serial ports, the Next button is dimmed). When the user does advance, the values of the popups are stored in the global values dictionary. <li>UserPass &#151; This is the second panel displayed. It managed three text fields that allow the user to enter a user name, password, and a phone number to dial. The initial values for these fields are obtained from the global values dictionary. This allows you to hardwire the fields to known values during debugging. The panel will not let the user advance until all fields are non-empty. The final values of the fields are written to the global values dictionary.<br> <table border=0 cellpadding=3 width=500> <tr> <td bgcolor="#EEEEE0"> <p><b>Note:</b><br>The name &quot;UserPass&quot; is slightly misleading. In an earlier design this panel only asked for the user name and password, and the number was derived by other means. However, in the interests of shipping speedily, I never finished the implementation of those other means, so I modified the UserPass panel to collect the phone number as well.</p> </td> </tr> </table> </ul> <ul> <li>Setup &#151; This is the third panel displayed, which actually configures the network settings. The includes an Info button that you can click to see exactly what values will be written. The Do It button command handler (<code>SetupPanelCommandDoIt</code>) is the code that actually calls the platform to create the network configuration. <table border=0 cellpadding=3 width=500> <tr> <td bgcolor="#EEEEE0"> <p><b>Note:</b><br> This panel maintains a state variable (of type <code>SetupState</code>) that tracks the panels progress as it sets up the network configuration. In the current implementation this is very simple (the only asynchronous state is when the panel waits for a network control panel to quit); it future it may not be so.</p> </td> </tr> </table> </ul> <h3>Platform Support Layer</h3> <p>The platform support layer consists of two files, &quot;QISAPlatform.h&quot; and &quot;QISAPlatform.c&quot;. The header file contains an abstract API that is supported by both platforms (traditional Mac OS and Mac OS X). The implementation file contains three main components.</p> <ul> <li>Initialisation &#151; When the main application calls <code>QISAPlatformInit</code>, it loads the appropriate platform-specific bundle and extracts from it functions pointers for each of the platform functions. It stores these functions in global variables. <li>Dispatcher &#151; All of the other functions in &quot;QISAPlatform.c&quot; simply dispatch to the platform-specific bundle by calling the appropriate function pointer.<br> <table border=0 cellpadding=3 width=500> <tr> <td bgcolor="#EEEEE0"> <p><b>Note:</b><br> In the current implementation <code>QISACopyPlatformProperties</code> is locally implemented; &quot;QISAPlatform.c&quot; contains code that just reads the &quot;PlatformProperties.plist&quot; file directly. However, I include this under the umbrella of dispatched routines because in a future implementation it might dispatch to the plug-in to allow runtime determination of the properties.</p> </td> </tr> </table> </ul> <p>There are two platform-specific bundles.</p> <ul> <li>QISAPlatformMach-O.bundle &#151; This is a Mach-O bundle that implements the platform functions for Mac OS X. It makes heavy use of System Configuration framework. <li>QISAPlatformCFM.bundle &#151; This is a CFM bundle that implements the platform functions for traditional Mac OS. It uses the Network Setup API to modify network settings. </ul> <p>The platform-specific functions are listed below.</p> <ul> <li><code>QISACreatePortArray</code> and <code>QISACreateCCLArray</code> &#151; These entry points are used by the PortCCL panel to populate the serial port and CCL popup menus. For the Mach-O platform, these calls are routed directly through to the like-named routines in MoreSCF. The CFM platform uses MoreSCF to generate the CCL array but its port scanning code is completely distinct; it's implemented using Open Transport port registry calls. <li><code>QISADoesNetworkConfigExist</code> &#151; This routine isn't actually used by current implementation, although both platforms' implementations should work (but are untested). <li><code>QISAMakeNetworkConfig</code> &#151; This routine creates a new network location based on a copy of the global value dictionary (discussed <a href="#BasicProcess">earlier</a>) and makes it active. The Mach-O platform implements this routine by using MoreSecurity to invoke a privileged helper tool. The helper tool does the work by calling MoreSCF library routines, which in turn call System Configuration framework. The CFM platform implements this routine by calling MoreNetworkSetup, which in turn calls through to the Network Setup library. </ul> <p>In addition, each platform has a properties dictionary (stored in the &quot;PlatformProperties.plist&quot;) that is merged into the global values dictionary. This dictionary currently only contains a single key.</p> <ul> <li><code>kQISAKeyControlPanels</code> &#151; This is an array of control panels to quit before attempting to set up the network. This is required because each platform has (broken) control panels that don't recognise changes to the underlying preferences made via the platform API, but the actual list of control panels is different on each platform (&quot;System Preferences&quot; on Mac OS X; &quot;TCP/IP&quot;, &quot;Remote Access&quot;, and &quot;Modem&quot; on traditional Mac OS). </ul> <h4>Mac OS X Security Considerations</h4> <p>As Mac OS X is multi-user system, the Mach-O platform has to be concerned about security. Specifically, it must be careful to prevent a non-privileged user from messing up the machine's network configuration. It does this by tagging any set that it creates with a custom key, and only allowing you to modify sets that contain that key. See <code>CopyCustomDictionary</code> and <code>SetCustomDictionary</code> in &quot;QISASetupTool.c&quot; for the details.</p> <p>Ultimately I would like to be able to use Authorization Services to determine whether the user has the authority to create network locations and to switch the current location. However, <a href="rdar://problem/2939908">limitations</a> of the Authorization Services API prevent me from doing this at this time. Furthermore, the Apple menu (and its agent, the <code>scselect</code> command line tool) <a href="rdar://problem/2938322">allows any user</a> to switch the current location, so QISA does no worse than Mac OS X's out-of-the-box security.</p> <h2><a name="Caveats"></a>Caveats</h2> <p>QISA is still very much a work in progress. Ultimately I want it to create a temporary network configuration, dial the modem, download a configuration file, disconnect the modem, and then set up a permanent network configuration based on the configuration file. At the moment all that it does is create a basic network configuration. However, it does this with a single binary on both traditional Mac OS and Mac OS X, which makes it a valuable example already.</p> <p>I would also like to support plug-in panels in QISA. I didn't implement this feature in the current release because I wanted to ship it quickly. Also, there are technical problems with using NIB-based user interfaces in a plug-in environment on traditional Mac OS. Specifically, you can't move controls from one window to another on traditional Mac OS (<code>EmbedControl</code> returns <code>paramErr</code> in this case), so there's no way to load a panel's user interface from a NIB and then embed that user interface inside the main window.</p> <p>To simplify the platform plug-in API, I make use of Core Foundation types. However, the CFM platform is linked with InterfaceLib and would not normally have access to Core Foundation. To work around this, I built my own Core Foundation stub library and linked to that. This works in practice and is not particularly bad in theory. After all, the CFM platform is being hosted in a CarbonLib application, which means that Core Foundation is already instantiated within the process. I'm just simplifying the job of calling it from InterfaceLib-based code. I'm also confident that this approach will remain compatible because CarbonLib and Mac OS 9 are no longer being updated.</p> <p>There's currently no support for PPPoE. This would not be hard to do for Mac OS X but can't easily be supported on traditional Mac OS.</p> <p><code>QISADoesNetworkConfigExist</code> is not currently used for anything. The goal is to present a user interface to confirm the overwriting of the current QISA location.</p> <p>On traditional Mac OS on certain machines, the machine dials the modem as soon as QISA has finished configuring the network. I believe that this is being caused by some background-only application, not by QISA itself. Curiously, if you disconnect, then set up the network again using QISA, it doesn't happen again. I discovered this problem during testing (version 1.0a2), however, I didn't consider it significant enough to hold up the release.</p> <p>There are a number of other problems that I would classify as bugs. I didn't fix them because they didn't seem important enough.</p> <ul> <li>Panels are not terminated if you quit the application without closing the window. This wouldn't be hard to fix but I didn't need the fix in order to release QISA. <li>While I prevent you from entering a CR into a single line text field, you can circumvent this by using the clipboard to paste into the field. <li>I don't properly enable and disable the text editing commands on the Edit menu (Cut, Copy, Paste, Clear). </ul> <h2>Credits and Version History</h2> <p>If you find any problems with this sample, mail &lt;[email protected]&gt; and I&#146;ll try to fix them up.</p> <p>1.0d1 (Nov 2002) was a pre-release version with limited functionality. It was distributed to a small number of developers at a kitchen.</p> <p>1.0d2 (Nov 2002) was another pre-release version.</p> <p>1.0a1 (Mar 2002) was yet another pre-release version.</p> <p>1.0a2 (Apr 2003) was sent to a limited number of DTS engineers for internal testing.</p> <p>1.0a3 (Apr 2003) was the first released version.</p> <p>Share and Enjoy.</p> <p>Apple Developer Technical Support<br> Networking, Communications, Hardware</p> <p>25 Apr 2003</p> <p><!--$Log$--></p> </body></html></pre>
<!--googleoff: index -->
</td>
</tr>
</table>
<!-- END WIDE COLUMN -->
<!-- END MAIN CONTENT -->
<table width="680" border="0" cellpadding="0" cellspacing="0">
<tr>
<td><div style="width: 100%; height: 1px; background-color: #919699; margin-top: 5px; margin-bottom: 15px"></div></td>
</tr>
<tr>
<td align="center"><br/>
<table border="0" cellpadding="0" cellspacing="0" class="graybox">
<tr>
<th>Did this document help you?</th>
</tr>
<tr>
<td>
<div style="margin-bottom: 8px"><a href="http://developer.apple.com/feedback/?v=1&url=/samplecode/QISA/listing62.html%3Fid%3DDTS10000714-1.0&media=dvd" target=_new>Yes</a>: Tell us what works for you.</div>
<div style="margin-bottom: 8px"><a href="http://developer.apple.com/feedback/?v=2&url=/samplecode/QISA/listing62.html%3Fid%3DDTS10000714-1.0&media=dvd" target=_new>It’s good, but:</a> Report typos, inaccuracies, and so forth.</div>
<div><a href="http://developer.apple.com/feedback/?v=3&url=/samplecode/QISA/listing62.html%3Fid%3DDTS10000714-1.0&media=dvd" target=_new>It wasn’t helpful</a>: Tell us what would have helped.</div>
</td>
</tr>
</table>
</td>
</tr>
</table>
<!-- START BOTTOM APPLE NAVIGATION -->
<!--#include virtual="/includes/footer"-->
<!-- END BOTTOM APPLE NAVIGATION -->
<!-- START CENTER CLOSE -->
</center>
<!-- END CENTER CLOSE -->
</body>
</html>