Mar 04

ExtPHP LogoIt is something that I had to think about in my day job, because my team is migrating to PHP for web development and I believe that we simply do not have enough time for them to learn JavaScript’s intricacies, I needed to be the one person who would have to wrestle JavaScript when problems happened. I therefore needed a way to insulate them from the gory details, which is why I created ExtPHP.
As you may have guessed from subtle hints, such as this entry’s 12-feet tall header, ExtPHP creates a PHP wrapper for ExtJS.

ExtPHP In ActionI noticed, at dzone.com, that the last time someone created a wrapper for JavaScript, many readers complained about how intrusive his approach was. Well, be assured that ExtPHP does not foil ExtJS’ non-intrusive take. Of course, with ExtJS itself, it’s up to the developer to decide what kind of style they wish to adopt, and ExtPHP follows suit.

ExtPHP Doc ScreenshotI guess the introduction I wrote in ExtPHP’s documentation explains fairly clearly what the idea is: “ExtPHP is a wrapper for ExtJS. This is version 0.1, so I expect that a lot of things can be improved upon and your feedback is greatly appreciated. ExtPHP can be used to write both intrusive and non-intrusive Javascript, just like ExtJS itself. Use it responsibly. One of the many advantages of this design is that unknown/misspelled/misused methods are detected in your PHP editor rather than forcing you to debug your JavaScript code in your web browser. ”

Documentation? Indeed, I took some time to write a much-needed PDF document. Let me know how I can improve it, I am sure that you will find it lacking - because it is.

Anyway, I am releasing this as a “Technology Preview” and I will greatly appreciate your help beta-testing it.

Cheers.

Download

Sphere: Related Content

Mar 02

ADrive LogoYup. I am completely, arbitrarily, crowning them “best service” in my book.
So, you may ask, what amazing feature are they offering, thus justifying my edict?
After all, my previous favourites were xdrive.com and box.com, both piling on announcements of sexy new features, such as an AIR desktop or widgets.
Well, here it is, in all its glory: more free storage space. That’s all. Where xdrive offers 5GB, they, no-doubt, did the math and realized that with storage space becoming an ultra-cheap commodity, they could give their users 50GB free.
So, that’s it. The killer feature: more.
Oh, and, icing on the cake, their web interface doesn’t suck. A mandatory requirement that some free providers seem to forget.
OK, now I’ve listed the whole package.

Of course there are some concerns that I hope they address soon: their “about us” page is quite laconic and they do not seem, like many other Web2.0 outfits, to have thought of a business plan yet. Well, their site offers ads for paid storage services -that so happen not to be theirs. Weird.

Sphere: Related Content

Dec 04

KodachiKodachi v0.5.1 is out! It’s good news for developers who want to write plug-ins or if you wish to change the look and feel of the application:

  1. A demo plug-in is now included. All it does is add a new direct word to Kodachi’s vocabulary: ‘Demo‘. Type it, select some action, and it will display a Growl-like notification confirming your action. A very easy starting place for budding plug-in developers.
    -
  2. Kodachi’s user interface is now skinnable. Actually this goes a bit beyond a simple skin as you can change its behaviour alltogether. Note that when launching Kodachi, you will now see the new demo skin, called ‘Bezel‘, that I created. If you are familiar with QuickSilver, this is certainly an interface you are already used to. If you wish to work with the old interface, simply disable the ‘BezelInterface’ plug-in.
    -
  3. The installer now checks which version of .Net is installed on your PC, if any, and offers to install the correct version if necessary.

Download Kodachi 0.5.1

Sphere: Related Content

Dec 02

Air LogoEver used GenPass? SuperGenPass?
What do you mean, you do not know what I am talking about? Oh, you need to read on.
Of course, I am referring to SuperGenPass, developed by Chris Zarate. This wonderful bookmarklet automatically generates strong passwords for you, based on the url of the web sites you are visiting. You only need to memorize your master password and that is all.
This is a great tool on so many levels. It works for broken brains -like mine: you take all your passwords with you wherever you go since all you have to do is use the bookmarklet in any foreign browser. It is secure: no password is in fact stored anywhere.

What are the advantages of Air GenPass?

  • Well, first of all, it allows you to run the tool with web browsers that do not provide correct support for bookmarklets. Safari for Windows, I am looking at you.
  • If you are a tad paranoid, like me, but have to use browsers that are unable to store such a big bookmarklet, for instance Internet Explorer or Opera, you may not wish to use Chris Zarate’s server to run it every time you need to regenerate a password.
  • If you are at a friend’s house and they do not wish to let you install a bookmarklet in their browser, no problem: GenPass is portable and you can carry it around with you on a USB stick. Of course, one may argue that they still have to agree to install Air ;)

Explaining how this application works is a breeze, mostly because there isn’t much to explain. When you open it, you see three text fields. Enter your master password in the bottom one and click on the tiny icon to close it. The top text field will contain the password generated by the tool and you will be able to copy them to the clipboard using its own icon. The middle field is the one where you will enter or paste the link of the site you are currently visiting. Since Air is a desktop application, you can alternatively grab the link’s icon in your browser’s address bar and drop it on the application.

You can stop reading here and download the application directly if you are not interested in the technology behind this simple guy.

This is my first Air application. So, how hard was it?

I used the latest release of Aptana, which is very nice for creating Air applications. That is, as long as your Air applications do not rely on Flex.

application.xml contains all the information pertaining to your application. Note that this information is not used by the Air installer. It seems that the installer only looks at the certificate used to sign your application. Since the only certificates currently available can be bought from Thawte for several hundred dollars, I believe that the fact that the installer does not claim that “Chris was here!” is a reasonable trade-off.

You can edit this file manually to provide information such as application license and icons.

AIRAliases.js is the library that links the objects used by Air’s bridge.

If you are a total Air newbie, just like I was before I wrote this tiny application, you have no idea what is this bridge that I am talking about.

The first iterations of Air -formerly known as Apollo- did not come with a security model and it was potentially possible to do all sorts of nasty things with Javascript code that could simultaneously talk to the Internet and clobber your local filesystem if it felt like it.
Adobe quickly introduced their own security model, which happens to be kind of kludgey but certainly makes sure that any connection between the World and your local resources is voluntary.

unsafe.html is a html page that is included in a frame. This simple fact means that it has access to all your web browser resources and no access to your computer’s resources. This is the Web sandbox and is usually used as presentation layer.
In my case, of course, because I am a little piggy, al l the presentation is done in the top frame, which happens to have access to your computer resources but cannot run queries to the World or execute arbitrary code through the use of eval() or setTimeout()
Joking aside, it is perfectly legit to use the top frame as presentation layer; it just makes your life harder if you use some libraries that make extensive use of eval()

GenPass.html is our top frame, just described in the previous paragraph. It contains a lot of Javascript and the definition of the iframe
container that links to unsafe.html. I have no right to be proud of this Javascript because I did not write most of it. It’s actually Chris Zarate’s supergenpass bookmarklet code, only modified just to the point where it can be included in an Air application. The rest of the code is the UI, which relies on jQuery. Because, good news, jQuery works on Air!

<iframe id=”unsafe”
src=”unsafe.html”
sandboxRoot=”http://voilaweb.com/”
documentRoot=”app-resource:/”
width=”0%”
height=”0%”
style=”border: 0px; margin: 0px; padding: 0px; width: 0%; height: 0%; visibility:hidden;”>
</iframe>

What’s really important here -save for the fact that I am setting all sizes to ‘0′ because I do not want to display the frame- is the src attribute. The page that will run in the web sandbox is unsafe.html

function notworking()
{
$(’#working’).css(’visibility’, ‘hidden’);
}

// Bridge
var Exposed = {};
Exposed.notworking = notworking;

$(document).ready(function() {
document.getElementById(’unsafe’).contentWindow.parentSandboxBridge = Exposed;

Do not blink: this is where it’s happening!
If it were not for this bit of code, we would not need our iframe. But since we wish to be able to invoke notworking() using setTimeout(), now we have to jump through hoops. Fortunately, these are simple hoops once you understand them.
First, we create an object called Exposed. We store a reference to our callback method in this object.
Then, when the DOM is ready according to jQuery, we take advantage of the fact that top frames are allowed to access the content of iframes: we store a reference to Exposed in the child document (remember that when we created our iframe, we gave it an id of ‘unsafe’? This is how we are accessing it now).

When the user clicks on the ‘Copy to Clipboard’ icon, we display an animated gif: a couple spinning arrows. We wish to display these guys for a second, then get rid of them. Of course, that’s the rub: since we are in the local sandbox, we cannot invoke setTimeout(). No problem! Let’s ask our child document, who lives in the Web sandbox, to do this for us. We are keeping, in our top document, a reference to the only method contained in the child document: localpause(). It is now time to invoke it. Let’s have a look at its content:

function localpause()
{
setTimeout(’parentSandboxBridge.notworking()’, 1000);
}

It is pretty straightforward: after a second, it will invoke the parent’s notworking() method, which will hide the animated gif (see above).

And that’s all there is to it, really.

Feel free to leave a comment if you have more questions.

I want to download it!

Oh, yes. Sure. Clicky.

Sphere: Related Content

Aug 06

Backup 1Whether you are a web host, an IT professional or a hobbyist, if you have one or more headless Linux servers, backups are one of your main concerns. And incremental backups are your friends.
Amazon S3 (http://www.amazon.com/aws) offers a very interesting storage solution, especially since they lowered their already low rates.
It even comes with a tool called ’s3sync’ that works a bit like rsync.
Unfortunately it only works ‘a bit’ like rsync; it does not check if a remote file with the same timestamp and/or checksum exists, and it ends up using up much more bandwidth than you originally planned for.
This could be avoided if S3 supported rsync; unfortunately it does not.

An ideal solution would be a local rsync, which would be smart about copying files.
No problem! This can be achieved by mounting an S3 bucket as a local disk; here is how.

In this tutorial, I am going to refer to your headless web server as your ‘Linux box’. So, if your local box also runs Linux, please bear with me: I am not talking about this box!

Here we go:

JunglediskDownload the USB key version of Jungledisk from http://www.jungledisk.com/download.shtml and run it on your local machine. It does not matter if you’re running Windows, OS X or Linux. All three systems are supported. Jungledisk will create a configuration file called ‘jungledisk-settings.ini’
If you need to modify this file, run junglediskmonitor and modify your settings.

Download the Linux version of Jungledisk, expand the archive and copy ‘jungledisk’ to its own directory on your Linux box.
Copy your local jungledisk-settings.ini to your Linux box in the same directory as ‘jungledisk’. You do not need to copy and run ‘junglediskmonitor’ on that box, since all it would do is modify the .ini file.

Everyting from this point on is going to happen on your Linux box.

If you do not have Fuse, download it from http://sourceforge.net/project/showfiles.php?group_id=121684&package_id=132802
Expand the package, go to the new Fuse directory.
Type:
./configure --enable-lib
make && make install

If you forget --enable-lib, the dynamic library will not be created.

Alternatively you could use Coda instead of Fuse but it tends to come with your OS and you may end up using a wrong version of Coda with Davfs. And I like the flexibility of Fuse. Research it a little bit: installing Fuse buys you much more than what is covered in this tutorial.

Make and install libneon. You may already have a neon package installed. If so, you can try to proceed without downloading a newer version. If you systematically experience ‘mount’ - cf below - complaining about ‘invalid URL’, I recommend upgrading libneon.
Get it at http://www.webdav.org/neon/

Expand, go to the new directory, type:
./configure
make && make install

Make and install davfs. Get it at http://dav.sourceforge.net/
Actually, you may find a binary that perfectly suits your box and not even need to build it. Otherwise, type:
./configure
make && make install

Let’s create a user/group for davfs:
groupadd davfs2
useradd davfs2 -g davfs2

You now have all the pieces required. Let’s get crankin’:

Run ‘jungledisk’:
./jungledisk

You are likely to have a text-mode browser, either ‘lynx’ or ‘links’. Let’s pick one -in my case: ‘links’
links http://localhost:2667

If it displays an XML header rather than rejecting your connection, then jungledisk is running correctly.

Time to mount your disk. Here is how:
mkdir /mnt/J # (or any other directory you wish to use)
mount http://localhost:2667 /mnt/J --nolock -t davfs

The --nolock may seem a bit superstitious but in my experience mounting a remote FS without it can lead to catastrophic crashes.

You now have an unlimited disk drive mounted at /mnt/J/

If all this works correctly, you can now start thinking of mounting your disk at boot-up time.
First, you need to start ‘jungledisk’ everytime. Either create a start-up script in /etc/init.d and use chkconfig or if you wish to keep things simple, add a call to jungledisk at the end of your /etc/rc.d/rc.local. I have to check that the latter works though as I believe that Linux will try to mount your disk before calling rc.local

And finally, let’s make sure that we have an entry in /etc/fstab:
http://localhost:2667 /mnt/J davfs noauto,user 0 0

That’s all!

Backup 2Oh, wait. Right. What about backups?
As I wrote earlier, rsync remains your best bet. Here is how to run it:

mkdir -p /mnt/J/home/1
rsync -aHx --numeric-ids --no-whole-file --size-only /home/ /mnt/J/home/1/

This example shows how to perform smart backups of your /home directory; the reason why I am pushing this backup to a directory called ‘1′ is that I am performing real incremental backups with automated backup rotation.
If you have questions about it, I will write another tutorial where I explain how to use hard links to rotate backups without wasting disk space. But in the meantime, do not let that ‘1′ scare you.

So, what’s this then?
--no-whole-file is extremely important: rsync thinks that you are copying your files to a local disk and decides to favour local speed as opposed to saving on bandwidth usage. This can be very bad. This parameter forces it to be smarter than that.
-a tells rsync to use an ‘archive’ mode where all important files information is preserved
-H allows us to preserve hard links - not covered by ‘a’
-x is important as well: you will not end up creating back ups of whatever remote devices you have mounted locally
-size-only new: suggested by, I guess, Eric Johnson, is important for the reasons enumerated in his comments below (mtexte)

Eric also suggests using ‘inplace but I am not so sure about that yet.

OK, *now* that’s all (for now!)

Sphere: Related Content

Jul 22

FeedBurner LogoAs you, no doubt, have noticed, I have decided to stop serving this blog’s content using Wordpress’ standard RSS script; instead, Feedburner is now in charge -note that this option is available to any Zteo blog owner.

Why would I want to do that? An obvious answer is that it keeps track of my feeds’ popularity and is amazingly friendly. But Feedburner can do much, much more for you than just counting readers.

  1. What about those readers who are afraid of syndication? There are some good reasons to be and the main one is that, to use my case as an example, reading RSS feeds is definitely sucking all my free time -the whole daily hour of it I was hoping to scrape… For these user, it is possible, using the same engaging interface, to ask Feedburner to send any new post of interest to their email inbox. No need to maintain a list of feeds, download an RSS reader or find an online one that doesn’t suck.
    .
  2. Select your feed’s format on demand: no need to decide between RSS and Atom. Feedburner will automatically present to your readers whatever format they favor.
    .
  3. Feedburner will also adapt your RSS output to a more palatable one if you’re still using an old version of your blogging program.
    .
  4. NetworkAuto ping: Whenever you make a new post, Feedburner can be configured to alert more blog directories than your default Wordpress installation does. And it does it seamlessly.
    .
  5. Add to Digg/Delicious/FaceBook/etc: I know there are plugins that do this, and do it well. But Feedburner does this AND many other things for you.
    .
  6. Create your own widgets for syndication: You too can offer your supporters to display your feed’s widget on their personal page. Certainly adds quite a touch of professionalism to your blog. You can event create a feed ticker or an animated ‘headline’ but I am having a hard time finding any advantage in doing so.
    .
  7. Create an event feed: Just like upcoming.org, you can have your own feed. Not everyone is going to find a use for this feature but if you’re talking at conferences or simply trying to remind your family of important personal events, it is for you.
    .
  8. Blog PageRe-export your feed to html: …basically, close the loop. From your web page to a feed to another web page. This feature can be helpful if you wish to integrate your blog in another web site. No need to program anything, just copy/paste their code.
    .
  9. Protect your feed: Your feed can be password-protected, so that only your friends/subscribers have access to it.
    .
  10. Monetize: This one is a bit trickier because it does not depend on you. If the good folks at Feedburner think that your blog is valuable, you may suddenly find the Feedburner fairy knocking at your door and offering to join their ad network. I really do not know how good that network is but I imagine that if you get contacted by Feedburner, your blog must be worth something and it’s good news. Period.

These are the things I’ve learned about Feedburner since I started using their services. Let me know if I am missing some interesting stuff in this post.

Sphere: Related Content