Posted by & filed under Programming.

The last step in signing the API request to AWS is calculating the signature using the secret key. Here is a subroutine to calculate it in a bash script. Make sure openssl is at least 1.0.0

function sign {
  kSecret=$(printf "AWS4$1" | xxd -p -c 256)
  kDate=$(printf "$2" | openssl dgst -binary -sha256 -mac HMAC -macopt hexkey:$kSecret | xxd -p -c 256)
  kRegion=$(printf "$3" | openssl dgst -binary -sha256 -mac HMAC -macopt hexkey:$kDate | xxd -p -c 256)
  kService=$(printf "$4" | openssl dgst -binary -sha256 -mac HMAC -macopt hexkey:$kRegion | xxd -p -c 256)
  kSigning=$(printf "aws4_request" | openssl dgst -binary -sha256 -mac HMAC -macopt hexkey:$kService | xxd -p -c 256)
  signedString=$(printf "$5" | openssl dgst -binary -hex -sha256 -mac HMAC -macopt hexkey:$kSigning | sed 's/^.* //')
  $(printf $signedString > $6)
}

Call it using

sign $KEY $DATE $REGION $SERVICE "$STRING" $OUTPUT

Posted by & filed under News & Politics.

There has been a lot of talk in the media lately about the future of the Android operating system. The trigger this time was the resignation of Android chief Andy Rubin.

One post in particular has caught my attention. Rather than focusing on Andy’s departure, it shines light on Sundar Pichai, currently head of Chrome OS project, who will be taking over Android. The article then claims Chrome OS and Android will merge and achieve what Windows 8 could not – single platform running on full gamut of devices.

The article is wrong on one fundamental level – Chrome OS and Android are completely different systems, designed with different goals in mind. Merging them together is simply impossible, one would cease to exist in the process. What can happen is feature migration from one to another. Chrome OS has the goal of proving the Web to be a viable operating system, with all data stored in the cloud, and the physical device being only a thin client accessing that data. It’s a great project, but is still an esoteric system, not for everyday use.

It’s hard to predict the future, especially in technology. Chrome OS and Android may one day merge, but I doubt it. Likewise, I don’t expect Android in the current state to run on a laptop, much like Gingerbread wasn’t meant to be run on tablets. Both technologies will evolve, shaped by Google, Google’s hardware partners, application developers, and the users. Where we end up is anyone’s guess.

Full disclosure: I’ve dedicated countless hours to application development on Android, and am heavily invested in its future.

Posted by & filed under News & Politics.

I updated my site & blog for 2013, making it more responsive and mobile-friendly.

As part of the redesign, I created a plugin to WordPress, connecting to my 500px account. It pulls in my profile once a day, posting any new photographs to the blog. This automated posting saves me from posting to the site manually, so hurray for laziness. I published the plugin on github under an MIT license if anyone is interested.

Best of luck in the new year!

Posted by & filed under Programming.

Doctrine 2.0 documentation recommends against serializing entities. If you ignore the documentation, you will be faced with PHP notices, such as

Notice: Unknown: "id" returned as member variable from __sleep() but does not exist in Unknown on line 0

as well as broken object relations on unserialized objects. But its very tempting to use the entities in situations that implicitly require serialization – for example in Zend_Auth. A “User” entity used in Zend_Auth would be written to session, and thus serialized implicitly, creating the already mentioned problems.

However, its relatively easy to create a proxy to the entity. For example:


class UserProxy {
    protected $entity;
    protected $identity;
   
    public function __construct($entity)
    {
        $this->entity = $entity;
        // Get the identifier from the entity
        $this->identity = $this->entity->getId();
    }
   
    public function __call($name, $arguments)
    {
        return call_user_func_array(
            array($this->entity, $name),
            $arguments);
    }
   
    public function __sleep()
    {
        return array('identity');
    }
   
    public function __wakeup()
    {
        $this->restore();
    }
   
    protected function restore()
    {
        if (!empty($this->identity)) {
        // Replace with however you get
        // the entity manager
        $entityManager = Zend_Registry::get('em');
        $this->entity = $entityManager
            ->find('User', $this->identity);
    }
}

Now you just use the proxy in place of the entity in situations requiring serialization.


$toSerialize = new UserProxy($userEntity);

Any method calls made to the Proxy will be forwarded to the entity by the magic method. If the Proxy object is serialized, upon waking up, it will use the identifier to restore the entity.

Posted by & filed under Programming.

Those of you using Bisna library to easily hook Doctrine 2 ORM into Zend Framework, may find that it is incompatible with Doctrine 2.1. The reason is the rewritten annotation reader in Doctrine 2.1, which Bisna doesn’t support. However, its easy to update it.

In Bisna/Application/Container/DoctrineContainer.php, find the method startORMMetadata (should be the last method in the file), and replace it with the following (apologies for messed up indentation :():


private function startORMMetadata(array $config = array())
{
$metadataDriver = new \Doctrine\ORM\Mapping\Driver\DriverChain();

// Default metadata driver configuration
$defaultMetadataDriver = array(
'adapterClass' => 'Doctrine\ORM\Mapping\Driver\AnnotationDriver',
'mappingNamespace' => '',
'mappingDirs' => array(),
'annotationReaderClass' => 'Doctrine\Common\Annotations\AnnotationReader',
'annotationReaderCache' => $this->defaultCacheInstance,
'annotationReaderNamespaces' => array()
);

foreach ($config as $driver) {
$driver = array_replace_recursive($defaultMetadataDriver, $driver);

// Register the ORM Annotations in the AnnotationRegistry
\Doctrine\Common\Annotations\AnnotationRegistry::registerFile(
APPLICATION_PATH . '/../library/Doctrine/ORM/Mapping/Driver/DoctrineAnnotations.php');

$reflClass = new \ReflectionClass($driver['adapterClass']);
$nestedDriver = null;

if (
$reflClass->getName() == 'Doctrine\ORM\Mapping\Driver\AnnotationDriver' ||
$reflClass->isSubclassOf('Doctrine\ORM\Mapping\Driver\AnnotationDriver')
) {
$annotationReaderClass = $driver['annotationReaderClass'];
$reader = new $annotationReaderClass();
$reader->setDefaultAnnotationNamespace('Doctrine\ORM\Mapping\\');
$reader->setIgnoreNotImportedAnnotations(true);
$reader->setEnableParsePhpImports(false);

foreach ($driver['annotationReaderNamespaces'] as $alias => $namespace) {
$reader->setAnnotationNamespaceAlias($namespace, $alias);
}

$annotationReader = new \Doctrine\Common\Annotations\CachedReader(
new \Doctrine\Common\Annotations\IndexedReader($reader),
new \Doctrine\Common\Cache\ArrayCache()
);
$nestedDriver = $reflClass->newInstance($annotationReader, $driver['mappingDirs']);
} else {
$nestedDriver = $reflClass->newInstance($driver['mappingDirs']);
}

$metadataDriver->addDriver($nestedDriver, $driver['mappingNamespace']);
}

if (($drivers = $metadataDriver->getDrivers()) && count($drivers) == 1) {
reset($drivers);
$metadataDriver = $drivers[key($drivers)];
}

return $metadataDriver;
}

You should be good to go. Hopefully this saved you some time in research. I’ll try to push this update to github as well.

Any comments about missed configuration options are always welcomed!