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>
...

Wednesday, August 19, 2009

XCode 3.1.3 works with jailbroken iPhone 3.0

As my iPhone development is not something I do on daily basis, it took me some time to realize that development on jailbroken iPhone is possible again!

Great article describing step-by-step how to make your XCode work for you again. I can confirm it works, just read through carefully.

Update (09/10/2009):
You can make Xcode 3.2 work with iPhone 3.1 - build & go + debugging.

Tuesday, July 21, 2009

Error: There was a problem reading this document (109)

Usually browsers armed with Acrobat Reader plugin can open .pdf files directly. Unfortunately sometimes it so happens that a user gets the 109 error and is unable to open the document before they save it locally.

There are a couple of solutions suggested all around the Web, one of them being to give a user choice between saving file locally or open it in Adobe Reader window. One of the ways to do it is changing MIME type of the .pdf file and Content-Disposition header. Instead of default application/pdf we would be serving more generic application/octet-stream. Content-Disposition header has to be set as attachment. Here is an example PHP script which sends any existing .pdf file from the script's directory:
$file = $_GET['file'] . '.pdf';

if (preg_match('/^[a-zA-Z0-9_\-]+\.pdf$/', $file)
&& file_exists($file)) {
header('Content-Type: application/octet-stream');
header('Content-Disposition: attachment; filename=' . $file);
readfile($file);
} else {
header("HTTP/1.0 404 Not Found");
}
Even though it works, it is not very elegant. We might want to link directly to .pdf documents instead of pdf.php?file=document.pdf and serve the files transparently through the php script.
For Apache users it is quite easy to achieve. An example .htaccess file:
RewriteEngine On
RewriteBase /your.directory.with.documents/pdf
RewriteCond %{REQUEST_FILENAME} -f
RewriteRule ^(.+)\.pdf$ ./pdf.php?file=$1 [L,NC,QSA]
A few words of explanation:
  • Third line says to redirect to pdf.php script only valid requests for existing files.
  • Fourth line rewrites requests for .pdf files only as this is all we are interested in. The script gets filename without extension, eg. "document.pdf" is passed to the script as "document".
  • More about rewrite_mod for apache you can find in the documentation.

Tuesday, July 14, 2009

Custom Paragraph Classes in Typo3 RTE

Sometimes it is important to apply custom classes to paragraphs in RTE. Typo3 allows you to customize the "Block style" list easily. All it takes is a few lines of Typo Script in page TSconfig.

Let's add class lead for leading paragraph. We want this class to appear as "Leading paragraph" and be indicated with slightly bigger font on the "Block style" list. Here is how to do it in page TSconfig:
RTE {
classes.lead {
name = Leading paragraph
value = font-size:1.4em;
}

default {
contentCSS = fileadmin/templates/css/rte.css
proc.allowedClasses = lead
classesParagraph = lead
}
}
A few words of explanation:
  1. RTE.default.contentCSS defines css file used by RTE to render text in the editing window. It is required that the class we want to add is defined in this file
  2. RTE.classes.lead defines the entry for the "Block style" list; the value is inline style used to preview the class in the drop-down
  3. RTE.default.proc.allowedClasses tells RTE not to strip these classes when saving content to the database
  4. RTE.default.classesParagraph associates given class with paragraph, so you can see the selector on the "Block style" list when you choose "Paragraph" from the "Type of block" drop-down.
Further details (and much more) you can find in the page TSconfing documentation.

Saturday, July 11, 2009

Stopping PHP Script Execution

Do you know all the ways of stopping PHP script execution? Put your knowledge to a test with this question from the Zend PHP 5 Certification Mock Exam.

The question is as follows. Correct answers in bold.
What would go in place of ?????? below to make this script execute without a fatal error?
<?php

$a = 1;
$b = 0;

??????

$c = $a / $b;
?>
  • quit();
  • die();
  • stop();
  • __halt_compiler();
  • exit();
die() and exit() are quite obvious, stop() and quit() do not exist and what about __halt_compiler()? The latter was introduces in PHP5. Manual page says it stops the execution of the compiler and nothing after this call is executed.

Tuesday, July 7, 2009

Custom Frames for Content Elements in Typo3

The "Frame" option for Content Element in Typo3 becomes handy. What if default list does not suit your needs? You need to customize it then.

It is not difficult, event though not very easy to find. The functionality is built upon two different lists. One is a list of frame ids and corresponding labels visible in the BE. For each of these ids the other list defines actual "frame" - wrapper visible in the FE.

The first list is defined in page TSconfig as it is dealing with the back end. Here is an example:
TCEFORM.tt_content.section_frame {
removeItems = 5,6,10,11,12,20,21
altLabels.1 = Rounded
addItems.2 = Highlighted
}
Second line removes all the default items from the list, except for the one with id=1. Third line amends label of that element setting it to 'Rounded'. Finally, the fourth line adds new item to the list with id=2 and label 'Highlighted'.

The second list is defined in TS template as it is dealing with the front end. The example:
tt_content.stdWrap.innerWrap.cObject {
1 = TEXT
1.value = <div class="rounded">|</div>
2 = TEXT
2.value = <div class="highlighted">|</div>
}

Sunday, July 5, 2009

Find Missing Value in a Sequence in SQLite

Sometimes it is important to find gaps in sequenced values in your table, for instance id. How do you do it in SQLite? How do you do it in an efficient manner?

First things first. Google it up. Doing so I found very useful article "
How to find missing values in a sequence with SQL". Very inspiring. The idea is to check the list against itself only shifted by one. I tried the following query:
SELECT DISTINCT m1.id + 1
FROM mytable as m1
LEFT JOIN mytable as m2 ON m1.id + 1 = m2.id
WHERE m2.id IS NULL;
I had to use DISTINCT as mytable is just a helper table for many-to-many relationship and same id may appear many times. The query worked straightaway and was quite quick as I had and index on id field. Here are the basic information about the data:
  • no of records: 3360
  • no of unique ids: 228
The query above took 0.030s to execute on average.

That is not bad. Although I thought I would try a sub-query as well, even though they are usually discouraged as being too slow. I have re-written the query slightly:
SELECT DISTINCT id +1
FROM mytable
WHERE id + 1 NOT IN (SELECT DISTINCT id FROM mytable);
The query above took 0.014s to execute on average.

That means sub-query was faster than the join! I do not think it is a big surprise, though. Given the id column does not held unique values, and there are around 15 occurrences of each id, apparently it takes longer to create a join on all the values than to create a temporary table for the sub-query.

Concerns
  • Biggest missing value returned
    It is always max(id) + 1, so unless you need it, you might want to deal with it differently.
  • Lowest missing value returned
    The query does not recognize a gap between 0 and the lowest value in the sequence. Therefore the lowest missing value would be always bigger than the minimum.

Wednesday, July 1, 2009

Generating Custom Session ID in PHP 5

Another one of my favorite questions from Zend PHP 5 Certification Mock Exam. Correct answer in bold.
If you would like to change the session ID generation function, which of the following is the best approach for PHP 5?
  • Set the session.hash_function INI configuration directive
  • Use the session_set_id_generator() function
  • Set the session id by force using the session_id() function
  • Use the session_regenerate_id() function
  • Implement a custom session handler
Surprisingly, the most obvious answer, made sound like something not really reasonable, is the correct one. A few words of explanation.
And session_id() is the only one on the list allowing to set custom session id and definitely it is the correct answer.

Tuesday, June 30, 2009

Zend Engine Executor Models in PHP 5

Yet another tricky question from the Zend PHP 5 Certification Mock Exam. It took some time to find it, so I thought it might be worth to put it here. Correct answers are in bold.

Which of the following are examples of the new engine executor models available in PHP 5?
  • Switch
  • Conditional
  • Goto
  • Call
  • Dynamic
It has been nicely described on Zend Devzone.

Sunday, June 28, 2009

Zend PHP 5 Certification Mock Exam: SQLite

I came across this tricky question while solving the PHP 5 Certificatin Mock Exam. The answers in bold are the correct ones. I have also added a few words of explanation to each of them.

Which of the following SQL statements will improve SQLite write performance?
  • PRAGMA locking_mode = "Row";
    locking_mode can only be "NORMAL" or "EXCLUSIVE"
  • PRAGMA count_changes = Off;
    it is believed to increase the speed slightly
  • PRAGMA default_synchronous = Off;
    synchronous set to "Off" makes SQLite continue after write operation without waiting for the storage to finish writing - this might give a real boost
  • PRAGMA default_synchronous = On;
    synchronous can only be "OFF", "NORMAL" or "FULL"
  • PRAGMA locking_mode = "Table";
    locking_mode can only be "NORMAL" or "EXCLUSIVE"

Thursday, June 25, 2009

Most Useful Apps from Cydia

My Cydia selection:
  1. OpenSSH
    allows you to access your iPhone filesystem remotely, you should change password for root and mobile users as soon as possible after installing it
  2. Mobile Substrate
    allows to hook functionality into existing application, eg. make VoIP calls from Skype on 3g
  3. VoIPover3G
    relays on Mobile Substrate, tricks applications into using VoIP over 3g, eg. Skype
  4. CyDelete
    allows to delete Cydia apps directly from SpringBoard just like AppStore apps
  5. Siphon
    VoIP SIP client for iPhone, works fine with voipdiscount.com

Jailbroken iPhone OS 3.0 is out!

This is some really cool news. The guys have already published Pwnage Tool for iPhone OS 3.0. The process is same as before. If you have pwned your iPhone before you would be familiar with it. I do it as follows and it works for me every time:
  1. I download the Pwnage Tool from original website
  2. When I connect my iPhone to my Mac, iTunes starts screaming about new firmware. I choose "download only"
  3. When the firmware is already on my machine, I run Pwnage Tool in simple mode, it finds the firmware and creates pwned one on my Desktop
  4. Meanwhile I create a backup copy of my iPhone using iTunes - this point is crucial if you want to preserve your data
  5. When it's all done I quit iTunes
  6. Then I put my iPhone into DFU mode using Pwnage Tool and follow the instructions (quit Pwnage Tool).
  7. I open iTunes and it says about iPhone i recovery mode. It is all right and I press and hold Alt + Option while clicking "Restore" in iTunes
  8. iTunes shows a dialog allowing me to choose the firmware file - I select newly created pwned firmware
  9. iTunes uploads the firmware and reactivates iPhone
  10. I restore my data from backup copy created in point 4.
  11. I am happy and relaxed

Tuesday, June 23, 2009

Cross-Site Scripting (XSS)

Today I came across a question: "what is most important when trying to prevent a cross-site scripting attack?"

The answer is most intuitive. The most important rule to prevent cross-site scripting is "never trust user input". Not far behind comes "escape output".
These are general server-side programming rules, they do not apply only to specific language, like PHP.

Identity in PHP4 and PHP5

The Bible says:

In PHP4 two object instances are equal if they have the same attributes and values, and are instances of the same class.
In PHP5 when using the identity operator (===), object variables are identical if and only if they refer to the same instance of the same class.