Wednesday, June 24, 2009

GriP 0.1-11n Released

GriP 0.1-11n (r344) is released and can be downloaded from This version will be the last revision with Memory Watcher bundled. Starting from next revision, Memory Watcher will be moved to another package.

GriP 0.1-11n features following changes:
  • (r327) GriP will use Preference Loader to inject the preferences. You'll have to install PreferenceLoader first.
  • (r327) GriP Modal Tables can now be themed.
  • (r331) All recent GriP messages will be logged.
  • (r332) The detail disclosure thing (▼) is available in You've Got Mail again.
  • (r333) Game mode now works in 3.0
  • (r334) Dismissing the modal table by home button works correctly in 3.0.
  • (r340) Added Polish localization.
  • (r343) 3.0 Push notification plug-in.
  • (As usual) Other bug fixes.

Note that if you've downloaded the r341 version that I've uploaded by mistake this morning, you'll experience a memory leak. Please upgrade immediately.

Tuesday, June 23, 2009

Sending push notification locally.

So far I haven't found a reliable push notification app yet to test GriP Push Notification (QuickPigeon is the most reliable one I've ever tried, but it held up 2 trial mails quite a long time).

So what about faking push notifications? After a push notification is just a TCP packet. The first thing I do is to set a breakpoint on the most suspicious method -- -[SBRemoteNotificationServer connection:didReceiveMessageForTopic:userInfo:] (0x9ffa5). And indeed, when a push notification comes, the break point is hit (multiple times).

I used the breakpoint command
call (void)CFShow($r2)
call (void)CFShow($r3)
call (void)CFShow(*$sp)

to record the arguments. And not surprisingly, the userInfo is an NSDictionary of the payload, like
aps = {
sound = "hello.aif";
alert = "Hello world!";

The Apple's documentation on this is more in detail. The "topic" parameter is the bundle ID of the app to receive the notification, and connection is an APSConnection object.

Given these results, we can craft our notification packet with a Mobile Substrate extension.

Right now, you can download and test it out. To install:
  1. Put the .dylib and the .plist to /Library/MobileSubstrate/DynamicLibraries
  2. Put the executable (FakePushNotification) to /usr/bin and chmod a+x it.
  3. Respring
  4. In command line, type e.g.:
    FakePushNotification com.yourcompany.pushEnabledApp -
    body = "Hello world!";
    action-loc-key = "Welcome!";

    The "payload" must be in plist format, not JSON format.

Note: the program is written to demonstrate how it can be done. It is not bug free. In particular, sending a string that cannot be interpreted as a plist will cause your device crash and go into safe mode. Use with caution.

Monday, June 22, 2009

openURL for 3.0 (and 2.x too, probably)

openURL is part of Erica Utilities. On 3.0, it is not usable anymore because Apple now always throw a "There can only be one UIApplication instance." error even if [UIApplication sharedApplication] still returns nil.

But openURL doesn't require UIApplication. The core method, -[UIApplication openURL:] is actually a wrapper of the undocumented function, GSEventSendApplicationOpenURL.

I've rewritten openURL using GSEventSendApplicationOpenURL, and can be downloaded from Note that GSEventSendApplicationOpenURL relies on the Graphics Services private framework, and this framework isn't very stable, so there is a chance it won't work on 4.0.

You'll notice that there's now a new argument, "port-name". That's actually not quite useful, but I found that it's used in UIKit, so just added it in. (One more reason is that, the function that obtains the default port is renamed in 3.0.) And that piece of UIKit code doesn't work :(.

3.0's presentModalViewController:withTransition:

In 3.0 the algorithm -presentModalViewController:animated: is changed. The most prominent change I can see is that the modal view controller will always use the application frame instead of the parent view controller's frame. This breaks modal table theming in GriP. Fortunately, probably Apple also thinks the change to too drastic, they've also provided -_legacyPresentModalViewController:withTransition: that uses the old algorithm, so until iPhoneOS 4.0 comes we can still ignore this problem.

The 3.0's -presentModalViewController:animated: calls the undocumented method -presentModalViewController:withTransition: as a backend, where the 2nd parameter "transition" is an integer. For official SDK there're 5 official transitions (present and dismiss count as 2): Slide up/down, Flip to left/right, and cross fade.

But -presentModalViewController:withTransition: supports a bit more:
1Push from right to left
2Push from left to right
3Push from bottom to top
7Push from top to bottom
8Slide from bottom to top
9Reveal from top to bottom
10Flip from left to right
11Flip from right to left

Saturday, June 20, 2009

3.0 Status

  1. iKeyEx beta for 3.0 has been out there for weeks. Check the newest posts.
  2. Calculator.searchBundle won't work until someone completely rewrites Spotlight. The guy behind iFile tried to enable custom search bundles before, but the overly-optimized interface made it impossible without rewrites.

iPhoneOS 3.0 has been released and jailbroken, and I've also upgraded, so from now on my primary focus of OS will be 3.0, instead of 2.2.1.

GriP worked pretty well on 3.0. It is predictable as GriP was designed to be as SDK-compatible as much, and I've tested it on 3.0b1 (simulator) from the start.

But iKeyEx is totally different. It cannot work on 3.0 without in-depth investigation on UIKit again. The primary reason is in 3.0 Apple redesigned a lot in language UI. 80% code of UIKit is about the new keyboard UIKeyboardLayoutStar. The input manager is so heavy that split into its own private framework, TextInput.framework. That carries away UIKeyboardInputManagerAlphabet which iKeyEx relies on.

iKeyEx will be 3.0-ready, of course, but it will be a long time to wait.

(And because 3.0 supports single-clipboard copy-and-paste natively, I'll discontinue the current form ℏClipboard. I may write a multi-clipboard extension though.)

As for the side-projects, Calculator.searchBundle does not work as I expected. I need to check the source code of Search.framework again. And I haven't checked if AdKiller works or not.

Sunday, June 7, 2009

An incomplete list of entitlement keys

KeyTypeUsed byChecked byNotes


?The only documented entitlement key, means "Can be debugged".
keychain-access-groupsarray of stringsToo many
?Everyone uses it has the value (apple).
application-identifierstringToo many
?The content may not be the same as the bundle ID. For example, the application-identifier for AppStore apps will be (10 random characters).(bundle ID)
array of strings


The entitlement of a task can be obtained using the undocumented SecTask*** functions. Because of this, a library can define a set of entitlement keys other applications using it must follow.

Friday, June 5, 2009

GriP 0.1-11m released

GriP 0.1-11m (r323) is released, and can be downloaded at

The biggest change in 11m is the support for "Modal Table View". You've Got Mail has been modified to support this. The new mail message now looks like:

Note that the "detail disclosure button" is not there. When you tap on the message a table will pop up:

You can click on each item to view the message (not as ideal as, but still readable):

Why is this change? My rationale is that, if you want to show the detail, you are focusing on the message, and stuffing that much information in that message is not good. If you're focusing on it, why not maximize the view? Hence it is shown as a "Modal Table View".

Does this contradict with the philosophy behind GriP (unobstructive)? No, because this modal thing already has user confirmation, while for alert boxes they just pop up with no prior consent.

(If you don't like this, you can always downgrade to 0.1-11k available in

Thursday, June 4, 2009

Displaying UIView hierarchy of a compiled app

Suppose you want to investigate the view hierarchy of some app you did not write. There is a simple way using GDB:

  1. Compile UIUtilities.m into a dylib or bundle. You can download it precompiled here.
  2. Upload the file to the device, e.g. /var/mobile/UIUtilities.bundle. Do not put it in /var/root/.
  3. Now attach gdb to the executable you want to investigate.
  4. Inject UIUtilities to the executable. In the gdb prompt, type:
    call (int)dlopen("/var/mobile/UIUtilities.bundle", 10)
    If a nonzero value appears, injection succeeded.
  5. Finally, type:
    call (void)UILogViewHierarchy((int)[[UIApplication sharedApplication] keyWindow])
    The UIView hierarchy of the key window will be recorded in syslog.

Monday, June 1, 2009

Testing various Regular Expression solutions, Part 1.5

One thing I really like about blogs is that you can exchange ideas and learn something you naturally won't know for a lifetime because you are not an expert. (And I hate you, Xanga Friends Lock users.)

Firstly, I have added the 3 options -DNS_BLOCK_ASSERTIONS=1 -DRKL_CACHE_SIZE=307 -DRKL_FAST_MUTABLE_CHECK=1 as instructed and able to reduce the running time from 1.7s to 0.7s, but still quite slow compared with ICU at 0.25s. Then I increased the cache size to 709, and the running time is now 0.4s. Further increasing to 1619 starts make the running time longer probably due to excessive memory use.

RKL,307 RKL,709
0.691226s 0.384044s
0.692440s 0.381194s
0.684274s 0.381550s
0.689568s 0.382489s
0.683985s 0.384499s

Then I consider rolling all 16 pattern into one big RegExp like RE1|RE2|RE3|.... One problem with this is each pattern must not have back-references, but this is fine for wildcard rules since back-references do not appear at all. But another nasty thing is that AdBlock Plus rules has the so called filter options which prevents simple merging to take place. Anyway, the running time after merging are:

ICU       PCRE      regex.h   RKLite    JSRegExp
0.260404s 0.189028s 2.526485s 0.268121s 0.141875s AllInOne
0.256532s 0.160290s 2.526872s 0.264368s 0.141586s
0.257263s 0.160135s 2.536937s 0.266934s 0.142434s
0.256900s 0.160222s 2.532003s 0.265274s 0.141467s
0.256744s 0.160232s 2.528987s 0.264851s 0.142299s
0.253102s 0.067551s 0.235714s 0.382489s 0.113274s SeveralInst (median of 5)

So while RegexKitLite does become faster, all other methods are dragged down, esp. the POSIX ERE. This confirms johne's statement.

There are some other developments: (1) I've found the fnmatch function that does wildcard matching, but the running time is 0.8s, probably due to the use of recursion and implicit calls on locales. (2) Then I've written a specific routine that checks using pure C string, and the result is dramatic -- the function only takes 0.02 seconds! This restored some of my logical beliefs :D.


The new source code can be found in: