TweetFollow Us on Twitter

Packaging Special Payloads with PackageMaker

Volume Number: 24
Issue Number: 10
Column Tag: PackageMaker

Packaging Special Payloads with PackageMaker

Bringing drivers, libraries, and plug-ins to the OS X target

by José R.C. Cruz

Introduction

One task that some developers face is to deliver special payloads such as device drivers, frameworks, and codecs to their users. Unlike applications or files, these payloads must reside in specific locations on the target system. They must have the right settings for permissions, UID, and GID. Some payloads require specific hardware to operate. Some require authentication or a specific post-install action.

In this article, we will explore the issues behind delivering these special payloads. First, we will list each payload and look at how to handle each one. Then, we will learn how to check for specific hardware on the target system. Next, we will build a demo package with three payloads, two of which are special. We will then test this package and study its behavior.

As always, the installer project featured here is available from the MacTech website. To get a copy of the project, go to the following URL.:

ftp.mactech.com/src/mactech/volume24_2008/24.10.sit

The Special Payloads

As stated earlier, special payloads need special handling. To correctly install this payload, first know what its needs are and how to address them. Doing so will help avoid any post-install issues such as system hangs, freezes, or even a kernel panic.

The following are three basic groups of special payloads that you will encounter most. Some payloads do not fit into any these groups, but those are few and far between.

Drivers

The job of a driver is to add or extend system functionality. Drivers in OS X are often in the form of a kernel extension. You can place the driver inside an application bundle or in the directory /System/Library/Extensions. If the latter, prepare each driver as follows.

  • First, set the bundle's UID and GID to root and wheel. Make sure to use the same UID and GID to the bundle's subdirectories and component files.

  • Next, set its permission flags to rwxr-xr-x. Use the same flags for the bundle's subdirectories and executable items. For the component files, however, use the flags rw-r-r-.

Now some drivers work only if the target system has the correct hardware. Others need the system restarted in order to become active. Lastly, since access to /System/Library/Extensions is restricted, users must authenticate the install session.

Libraries

Libraries carry code and data that provide services to various OS X applications. They can come in several formats, with the most common being the framework bundle.

There are several places wherein to store a framework. Choosing which one to use depends on the framework at hand. For most frameworks, use the directory /Library/Frameworks. This location gives all applications access to the framework code. To limit access only to applications that the user owns, use the directory ~/Library/Frameworks. Both directories are public and as such do not need users to authenticate the install session.

For frameworks that provide system-wide services, use /System/Library/Frameworks. For those meant only for in-house or private use, use the location /System/Library/PrivateFrameworks. Both locations, however, will require users to authenticate the install session. Also, Apple reserves the right to modify either location during every OS X upgrade. Make sure to provide a way to backup any custom frameworks in these locations.

Frameworks that go into the /Library or ~/Library locations can use the user's login name and admin as their UID and GID. Those that go into the /System/Library locations must use root and wheel. As for permission flags, use rwxr-xr-x for the framework, its subdirectories, and its binary files. For any text files inside the framework, set their permission flags to rw-r-r-.

Other libraries use a proprietary file format. They also have their own locations on the target volume. For instance, Python packages use either /Library/Python or ~/Library/Python as their locations. Perl modules, on the other hand, go into either /Library/Ruby or ~/Library/Ruby. And POSIX libraries use the "invisible" directory /usr/lib. The UID and GID for these libraries are root and wheel. Their permissions flags are always set to rwxr-x-r-x.

Plug-ins

Plug-ins add custom features or functions to a software client, which can be either an application or a system service. The client loads a plug-in on demand and after its host system has booted up.

Most plug-ins go in specific directories inside either /Library or ~/Library. Each plug-in directory is named after the plug-in service or after the plug-in's client. For instance, osax plug-ins, used by the AppleScript runtime, go into the directory ScriptingAdditions. QuickTime codecs use the similarly named QuickTime directory. Preferences panels are stored in the PreferencesPanes directory. And Dashboard widgets go in the Widgets directory. Consult your project guidelines for the correct directory for your plug-ins.

Also, most plug-ins use the user's login name as their UID, and admin as their GID. As for permission flags, these vary with the type of plug-in. For example, osax plug-ins use rwxrwxrwx for their bundle directories and files. QuickTime codecs use rwxr-xr-x for its subdirectories and binary files, but rw-r-r- for its support files. Again, check your project guidelines for the correct settings.

Checking For Hardware

As stated earlier, some special payloads need the right hardware present on the target platform. So, if you let the package to check the target's hardware, you can reduce the number of unwanted files stored on the target. Fewer unwanted files means more space to store user data. It also means a leaner and more responsive system.

You can perform the hardware check in a number of ways. One way is to use one of the preset conditions in the Requirements Editor. Another way is to use a script to do a sysctl query. A more elegant way is to query the IORegistry with JavaScript.

Using preset conditions

Figure 1 shows the two sets of conditions that you can use for a hardware check. When creating a package with PackageMaker, choose the Requirements tab to specify requirements that this package must meet. The first set (shaded in green) focuses entirely on the host's hardware traits. To use one of the conditions, first select them from the If pop-up menu. Then choose the Boolean operator from the is menu. Next, enter the desired value to the field provided. Or if the condition provides a menu of Boolean flags, choose the right flag from that menu.


Figure 1. The preset conditions for hardware checks

For example, Figure 2 shows two hardware checks using the preset conditions. The one on the left checks to see if there are at least two CPUs present. And the one on the right checks if the hardware supports 64-bit instructions.


Figure 2. Two sample hardware checks

The second set of conditions (shaded in blue) focuses on devices attached to the host platform. Each condition looks for the device by examining one of three hardware buses: FireWire, USB, and PCI. If the device is present on the bus, the condition returns a TRUE; otherwise, it returns a FALSE.

To illustrate, assume your payload uses the FlashGO! USB card reader from Imation Corp. To look for this device, setup the hardware check as shown in Figure 3. If the device is absent, the check can either disable the payload or display an error dialog. Note the name used in the device field. This is the name under which the device appears in the IORegistry. It is not always the same as the product name.


Figure 3. Checking for a USB device

Using system.sysctl()

You can also use the Requirements Editor to run a sysctl query. To do so, choose Results of Sysctl as the check condition. Enter the sysctl node and value in the fields provided, and then choose the Boolean operator from the is pop-up menu. For example, assume your payload works only if the host has a bus frequency of at least 100 MHz. For this check, setup the editor dialog as shown in Figure 4. Here, the sysctl node hw.busfrequency goes in the field labeled value. Then the sysctl value of 100000000 goes in the field next to the Boolean pop-up menu.


Figure 4. Checking the system bus frequency

You can also add several sysctl queries using the Requirements Editor. The package, however, treats the check results in an all or nothing manner. If at least one sysctl check fails, then the entire group of checks also fails. For a more complex check logic, use a custom JavaScript function to do the query.

Listing 1 shows one example of such a function. This function first checks if the host platform has more than one CPU. If the check proves false, the function then checks if the CPU can handle 64-bit processes. Now if the CPU can handle 64-bit tasks, the function returns a TRUE when the CPU speed is greater than 100 MHz. But if the CPU handles only 32-bit tasks, the function returns TRUE only when the CPU speed is at least 200 MHz.

Listing 1. Checking the hardware with system.sysctl()

function check_sysctl() {
   tCPU = system.sysctl('hw.ncpu');
   if (tCPU == 1) {
      tTyp = system.sysctl('hw.cpu64bit_capable');
      tClk = system.sysctl('hw.cpufrequency');
      if (tTyp = 1)
         return (tClk > 1000000000);
      else
         return (tClk > 2000000000);
   }
   else if (tCPU > 1)
      return true;
   else
      return false;
}

To use the above function, first add the script to the project's Script Repository. Then choose Result of JavaScript as the check condition. Enter the function's name into the function field. Set the Boolean operator and value as shown in Figure 5.


Figure 5. Calling the custom function check_sysctl()

Checking The IORegistry

Sometimes, you want hardware checks that are difficult to do using either a preset condition or a sysctl query. So to do these checks, you will access the IORegistry directly. The IORegistry is a database of services nodes on OS X. Each node can be an active hardware or driver. The IORegistry is also dynamic by design. It updates its list of nodes each time hardware or driver is added or removed. Equally important, the IORegistry shows how the nodes related to each other.

Viewing the IORegistry

To view the IORegistry, use the Xcode utility tool IORegistryExplorer. This tool displays the entire IORegistry as a hierarchical tree on the left panel (Figure 6). Selecting a node on the tree displays that node's properties on the right panel. Nodes that have a triangle widget have child nodes under it. Clicking the widget hides or shows the children for that node.


Figure 6. Main window of the IORegistry tool

The top pane on the window controls how the tool displays the IORegistry. By default, the tool shows all the active nodes on the tree. To view only nodes that belong to a specific category, choose the category from the upper-left pop-up menu (Figure 7). Your choices include IODeviceTree (default), IOFireWire, IOPower, and IOUSB. Also, as stated earlier, the tool uses a hierarchical tree to view the IORegistry. To switch to a columnar view, click the second button near the upper-left corner.


Figure 7. Controls on the IORegistryExplorer tool

The second pop-up menu displays the absolute path of the selected node on the IORegistry. If there is only one instance of the node, this menu displays only one path. But if there are multiple instances of the same node, the menu will show multiple paths. For example, on the iBook/G4 system, selecting the node CHUDProf displays only one path.

   IOService:/IOResources/CHUDProf

But selecting the IONetworkStack node displays four possible paths (Figure 8). Here, a checkmark precedes the path of the selected node. Each instance of IONetworkStack belongs to a different network device. Selecting the path to each instance also selects that node on the IORegistry.


Figure 8. Multiple instances of IONetworkStack

Finally, on the upper-right corner of the pane is the filter field. Use this to show only those nodes that have a certain string. Assume, for example, your target platform has a number of Macally hardware products. To display the nodes for those products, type the string "Macally" into the filter field. The tool then updates its IORegistry display as shown in Figure 9. Note the matching nodes are in bold, whereas their parent nodes are in grey text.


Figure 9. Filtering the IORegistry display

Querying the IORegistry

Use the system.ioregistry() property to query the IORegistry data from the installer package. This property is an instance of the JavaScript object, also named IORegistry (Figure 10). It is available only to the InstallationCheck phase of the install session.


Figure 10. The IORegistry object

The IORegistry object has three sets of functions, all of which return an associative Array as their results. Some functions take the node's name or class as input, but most take the absolute path to the node. You can get this path by using the IORegistryExplorer tool.

The first set of IORegistry functions returns the parents or children of a specific node. For example, assume you want to query the node com_apple_driver_AudioIPCDevice. To get a list of children for this node, use the childrenOf() function. Pass the absolute path to the node as the input string.

   tChild = system.ioregistry("IOService:/IOResources/¬
      com_apple_driver_AudioIPCDevice")

To get a list of parent nodes, use the parentOf() function.

   tParents = system.ioregistry("IOService:/IOResources/¬
      com_apple_driver_AudioIPCDevice")

If the node has neither children nor parents, both functions will return a NULL.

The second set of functions searches for a node in the IORegistry. They serve the same task as the filter field on the IORegistryExplorer tool. Use the function matchingName() to search for a node with a given name. Pass the name string as the function's input. For example, the snippet below searches for all nodes with the string "Macally".

   tMacally = system.ioregistry.matchingName("Macally")

If, however, you want nodes belonging to a specific class, use the matchingClass() function. Again, pass the class name as the input string. To illustrate, the following snippet will search for all FireWire nodes.

   t1394 = system.ioregistry.matchingClass("FireWire")

If either search fails, the functions will return a NULL.

The third set consists one function that retrieves the properties for a given node. This function, fromPath(), takes one argument, which is the absolute path to the node. For example, to read the properties of the node CHUDProf, use the function as follows.

   tCHUD = system.ioregistry.fromPath("IOService:/IOResources/CHUDProf")

Again, if the node is absent, the function returns a NULL.

Now, you can read the Array elements in two ways. One way is to access each element via indices. Assume you want to examine all the child nodes of AppleACPIPlatformExpert. Listing 2 shows how you can do so using a for block. You can also use a do...while or a while block to do the same task.

Listing 2. Reading the children nodes of AppleACPIPlatformExpert

   var tSib = 
      system.ioregistry.childrenOf("IOService:/AppleACPIPlatformExpert");
   if (tSib != null) {
      for (var tIdx = 0; tIdx < tSib.length; tIdx++) {
         var tNod = tSib[tIdx];
         // - process each child node
      }
   }

Another way is to iterate through each Array element using a for...in iterator. This method works best if the Array data is a list of properties. For example, assume you want to examine the properties of CHUDProf. Listing 3 shows how you can do so with the iterator.

Listing 3. Reading the properties of CHUDProf

   var tDev = 
      system.ioregistry.fromPath('IOService:/IOResources/CHUDProf');
   if (tDev != null) {
      for (var tInf in tDev) {
         var tProp = tDev[tInf]
         // - process each node property         
      }
   }

Building The Package

In this section, you will build a basic installer package of special payloads. You will setup the package using the some of the information featured earlier. For a realistic touch, the payloads will be support software for the Macally USB product, the IceCad graphics tablet. These payloads are as follows.

  • a configuration utility named Macally IceCad.app
  • a StartupItem bundle named TabletApp

  • a kernel driver named TabletDrv.kext

Due to copyright restrictions, the installer project will not include the Macally software. But you can get your copy of the software at the following URL:

http://www.macally.com/en/Techsupport/Drivers.asp

Adding payloads

Start by creating a new installer project. On the Install Properties dialog, choose 10.4 as the minimum target platform. You can also try 10.5, though you will find little, if any, change in behavior. For now, the rest of the article assumes a 10.4 target. It also assumes the payloads are inside a directory named macally.

Save the project file as Foobar_Macally. Click the package icon on the payload list to get the Configuration panel for the entire package. Update the panel as shown in Figure 11. Here, the package will display the Custom Install panel to the user. And it will allow users to choose a target volume for the payloads. Save your changes by choosing Save from the File menu.

Now click the + button on the lower-left corner of the payload list. Use the Open File dialog to go to the macally directory and to select the utility Macally IceCad.app. Click the Choose button to add the utility to the list. Then display the Configuration panel for that payload (Figure 12). Notice the payload gets /Applications as its destination. Change this to /Applications/Macally IceCad.app. Leave the rest of the panel at their default settings. Save your changes when done.


Figure 11. Configuring the entire package


Figure 12. Configuring the application payload Macally IceCad.app

Click the + button again, and add the StartupItem bundle TabletApp to the project. Then bring up the Configuration panel for that payload (Figure 13). This time, the payload gets / as its destination. Since this is incorrect, change the path to /Library/StartupItems. Also, a StartupItem bundle must be loaded at boot-time. So, go to the Restart Action pop-up menu and choose Require Restart as the action. Leave the rest of the settings unchanged and save your changes.

Next, use the same steps to add TabletDrv.kext to the project. Then display the Configuration panel for this payload (Figure 14). Since the payload is a kernel extension, it gets /System/Library/Extensions as its destination. As that location has restricted access, make sure to set the checkbox Require admin authentication. But leave the restart action to None. OS X loads this extension only when it finds the Macally graphics table plugged in.


Figure 13. Configuring the StartupItem payload TabletApp


Figure 14. Configuring the driver payload TabletDrv.kext

Making checks

Next, you will add two simple checks to the package. Start by displaying the Requirements panel for the entire package. Then click the + button to get the editor dialog window. Update the dialog as shown in Figure 15. This check scans the USB bus for the Macally IceCad tablet. If the tablet exists, the check allows the install session to continue. Otherwise, it displays the specified error message.

To add the second check, select the choice for the payload TabletApp. Go to its Configuration panel and make sure the checkboxes Selected and Enabled are set. Now go to the Requirements panel for that choice. Click the + button to get the editor dialog. Update the dialog as shown in Figure 16. This checks examines the system version of the target platform. If the system happens to be 10.4 or older, the check leaves the choice's state unchanged. Otherwise, it disables and deselects the choice. The reason for this check is that StartupItem bundles are now deprecated on 10.5, in favor of LaunchAgents and LaunchDaemons. Since the package also supports 10.4 targets, it must know when to correctly disable this choice.


Figure 15. Checking for the graphics tablet


Figure 16. Checking for the target system

Setting up

Now it is time to set the permission flags, UIDs and GIDs of each payload. Start by selecting the payload Macally IceCad from the payload list. Then click the Contents tab to display that payload's Contents panel. Click the triangle widget next to the payload's name. Repeat the same step until you see all the files contained in the bundle (Figure 17). Select all the files and directories by choosing Select All from the Edit menu.


Figure 17. Setting the permissions, UID, and GID for Macally IceCad.

To set the payload's UID, choose root from the Owner pop-up menu. Conversely, let the GID be the default Group value of admin. Next, carefully select only the directories and bundles that make up the payload. Set the checkboxes Read, Write, and Execute for both Owner and Group. For Others, however, set only the checkboxes Read and Write. Use the same settings for the executable file inside Contents/MacOS. For the rest of the files, set the checkboxes Read and Write for both Owner and Group, but only the Read checkbox for Others. Save your changes when you are done.

Next, select TabletApp from the payload list. Use the Contents panel to display all the directories and files in that payload. Then choose Select All from the Edit menu. For the payload's UID, choose root from the Owner pop-up menu; for the GID, choose wheel from the Group menu. Then set the checkboxes Read, Write, and Execute for the Owner. But set only the Read and Execute checkboxes for both Group and Others.

Finally, select the payload TabletDrv.kext from the list. Go to its Contents panel and display all the items belonging to this payload. Select all the items and set their UID and GID to root and wheel. Next, select only the directories and bundles in the payload. Set the checkboxes Read, Write, and Execute for the Owner, but only Read and Execute for the Group and Others. Now select just the files in the payload. Set the checkboxes Read and Write for the Owner, but only Read for Group and Others. Save your changes immediately.

Package testing

You are now read to test your installer package. Start by choosing Build and Run from the Project menu. When prompt for a package name, enter the name Macally_Demo. PackageMaker then builds a distribution package with the three payloads. It sets the correct permissions, UID, and GID for each payload. Once done, it tells the Installer core utility to open the package and start the install session.

At the start of the session, the first panel you see is the Welcome panel (Figure 18). But this panel appears only when the target has the IceCad graphics tablet attached. If the tablet is absent, an error dialog appears on top of the panel (Figure 19). Clicking the Close button then ends the install session.


Figure 18. The Welcome panel

You can disable the InstallationCheck phase if you do not have the right graphics tablet. First, bring up the check for the tablet into the Requirements Editor (see Figure 3). Then change the check results from TRUE to FALSE.


Figure 19. When the IceCad tablet is absent

Let us assume that you do have the graphics tablet. Click the Continue button to switch to the Destination Select panel (Figure 20). Note the panel presents two possible locations for the payload. For this test, select the first location on the list. Click Continue to proceed to the Custom Install panel.

BUG ALERT:

Sometimes, the package will not display the Destination Select panel, proceeding instead to the next panel. This happens even if there are several mounted volumes and the package allows users to choose one of the volumes as the target. This appears to be a bug in version 3.0.1 of the Installer utility. It is unknown if this same bug is present in later versions.


Figure 20. Choosing a destination

On the Custom Install panel (Figure 21), you will see a list of three payload choices. Note the second choice, TabletApp, is disabled and unselected. In this case, the host system happens to be Leopard (10.5). If the host uses Tiger (10.4), the TabletApp choice will be both enabled and selected by default.

Leave the selections as is and click the Install button. First, the package prompts you to authenticate the install session. Then it installs the two selected payloads onto their respective locations. Once it displays the Conclusion panel, choose Quit Installer from the Installer menu. Switch to the Finder and locate the /Applications directory. In there, you will find the utility Macally IceCad.app. Now go to the directory /System/Library/Extensions. Here, you will find the kernel extension TabletDrv.kext. Select each installed payload and choose Get Info from the File menu. Examine the UID, GID, and permission flags for each payload. They should match the ones you have set in the Contents panel for each payload.

Finally, go to the directory /Library/Receipts. Here, you will find two receipt bundles, one for each installed payload. Now if you built package using the new flat-file format, you will not find any receipts for your payloads. Instead, the Installer tool will log the session in its private database named areceipt.db. This makes verifying and undoing an installation more challenging. But that is a topic for another time.


Figure 21. A list of payloads

Concluding Remarks

Special payloads need extra handling when added to an installer package. Otherwise, they may cause problems in the target if they are installed incorrectly. Some payloads need to be in the right location on the target. Some need the right hardware present. Some must have the right permissions set, others the right UID and GID. PackageMaker 3 gives you the means to address these needs. You can set the right permissions, UID, and GID of each payload via the Contents panel. You can use the Requirements Editor to add a simple hardware check or an external script to do complex checks. And you can set the right location and restart action on each payload's Configuration panel.

In the next article, I will explore the concept of an installer plug-in. I will show how to write a simple plug-in and add it to an installer package. Until then, I bid you well.

Bibliography and References

Apple Computers. PackageMaker Users Guide. 2007 Jul 23. Copyright 2007. Apple Computers, Inc. Online:

http://developer.apple.com/DOCUMENTATION/DeveloperTools/Conceptual/PackageMakerUserGuide

Apple Computers. Software Delivery Guide. 2006 Jul 24. Copyright 2007. Apple Computers, Inc. Online:

http://developer.apple.com/documentation/DeveloperTools/Conceptual/SoftwareDistribution

Apple Computers. "IORegistry Class Reference". Installer JavaScript Reference. 2007 Jul 23. Copyright 2007. Apple Computers, Inc. Online:

http://developer.apple.com/documentation/DeveloperTools/Reference/InstallerJavaScriptRef/ioregistry/ioregistry.html

Apple Computers. "The I/O Registry Explorer". I/O Kit Fundamentals. 2007 May 17. Copyright 2001-2007. Apple Computers, Inc. Online:

http://developer.apple.com/documentation/DeviceDrivers/Conceptual/IOKitFundamentals/TheRegistry/chapter_4_section_3.html/P>

Apple Computers. "Installing Your Framework". Framework Programming Guide. 2006 Nov 07. Copyright 2007. Apple Computers, Inc. Online:

http://developer.apple.com/documentation/MacOSX/Conceptual/BPFrameworks/Tasks/InstallingFrameworks.html


JC is a freelance engineering writer from North Vancouver, British Columbia. He spends his time writing technical articles; tinkering with Cocoa, REALbasic, and Python; and visiting his foster nephew. He can be reached at anarakisware@gmail.com.

 
AAPL
$97.54
Apple Inc.
+2.82
MSFT
$44.79
Microsoft Corpora
-0.04
GOOG
$596.63
Google Inc.
+1.89

MacTech Search:
Community Search:

Software Updates via MacUpdate

Firefox 31.0 - Fast, safe Web browser. (...
Firefox for Mac offers a fast, safe Web browsing experience. Browse quickly, securely, and effortlessly. With its industry-leading features, Firefox is the choice of Web development professionals... Read more
Little Snitch 3.3.3 - Alerts you to outg...
Little Snitch gives you control over your private outgoing data. Track background activityAs soon as your computer connects to the Internet, applications often have permission to send any... Read more
Thunderbird 31.0 - Email client from Moz...
As of July 2012, Thunderbird has transitioned to a new governance model, with new features being developed by the broader free software and open source community, and security fixes and improvements... Read more
Together 3.2 - Store and organize all of...
Together helps you organize your Mac, giving you the ability to store, edit and preview your files in a single clean, uncluttered interface. Smart storage. With simple drag-and-drop functionality,... Read more
Cyberduck 4.5 - FTP and SFTP browser. (F...
Cyberduck is a robust FTP/FTP-TLS/SFTP browser for the Mac whose lack of visual clutter and cleverly intuitive features make it easy to use. Support for external editors and system technologies such... Read more
iExplorer 3.4 - View and transfer all th...
iExplorer is an iPhone browser for Mac lets you view the files on your iOS device. By using a drag and drop interface, you can quickly copy files and folders between your Mac and your iPhone or... Read more
Airmail 1.4 - Powerful, minimal email cl...
Airmail is a powerful, minimal mail client.It was designed to retain the same experience with a single or multiple accounts and provide a quick, modern and easy-to-use user experience. Airmail... Read more
Macs Fan Control 1.1.12 - Monitor and co...
Macs Fan Control allows you to monitor and control almost any aspect of your computer's fans, with support for controlling fan speed, temperature sensors pane, menu-bar icon, and autostart with... Read more
A Better Finder Rename 9.37 - File, phot...
A Better Finder Rename is the most complete renaming solution available on the market today. That's why, since 1996, tens of thousands of hobbyists, professionals and businesses depend on A Better... Read more
MacBook Air EFI Firmware Update 2.9 - Fo...
MacBook Air EFI Firmware Update is recommended for MacBook Air (Mid 2011) models. This update addresses an issue where systems may take longer to wake from sleep than expected and fixes a rare issue... Read more

Latest Forum Discussions

See All

Ex-Angry Birds Developers Release Monsu...
Ex-Angry Birds Developers Release Monsu Teaser Trailer Posted by Jennifer Allen on July 23rd, 2014 [ permalink ] Finnish developer Boomlagoon has released a teaser trailer of their forthcoming side-scrolling action platformer, | Read more »
Lots of New Modes Have Been Added to Can...
Lots of New Modes Have Been Added to Canabalt Posted by Jennifer Allen on July 23rd, 2014 [ permalink ] Universal App - Designed for iPhone and iPad | Read more »
Stronghold 3: The Campaigns Review
Stronghold 3: The Campaigns Review By Jennifer Allen on July 23rd, 2014 Our Rating: :: DULL STRATEGIZINGiPad Only App - Designed for the iPad A cumbersome strategy game, Stronghold 3: The Campaigns has a few too many issues to... | Read more »
Table Tennis Touch on Sale for a Limited...
Table Tennis Touch on Sale for a Limited Time Posted by Jessica Fisher on July 23rd, 2014 [ permalink ] Universal App - Designed for iPhone and iPad | Read more »
Secret Files Tunguska Review
Secret Files Tunguska Review By Jennifer Allen on July 23rd, 2014 Our Rating: :: CONSPIRACY-LITTERED ADVENTURINGUniversal App - Designed for iPhone and iPad Offering traditional adventuring with no fear of in-app purchases, Secret... | Read more »
Celebrate Summer With a Cat in the Hat L...
Celebrate Summer With a Cat in the Hat Learning Library Sale Posted by Ellis Spice on July 22nd, 2014 [ permalink ] Universal App - Designed for iPhone and iPad | Read more »
Dragon Raiders Review
Dragon Raiders Review By Nadia Oxford on July 22nd, 2014 Our Rating: :: RUN, DRAGON, RUNUniversal App - Designed for iPhone and iPad Dragon Raiders is rough and scaly in some parts, but overall it’s an enjoyable level-based running... | Read more »
MyTaskList Review
MyTaskList Review By Jennifer Allen on July 22nd, 2014 Our Rating: :: EFFECTIVE IF PLAINUniversal App - Designed for iPhone and iPad It’s not the most stylish of task management apps, but MyTaskList has all the features you could... | Read more »
FlyCraft Herbie: Crazy Machines Review
FlyCraft Herbie: Crazy Machines Review By Jennifer Allen on July 22nd, 2014 Our Rating: :: TRICKY FLYINGUniversal App - Designed for iPhone and iPad A tough game of careful thrusting and navigation, FlyCraft Herbie: Crazy Machines... | Read more »
MTN Review
MTN Review By Jessica Fisher on July 22nd, 2014 Our Rating: :: ADORABLE, SERENE, AND AMUSINGUniversal App - Designed for iPhone and iPad MTN is an adorable, talking pet mountain that is less game and more zen garden.   | Read more »

Price Scanner via MacPrices.net

With The Apple/IBM Alliance, Is The iPad Now...
Almost since the iPad was rolled out in 2010, and especially after Apple made a 128 GB storage configuration available in 2012, there’s been debate over whether the iPad is a serious tool for... Read more
MacBook Airs on sale starting at $799, free s...
B&H Photo has the new 2014 MacBook Airs on sale for up to $100 off MSRP for a limited time. Shipping is free, and B&H charges NY sales tax only. They also include free copies of Parallels... Read more
Apple 27″ Thunderbolt Display (refurbished) a...
The Apple Store has Apple Certified Refurbished 27″ Thunderbolt Displays available for $799 including free shipping. That’s $200 off the cost of new models. Read more
WaterField Designs Unveils Cycling Ride Pouch...
High end computer case and bag maker WaterField Designs of San Francisco now enters the cycling market with the introduction of the Cycling Ride Pouch – an upscale toolkit with a scratch-free iPhone... Read more
Kingston Digital Ships Large Capacity Near 1T...
Kingston Digital, Inc., the Flash memory affiliate of Kingston Technology Company, Inc.,has announced its latest addition to the SSDNow V300 series, the V310. The Kingston SSDNow V310 solid-state... Read more
Apple’s Fiscal Third Quarter Results; Record...
Apple has announced financial results for its fiscal 2014 third quarter ended June 28, 2014, racking up quarterly revenue of $37.4 billion and quarterly net profit of $7.7 billion, or $1.28 per... Read more
15-inch 2.0GHz MacBook Pro Retina on sale for...
B&H Photo has the 15″ 2.0GHz Retina MacBook Pro on sale for $1829 including free shipping plus NY sales tax only. Their price is $170 off MSRP. B&H will also include free copies of Parallels... Read more
Apple restocks refurbished Mac minis for up t...
The Apple Store has restocked Apple Certified Refurbished Mac minis for up to $150 off the cost of new models. Apple’s one-year warranty is included with each mini, and shipping is free: - 2.5GHz Mac... Read more
Twelve South HiRise For MacBook – Height-Adju...
If you use your MacBook as a workhorse desktop substitute, as many of us do, a laptop stand combined with an external keyboard and pointing device are pretty much obligatory if you want to avoid... Read more
Why The Mac Was Not Included In The Apple/IBM...
TUAW’s Yoni Heisler cites Fredrick Paul of Network World whoi blogged last week that the Mac’s conspicuous absence from Apple and IBM’s landmark partnership agreement represents a huge squandered... Read more

Jobs Board

Sr. Product Leader, *Apple* Store Apps - Ap...
**Job Summary** Imagine what you could do here. At Apple , great ideas have a way of becoming great products, services, and customer experiences very quickly. Bring Read more
Sr Software Lead Engineer, *Apple* Online S...
Sr Software Lead Engineer, Apple Online Store Publishing Systems Keywords: Company: Apple Job Code: E3PCAK8MgYYkw Location (City or ZIP): Santa Clara Status: Full Read more
*Apple* Retail - Multiple Positions (US) - A...
Sales Specialist - Retail Customer Service and Sales Transform Apple Store visitors into loyal Apple customers. When customers enter the store, you're also the Read more
*Apple* Retail - Multiple Positions (US) - A...
Sales Specialist - Retail Customer Service and Sales Transform Apple Store visitors into loyal Apple customers. When customers enter the store, you're also the Read more
Sr *Apple* Engineer - IT - Requisition #: -...
For more information about TIAA-CREF, visit our website . The Apple Engineer will provide engineering and third-level incident support for 300- 500 MacOS desktop/laptop Read more
All contents are Copyright 1984-2011 by Xplain Corporation. All rights reserved. Theme designed by Icreon.