20101126

Sams Teach Yourself C# in 24 Hours (Hour 1)

Sams Teach Yourself C# in 24 Hours

Sams Teach Yourself C# in 24 Hours More Information
Learn C#, Microsoft's newest programming language, one step at a time from leading expert, James Foxall. ...

Table of Contents



Copyright

Copyright © 2002 by Sams Publishing

All rights reserved. No part of this book shall be reproduced, stored in a retrieval system, or transmitted by any means, electronic, mechanical, photocopying, recording, or otherwise, without written permission from the publisher. No patent liability is assumed with respect to the use of the information contained herein. Although every precaution has been taken in the preparation of this book, the publisher and author assume no responsibility for errors or omissions. Nor is any liability assumed for damages resulting from the use of the information contained herein.
Library of Congress Catalog Card Number: 2001093572
Printed in the United States of America
First Printing: February 2002
05 04 03 02 4 3 2 1

Trademarks

All terms mentioned in this book that are known to be trademarks or service marks have been appropriately capitalized. Sams Publishing cannot attest to the accuracy of this information. Use of a term in this book should not be regarded as affecting the validity of any trademark or service mark.

Warning and Disclaimer

Every effort has been made to make this book as complete and as accurate as possible, but no warranty or fitness is implied. The information provided is on an "as is" basis. The author and the publisher shall have neither liability nor responsibility to any person or entity with respect to any loss or damages arising from the information contained in this book.

Credits

Associate Publisher
Linda Engelman
Acquisitions Editor
Sondra Scott
Development Editor
Ginny Bess
Managing Editor
Charlotte Clapp
Project Editor
Carol Bowers
Copy Editor
Barbara Hacha
Indexer
Erika Millen
Proofreader
Jody Larsen
Technical Editors
Joel Mueller
Deon Schaffer
Team Coordinator
Lynne Williams
Media Developer
Dan Scherf
Interior Designer
Gary Adair
Cover Designer
Aren Howell
Page Layout
D&G Limited, LLC

Dedication

To my children, Ethan and Tess.
—James Foxall
To my parents, Olga and Alfonso, and my love, Dave.
—Wendy Haro-Chun


About the Authors

James Foxall is Vice President of Development and Support for Tigerpaw Software, Inc. (www.tigerpawsoftware.com)—an Omaha, Nebraska, Microsoft Certified Partner specializing in commercial database applications. James manages a commercial suite of programs designed to automate contact management, marketing, service and repair, proposal generation, and inventory control and purchasing. James's experience in creating certified Office-compatible software has made him an authority on application interface and behavior standards of applications for the Microsoft Windows and Microsoft Office environments.
James has personally written more than 150,000 lines of commercial production code, both in single programmer and multiple programmer environments. He is the author of numerous books, including Practical Standards for Microsoft Visual Basic and MCSD in a Nutshell: The Visual Basic Exams, and he has written articles for Access-Office-VBA Advisor and Visual Basic Programmer's Journal. James is a Microsoft Certified Solution Developer and an international speaker on Microsoft programming technologies. When not programming or writing about programming, he enjoys spending time with his family, playing guitar, doing battle over the chess board, listening to Pink Floyd, playing computer games, and (believe it or not) programming! You can reach James at jamesf@tigerpawsoftware.com.
Wendy Haro-Chun, MCSD, holds a B.S. in Computer Science and an M.B.A. with an emphasis in International Business. She is Assistant Vice President of Research and Development for SunGard Insurance Systems. Her areas of technological expertise include .NET, C#, ASP, DHTML, JavaScript, XML, COM, VB, ADO, and Microsoft SQL Server. Wendy has also served as technical editor and reviewer on numerous computer technology books. She lives in Miami with her husband, Dave, and her two beagles, Buster and Belle. She can be reached at wharo@bellsouth.net.



Acknowledgments

James's acknowledgements:
To Sondra Scott, both for the opportunity to do this book as well as just being a great person to work for!
To Wendy for her wonderful contributions, Carol Bowers, Ginny Bess, Joel Mueller, Deon Schaffer, and everyone else that had a hand in this book—thanks guys!
To Matt Wagner at Waterside Productions for all his help behind the scenes.
To my wife and children for always supporting and encouraging me through these projects. You are the best!
Finally, a special thanks to Mike Pizzo at Microsoft for his contributions to the ADO.NET chapter.
Wendy's acknowledgements:
I would like to thank Sondra Scott for giving me the opportunity to work on this great project. I would also like to thank Ginny Bess and Carol Bowers for making sure everything came together and technical editors Joel and Deon for making sure this new technology worked the way I said it did. Also, special thanks to Peter Farquharson, David Marcato, Deon Schaffer, and Larry Wall for helping to get this project started on a good foundation.
To James Foxall, I have enjoyed reading your VB .NET book, and it has been a great pleasure working with you on this C# book.
A big thanks goes out to my husband, Dave, for his constant support in all my projects and for always believing in me.
To Olga and Alfonso, thank you for all the support, encouragement, and love you have always given me.
Finally, thanks to all my relatives and friends for buying this book!


Tell Us What You Think!

As the reader of this book, you are our most important critic and commentator. We value your opinion and want to know what we're doing right, what we could do better, what areas you'd like to see us publish in, and any other words of wisdom you're willing to pass our way.
As an Associate Publisher for Sams Publishing, I welcome your comments. You can fax, e-mail, or write me directly to let me know what you did or didn't like about this book—as well as what we can do to make our books stronger.
Please note that I cannot help you with technical problems related to the topic of this book, and that because of the high volume of mail I receive, I might not be able to reply to every message.
When you write, please be sure to include this book's title and author as well as your name and phone or fax number. I will carefully review your comments and share them with the author and editors who worked on the book.
Fax: 317-581-4770
E-mail: feedback@samspublishing.com
Mail: Linda Engelman
Sams Publishing
201 West 103rd Street
Indianapolis, IN 46290 USA

Introduction

With Microsoft's introduction of the .NET platform, a new, exciting programming language was born. C# is the language of choice for developing on the .NET platform, and Microsoft has even written a majority of the .NET Framework using C#. C# is a modern object-oriented language designed and developed from the ground up with a best-of-breed mentality, implementing and expanding on the best features and functions found in other languages. C# combines the power and flexibility of C++ with the simplicity of Visual Basic.



Audience and Organization

This book is targeted toward those who have little or no programming experience. The book has been structured and written with a purpose, and that is to get you productive as quickly and as smoothly as possible. I've used my experiences from writing large commercial applications to create a book that, hopefully, cuts through the fluff and teaches you what you need to know. All too often, authors fall into the trap of focusing on the technology rather than on the practical application of the technology. I've worked hard to keep this book focused on teaching you practical skills that you can apply immediately toward a development project. Please feel free to send me your suggestions or success stories at jamesf@tigerpawsoftware.com.
This book is divided into five parts, each of which focuses on a different aspect of developing applications with C#. These parts generally follow the flow of tasks you'll perform as you begin creating your own programs using C#. I recommend that you read them in the order in which they appear.
  • Part I The Visual Studio Environment teaches you about the Visual Studio's C# development environment, including how to navigate and access 'numerous tools. In addition, you'll learn some key development concepts such as objects, collections, and events.
  • Part II Building a User Interface shows you how to build attractive and functional user interfaces. In this part, you'll learn about forms and controlsthe user-interface elements such as text boxes and list boxes.
  • Part III Making Things HappenProgramming! teaches you the nuts and bolts of C# programmingand there's a lot to learn. You'll discover how to create methods, as well has how to store data, perform loops, and make decisions in code. After you've learned the core programming skills, you'll move into object-oriented programming and debugging applications.
  • Part IV Working with Data introduces you to working with a database and shows you how to automate external applications such as Word and Excel. In addition, this part teaches you how to manipulate a user's file system.
  • Part V Deploying Solutions and Beyond shows you how to distribute an application that you've created to an end user's computer. Then, the focus is brought back a bit to take a look at Web programming and Microsoft's .NET initiative from a higher, less-technical level.


Conventions Used in This Book

This book uses several conventions to help you prioritize and reference the information it contains:
  • Tips highlight information that can make your C# programming more effective.
  • Cautions focus your attention on problems or side effects that can occur in specific situations.
  • Notes provide useful sidebar information that you can read immediately or circle back to without losing the flow of the topic at hand.
  • New Term icons signal places where new terminology is first used and defined. Such terminology appears in an italic typeface for emphasis.
In addition, this book uses various typefaces to help you distinguish code from regular English. Code is presented in a monospace font. Placeholderswords or characters used temporarily to represent the real words or characters you would type in codeare typeset in italic monospace.
Some code statements presented in this book are too long to appear on a single line. In these cases, a line-continuation character (an underscore) is used to indicate that the following line is a continuation of the current statement.



Onward and Upward!

This is an exciting time to be learning how to program, and it's my sincerest wish that when you finish this book, you will feel capable of creating, debugging, and deploying modest C# programs using many C# and Visual Studio tools. Although you won't be an expert, you'll be surprised at how much you've learned. And hopefully, this book will help you determine your future direction as you proceed down the road to C# mastery.


Part I: The Visual Studio Environment

Before you can begin to create C# applications for Windows and the Web, you need to have a thorough grasp of the C# environment as well as some key development concepts. In this part, you'll get an overview of developing a project in C#, you'll learn all about the C# interface, and you'll learn about objects, collections, and events—concepts that are critical to your success as a C# developer.
  • Hour 1: A C# Programming Tour
  • Hour 2: Navigating C#
  • Hour 3: Understanding Objects and Collections
  • Hour 4: Understanding Events

Hour 1. A C# Programming Tour

Learning a new programming language can be intimidating. If you've never programmed before, the act of typing seemingly cryptic text to produce sleek and powerful applications probably seems like a black art, and you may wonder how you'll ever learn everything you need to know. The answer is, of course, one step at a time. The first step to learning a language is the same as that of any other activity—building confidence. Programming is part art and part science. Although it may seem like magic, it's more akin to illusion; after you know how things work, a lot of the mysticism goes away, freeing you to focus on the mechanics necessary to produce the desired result.
In this hour, you'll complete a quick tour that takes you step-by-step through creating a complete, albeit small, C# program. I've yet to see a "Hello World" program that's the least bit helpful (they usually do nothing more than print "hello world" to the screen—oh, fun). So instead, you'll create a picture-viewer application that lets you view Windows bitmaps and icons on your computer. You'll learn how to let a user browse for a file and how to display a selected picture file on the screen, both of which are skills that will come in handy in later applications that you create. Creating large, commercial solutions is accomplished by way of a series of small steps. After you've finished creating this small project, you'll have an overall feel for the development process.
The highlights of this hour include the following:
  • Building a simple, yet functional, C# application
  • Letting a user browse a hard drive
  • Displaying a picture from a file on disk
  • Getting familiar with some programming lingo
  • Learning about the Visual Studio—C# IDE
I hope that by the end of this hour, you'll realize just how much fun it is to program using C#.


Starting C#

You must become familiar with a few terms before you begin to create programs in C#:
  • Distributable Component The final, compiled version of a project. Components can be distributed to other people and other computers and do not require C# to run (although the .NET Framework is required, which you'll learn about in coming hours). Distributable components are also called programs. In Hour 22, "Deploying a Solution," you'll learn how to distribute the Picture Viewer program that you're about to build to other computers.
  • Project A collection of files that can be compiled to create a distributable component (program). There are many types of projects, and complex applications may consist of many projects, such as a Windows Application project and support DLL projects.
  • Solution A collection of projects and files that compose an application or component.
Start the C# IDE now by choosing Microsoft Visual Studio .NET from within the Microsoft Visual Studio .NET folder on your Start menu.




Creating a New Project

When you first start Visual Studio .NET, you're shown the Visual Studio Start Page tab within the IDE. Using this page, you can open projects created previously or create new ones (see Figure 1.1). For this quick tour, you're going to create a new Windows application, so click New Project to display the New Project dialog box shown in Figure 1.2.
01fig01.jpg Figure 1.1 You can open existing projects or create new projects from the Visual Studio Start page.
01fig02.jpg Figure 1.2 The New Project dialog box allows you to create many types of .NET projects.
You can create many types of projects with C#, as well as with the other supported languages of the .NET platform. The New Project dialog box is used to specify the type of C# project you want to create. If the Visual C# Projects folder isn't selected, click it to display the C# project types and then make sure the Windows Application icon is selected (if it's not, click it once to select it). At the bottom of the New Project dialog box is a Name text box, in which you specify the name of the project you're creating; in the Location text box, you can enter the location in which to save the project files.
Type Picture Viewer into the Name text box to name your project. There's no need to change the location where the project files are to be saved at this time, so go ahead and create the new Windows Application project by clicking OK. C# creates the new project, complete with one form (design window) for you to begin building the interface for your application (see Figure 1.3).
01fig03.jpg Figure 1.3 New Windows applications start with a blank form; the fun is just beginning!
Your C# environment may look different from that shown in the figures of this hour, depending on the edition of C# you're using, whether you've already played with C#, and other factors such as the resolution of your monitor. All the elements discussed in this hour, however, exist in all editions of C#. (If your IDE doesn't have a window displayed that is shown in a figure, use the View menu to display the window.)

Giving the Form an Icon

Everyone who has used Windows is familiar with icons, which are the little pictures used to represent programs. Icons most commonly appear in the Start menu next to the name of their respective programs. In C#, you not only have control over the icon of your program file, you can also give every form in your program a unique icon if you want to.
To give the form an icon, follow these steps:
  1. In the Properties window, click the Icon property to select it.
  2. When you click the Icon property, a small button with three dots appears to the right of the property. Click this button.
  3. To locate the HourOne.ico file or another ico file of your choice, use the Open dialog box that appears. When you've found the icon, double-click it, or click it once to select it and then click Open.
After you've selected the icon, it appears in the Icon property along with the word (Icon). A small version of the icon appears in the upper-left corner of the form, as well. Whenever this form is minimized, this is the icon that's displayed on the Windows taskbar. (Note: This doesn't change the icon for the project as a whole. In Hour 22, you'll learn how to assign an icon to your distributable file.)



Changing the Size of the Form

Next, you're going to change the Width and Height properties of the form. The Width and Height values are shown collectively under the Size property; Width appears to the left of the comma, Height to the right. You can change the Width or Height by changing the corresponding number in the Size property. Both values represent the number of pixels of the dimension. To display and adjust the Width and Height properties separately, click the small plus sign (+) next to the Size property (see Figure 1.4).
01fig04.jpg Figure 1.4 Some properties can be expanded to show more specific properties.
Change the Width property to 400 and the Height to 325. To commit a property change, press Tab or click a different property or window. Your screen should now look like the one in Figure 1.5.
01fig05.jpg Figure 1.5 A change in the Properties window is reflected as soon as the change is committed.
When you first created this project, C# saved a copy of the source files in their initial state. The changes you've made so far exist only in memory; if you were to turn your computer off at this time (don't do this), you would lose any and all work up to this point. You should get into the habit of saving your work frequently. Save the project now by choosing Save All from the File menu or by clicking the Save All button on the toolbar (it has a picture of stacked disks on it).


Adding Controls to a Form

01fig06.jpg Figure 1.6 The toolbox is used to select controls to build a user interface.
The toolbox closes itself soon after you've added a control to a form and the pointer is no longer over the toolbox. To make the toolbox stay visible, click the little picture of a pushpin located in the toolbox's title bar.
Your Picture Viewer interface will consist of the following controls:
  • Two Button controls
  • A PictureBox control
  • An OpenFileDialog control


Designing an Interface

It's generally best to design the user interface of a form and then add the code behind the interface that makes the form functional. The user interface for your Picture Viewer program will consist of a View Picture button, a Close button, and a PictureBox in which to display a picture.

Adding a Visible Control to a Form

Start by adding a Button control to the form. Do this by double-clicking the Button item in the toolbox. C# then creates a new button and places it in the upper-left corner of the form (see Figure 1.7).
01fig07.jpg Figure 1.7 When you double-click a control in the toolbox, the control is added to the upper-left corner of the form.
Using the Properties window, set the button's properties as follows (note that you may want to change the Properties list to alphabetical, if it is not already, to make it easier to find these properties by name):
Property Value
Name btnSelectPicture
Text Select Picture
Location 301,10 (Note: 301 is the x coordinate, 10 is the y coordinate.)
Size 85,23
You're now going to create a button that the user can click to close the Picture Viewer program. Rather than adding a new button to the form, you're going to create a copy of the button you've already defined. To do this, right-click the button on the form and choose Copy from its shortcut menu. Next, right-click anywhere on the form and choose Paste from the form's shortcut menu. The new button appears over the button you copied, and it is selected by default. Change the properties of the new button as follows:
Property Value
Name btnQuit
Text Quit
Location 301,40
The last control you need to add to the form is a PictureBox control. A PictureBox has many capabilities, but its primary purpose is to show pictures—which is precisely what you'll use it for in this example. Add a new PictureBox control to the form and set its properties as follows:
Property Value
Name picShowPicture
BorderStle FixedSingle
Location 8,8
Size 282, 275
After you've made these property changes, your form will look like the one in Figure 1.8. Click the Save All button on the toolbar to save your work.
01fig08.jpg Figure 1.8 An application's interface doesn't have to be complex to be useful.


Adding an Invisible Control to a Form

To allow the user to select a picture to display, you need to give her the capability to locate a file on her hard drive. You've probably noticed in the past that whenever you choose to open a file from within any Windows application, the dialog box displayed is almost always the same. It doesn't make any sense to force each and every developer to write the code necessary to perform standard file operations. Instead, Microsoft has exposed the functionality via a control that you can use in your project. This control is called the OpenFileDialog control, and it will save you dozens of hours that you would otherwise spend trying to duplicate common functionality.
Scroll the toolbox until you can see the OpenFileDialog control, and then double-click it to add it to your form. (You may have to scroll the toolbox, which is done by clicking the up arrow toward the top of the window or the down arrow toward the bottom.) Note that the control isn't placed on the form, but it appears in a special area below the form (see Figure 1.9). This happens because the OpenFileDialog control has no interface to display to a user. It does have an interface, a dialog box that you can display as necessary, but it has nothing to display directly on a form.
01fig09.jpg Figure 1.9 Controls that have no interface appear below the form designer.
Select the OpenFileDialog control and change its properties as follows:
Property Value
Name ofdSelectPicture
Filter Windows Bitmaps|*.BMP|JPEG Files|*.JPG
Title Select Picture
The Filter property determines the filtering of the control. The text that appears before the pipe symbol (|) is the descriptive text of the file type, whereas the text after the pipe symbol is the pattern to use to filter files; you can specify more than one filter type. Text entered into the Title property appears in the title bar of the Open File dialog box.


Coding an Interface

The graphical interface for your Picture Viewer program is now complete, so click the pushpin in the title bar of the toolbox to close it. Now, you have to write code for the program to be capable of performing actions. C# is an event-driven language, which means that code is executed in response to events. These events may come from users, such as a user clicking a button, or from Windows itself (see Hour 4, "Understanding Events," for a complete explanation of events). Currently, your application looks nice but it won't do a darn thing. The user can click the Select Picture button, for example, until the cows come home, but nothing will happen because you haven't told the program what to do when the user clicks the button.
You're going to write code to accomplish two tasks. First, you're going to write code that lets the user browse his or her hard drives to locate and select a picture file and then display the file in the picture box (this sounds a lot harder than it is). Second, you're going to add code to the Quit button that shuts down the program when the user clicks the button.

Letting a User Browse for a File

The first bit of code you're going to write will allow the user to browse his or her hard drives, select a file, and then show the selected picture in the PictureBox control. This code will execute when the user clicks the Select Picture button; therefore, it's added to the Click event of that button (you'll learn all about events in later hours). When you double-click a control on a form in Design view, the default event for that control is created and displayed in a code window. The default event for a Button control is its Click event, which makes sense because clicking a button is its most common purpose. Double-click the Select Picture button now to access its Click event in the code window (see Figure 1.10).
01fig10.jpg Figure 1.10 You will write all code in a window such as this.
It's very important that you get in the habit of commenting your code, so the first line you're going to enter is a comment. Beginning a statement with the characters // designates the statement as a comment; the compiler won't do anything with the statement, so you can enter whatever text you want after the double slashes. Type the following statement exactly as it appears and press the Enter key at the end of the line.
// Show the open file dialog box.
The next statement you'll enter triggers a method of the OpenFileDialog control that you added to the form. You'll learn all about methods in Hour 3, "Understanding Objects and Collections." For now, think of a method as a mechanism to make a control take action. The ShowDialog method tells the control to show its Open dialog box and let the user select a file. The ShowDialog method returns a value that indicates its success or failure, which we are then comparing to a predefined result (DialogResult.OK). Don't worry too much about what is happening here, because you'll be learning the details of this in later hours. In a nutshell, the ShowDialog method is called to let a user browse for a file, and if the user selects a file, more code gets executed. Of course, there is a lot more to using the OpenFileDialog control than I present in this basic example, but this simple statement gets the job done. Enter the following if statement followed by an open brace:
if (ofdSelectPicture.ShowDialog() == DialogResult.OK)
 {
Time for another comment. Enter this statement and remember to press Enter at the end of each code line.
// Load the picture into the picture box.
You're now going to enter the next line of code. This statement, which appears within the if construct, is the line of code that actually displays the picture in the picture box. (If you're itching to know more about graphics, take a look at Hour 10, "Drawing and Printing.")
Enter the following statement:
picShowPicture.Image = Image.FromFile(ofdSelectPicture.FileName);
In addition to displaying the selected picture, your program is going to display the path and filename of the picture in the title bar. When you first created the form, you changed the Text property of the form using the Properties window. To create dynamic applications, properties need to be constantly adjusted at runtime, and this is done using code. Enter the following three lines of code:
// Show the name of the file in the form's caption.
this.Text = String.Concat("Picture Viewer (" + ofdSelectPicture.FileName + ")");
}

Checking Your Program Entry Point

All C# programs must contain an entry point. The Main() method is the entry point. In this sample you need to change the reference from Form1 to fclsViewer (this is necessary because we renamed the form earlier) . This statement will invoke the constructor on the form. C++ programmers will be familiar with the Main() entry point method, but they should take notice of the capitalization of Main. We will talk a bit more about the program entry point later in the book.
To update the entry point in this sample, press Ctrl+F to open the Find window, enter Form1, and click Find Next. Close the Find window and replace the text Form1 with fclsViewer. The updated statement should now read:
Application.Run(new fclsViewer());
After you've entered all the code, your editor should look like that shown in Figure 1.11.
01fig11.jpg Figure 1.11 Make sure your code exactly matches the code shown here.

Terminating a Program Using Code

The last bit of code you'll write will terminate the application when the user clicks the Quit button. To do this, you'll need to access the Click event handler of the btnQuit button. At the top of the code window are two tabs. The current tab has the text fclsViewer.cs. Next to this is a tab that contains the text fclsViewer.cs [Design]. Click this tab now to switch from Code view to the form designer. If you receive an error when you click the tab, the code you entered is incorrect, and you need to edit it to make it the same as I've presented it. After the form designer is displayed, double-click the Quit button to access its Click event.
Enter the following code in the Quit button's Click event handler:
this.Close();





Running a Project

Your application is now complete. Click the Save All button (it looks like a stack of disks) on the toolbar, and then run your program by pressing F5. You can also run the program by clicking the button on the toolbar that looks like a right-facing triangle and resembles the Play button on a VCR (this button is also found on the Debug menu, and it is called Start). However, learning the keyboard shortcuts will make your development process move along faster. When you run the program, the C# interface changes, and the form you've designed appears floating over the design environment (see Figure 1.12).
01fig12.jpg Figure 1.12 When in Run mode, your program executes the same as it would for an end user.
You're now running your program as though it were a standalone application running on another user's machine; what you see is exactly what someone else would see if they ran the program (without the C# design environment in the background, of course). Click the Select Picture button to display the Select Picture dialog box (see Figure 1.13). Use the dialog box to locate a picture file. When you've found a file, double-click it, or click once to select it and then click Open. The selected picture is then displayed in the PictureBox control, as shown in Figure 1.14.
01fig13.jpg Figure 1.13 The OpenFileDialog control handles all the details of browsing for files. Cool, huh?
01fig14.jpg Figure 1.14 C# makes it easy to display pictures with very little work.




Summary

When you're done playing with the program, click the Quit button and then save your project by clicking Save All on the C# toolbar.
That's it! You've just created a bona fide C# program. You've used the toolbox to build an interface with which users can interact with your program, and you've written code in strategic event handlers to empower your program to do things. These are the basics of application development in C#. Even the most complicated programs are built using this basic approach; you build the interface and add code to make the application do things. Of course, writing code to do things exactly the way you want things done is where the process can get complicated, but you're on your way.
If you take a close look at the organization of the hours in this book, you'll see that I start out by teaching you the C# environment. I then move on to building an interface, and later I teach you all about writing code. This organization is deliberate. You might be a little anxious to jump in and start writing serious code, but writing code is only part of the equation. As you progress through the hours, you'll be building a solid foundation of development skills.
Soon, you'll pay no attention to the man behind the curtain—you'll be that man (or woman)!


Q&A

  1. Can I show bitmaps of file types other than BMP and JPG?
    Yes. The PictureBox supports the display of images with the extensions BMP, JPG, ICO, EMF, WMF, and GIF. The PictureBox can even save images to a file.
  2. Is it possible to show pictures in other controls?
    The PictureBox is the control to use when you are just displaying images. However, many other controls allow you to display pictures as part of the control. For instance, you can display an image on a Button control by setting the button's Image property to a valid picture

    Workshop

    The Workshop is designed to help you anticipate possible questions, review what you've learned, and get you thinking about how to put your knowledge into practice. The answers to the quiz are in Appendix A,"Answers to Quizzes/Exercises."

    Quiz

  3. What type of C# project creates a standard Windows program?
  4. What window is used to change the attributes (location, size, and so on) of a form or control?
  5. How do you access the default event (code) of a control?
  6. What property of a PictureBox do you set to display an image?
  7. What is the default event for a Button control?

Exercise

  1. Change your Picture Viewer program so that the user can also locate and select GIF files. (Hint: Change the Filter property of the OpenFileDialog control.)
  2. Alter the form in your Picture Viewer project so that the buttons are side by side in the lower-right corner of the form, rather than vertically aligned in the upper-right corner.

20101105

mauritius

Cool, kom al stukken verder met de luxe hotel reservatie van justmauritius Benieuwd of dat wat gaat geven aan huwelijksreizen enzo. Hopelijk binnekort boekbaar. :D


-- map{ map{tr|10|# |;print} split//,sprintf"%.8b\n",$_} unpack'C*',unpack'u*',"5`#8<3'X`'#8^-@`<-CPP`#8V/C8`"

Exploring the Mac OS X Firewall

All Unix systems have a firewall. But on the Mac, it's installed by default and you can't turn it off. To keep things simple, and keep users from having to build their own firewall rules, OS X packages the firewall as a sub-menu of Sharing within System Preferences. The benefit of this approach is that the firewall can be tied to services. Turn on Personal Web Sharing, for example, and a new rule appears in the firewall to control access to the service.




Presently, I have Personal Web Sharing turned on in the Services menu. The firewall is turned on. And in the Firewall menu, there's a checkbox to allow access to my web server. Opening a terminal and typing sudo ipfw list allows me to see the actual firewall rules that Mac OS X has created.



02000 allow ip from any to any via lo*

02010 deny ip from 127.0.0.0/8 to any in

02020 deny ip from any to 127.0.0.0/8 in

02030 deny ip from 224.0.0.0/3 to any in

02040 deny tcp from any to 224.0.0.0/3 in

02050 allow tcp from any to any out

02060 allow tcp from any to any established

02070 allow tcp from any to any 80 in

02080 allow tcp from any to any 427 in

12190 deny tcp from any to any

65535 allow ip from any to any

ipfw is the heart of the Macintosh firewall; the listing is the set of rules that Mac OS X built based on the services I wanted to run. Apache runs on port 80 (for http), while port 427 is the service locator protocol. The first column is the rule number, and the rest is the rule itself. I will go into greater detail later. But for the moment, I will turn on Remote Login. A quick glance at the Firewall menu reveals that the Remote Login rules have been turned on. Looking at the output of sudo ipfw list shows how the rules were changed to allow the new service to run.



02000 allow ip from any to any via lo*

02010 deny ip from 127.0.0.0/8 to any in

02020 deny ip from any to 127.0.0.0/8 in

02030 deny ip from 224.0.0.0/3 to any in

02040 deny tcp from any to 224.0.0.0/3 in

02050 allow tcp from any to any out

02060 allow tcp from any to any established

02070 allow tcp from any to any 22 in

02080 allow tcp from any to any 80 in

02090 allow tcp from any to any 427 in

12190 deny tcp from any to any

65535 allow ip from any to any

The rules have been rewritten, and a new rule has been added to handle Remote Login. Remote Login is handled by ssh, which operates over port 22. I will turn the firewall off as a final test before I put everything back the way it was.



65535 allow ip from any to any

So even when we turn the firewall off, it is still running. It's just the rules that have changed. What I'm going to do in this article is explore ipfw to see how I can use it to better secure my Macintosh and learn something of the threats that assail our computers every day. But first, a few words of caution.



Don't Play with Fire

The firewall that comes with the Mac is a good and robust tool and will protect you from many things, and you should have it turned on all the time. Just because we can handcraft rules does not mean that we should. If we get it wrong, we could stop our computer from functioning and create security holes. In this article, we're going to play with the firewall, learn a few things about our Mac, and then just let the System Preferences take care of things (in most cases).



This is one area where a little knowledge can be dangerous. And it's important to remember that after reading this article you will not be an expert on firewalls.



Say Hello to ipfw

To get a feel for what your firewall is having to deal with, you'll get it to log all the decisions that it makes over the course of a few hours. This will show you what's really happening. First, create a file that contains a copy of the rules you're running. Call this file rules.



#!/bin/sh



IPFW='/sbin/ipfw -q'





$IPFW -f flush

$IPFW add 2000 allow ip from any to any via lo*

$IPFW add 2010 deny log ip from 127.0.0.0/8 to any in

$IPFW add 2020 deny log ip from any to 127.0.0.0/8 in

$IPFW add 2030 deny log ip from 224.0.0.0/3 to any in

$IPFW add 2040 deny log tcp from any to 224.0.0.0/3 in

$IPFW add 2050 allow log tcp from any to any out

$IPFW add 2060 allow log tcp from any to any established

$IPFW add 2070 allow log tcp from any to any 22 in

$IPFW add 2080 allow log tcp from any to any 80 in

$IPFW add 2090 allow log tcp from any to any 427 in

$IPFW add 12190 deny log tcp from any to any

These rules are a copy of the rules that Mac OS X generated for Personal Web Sharing and Remote Login with logging turned on. You do not need to enter rule 65535 as this is hard-coded into the firewall and cannot be changed. To run the rules just type in sudo sh rules followed by sudo ipfw list to make sure that they have loaded correctly. The final step is to turn logging on. Despite the rules requiring that the output be logged, this only actually happens when it is turned on with sysctl.



sudo sysctl -w net.inet.ip.fw.verbose=1

This might seem complicated, but it allows us to have logging permanently turned on in our rules, only writing to the log file when we want to. The logging is being written to /var/log/system.log. Logging can then be turned on and off without changing or even reloading the rules. To turn logging off, change the 1 to a 0. Leave this running for a few hours as we do all sorts of things that may generate traffic over the Internet. Just one little note of caution at this point: There will be one line in the log file for each packet processed by the firewall. The log file can get very large very quickly! Remember to come back and turn the logging off before your disk fills up.



Looking at the Log Results

/var/log/system.log now contains a large number of lines—one per packet that was handled by the firewall rules we created. Here is an example:



Nov 9 21:12:18 Peter-Hickmans-Computer kernel: ipfw: 2060

Accept TCP 216.65.98.71:119 192.168.1.100:54609 in via en0

After all the date and time cruft, we come to the action that was recorded, which says that rule number 2060 accepted an inbound TCP connection via the primary Ethernet interface from address 216.65.98.71 on port 119 to my computer (on address 192.168.1.100) port 54609. Port 119 is used to connect to Usenet news servers, and port 54609 was just a random port Mac OS X allocated for my program to make the connection. To make any sense of the 341,310 lines that the firewall logged while I had it turned on, we need a program to summarize the log. Let's call this program checkfw.pl.



#!/usr/bin/perl -w



use strict;

use warnings;



my %connections;



while ( my $line = <> ) {

next unless $line =~ m/ ipfw: /;



$line =~ s/.* ipfw: //g;



my ( $action, $from, $to, $direction )

= ( split( ' ', $line, 7 ) )[ 1, 3, 4, 5 ];



if ( check_address($from) and check_address($to) ) {

my $key = ( $direction eq 'out' ) ?

"$from $to" : "$to $from";

$connections{$action}->{$key}->{$direction}++;

}

}



foreach my $action ( sort keys %connections ) {

report( $action, %{ $connections{$action} } );

}



sub report {

my ( $action, %data ) = @_;



print "$action\n";

printf( "%21s Dir %21s : %8s : %8s\n",

'Inside IP', 'Outside IP', 'In', 'Out' );

print '-' x 69 . "\n";



foreach my $k ( sort keys %data ) {

my ( $inside, $outside ) = split( ' ', $k );



my $direction = '-->';

if ( $data{$k}->{in} ) {

$direction = ( $data{$k}->{out} ) ? '<->' : '<--';

}

printf( "%21s %s %21s : %8d : %8d\n",

$inside,

$direction,

$outside,

$data{$k}->{in}

0,

$data{$k}->{out}

0 );

}

print "\n";

}



##

## Filter the broken lines in the log

##



sub check_address {

my $text = shift;



# There should only be 1 colon

my $count = $text =~ tr/://;

return undef if $count != 1;



# There should only be three .s

$count = $text =~ tr/.//;

return undef if $count != 3;



my ( $ip, $port ) = split( ':', $text );



# Is the port number sensible

return undef if $port < 1 or $port > 65535;



# Are the address digits sensible

foreach my $x ( split( '\.', $ip ) ) {

return undef if $x < 0 or $x > 255;

}



# All is fine

return 1;

}

When run from the command line with the system.log file for input, it reads all the lines related to the firewall and extracts the action (Accept or Deny), from address, to address, and direction from the rule, then builds up a hash to summarize the data. The rules are always expressed as "from address" followed by "to address," so we need to switch them around so that packets going from B to A inbound are correctly paired with lines for A to B outbound. The check_address function is to weed out the few lines that logging seems to screw up every now and then. Here's an edited sample of the output. Let's first look at the traffic we accepted:



Accept

Inside IP Dir Outside IP : In : Out

------------------------------------------------------------

192.168.1.100:22 <-> 192.168.1.1:1059 : 80 : 81

192.168.1.100:45632 <-> 66.98.246.15:80 : 1 : 1

192.168.1.100:54609 <-> 216.65.98.71:119 : 19768 : 13114

192.168.1.100:54788 <-> 216.65.98.71:119 : 15 : 17

192.168.1.100:54789 <-> 216.65.98.71:119 : 15 : 14

192.168.1.100:54790 <-> 216.65.98.71:119 : 24924 : 16792

192.168.1.100:54799 <-> 62.253.162.50:110 : 89 : 82

192.168.1.100:80 <-> 210.246.12.35:10611 : 11 : 6

192.168.1.100:80 <-> 210.246.12.35:11823 : 11 : 10

First, an assumption: Any port number that is four or less digits long is a legitimate port. If it is five digits long, then it was just a port allocated to the process that initiated the connection. This is not always the case but it is a very useful rule of thumb.



The first line is a Remote Login connection (ssh on port 22) to my computer, and the next is a connection to a web site (http on port 80) from my computer. The next four are Usenet connections (nntp on port 119) from my computer followed by a connection from my computer to my ISP's mail server (pop3 on port 110). The next two are connections to the web server on my computer by another computer.



If you see a port number and are not sure what it is used by, look in /etc/services where most of the legitimate port numbers are listed. If you can't find it there or feel that you are not using the service, then Google for "port xxxx". Now let's look at the traffic we rejected:





Deny

Inside IP Dir Outside IP : In : Out

------------------------------------------------------------

192.168.1.100:1023 <-- 218.23.26.94:2385 : 1 : 0

192.168.1.100:1025 <-- 80.13.205.45:3369 : 1 : 0

192.168.1.100:1080 <-- 67.150.225.61:80 : 1 : 0

192.168.1.100:21 <-- 172.210.114.241:4535 : 2 : 0

192.168.1.100:25 <-- 222.156.17.50:2304 : 2 : 0

192.168.1.100:2745 <-- 80.108.169.225:1248 : 3 : 0

192.168.1.100:3127 <-- 24.48.194.98:4609 : 3 : 0

192.168.1.100:4000 <-- 159.226.150.135:1505 : 2 : 0

192.168.1.100:4899 <-- 80.200.148.8:4937 : 1 : 0

192.168.1.100:5554 <-- 200.28.99.6:4257 : 1 : 0

192.168.1.100:6112 <-- 211.138.113.23:57949 : 2 : 0

192.168.1.100:9898 <-- 218.16.83.117:3700 : 1 : 0

Related Reading





Essential Mac OS X Panther Server Administration

Integrating Mac OS X Server into Heterogeneous Networks

By Michael Bartosh, Ryan Faas



As these are all denied packets we are only interested in the port number that they were trying to connect to. Let's go over them:



1023

The Sasser worm runs an FTP server on port 1023 of infected machines. 218.23.26.94 is scanning for unpatched Windows machines still infected by the Sasser worm.

1025

Officially the port used by blackjack servers but also used by a backdoor trojan called PWSteal.ABCHlp. Again, I am being scanned by a computer looking for a backdoor.

1080

Officially used by the SOCKS proxy server. 67.150.225.61 is scanning me, hoping to find a proxy server that it can use to cover its tracks with.

21

At last a legitimate port, FTP. Here I am being scanned to see if I am running an FTP server that can be hacked by someone wanting somewhere to store some files or a place from which to run a warez site. I don't run an FTP server.

25

Another legitimate port, this time SMTP. This is someone looking for an open mail server to send spam through.

2745

Officially the port used by the urbisnet service but more commonly a backdoor installed by the W32.Beagle.E@mm worm.

You get the picture. It just goes on and on. Despite being immune to all these WinTel worms and viruses, we should note that there are people out there who will notice very quickly if we turn on our own mail or FTP servers. The same scripts that probe your computer for these services are designed to exploit them the moment they get a positive result. This is why we run a firewall and why we don't run unnecessary services.



Writing the ipfw Log Lines to a Different File

The system.log file is a general dumping ground for all log messages, but it has the facility to write specific messages to separate files. In this case, we're going to write the log lines from ipfw into /var/log/ipfw.log. This file already exists on my system, but at the moment, the /etc/syslogd.conf is not set up to send the messages to it. First, I must edit the /etc/syslogd.conf and add the following to the beginning of the file:



# Exclude ipfw from the main log

!-ipfw

This stops the ipfw log lines from being written to the system.log. Now add the following to the end of the file to get the ipfw log lines written to the correct file:



# Log ipfw to its own log

!ipfw

*.* /var/log/ipfw.log

Now it's time to restart syslogd so that the new configuration is loaded. There are two ways of doing this: the Windows way or the Unix way. Rebooting your computer is the Windows way, so we'll do it the Unix way.



sudo kill -s HUP `cat /var/run/syslog.pid`

The preceding line reads the pid of the existing syslogd process and gets it to reload its configuration file. All that remains is to turn logging on, sudo sysctl -w net.inet.ip.fw.verbose=1, generate some traffic, and look at the contents of the /var/log/ipfw.log file. No lines are being written to the system.log file any more. The main reason for this is that the ipfw logging generates so many lines in the system.log file that it makes finding other, non ipfw, messages much harder.



Writing Your Own Rules

Each packet that wants to pass through the firewall, in or out, is checked against the rules in the order in which they are numbered. Once a packet matches a rule, the assigned action is taken, and the next packet is processed. This is why rule 65535 is hard-coded into the firewall; it will match anything that does not match any other rule. Let's walk through the rules we created earlier.



02000 allow ip from any to any via lo*

The first rule allows any ip packet to any address via the loopback interface. The computer makes use of the loopback interface to talk to itself. Trust me when I say that this is useful.



02010 deny ip from 127.0.0.0/8 to any in

02020 deny ip from any to 127.0.0.0/8 in

02030 deny ip from 224.0.0.0/3 to any in

02040 deny tcp from any to 224.0.0.0/3 in

These rules, and others like them, are there to stop packets with spoofed IP addresses from entering. A more comprehensive set of rules would ban all private IP ranges. The anti-spoofing rules are placed here to stop any packets before they get to the rules that might let them in. If we wanted to bar known bad addresses, this would be the place to do it.



02050 allow tcp from any to any out

02060 allow tcp from any to any established

Here we allow any outbound packets through and follow this up by allowing any previously established connections back in. The firewall is "state-full"—that is to say it doesn't just process a packet and forget about it as it moves onto the next one. It remembers that it allowed a connection from my computer to my ISP's mail server and therefore can identify incoming packets as being part of the same connection and allow then back in without a whole host of new rules.



02070 allow tcp from any to any 22 in

02080 allow tcp from any to any 80 in

02090 allow tcp from any to any 427 in

This rule allows any inbound packet to the ports of the services that we are running in. This leaves just one more rule.



12190 deny tcp from any to any

This rule denies any tcp packet that has gotten this far.



Let's review. We have thrown out the spoofed addresses, we have allowed all outbound packets and all established inbound connections, and we have allowed inbound packets to the ports of the services we are running. All that is left are inbound packets to ports we have not allowed. It's a good thing we have stopped them here as rule 65535 would have let them in!



A quick overview of the rule set:



Allow loopback.

Deny spoofing and people we don't like.

Allow outbound connections.

Allow established connections.

Allow specific inbound connections.

Deny everything else.

All rules have the same basic structure, and a lot can be achieved with the simplest of rules. The basic shape of a rule, more information on which can be found with man ipfw, is quite simple:



[number] action [log] proto from src to dst [interface-spec]

If a rule is given without a number, the next number in sequence is taken. If a number is given, the rule will be positioned among the existing rules. If a rule with that number already exists, then the new rule will be added after the old one, and you will have two rules with the same number. The action can take many values, but for now we're only interested in allow and deny.



Allow will allow any matching packet to pass through the firewall, and deny will just drop them onto the floor.



The optional log parameter will write a line to the logfile for each packet that matched the rule. Lines are only written to the logfile if the system variable net.inet.ip.fw.verbose is set to 1. So we don't have to change the rules when we want to turn logging on and off.



The protocol is the type of packet. The only ones we are concerned with are tcp or ip (which is another way of saying all of them). As a rule of thumb all the protocols are layered over ip, and the most common one we encounter is tcp, with icmp and udp after that.



If you look in /etc/protocols you will see that there are a large number of protocols, most of which we will never encounter outside of this file. Most traffic is tcp, and our rules concentrate on this unless we are blocking something wholesale, in which case we use ip to mean any protocol. But a point of caution: In our "Deny everything else" rule, 12190, we only deny the tcp packets; changing this to deny ip packets may stop your computer from working as many behind-the-scene services still need to get through, such as DNS.



The src and dst are the source and destination addresses that can be defined as either:



any - any ip address

a specific ip address, 207.68.172.246, or hostname, msn.com

a netmask, 207.68.128.0/18 or 1.2.3.4:255.255.240.0

The address can be prefixed by not. Additionally, the address can be followed by a list of port numbers or service names (22 or ssh). For example, the following rules allow FTP connections:



allow tcp from any to any 20-21 in

allow tcp from any 20,21 to any 1024-65535 in

The two rules read:



Allow in any inbound tcp packets to ports 20 and 21 (ftp-data and ftp).

Allow in any inbound tcp packets coming from ports 20 or 21 that are trying to connect to ports 1024 to 65536.

The final element of the rule is the interface-spec. For simple rules, in and out are sufficient and, if omitted, the default is to allow both in and out. When added to a rule they limit the action of the rule to check only the inbound or outbound packets. The interface-spec allows much more control than we are showing here, for example, a rule about being bound to particular interfaces such as an Airport card rather then the normal RJ45 socket.



If we run ifconfig -l, we will get a list of interfaces that are available on our computer. Mine lists six, even though only three are active. The rules we are using will apply to any packet passing through any valid interface.



Our Own Startup Script

The statement "It's not possible to override the firewall built into Mac OS X" isn't entirely true. We could go in and hack around with the kext files, but this is more work than we really need to undertake. What we can do is create our own startup script that runs after the existing firewall to implement our rules. We need to create a directory called /Library/StartupItems/Firewall and include in it two files. The first is a generic startup script called Firewall.



#!/bin/sh



##

# Firewall

##



. /etc/rc.common



StartService ()

{

if [ "${FIREWALL:=-NO-}" = "-YES-" ]

then

ConsoleMessage "Starting Firewall"

sh /etc/rc.firewall > /dev/null

fi

}



StopService ()

{

ConsoleMessage "Stopping Firewall"

/sbin/ipfw -f -q flush

}



RestartService ()

{

StopService

StartService

}



RunService "$1"

Additionally, we require a StartupParameters.plist file to tell the system when to start our script.



{

Description = "Firewall";

Provides = ("Firewall");

Requires = ("NetworkExtensions","Resolver");

OrderPreference = "Late";

Messages =

{

start = "Starting firewall";

stop = "Stopping firewall";

};

}

The real work is undertaken by the /etc/rc.firewall script where the actual calls to ipfw are made. For a moment, let's just look at the Firewall script. The service will only start if the environment variable FIREWALL is set to YES. The advantage is that if FIREWALL is undefined, it will default to NO. This allows us to try out new firewall rules by running the /etc/rc.firewall script by hand. But if we have to reboot our computer, our rules will not be automatically loaded until we add the line FIREWALL=-YES- to the /etc/hostconfig file. This is a useful safety net when we are developing our own rules. Once we run our own rules, the firewall tab under services will not be usable until we run sudo ipfw flush to remove our rules.



Finally, we need to fill in /etc/rc.firewall. A copy of rules from earlier will do the job. With the changes made to the /etc/hostconfig file, our custom-made firewall rules will be loaded as part of the normal boot sequence. We now know nearly all we need know to play with our own rules.



How to Test Your Firewall

To test your rules, you need a few resources on hand. First, and most important, you should be working at your Macintosh. If you manage to create a set of rules that stops you from accessing the Internet, you will still be able to open up a terminal, take down the rules, and reestablish your connections. Failing that, you can at least get to the reboot switch. If you are tempted, as I have been, to ssh into your computer from work and make a couple safe changes, you'll discover that you've locked yourself out and will have to wait until you get home before you can fix anything.



Second, you will need access to a second computer that is outside your network. My Macintosh is plugged into a router and exposed as a DMZ host. I can plug my laptop into the same router and access the services on my Macintosh as any other computer would. This allows me to check that the services that I think I am exposing are in fact available.



This second computer also allows us to run nmap, our third resource. nmap is a port-scanning tool with a considerable pedigree. We are using it here to establish which ports are visible and accessible to the outside world. We know what services we intended to be available, but it can't do any harm to check.



$ sudo nmap -T3 -vv -sS -p 1-65535 -P0 example.com



Starting nmap 3.55 ( http://www.insecure.org/nmap/ ) at

2004-12-11 16:12 GMT

Host example.com (x.x.x.x) appears to be up ... good.

Initiating SYN Stealth Scan against example.com (x.x.x.x) at

16:12

Adding open port 80/tcp

Adding open port 22/tcp

The SYN Stealth Scan took 3127 seconds to scan 65535 ports.

Interesting ports on example.com (x.x.x.x):

(The 65532 ports scanned but not shown below are in state:

filtered)

PORT STATE SERVICE

22/tcp open ssh

80/tcp open http

427/tcp closed svrloc



nmap run completed -- 1 IP address (1 host up) scanned in

3128.366 seconds

The only port numbers that turned up were the ones we set up, and port 427 is closed to the outside world. Everything is looking good. Nmap is a powerful tool with many, varied options and is a useful program to master.



Why Would You Write Your Own Rules?

Given that the firewall that comes with the Macintosh does such a good job and is well integrated with the services that you can run, why would you want to write your own rules? If you have a lone Macintosh that connects to the Internet via an Ethernet cable, then you really don't need to write your own rules. However, if your Macintosh is part of a small network, you may well have services that you only want local machines to connect to. This is the situation I have where I allow remote control of my Macintosh via VNC from local machines but do not want anyone else to know that I even run the service, let alone have access to it.



Playing with a firewall can be quite scary, especially when you see what is attacking you for every moment that you are connected to the Internet. Your most prudent course of action at this point is to remove any custom rules that you have written and let the Sharing Control Panel take care of things. It was doing a perfectly good job before you knew what it was dealing with and will continue to do so going forward.



Peter Hickman is currently working as a programmer for Semantico, which specializes in online reference works and Access Control Systems. When not programming or reading about programming he can be found sleeping.





--------------------------------------------------------------------------------



Return to MacDevCenter.com.









Comments on this article



Showing messages 1 through 38 of 38.



running the pearl script

2007-08-30 20:22:53 thxueb [View]





when I tried to run the pearl script nothing happened. I was brought immediately to the terminal prompt with no output or result. I tried:

/...usr/local/bin/myScripts/checkfw.pl /var/log/system.log then I tried perl checkfw.pl /var/log/ipfw.logthen I changed #!/usr/bin/perl -w to #!/usr/bin/env perl -w and did perl /...usr/local/bin/myScripts/checkfw.pl /var/log/system.log all (and a few other variations) failed. I gave the checkfw.pl script execute privileges and i am certain it is in my path cause I see the path when I type env in the terminal.



How about opening a single nonstandard port

2006-10-11 17:42:47 TomEM [View]





I suspect my problem is pretty common. My ISP blocks Port 80 so I'm using another port for http traffic, specifying that in the URL. To run the firewall, I need to open up that extra port. Isn't there some easy to simply add another line to the rules in the part where the services are opened up? Or do I have to completely override the system preferences.



Thanks for any help. It makes a difference between running and not running the firewall...

StartupItems troubleshooting

2006-04-20 13:40:37 iamstein [View]





Hi, I followed the above directions for creating my custom firewall. I did the following:



1) Created a /System/Libraries/Firewall directory

2) Copyied and pasted the text from this website into a Firewall file and a StartupParameters.plist file in that subdirectory

3) Added a line to /etc/hostconfig that says:

FIREWALL='-YES-'



And yet, when I restart my computer, it's still using the same old firewall. Got any ideas?



Thanks, Andy

StartupItems troubleshooting

2006-04-21 10:55:45 peterhickman [View]





You have created the wrong directory, you need to create /Library/StartupItems/Firewall/ It is this directory, /Library/StartupItems/, that OSX looks for when looking for items to run at startup.



Otherwise the rest looks fine.



As I understand it from other people the /Library/StartupItems/ directory may not exist by default. It was so long ago that I can no longer remember if I created it or it was there all along. Here are the permissions from my machine:



drwxr-xr-x root wheel /Library/StartupItems/

drwxr-xr-x root wheel /Library/StartupItems/Firewall/



As a note, never do anything in the /System directory.



StartupItems troubleshooting

2006-04-21 08:24:14 iamstein [View]





Here's a little more info. I changed the name from Firewall to Firewall2, just to see what happened.



bacchus:~ root# /sbin/SystemStarter start Firewall2

Welcome to Macintosh.

Initializing network

Loading Shared IP extension

kextload: extension /System/Library/Extensions/SharedIP.kext appears to be valid

kextload: loading extension /System/Library/Extensions/SharedIP.kext

kextload: sending 1 personality to the kernel

kextload: extension /System/Library/Extensions/SharedIP.kext is already loaded

Loading IP Firewall extension

kextload: extension /System/Library/Extensions/IPFirewall.kext appears to be valid

kextload: loading extension /System/Library/Extensions/IPFirewall.kext

kextload: sending 1 personality to the kernel

kextload: extension /System/Library/Extensions/IPFirewall.kext is already loaded

Exec failed for item /System/Library/StartupItems/Firewall2: Permission denied

Firewall2 (396) did not complete successfully.

The following StartupItems failed to properly start:

/System/Library/StartupItems/Firewall2 - execution of Startup script failed

Startup complete.

Hangup



StartupItems troubleshooting

2006-04-20 13:58:33 iamstein [View]





Oh, yes, I also, of course created a /etc/rc.firewall file and at the terminal window, if



Furthermore, if I type:

sudo /etc/rc.firewall



It runs just fine

Usable on Mac OS X Server?

2005-04-10 00:25:10 lowrezz [View]





I work in a large Windows organization with a growning population of 8 Xserve systems.



Lately I've been experimenting with the firewall in the server manager and it's frustrating. Your article has provided great insight to refining my issues, but I don't know if the syntax

is applicable to the OS X Server 10.3.8 SW.

Adding firewall rules for NAT + question...

2005-04-06 11:13:06 efixler [View]





Thanks for this great article! I use my 10.3 (client) box as a DHCP/NAT gateway, and was looking for a way to add rules that would let clients on the internal networks comminucate with the outside world freely, without me having to open ports in the internal firewall. I modified your startup script like so:



StartService () {

...

/sbin/ipfw add 3000 allow ip from 192.168.0.0/24 to any in

/sbin/ipfw add 3010 allow ip from 10.0.2.0/24 to any in

fi

}



StopService ()

{

ConsoleMessage "Stopping Additional Firewall Rules"

/sbin/ipfw delete 3000

/sbin/ipfw delete 3010

}





When I run these rules, everything seems to work as intended. However, when the rules are in effect, System Preferences will no longer let me edit the built-in Firewall settings panel, as it can detect that 'other firewall software' is in use.



Anyone have any idea how it detects this; I'd like to circumvent this detection (so that I can edit the general rules while the internal network rules remain in effect)



thanks!

eric



Adding firewall rules for NAT + question...

2007-07-16 07:42:09 variac [View]





hi eric, were u able to find a solution to your problem. coz m facing the same problem

Adding firewall rules for NAT + question...

2007-07-16 07:41:54 variac [View]





hi eric,



were u able to find a solution to your problem. coz m facing the same problem

Mac firewall

2005-03-26 17:01:35 rspage [View]





What if I am using a router to network 2 Macs and 1 PC? The router has its own firewall. I have the Mac firewall turned off. Is this correct? Also, since I am using the routers firewall can I still turn on SSH and the other items in the Sharing pane of system preferences or would I need to turn them on using the router firewall?

logging

2005-03-25 06:26:35 Porcustal [View]





I can't get this logging to work at all. Nothing happens in my System.log when i start the logging with sudo sysctl -w net.inet.ip.fw.verbose=1



I just get the messege logging the use of sudo...



I did get somethings to log to my ipfw.log, but none was ipfw :/ this is prob because you have it as *.* in syslog.conf, might be better to do ipfw.* or ipfw.notice but of course it wouldn't work for me in the first place. I'm using 10.2.8 Jaguar still, could this be why??

another correction

2005-03-25 05:47:20 2002switcher [View]





The section Our Own Startup Script has the wrong path for creating the Firewall directory. It should be:



/System/Library/StartupItems/Firewall





another correction

2005-03-29 13:55:01 efixler [View]





Actually, the path in the article is correct. /Library/StartupItems is where you you put your own StartupItems. /System is only for stuff shipped by Apple.

perl-scripts with an input?

2005-03-24 12:14:43 Wikinator [View]





How can I do the perl-scripts with an input?

Am I right to copy the source of these scripts into a new file?

What about SMB?

2005-03-19 18:51:01 jace [View]





I've found that the firewall's default rule for SMB, opening just port 139, isn't adequate. With the firewall on, Windows or Linux users can't access my machine, which is unfortunate because SMB is the only filesharing protocol that works across platforms and usually comes pre-installed.



Do you know what other ports I need to open?

What about SMB?

2005-03-21 05:35:07 peterhickman [View]





If you know for sure that Windows and Linux users can access the SMB shares when the firewall is not running then it is a problem with the firewall. I don't run SMB shares but here is how I would approach the problem.



Find a Windows or Linux machine that wants to access the share and get it's ip address, say x.x.x.x. Then create a rule to allow full access for this address



ipfw add ????? allow log ip from x.x.x.x to any in



Remember to place this rule nice and early in the list (the rule number is at ?????). Now turn logging on and try to access the share (which should succeed). Having done that turn off logging and examine the log file for all references to x.x.x.x This will show you the ports and protocols (tcp, udp, icmp) that were used with the connection. You should be able to work from that. Remember the legitimate ports are usually less than five digits.



Then remove rule ?????.



Firewalls and Internet Sharing

2005-03-17 12:03:14 makalumatt [View]





It seems that if you enable "Internet Sharing" on a Mac, then that particula Mac can't have its firewall enabled, otherwise the other Macs on the network (those sharing the internet access) won't properly be able to access network services. Has anyone else experienced that?

Firewalls and Internet Sharing

2005-03-18 05:23:46 peterhickman [View]





The problem is that when you do internet sharing OS X does not create any special rules for the computers who are accessing the internet through the master computer. The rules for inbound packets are the same for access to your computer from the outside as they are for the sharees. I have found that as I only expose http and ssh then computers that are accessing the internet via my computer can only access http and ssh. What I do is add an extra rule to allow https access to my computer from the airport card so that my wife can access the shopping sites.



allow tcp from any to any https in via en1



Depending on how you feel about the people connecting to your computer you would need to set up a rule for each protocol that they are allowed to use or add a generic rule like



allow tcp from any to any in via en1



but this way you are putting a lot of trust in the users of your system that they will not use your machine as a gateway to spam from.



syslog.conf

2005-03-17 09:56:30 adrianmayo [View]





I was interested to see the use of

!-ipfw

and

!ipfw



I cannot find information on the '!' command in 'man 5 syslog.conf'. I can guess what is happening, but can you point me in the direction of this 'missing' syslog infomation.



Thanks.



syslog.conf

2005-03-30 22:54:45 johnwilkins [View]





Here's the man page for syslog.conf from FreeBSD 4.11 (the one OS X is based on). It gives a full description of the "program specififcation" ( !program_name and !-program_name).



http://www.freebsd.org/cgi/man.cgi?query=syslog.conf&apropos=0&sektion=0&manpath=FreeBSD+4.11-stable&format=html

syslog.conf

2005-03-18 01:08:22 peterhickman [View]





Strange I've never noticed that before. It isn't in the man page. It is mentioned in my redhat man page as an extension to the origonal BSD source. Seems to be working as expected, perhaps the OS X man pages need revising.





This syslogd(8) has a syntax extension to the original BSD source, that makes its use more intuitively. You may precede every prior-

ity with an equation sign (``='') to specify only this single priority and not any of the above. You may also (both is valid, too)

precede the priority with an exclamation mark (``!'') to ignore all that priorities, either exact this one or this and any higher pri-

ority. If you use both extensions than the exclamation mark must occur before the equation sign, just use it intuitively.



ftp rules?

2005-03-16 13:49:39 oefe [View]





For ftp FTP connections, the first rule seems to be clear:

allow tcp from any to any 20-21 in

This lets clients connect to the ftp port (21) and to ftp-data(20).



But what is the second rule supposed to be?

allow tcp from any 20,21 to any 1024-65535 in

This would allow clients to access any (unprivileged) port as long as they are connecting from port 20 or 21.



Is this somehow supposed to support passive ftp? But clients normally can't (and won't) use the privileged ports.



Indeed, with the firewall active, I can connect to the ftp server, but I can't up/download files or even get a directory listing.



How do I configure ipfw correctly for passive ftp? Or can I tell ftpd to use port 20 for the data connection?

ftp rules?

2005-03-22 20:23:03 coolmacguy [View]





That second line is indeed erroneous. The client is definitely not restricted to connecting from only port 20 or 21 when it initiates the second connection. According to my logs both Dreamweaver and Transmit use a port in the high 60000 range.

ftp rules?

2005-03-16 15:05:43 peterhickman [View]





The two rules that I gave for the firewall are just a copy of the rules that OS X creates when you turn on FTP and have a firewall running.



If you drop your firewall can you connect and use the FTP server and access it as you would expect? If not then the problem lies with the configuration of the FTP server and not the firewall.



Must confess I do not use the FTP server if I can help it, prefering SFTP.



ftp rules?

2005-05-06 01:16:43 gsyoungblood [View]





I've just run into this problem today.



I can confirm the problem as reported above.



With Mac OS X (10.3.9) firewall on, remote clients are not able to use passive. With the firewall stopped, FTP is fully functional, including passive.



This has been giving me grief, to say the least. Fortunately, my machine is behind a firewall already, so turning the Mac firewall off is not opening me up to problems externally. I'd still rather have it enabled.



If I figure out the solution tonight, I'll post a reply.

ftp rules?

2005-05-06 02:54:25 gsyoungblood [View]





The problem is quite simple. The FTP Access firewall rules only support Active FTP, not Passive. At least that is what it appears to be. For a pretty reasonable description and comparison of Active and Passive FTP, see Active FTP vs. Passive FTP, a Definitive Explanation [slacksite.com].



The short version is this: Passive FTP has a second connection from the client to a specified port on the server, a port that is not port 20 or 21. For this reason, the standard firewall rules for FTP Access do not permit Passive FTP.



I did not look at the configuration options in detail for the FTP server provided by Apple, but I do not recall seeing anyplace to restrict the passive FTP ports to a set range. This is important, otherwise you are going to be opening your firewall for every port over 1024, and that's not a good idea.



In general, the goal is to open the least number of ports necessary to support what you want to run.



Here is how I solved the problem and made Passive FTP work.



First, I decided to use a different FTP server. I decided to try PureFTPd Manager. After downloading and installing it, I ran it and went into Preferences. There, it lets you specify a range of ports to use for Passive FTP. Choose something you are comfortable with, for example 9900 to 9999 (for a small FTP server).



Next, go to System Preferences, and make sure FTP Access is checked in both Services and Firewall.



Finally, under Firewall, click New, to add a new firewall rule. Select Other from the drop down list, and enter the range of ports you decided to use, 9900-9999 using the previous example. Then, enter a description, such as FTP Access (Passive). When you click OK, the rule should be added and activated.



If everything is running and setup properly, Passive FTP should now be working.





Hostname in rules?

2005-03-16 10:52:06 Brad_Fleming [View]





I have an OSX machine that serves in a dynamic IP environment. I would like to add a rule requiring all ssh connections to originate from a *.house.domain.edu IP. The problem is that users can easily get an IP from several different subnets because they move from one building to another fairly often (what with meetings and wireless). Is this possible? If so, can somebody please help me with the syntax used? Thanks in advance.

Hostname in rules?

2005-03-17 01:22:33 peterhickman [View]





While you can have rules like



allow tcp from fred.house.domain.edu to any 22 in



I'm not sure that you could use a * instead of the fred. You would probably have to iterate all possible values for *. The only way to find out is to try it.



Do you have the netmask for *.house.domain.edu, you could use that.



allow tcp from xxx.xxx.0.0/24 to any 22 in



Is there another way of approaching this, could you just only allow the various private address ranges in and exclude the rest. Assuming that the *.house.domain.edu are all private.



Slight error

2005-03-16 09:18:48 finkga [View]





The article states:





02050 allow tcp from any to any out

02060 allow tcp from any to any established





> Here we allow any outbound packets through and

> follow this up by allowing any previously

> established connections back in. The firewall

> is "state-full"—that is to say it doesn't just

> process a packet and forget about it as it

> moves onto the next one. It remembers that it

> allowed a connection from my computer to my

> ISP's mail server and therefore can identify

> incoming packets as being part of the same

> connection and allow then back in without a

> whole host of new rules.







This is not an example of stateful processing. The first rule allows any outgoing tcp connection it doesn't care whether it is a new connection or an established one. To restrict the outbound rule to new connections only, you must append the word "setup" to this rule. This matches only tcp packets with the SYN bit set.



The second rule allows only tcp packets without the SYN bit set to pass. With the two rules entered as listed, someone with nmap can still use ACK packets (pretending to be part of an existing connection) to scan your machine.



If you really want stateful monitoring of connections you need to use the check-state rule and the keep-state actions. For instance, adding the rules:





add 2050 check-state

add 2060 allow tcp from me to any out setup keep-state





will make the firewall stateful. The first rule says, "match the packets against any of the dynamic rules I've made so far." If none of these matches, the next rule comes into play. Rule 2060 says, "if this is a new outgoing connection initiated by me, make a dynamic rule that will allow any traffic from this connection through."



With these modified rules, incoming ACK packets and other beasts trying to pretend they are part of an existing connection will not match and will be turned away at the door. Check out the ipfw man page for more details.



Hope this isn't as confusing as it sounds.



-- Glenn



Slight error

2005-03-17 01:01:12 peterhickman [View]





You are correct, I am using the term 'state-full' incorrectly here. What I wanted to get across was that ipfw did have a memory of previous connections and could recognise a packet as belonging to an already established / permitted connection.



Having said that 'state-full' does have a technical meaning in regards to firewalls an missusing it isn't going to help anybody.



Thanks again for the correction.



Slight error

2006-02-04 15:51:27 sumbach [View]





This still isn't quite right. Using your rules, ipfw doesn't have any memory at all--it's using the TCP flags to determine whether the connection is established or not.



A stateful ipfw ruleset will always contain at least one rule with the 'check-state' action and at least one rule with the 'keep-state' option. ipfw's "memory" is in the form of dynamic rules.

edit or create?

2005-03-16 04:31:07 Oneida [View]





Nice article. I use the default set of rules, but restricted to certain IPs for ssh, and a high numebered port in the router pointing to the ssh port in my mac.



OK. In "Writing the ipfw Log Lines to a Different File" you edit /etc/syslogd.conf.



My mac with 10.3.8 does not have that file, but it does have /etc/syslog.conf which has lines that define where to log things, such as



mail.* /var/log/mail.log



And others.



Should we create /etc/syslogd.conf or use /etc/syslog.conf instead? And if we have to create it, which permissions should we use?



Thanks



edit or create?

2005-03-16 12:19:19 peterhickman [View]





Sorry that is a typo of mine. As Glen has pointed out in his reply to your question /etc/syslog.conf is the file to use.



Thank you for catching that for me Glen



edit or create?

2005-03-16 10:17:11 finkga [View]





Just use the existing /etc/syslog.conf. But first, I recommend making a backup copy of the file.

-- Glenn

name resolution

2005-07-15 14:58:57 ruy_lopez [View]





Anyone any ideas for adding name resolution to the checkfw.pl script. I think it would be a good enhancement.



All worked flawlessly by the way.



Nice article.

name resolution

2005-07-23 07:05:17 peterhickman [View]





The code to do this, taken from perldoc -f gethostbyaddr, would be something along the lines of this, put



use Socket;



at the top with the other use statements, and then when you are about to print out the address do sothing like the following.



my $iaddr = inet_aton("211.22.171.213");

my $name = gethostbyaddr($iaddr, AF_INET);

print "$name\n";



However I find the raw IP addresses best as I can just drop them into my firewall.



name resolution

2005-07-25 08:35:21 ruy_lopez [View]





Thanks Peter for the push in the right direction. I now post (for any who are interested) the resulting ammendments to achieve name resolution AND ip data for each ipfw.log event. The result (after a bit of hammering) is the inclusion of these lines:



# obviously include: use Socket; at the top, then:



#look for this part of original script.



printf( "%21s %s %21s : %8d : %8d\n",

$inside,

$direction,

$outside,

$data{$k}->{in}

0,

$data{$k}->{out}

0 );



# and in line with the indents apend ( or rather insert after the above ) the following :



my ( $inaddress, $inport ) = split( ':' ,

$inside );

my $iaddr = inet_aton("$inaddress");

my $namein = gethostbyaddr($iaddr,AF_INET);

my ( $outaddress, $outport ) = split( ':' , $outside );

my $oaddr = inet_aton("$outaddress");

my $nameout = gethostbyaddr($oaddr,AF_INET);

if ( defined($namein) ) {

$namein = $namein;

} else {

$namein = "unresolved";

}

if ( defined($nameout) ) {

$nameout = $nameout;

} else {

$nameout = "unresolved";

}

printf( "%21s %s %21s\n",

$namein,

$direction,

$nameout );

print "\n";



# now the original script continues with these lines:



}

print "\n";

}



I warn you that this runs in a rather dirty spluttering manner but should work without errors.



I'm not sure that I'll use it too much but I'm considering using it for daily crontab emailing (I've already changed ipfw from weekly to daily in /etc/periodical), so I get an email of all the addresses and names that ipfw has encountered during the day.



Also, I'm sure the above could be simplified but my perl skills are not yet up to the task.



Tagged Articles

Post to del.icio.us



This article has been tagged:



osxsecuritymacfirewallnetworkosx

Articles that share the tag osx:



Top Ten Mac OS X Tips for Unix Geeks (302 tags)



Automated Backups on Tiger Using rsync (109 tags)



Start Me Up: Writing and Understanding OS X StartupItems (75 tags)



How Does Open Source Software Stack Up on the Mac? (71 tags)



Write Your Own Automator Actions (64 tags)



View All

security

Articles that share the tag security:



Secure RSS Syndication (169 tags)



Google Your Site For Security Vulnerabilities (74 tags)



Building a Desktop Firewall (64 tags)



The Next 50 Years of Computer Security: An Interview with Alan Cox (42 tags)



Protect Yourself from WiFi Snoops (40 tags)



View All

mac

Articles that share the tag mac:



Top Ten Mac OS X Tips for Unix Geeks (300 tags)



Automated Backups on Tiger Using rsync (98 tags)



Getting Things Done with Your Mac (89 tags)



How Does Open Source Software Stack Up on the Mac? (81 tags)



Write Your Own Automator Actions (55 tags)



View All

firewall

Articles that share the tag firewall:



Building a Desktop Firewall (73 tags)



Exploring the Mac OS X Firewall (33 tags)



Using IPFW Rulesets with BSD Firewalls (8 tags)



Feather Linux for Firewalls (4 tags)



Monitoring IPFW Logs (4 tags)



View All

network

Articles that share the tag network:



Untwisting Python Network Programming (67 tags)



Wireless Mesh Networking (52 tags)



Building a Desktop Firewall (24 tags)



VPN on Mac OS X (19 tags)



Demystifying LDAP (19 tags)



View All



Sponsored Resources

Inside Lightroom

Related to this Article

Take Control of Passwords in Mac OS X

October 2010

$10.00 USD





Take Control of PDFpen 5

October 2010

$10.00 USD













©2010, O'Reilly Media, Inc.

(707) 827-7000 / (800) 998-9938

All trademarks and registered trademarks appearing on oreilly.com are the property of their respective owners. About O'Reilly

Academic Solutions

Contacts

Customer Service

Careers

Press Room

Privacy Policy

Terms of Service

Writing for O'Reilly

Community

Authors

Forums

Membership

Newsletters

RSS Feeds

User Groups

More O'Reilly Sites

igniteshow.com

makerfaire.com

makezine.com

craftzine.com

labs.oreilly.com

Partner Sites

InsideRIA

O'Reilly Insights on Forbes.com

20100828

simplest way to make an application bundle using nothing but notepad.

Create a Application Bundle in 3 easy steps ;)

No Xcode needed, just a filebrowser and a texteditor. While poking around with .app dirs I noticed that as soon as I provided a MacOS folder containing something executable named the same as the app, my tiger box happily starts to run it without needing or checking a .plist or anything....

Sweet :) 
here goes ;) 


* in the terminal:
 bash$ mkdir -p MyShinyShellScriptWrapper.app/MacOS  
 bash$ echo -e "#!/bin/bash\necho \$(date) >  ~/Desktop/proofofexecution.txt" \  >MyShinyShellScriptWrapper.app/MacOS/MyShinyShellScriptWrapper 
 bash$ chmod 755 MyShinyShellScriptWrapper.app/MacOS/MyShinyShellScriptWrapper 



* or in the finder:
Open a finder window and create a new folder.  Open it and in it create a MacOS folder, now decide on a name. Create a new (plain) text document in the newly created folder and name it YourProgramName
 Now type these two lines in the textdocument:
#!/bin/bash
echo $(date) > ~/Desktop/proofofexecution.txt
Right! Close the file and save it as YourProgramName without an extension. (eg no .txt or .html or .whatever)
Right click on the file and  select Get Info.  Here you.... pfff, here you DONT find a set permissions to executable.
Anyway, open up a Terminal and type chmod 755 YourProgramName and close it off/ (is this even neccessary?)
Now go 2 levels up in the folder and rename the folder that you created in the beginning to  YourProgramName.app

Now it should've turned into an application with a broken icon. This is good :) Double click the icon to start it up!

Nothing much happened? The script runs in the background and takes a nanosecond to finish so nothing much should happen, but on your Desktop 
You should now see a new file called proofofexecution containing a timestamp.

Shweeet





How to make a shell script into a apple macintosh app application bundle using nothing but common household tools ;-)



dd
Sweet :)

10.4: Remapping keys in Mac OS X 10.4

10.4: Remapping keys in Mac OS X 10.4 

10.4: Remapping keys in Mac OS X 10.4 System 10.4
The Mac OS X 10.4 Keyboard & Mouse preference pane provides a way to remap certain keys. However, the interface doesn't expose the full functionality -- a common problem with Apple software. Note that this guide assumes you'using the bash shell.

Read on to learn...
  • What keys can be remapped without the use of any third–party software?
  • How do I remap those keys?
  • How do I remap the Caps Lock key to the Escape key?


What keys can be remapped without the use of any third–party software? (The following list shows the key name on the left, and that key's value on the right.)
  • None — –1
  • Caps Lock — 0
  • Shift (Left) — 1
  • Control (Left) — 2
  • Option (Left) — 3
  • Command (Left) — 4
  • Keypad 0 — 5
  • Help — 6
  • Shift (Right) — 9
  • Control (Right) — 10
  • Option (Right) — 11
  • Command (Right) — 12
  • Kernel Panic — 16
Be warned that the code 16, when used as the destination of a mapping, actually causes a kernel panic on keypress -- as I've found out the hard way.

How do I remap those keys?
  1. Remap one of the keys available in the Keyboard & Mouse preference pane in order to make the following steps easier.
  2. Locate the hidden property list file used to store the settings. It's in your user's Library/Preferences/ByHost folder, and is named.GlobalPreferences.000d*. I assume there'll be only one such file; you'll need to verify that. From here on, that file and path are referred to as$FILE.
  3. Duplicate the file and convert it to the XML property list format:
    $ cp $FILE ~/keys-binary.plist
    $ plutil -convert xml1 -o ~/keys-xml.plist ~/keys-binary.plist
  4. Open the resulting XML file and locate thecom.apple.keyboard.modifiermapping key. Its value is an array containing several entries, each in turn containingHIDKeyboardModifierMappingSrc and HIDKeyboardModifierMappingDstkeys. The values of those keys are described in the table above. Make the changes you wish to make, and save your work.
  5. Convert the file back to the binary property list format, and put it back in the correct location:
    $ plutil -convert binary1 -o ~/keys-binary.plist ~/keys-xml.plist
    $ cp ~/keys-binary.plist $FILE
  6. Log out and back in to apply changes.
How do I remap the Caps Lock key to the Escape key?

Unfortunately, this will require the use of a third–party program. I used a free trial version of Keyboard Maestro by Stairways Software. First, remap the Caps Lock key to the Help key, following the instructions above. Then, in Keyboard Maestro:
  • Create a new macro.
  • Add a Simulate Keypress action, with an User Keystroke — the Escape key.
  • Add a Hot Key trigger, set to the Help key.
  • In the Preferences section, enable the Launch Engine at Login option. While you're at it, you might also want to disable all other unnecessary features.
An always up–to–date version of this guide can be found on my blog...

20100827

multitail bus error on osx

I tried to install and use multitail this morning.

sudo port install multitail

everything seems to build/install

multitail /opt/local/apache2/logs/access_log /opt/local/apache2/logs/ 
error_log

gives me a "Bus error" - along with 2 processes running tail...

Installs and runs just fine on Panther (just checking)

I can download and build the source in my home directory. That works  
just fine, and runs.

For entertainment value I created /opt/local/etc/multitail.conf (from  
the /opt/local/etc/multitail.conf.new file)

Bus error stopped happening...

Executed in subshell, trap on exit


#!/bin/bash
# --- subshell_trap.sh -------------------------------------------------
# Example script for handling bash errors.  Exit on error.  Trap exit.
# This script is supposed to run in a subshell.
# See also: http://fvue.nl/wiki/Bash:_Error_handling

    # Let shell functions inherit ERR trap.  Same as `set -E'.
set -o errtrace 
    # Trigger error when expanding unset variables.  Same as `set -u'.
set -o nounset
    #  Trap non-normal exit signals: 1/HUP, 2/INT, 3/QUIT, 15/TERM, ERR
    #  NOTE1: - 9/KILL cannot be trapped.
    #+        - 0/EXIT isn't trapped because:
    #+          - with ERR trap defined, trap would be called twice on error
    #+          - with ERR trap defined, syntax errors exit with status 0, not 2
    #  NOTE2: Setting ERR trap does implicit `set -o errexit' or `set -e'.
trap onexit 1 2 3 15 ERR


#--- onexit() -----------------------------------------------------
#  @param $1 integer  (optional) Exit status.  If not set, use `$?'

function onexit() {
    local exit_status=${1:-$?}
    echo Exiting $0 with $exit_status
    exit $exit_status
}



# myscript



    # Allways call `onexit' at end of script
onexit

http://www.gfxcoder.us/wiki/programming/bash


Handy BASH reference (link)

robust script writing (link)

lockfile
lockfile a.lock
#do stuff hererm -f a.lock

date (link)

Spicing up your shell script (link)

parameters (link)

Tutorials

misc (link, link)
functions (link)

timing commands
/usr/bin/time -o outfile -v command # prints verbose stats into outfile from running command

BASH internal variables (link)

for loops (link)
for i in 1 2 3 4 5
do
  echo "Welcome $i times"
done

for i in {1..5}
do
  echo "Welcome $i times"
done

for i in {0..10..2} # skip by 2s, only BASH 4.0+
do
  echo "Welcome $i times"
done

for (( c=1; c<=5; c++ ))
do
  echo "Welcome $c times"
done

for i in 1 2 3 4 5
do
  echo "Welcome $i times"
  if ( condition )
  then
    break
  fi
done
# continue - jumps to beginning of loop with next iteration

for file in /etc/*
do
  if [ "${file}" == "/etc/resolv.conf" ]
  then
    echo "file ${file} found!"
  fi
done

files="$@"
for f in $files
do
  if [ -f ${f} ]
  then
    echo "{f} is a file"
  else
    echo "${f} is not a file"
  fi
done

pausing with read (link)
$ read -p "Press enter to quit..."                   # reads one line
$ read -n 1 -p "Press any key to start backup..."    # reads only one char
$ read -n 1 -s -t 5                                  # reads one char, no echo, 5sec timeout
$ read -n 1 -s key                                   # reads one char, no echo, stores in ${key}

terminate commands after timeout (link)
#!/bin/bash
# License: BSD License
# As Example we start 3 production processes in the background
# always record PID in PRODPID

sleep 50 &
PRODPID[1]=$!

sleep 20 &
PRODPID[2]=$!

# multiple processes in a subshell as example
(sleep 20 ; sleep 10 ; sleep 5)&
PRODPID[3]=$!

export PRODPID

# record own PID
export PID=$$


# define exit function
exit_timeout() {
  echo "Timeout. These processes are not finished:"
  for i in ${PRODPID[@]} ; do
    ps -p $i |grep -v "PID TTY      TIME CMD"
    if [ $? == 0 ] ; then
      # process still alive
      echo "Sending SIGTERM to process $i"
      kill $i
    fi
  done
  # timeout exit
  exit
}

# Handler for signal USR1 for the timer
trap exit_timeout SIGUSR1

# starting timer in subshell. It sends a SIGUSR1 to the father if it timeouts.
export TIMEOUT=30
(sleep $TIMEOUT ; kill -SIGUSR1 $PID) &

# record PID of timer
TPID=$!

# wait for all production processes to finish
wait ${PRODPID[*]}

# Normal exit
echo "All processes ended normal"

# kill timer
kill $TPID
or (link)
runtime=${1:-1m}
mypid=$
cp /Database/Client_db_200802110231.BAK .&
cpid=$!
sleep $runtime
kill -s SIGTERM $cpid
echo "Both processes are terminated".



catching traps (link)
# trap [commands] [traps]
trap "echo Booh!" SIGINT SIGTERM


aoeu
aoeu

20100824

aomk

maybe a raving loony, and even mentally retarded, BUT i really do Avoid at all costs to upload magic to ungrateful fucks like you, just as i did many times in the past to fuck users who are now on AOM, NEO, MT, EXO, and the rest of the copy magic sites




-- map{ map{tr|10|# |;print} split//,sprintf"%.8b\n",$_} unpack'C*',unpack'u*',"5`#8<3'X`'#8^-@`<-CPP`#8V/C8`"

20100813

Dieter Steffman Fonts

Designers



Due to increasing bandwidth charges Dieter decided to remove his fonts from his website. That's why they are hosted here. Special thanks to those font-enthusiasts who located the missing fonts - it seems the collection has been completed :)





-- map{ map{tr|10|# |;print} split//,sprintf"%.8b\n",$_} unpack'C*',unpack'u*',"5`#8<3'X`'#8^-@`<-CPP`#8V/C8`"

20100812

http://code.google.com/webfonts/preview#font-family=Cantarell

http://code.google.com/webfonts/preview#font-family=Cantarell


webfont previewer

lol, found you :)

 http://l.i2p/?i2paddresshelper=Wpu7frtxXSub11MOI~lbH260SUh~xiodPfQiDXdgJ5fdawCHi2dRZVizSvCtEGa6MfMMlxtUFUYNu9-f9YC5l0BCPe0Fqy31ArJZOegkvIXInRRyc0vLpfNHToDjyVdfSYa-ZqT6w2oZzRzqdXd5cw3jYvYURhuBzfksJpKM91tpSK0jOUFxZAp3NAJCEEANoiaqzUuZi1QNJs5yBn1gAIWDrFoVQv21oFdhYBToY18yupRw-pRQDCJZcDY5N8UhgUsdA611LwhTB6uMcdpjuxwoJeVddKFrQLnkPXuKqD83uMYm~XFS04F0B34L2umUEFGipULpWQbOUrngeyhMpm4FE1gme85wdHr7zz8m5~r-tu5mK3a9mn70pkbjQ0sc4~uBvkItfbxs7~aLOpO6tHuDSr4mUNp0PGvVy3KgTVm71HHVZ5RsnVTRCrlpC~kvFBrdHCPv0GkQhexouKwrD0gQ4dxenIWRBMaXqEBJoC-heI5IAShEzSHIGrFmgJ8BAAAA

 http://uhfunkqudthohkjeqdmgmuisoy3we27eo75h37yksojf6ki3zfua.b32.i2p/


http://stats.i2p/cgi-bin/jump.cgi?a=l.i2p


http://stats.i2p/cgi-bin/hostquery.cgi?a=l.i2p

http://stats.i2p/cgi-bin/newhosts.txt

http://l.i2p





-- map{ map{tr|10|# |;print} split//,sprintf"%.8b\n",$_} unpack'C*',unpack'u*',"5`#8<3'X`'#8^-@`<-CPP`#8V/C8`"