Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

Beginning Mac OS X Tiger Dashboard Widget Development (2006)

.pdf
Скачиваний:
17
Добавлен:
17.08.2013
Размер:
9.7 Mб
Скачать

14

SecureCopy Widget

In addition to providing web content at your fingertips, widgets can serve as an interface to any of the command-line utilities on your Macintosh. If you have trouble remembering the syntax for a command-line utility, you can easily build a widget that calls the utility using the widget.system method and you won’t have to remember the syntax for those powerful but infrequently used commands. This chapter looks at a widget that demonstrates building an interface for the scp utility in Darwin.

SSH & scp

FTP may be the most familiar means of transferring files between two computers on the Internet, but it is not the most secure. It sends your password and data in clear text that can easily be intercepted and viewed by malicious users. A more secure means of transferring files is available using SSH, or secure shell. SSH is both a set of command-line utilities and a protocol for gaining access to a remote computer, already built in to the Mac OS. The SSH suite includes slogin, ssh, and scp for securely connecting to a remote machine, running a remote shell, and copying files to a remote machine, respectively. With SSH, client and server connections are authenticated using a digital certificate and passwords. The digital certificate and passwords — and in fact the entire session — are all protected by encryption. The security in SSH comes through RSA public key cryptography.

You may think that because you are copying files between machines within your own local network, you probably don’t have need for such strong security. You may be right. But you are overlooking a more mundane use of scp. If you want to copy files or directories between two Macs, your options are burning the data to CD, swapping an external drive, personal file sharing, FTP, or scp. scp allows you to copy files between two Macs without mounting filesystems and incurring the overhead of the Finder dealing with another mounted filesystem.

In true Unix fashion, scp is a command-line utility. To copy a file from one Macintosh to the other using scp, you pass the utility the file you want to copy, the Macintosh you want to copy it to, and the file’s name on that computer, like so, using the Terminal application.

[offhook:~/.ssh] pfterry% scp traffic.tiff pfterry@desklamp:traffic.tiff

Chapter 14

You will be prompted for your password on the computer to which you are copying. If this is your first connection to the remote computer, you will be asked to accept its SSH key.

[offhook:~/.ssh] pfterry@desklamp’s password:

When you enter your password and press Return, the file is copied from your Macintosh to the other Macintosh. In the terminal, the filename, percentage of the file copied, and the speed of the copy, and time remaining until the copy is complete are displayed as the file is copied.

traffic.tiff

3%

30MB

1.7MB/s

07:48 ETA

If you substitute the path to a directory for the file and include a –r switch, scp copies the directory and all of the directories or files in it recursively to the other Macintosh.

You can reverse the process if you know the path to a file or directory on a networked Macintosh that you want copied to your Macintosh.

[offhook:~/.ssh] pfterry% scp pfterry@countzero:~/Desktop/traffic.tiff .

In this case, you are copying the traffic.tiff file from the desktop of your account on the networked Macintosh to the current directory on your local Macintosh. The dot indicates that you are copying the file to the current directory. You will be prompted for your password on the computer that you are copying from.

[offhook:~/.ssh] pfterry@countzero’s password:

As the file is copied from the remote computer to the local computer, you can see the transfer statistics.

The SecureCopy Widget

The SecureCopy widget takes advantage of the widget.system method to perform the same function as the scp command-line utility. It takes advantage of Dashboard’s drag-and-drop capabilities so you do not have to enter the full path to the file that you want to copy to a networked Macintosh.

The Interface

The SecureCopy widget provides a Dashboard interface to the scp command-line utility. The interface is a set of text boxes where you can enter the information that you would normally type in your terminal (Figure 14-1). The Host field takes the name or IP address of the computer to or from which you are copying the file. The Filename field takes the path to the file you want to copy. If you are copying the file from your local Macintosh, you can drag the file to the Filename field. The Switches field takes the com- mand-line switches that you would enter to copy a directory. You enter your user name on the remote computer in the User Name field.

Once you have entered the information for the copy in the widget, you can click the Copy To button to copy the local file to the remote computer. If you are copying the file from the remote computer to your local computer, you click the Copy From button.

212

SecureCopy Widget

Figure 14-1

The back of the widget contains help information about the switches that are available for scp (Figure 14-2).

Figure 14-2

SecureCopy Internals

Like most widgets, SecureCopy has the basic set of files required for the widget (Figure 14-3).

Figure 14-3

213

Chapter 14

Info.plist

The widget has the AllowNetworkAccess, AllowSystem, and AllowFileAccessOutsideOfWidget access keys set. It needs these three because it needs access to the network to copy the files and directories, and it needs access to the filesystem to run the scp command-line utility. The widget needs access outside of the widget so you can copy files from anywhere on your hard disk.

<plist version=”1.0”> <dict>

<key>AllowFileAccessOutsideOfWidget</key>

<true/>

<key>AllowNetworkAccess</key>

<true/>

<key>AllowSystem</key>

<true/>

<key>CFBundleDisplayName</key>

<string>SecureCopy</string>

<key>CFBundleIdentifier</key>

<string>com.apple.widget.securecopy</string>

<key>CFBundleName</key>

<string>SecureCopy</string>

<key>CFBundleShortVersionString</key>

<string>.5</string>

<key>CFBundleVersion</key>

<string>.5</string>

<key>CloseBoxInsetX</key>

<integer>6</integer>

<key>CloseBoxInsetY</key>

<integer>6</integer>

<key>MainHTML</key>

<string>scp.html</string>

</dict>

</plist>

HTML/CSS

The scp.html file isn’t very complicated. The text fields for user input are provided through a standard text input form. The Apple Class JavaScripts to animate flipping the widget (for the info button and for the Done button) are imported in addition to the scp.js widget JavaScript. The widget also has front and back <div>s, and the form and info button are placed in the front <div>.

<html>

<style type=”text/css”> @import “scp.css”;

</style>

<script type=”text/javascript” src=”scp.js” />

<script type=”text/javascript” src=”AppleClasses/AppleButton.js” charset=”utf-

8”/>

<script type=”text/javascript” src=”AppleClasses/AppleInfoButton.js” charset=”utf-8”/>

<script type=”text/javascript” src=”AppleClasses/AppleAnimator.js” charset=”utf-8”/>

</head>

214

SecureCopy Widget

<body onload=”setup()”> <div id=”front”>

<!-- the widget background --> <img src=”Default.png”></img>

<!-- the widget title -->

<span class=”windowLabel”>SecureCopy</span>

<!-- the filename label and input --> <span class=”fileLabel”>Local file:</span>

<input type=”text” value=”enter unix file path...” id=”fileText” ondragenter=”dragenter(event);” ondragover=”dragover(event);” ondrop=”dragdrop(event)” ondragleave=”dragleave(event)”></input>

<!-- the host label and input --> <span class=”hostLabel”>Host:</span>

<input type=”text” value=”enter name or IP address...” id=”hostText”></input>

<!-- the username label and input --> <span class=”userLabel”>User Name:</span>

<input type=”text” value=”enter user name...” id=”userText”></input>

<!-- the switches label and input -->

<span class=”switchesLabel”>Switches:</span>

<input type=”text” value=”enter switches for the copy...” id=”switchesText”></input>

<!-- the copy to button -->

<div id=”copyToButton” onmousedown=”copyTo();” onmouseup=”buttonUpOut(“toButtonImage”);” onmouseout=”buttonUpOut(“toButtonImage”);”>

<img id=”toButtonImage” src=”Images/Button.png”></img> <div id=”toButtonText”>Copy To</div>

</div>

<!-- the copy from button -->

<div id=”copyFromButton” onmousedown=”copyFrom();” onmouseup=”buttonUpOut(“fromButtonImage”);” onmouseout=”buttonUpOut(“fromButtonImage”);”>

<img id=”fromButtonImage” src=”Images/Button.png”></img> <div id=”fromButtonText”>Copy From</div>

</div>

<div id=”flip”></div> </div>

<div id=”back”>

<img span=backgroundImage src=”Back.png”> <div id=”man”>

<table><tr>

<td id=”r1c1”>-P #</td>

<td>Specifies the port to connect to on the remote host. Note that this option is written with a capital `P”, because -p is already reserved for preserving the times and modes of the file in rcp(1).</td>

</tr><tr>

215

Chapter 14

<td id=”r2c1”> -p</td>

<td>

Preserves modification times, access times, and modes from the

 

original file.

</td></tr><tr>

<td id=”r3c1”> -q</td>

<td>

Disables the progress meter.

</td></tr><tr>

<td id=”r4c1”> -r </td>

<td> Recursively copy entire directories. </td></tr></table>

</div>

<div id=”doneButton”></div> </div>

</body>

</html>

The back <div> contains some help information about the switches that the user might want to use with SecureCopy as well as copyright information and the Done button.

The selectors in the scp.css file are grouped according by front and back. All of the buttons are grouped together as well. The table selector at the bottom of the CSS file formats the switch information on the back side of the widget.

body { margin: 0;

}

#front { display: block;

position: absolute; top: 0px;

left: 0px;

}

.windowLabel {

font: 15px “Helvetica Neue”; font-weight: bold;

color: black; position: absolute; left: 20px;

top: 10px;

}

.fileLabel {

font: 11px “Helvetica Neue”; font-weight: bold;

color: black; position: absolute; left: 34px;

top: 64px;

}

#fileText {

font: 12px “Courier New”;

216

SecureCopy Widget

font-weight: bold; color: green; position: absolute; left: 93px;

top: 60px; width: 205px;

border-width: 0px; border-color: transparent; background-color: transparent;

-apple-dashboard-region: dashboard-region(control rectangle);

}

.hostLabel {

font: 11px “Helvetica Neue”; font-weight: bold;

color: black; position: absolute; left: 56px;

top: 43px;

}

#hostText {

font: 12px “Courier New”; font-weight: bold; color: green;

position: absolute; left: 93px;

top: 38px; width: 205px;

border-width: 0px; border-color: transparent; background-color: transparent;

-apple-dashboard-region: dashboard-region(control rectangle);

}

.userLabel {

font: 11px “Helvetica Neue”; font-weight: bold;

color: black; position: absolute; left: 31px;

top: 110px;

}

#userText {

font: 12px “Courier New”; font-weight: bold; color: green;

position: absolute; left: 93px;

top: 104px; width: 205px; border-width: 0px;

border-color: transparent;

217

Chapter 14

background-color: transparent;

-apple-dashboard-region: dashboard-region(control rectangle);

}

.switchesLabel {

font: 11px “Helvetica Neue”; font-weight: bold;

color: black; position: absolute; left: 26px;

top: 86px;

}

#switchesText {

font: 12px “Courier New”; font-weight: bold; color: green;

position: absolute; left: 93px;

top: 82px; width: 205px;

border-width: 0px; border-color: transparent; background-color: transparent;

-apple-dashboard-region: dashboard-region(control rectangle);

}

#toButtonImage { position: absolute; left: 140px;

top: 130px;

-apple-dashboard-region: dashboard-region(control rectangle);

}

#toButtonText {

font: 12px “Helvetica Neue”; font-weight: Bold;

color: white;

text-shadow: black 0px 1px 0px; position: absolute;

left: 155px; top: 136px;

}

#fromButtonImage { position: absolute; left: 225px;

top: 130px;

-apple-dashboard-region: dashboard-region(control rectangle);

}

#fromButtonText {

font: 12px “Helvetica Neue”; font-weight: Bold;

218

SecureCopy Widget

color: white;

text-shadow: black 0px 1px 0px; position: absolute;

left: 230px; top: 136px;

}

#flip {

position: fixed; bottom: 32px; left: 14px;

}

.backgroundImage { position: absolute; top: 0px;

left: 0px;

}

#back { display: none;

position: absolute; top: 0px;

left: 0px;

}

#doneButton { position:absolute; bottom:20px; left:254px;

}

#man {

font: 10px “Helvetica Neue”; color: white;

position: absolute; left: 20px;

top: 20px; width: 85%;

}

table {table-layout: auto; width: auto; font: 10px “Helvetica Neue”; color: white;} #r1c1 {width:10%; vertical-align: top;} #r2c1 {width:10%; vertical-align: top;} #r3c1 {width:10%;}

#r4c1 {width:10%;}

#copyright {

font: 10px “Helvetica Neue”; color: white;

position: absolute; left: 75px; bottom:20px;

219

Chapter 14

JavaScript Functionality

Though the JavaScript is based on the command and switches typed on the command line, it contains other functions to provide standard features. For example, the variables at the top of the JavaScript and the use of the Apple Classes provide the info and Done buttons and the Apple Classes are called in the setup() function.

// Global variables for the info and done buttonsvar glassDoneButton; var whiteInfoButton;

function setup()

{

// Setup Apple Classes

glassDoneButton = new AppleGlassButton(document.getElementById(“doneButton”), “Done”, hidePrefs);

whiteInfoButton = new AppleInfoButton(document.getElementById(“flip”), document.getElementById(“front”), “white”, “white”, showPrefs);

The dragdrop(event) function takes care of getting the path to the file or directory that you drop on the widget, removing the prefix, and removing the spaces from the path. This converts the path into something the scp utility can use. This method allows you to drop the file or directory over the filename and saves you the trouble of typing the exact path to the file or directory.

function dragdrop(event) { var uri = null;

try {

uri = event.dataTransfer.getData(“text/uri-list”); } catch (ex) {

}

alert(uri);

if (uri) {

//remove the “file://localhost” uri prefix: var theFile = uri.split(“file://localhost”);

document.getElementById(“fileText”).value = theFile[1];

//remove any spaces “%20”. WARNING: NOT ACCOUNTING FOR ALL SPECIAL CHARACTERS!!!

theFile = theFile.replace(/%20/, “ “) document.getElementById(“fileText”).value = theFile;

}

event.stopPropagation();

event.preventDefault();

}

The copyFrom() function is the portion of the JavaScript that is based on the command typed in Terminal. The function is executed when the Copy From button is clicked. The command is built from the host, filename, switches, and user fields and sent to the command line through the widget.system method.

//The copyFrom() function is called when the Copy button is pressed.

//It uses the widget.system call synchronously to execute scp with the command built from the information in the widget fields.

220