Tuesday, October 20, 2009

Xcode 3.2.1 and Jailbroken iPhone 3.1.2 is Build & Go!

XCode 3.2.1 on Snow Leopard plays nicely with jailbroken iPhone OS 3.1.2. You can do Buid & Go and even debug directly on the device. The procedure described for XCode 3.2 and iPhone OS 3.1 is exactly the same. However, I have been asked a couple of times to put it all together and make a step-by-step guide and this seem to be a good occasion.

First things first: a jailbroken iPhone 3.1.2

If your iPhone is already jailbroken, you should know what to do. I used Pwnage Tool 3.1.4 and the good news is that this time there is no need to enter DFU mode!

If your iPhone is still jailed, it would be probably a good idea to read through the Pwnage Tool 3.1.4 release news and maybe have a look at the jailbreaking step-by-step guide which works for me every time.

Once your iPhone is jailbroken, open Cydia go to the "Manage" tab, select "Sources" and add http://iphone.org.hk/apt/. Then install "Installd Patch" (see image). This is crucial for installing your own application on your iPhone using XCode.

Obtain a self-signing identity

Jailbroken or not iPhone needs software to be signed. If this is your first time, you need to create your own signing certificate. The whole process is described in detail in the original Apple document titled "Obtaining Signing Identity".

Make sure you create the certificate in the default "login" keychain. For avoidance of doubt you would probably like to call your identity "iPhone Developer". This EXACT name is being used in most of the online resources I have seen so far.

Once you have the certificate, switch to XCode and go to Project -> Edit Project Settings, scroll to Code Signing / Code Signing Identity / Any iPhone OS Device and change the value to your freshly created identity name, probably "iPhone Developer" (see image). This step needs to be repeated for each of the existing projects. All new projects should get the value automatically.

Make XCode 3.2.1 compile for your iPhone 3.1.2

Self-signing certificate is good enough for you, it should be so for XCode. Let's tell him. In the file:
/Developer/Platforms/iPhoneOS.platform/Info.plist
find line 46 and replace "XCiPhoneOSCodeSignContext" with "XCCodeSignContext" (see image). Repeat the operation for line 79 and save the file.

If you want to stop here because you don't need debugging, just restart XCode and you should be able to use Build & Go to compile and install applications on your iPhone directly from XCode.

Make XCode 3.2.1 debug on your iPhone 3.1.2

There is some small work to be done if you want to make your XCode 3.2.1 debug on your iPhone 3.1.2 for you. First of all you need to have ldid and ldid2. ldid is a replacement for codesign, which adds entitlements necessary for debugging. We have lost the feature in previous part and now it is time to get around. ldid2 is a shell script which makes use of ldid.

After you have downloaded the archive, unpack the files and put them into /usr/local/bin directory. Then make sure they are both executable.

The last step would be to tell XCode it needs to use ldid2 instead of codesign. In the file: /Developer/Platforms/iPhoneOS.platform/Developer/Library/Xcode/Plug-ins/iPhoneOS Build System Support.xcplugin/Contents/Resources/iPhoneCodeSign.xcspec find line 12 and replace "/usr/bin/codesign" with "/usr/local/bin/ldid2" (see image).

Now restart XCode and you should be able to do Build & Go and debug directly on your iPhone.

Update (26/10/2009)
Well, almost. Just one tiny thing remaining. For every project you want to debug, you need to add -gta flag to "Other Code Signing Flags" in the project settings.

I hope you found this guide useful, it worked for you and made you a bit happier. Please don't think twice before you leave your comment.

Thanks for reading,
Jacek

Acknowledgements

This guide could not be possible if not for two great articles:

Friday, October 2, 2009

XCode 3.2 Build & Go with jailbroken iPhone 3.1

XCode 3.2 on Snow Leopard works fine with jailbroken iPhone 3.1! And even better: Build & Go works as well as debugging on the device. I tried a couple of different ways to get there, went through a few blogs and here is the conclusion.

Update (21/10/2009):
XCode 3.2.1 works fine with iPhone 3.1.2 as well

Xcode 3.2 and iPhone 3.1

  1. First of all you need a jailbroken iPhone. The procedure for 3.1 is same as for 3.0, only the Pwnage Tool is in new version.
  2. Follow first three steps of the "Developing for a jailbroken iPhone" guide and disregard completely anything after "Add the special 3.0 sauce:". We are not going to patch the binary this time. Make sure you have installed "Installd Patch" on your iPhone. It is critical.
  3. Follow the section "I want to compile" from the "Compiling iPhoneOS (3.1) apps with Xcode 3.2 without Provisioning Profile" Guide. At this stage you should be able to compile application and install it on your iPhone. Keep in mind that you have Installd Patch installed. This is something the author was not aware of.
  4. If you want to debug on your device, all you need to do is to follow only first four steps from the section "I want to install and debug too". This is because you can already install and following the first four steps allows you do debug.
That's pretty much it. Now you should be able to use Build & Run, Install and Debug your app directly on your jailbroken iPhone 3.1 using XCode 3.2. Enjoy!

Leftovers from Xcode 3.1.3 and iPhone 3.0

If you made Xcode 3.1.3 work with iPhone 3.0 before following the "Developing for a jailbroken iPhone" guide you may have added "New Run Script Build Phase" for your projects. As it is no longer necessary, you may want to do some housekeeping and get rid of the scripts. Here is how to do it:

In order to remove the scripts you need to open your project, then in the left hand pane called "Groups & Files" (the one showing tree view of your project) find "Targets". Expand if necessary and there you should see your app name. Expand again and there you should get a few entries including "Run Script" - which you were looking for. It is described in the documentation included in the XCode (/Developer/Platforms/iPhoneOS.platform/Developer/Documentation/DocSets/com.apple.adc.documentation.AppleiPhone3_1.iPhoneLibrary.docset/Contents/Resources/Documents/documentation/DeveloperTools/Conceptual/XcodeBuildSystem/200-Build_Phases/bs_build_phases.html) and illustrated on the left.

Friday, September 25, 2009

PHP5: Sending headers

Http headers can be sent only before any other output. This is a simple requirement and funny how big impact it may have on application architecture and how many tricky questions may be asked about it. Here is one from the Zend PHP 5 Certification Mock Exam.

You will find correct answer in bold.

One can ensure that headers can always be sent from a PHP script by doing what?
  • Enable header buffering in PHP 5
  • Set the header.force INI directive to true
  • Enable output buffering in PHP 5
  • There is no way to ensure that headers can always be set, they must always be checked
  • None of the above

The header documentation page says: "As of PHP 4, you can use output buffering to get around this problem". That obviously makes sense on the contrary to header buffering suggested by the first answer. Header buffering would not help because the troublemaker here is premature output.
According to PHP manual there is no such directive as header.force and does not seem to have much sense as well, which shoots off the second answer.
The third one has some potential but is not correct - output buffering has been avaiable since PHP4.
And as output buffering seems to combat the problem successfully, the fourth answer is there only to trick you.

Thursday, September 24, 2009

PHP: empty $_FILES array

This experience might be really time consuming. You get a simple form with a simple input field of type="file" and on the server side you get nothing. The $_FILES array is empty as a whistle.

You can get really frustrated after checking whether file_uploads = 1, upload_temp_dir is accessible and upload_max_filesize is big enough and everything seems fine.

In this case it's worth checking if the troublemaker is not... the form itself. If there is no enctype="multipart/form-data" in the form tag, you may want to try it. Here is an example of working file upload:

<form name="form" action="index.php" method="post" enctype="multipart/form-data">
<fieldset>
<label>Upload file</label>
<input type="file" name="userfile" />
</fieldset>
<fieldset>
<input type="submit" value="OK" />
</fieldset>
$lt;/form>


I have found a Nice thread about the above issue which you might be interested in as well.

Wednesday, September 16, 2009

Zend PHP 5 Certification Mock Exam: how to destroy a session

Here is another question about sessions from the Zend PHP 5 Certification Mock Exam. Good answers are in bold:
To destroy a PHP session completely, one must which of the following?
  • Regenerate the session ID using session_regenerate_id()
  • If cookies are used, destroy it
  • Use session_demolish() to completely destroy the session
  • Change the session name using session_name()
  • Destroy the session data using session_destroy()
A few words of explanation. To destroy a session we need to remove all the data associated with the session and try to prevent the client from requesting the session using the id. Usually the session id is stored on the client side as a cookie. In this case, we need to destroy the cookie, which means that the second answer is correct. To remove all the data stored associated with the session, we need to use session_destroy function, and this also means the last answer is correct. It is described briefly on the session_destroy manual page.

Regarding three remaining answers, regenerating session id is useful for preventing session fixation. There is not such a function as session_demolish() described in PHP manual. Changing session name does not remove the data, it simply changes the name of the cookie storing the session id.

Tuesday, September 1, 2009

Zend PHP 5 Certification Mock Exam: magic function

One of the Zend PHP 5 Certification Mock Exam questions shows recursive function called "magic". The question reads as follows (correct answer in bold):
What does the following function do, when passed two integer values for $p and $q?
<?php
function magic($p, $q) {
return ($q == 0)
? $p
: magic($q, $p % $q);
}
?>
  • Loops infinitely
  • Switches the values of $p and $q
  • Determines if they are both even or odd
  • Determines the greatest common divisor between them
  • Calculates the modulus between the two
It turns out that the function is simply on of the Euclidean algorithm implementations. If you do not remember from your math class how it works, here is the the Euclidean algorithm procedure described.

Friday, August 21, 2009

Gracefully downgradable javascript for accessibility

JavaScript contributes by a great deal to user experience on the Web and it does not have to be an obstacle for accessibility. The goal is to allow the user access all of the website's content when JS is enabled as well as when it is disabled.

Let's consider two versions of the webpage: one is interactive JavaScript enriched and the other one is just static. I think it is safe bet that both of them initially share same markup and only differences occur in styling.

If we stop to think about it, we have just one markup with two possible stylings applied to it. If we could detect within CSS which version of styling should be applied that would solve the case. Of course CSS on its own have no such ability but that is exactly where the "C" from CSS comes to aid: Cascading.

JavaScript, when enabled, can amend DOM. In particular it can add a class to body tag, say "js-enabled". Having styles for specific areas of the webpage, cascaded down through .js-enabled class allows you to differentiate between JS enabled and disabled state on the CSS level.

The simplest example would be a definition list. We want to display all the terms but not the definitions. The latter would be expanded and visible only when corresponding term was clicked, which needs some simple JavaScript functionality to work. On the other hand, when JS is not available the user should be able to see the whole list: the terms along with the definitions. We could do it using this CSS:
.js-enabled dd {display:none;}
.js-enabled dd.expanded {display: block;}

JavaScript would add the class "expanded" whenever there is a need to show the definition. Simply removing the class would hide the element again. I am not going to go into details of the implementation as it is not very interesting. What is interesting though is when to add the class "js-enabled" to the body tag.

If it was added after the document has been fully loaded (for example from within the "document.onload" event handler), the list would be rendered without the "js-enabled" class at first and both terms and definitions would be visible. Then adding the class would cause hiding all the definitions and as a result ugly jumping of content on the page. To prevent this effect we have to add "js-enabled" class as soon as the body tag is available for manipulating but before the document has been rendered:

<body>
<script type="text/javascript">
try {
document.getElementsByTagName("body")[0].className += " js-enabled";
} catch(e) {}
</script>
...