Month: February 2015

PHP Curl SSL on Windows

When developing on Windows I regularly found myself using the line below to circument SSL errors on Windows when using Curl in PHP:

curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);

If I do not set these curl options, the request would fail with the message: Details: SSL3_GET_SERVER_CERTIFICATE:certificate verify failed. This is a
warning you normally only expect when connecting to a host with a self-signed certificate or something else. But on Windows this also happens for correct
certificates, because the certificate chain cannot be established. This can be solved in two steps:

  1. Download file with root certificates from http://curl.haxx.se/docs/caextract.html
  2. Add the lines below to your php.ini file (where the path is where you downloaded the file in step 1.

    [PHP_CURL]
    curl.cainfo=c:\apps\php\cacert.pem

This post is based on a solution in a stackoverflow post.

Leave a Comment

Kanboard Trello Import tool

Recently I found kanboard, an open source tool which allows you to organize projects
and tasks on a board with columns. Until now I was using Trello. My preference is not to use
Cloud Services for my private data. Kanboard is a perfect alternative to Trello for the functionality that I use.

I wrote a small script to import a Trello json export via the Kanboard json RPC interface. This can be found
at github.

Leave a Comment

Amazon Elastic Transcoder Notifications

The Elastic Transcoder can be configured via the Simple Notification Service (SNS) to send notifications when a transcoding job changes
it state (new, in progress, completed, etc.). The details of these notifications are not defined clearly in the documentation, which is
why I list them in this post. These are actual notification from my set up in AWS. See the documentation
on how to set up the notifications.

Each notification has the default attributes every notification has. The Message attribute has a JSON encoded string that contains the
Elastic Transcoder specific information. See examples below, I only use the COMPLETED and ERROR type of notifications.

From the data the URL to the video can be deduced, if you know the configured output bucket for the pipeline in the Elastic Transcoder.

Completed

{
  "Type" : "Notification",
  "MessageId" : "dd1bf740-2a0a-5173-a792-ba70434938b4",
  "TopicArn" : "arn:aws:sns:eu-west-1:778005704149:ddnl-transcoding-dev",
  "Subject" : "Amazon Elastic Transcoder has finished transcoding job 1421240053904-6ozpim.",
  "Message" : "{\n  \"state\" : \"COMPLETED\",\n  \"version\" : \"2012-09-25\",\n  \"jobId\" : \"1421240053904-6ozpim\",\n  \"pipelineId\" : \"1419424647588-9osc91\",\n  \"input\" : {\n    \"key\" : \"uploads/0ad92625/ffb5d317/cef636ae/20150113101221.video.mp4\"\n  },\n  \"outputKeyPrefix\" : \"video/uploads/0ad92625/ffb5d317/cef636ae\",\n  \"outputs\" : [ {\n    \"id\" : \"1\",\n    \"presetId\" : \"1419429926952-dmb9yx\",\n    \"key\" : \"9946d18c.mp4\",\n    \"thumbnailPattern\" : \"9946d18c-{count}\",\n    \"status\" : \"Complete\",\n    \"duration\" : 4,\n    \"width\" : 480,\n    \"height\" : 480\n  } ],\n  \"userMetadata\" : {\n    \"todReplyId\" : \"5\"\n  }\n}",
  "Timestamp" : "2015-01-14T12:54:27.285Z",
  "SignatureVersion" : "1",
  "Signature" : "xxx",
  "SigningCertURL" : "https://sns.eu-west-1.amazonaws.com/SimpleNotificationService-xxx.pem",
  "UnsubscribeURL" : "https://sns.eu-west-1.amazonaws.com/?Action=Unsubscribe&SubscriptionArn=xxx"
}

Message JSON

{
    "state": "COMPLETED",
    "version": "2012-09-25",
    "jobId": "1421240053904-6ozpim",
    "pipelineId": "1419424647588-9osc91",
    "input": {
        "key": "uploads/0ad92625/ffb5d317/cef636ae/20150113101221.video.mp4"
    },
    "outputKeyPrefix": "video/uploads/0ad92625/ffb5d317/cef636ae",
    "outputs": [{
        "id": "1",
        "presetId": "1419429926952-dmb9yx",
        "key": "9946d18c.mp4",
        "thumbnailPattern": "9946d18c-{count}",
        "status": "Complete",
        "duration": 4,
        "width": 480,
        "height": 480
    }],
    "userMetadata": {
        "replyId": "5"
    }
}

Error

{
  "Type" : "Notification",
  "MessageId" : "6bc8acdb-8b39-5304-a8c7-e1ebec43d0ae",
  "TopicArn" : "arn:aws:sns:eu-west-1:778005704149:ddnl-transcoding-dev",
  "Subject" : "The Amazon Elastic Transcoder job 1421239606502-mfglq3 has failed.",
  "Message" : "{\n  \"state\" : \"ERROR\",\n  \"errorCode\" : 3002,\n  \"messageDetails\" : \"3002 2f870169-d5b7-4d5a-b042-a79498c8b428: The specified object could not be saved in the specified bucket because an object by that name already exists: bucket=ddnl-transcoding, key=video/uploads/0ad92625/ffb5d317/cef636ae9946d18c.mp4.\",\n  \"version\" : \"2012-09-25\",\n \"jobId\" : \"1421239606502-mfglq3\",\n  \"pipelineId\" : \"1419424647588-9osc91\",\n  \"input\" : {\n    \"key\" : \"uploads/0ad92625/ffb5d317/cef636ae/20150113101221.video.mp4\"\n  },\n  \"outputKeyPrefix\" : \"video/uploads/0ad92625/ffb5d317/cef636ae\",\n  \"outputs\" : [ {\n    \"id\" : \"1\",\n    \"presetId\" : \"1419429926952-dmb9yx\",\n    \"key\" : \"9946d18c.mp4\",\n    \"thumbnailPattern\" : \"9946d18c-{count}\",\n    \"status\" : \"Error\",\n    \"statusDetail\" : \"3002 2f870169-d5b7-4d5a-b042-a79498c8b428: The specified object could not be saved in the specified bucket because an object by that name already exists: bucket=ddnl-transcoding, key=video/uploads/0ad92625/ffb5d317/cef636ae9946d18c.mp4.\",\n    \"errorCode\" : 3002\n  } ],\n  \"userMetadata\" : {\n    \"todReplyId\" : \"5\"\n  }\n}",
  "Timestamp" : "2015-01-14T12:46:50.326Z",
  "SignatureVersion" : "1",
  "Signature" : "xxx",
  "SigningCertURL" : "https://sns.eu-west-1.amazonaws.com/SimpleNotificationService-xxx.pem",
  "UnsubscribeURL" : "https://sns.eu-west-1.amazonaws.com/?Action=Unsubscribe&SubscriptionArn=xxx"
}

Message JSON

{
    "state": "ERROR",
    "errorCode": 3002,
    "messageDetails": "3002 2f870169-d5b7-4d5a-b042-a79498c8b428: The specified object could not be saved in the specified bucket because an object by that name already exists: bucket=ddnl-transcoding, key=video/uploads/0ad92625/ffb5d317/cef636ae9946d18c.mp4.",
    "version": "2012-09-25",
    "jobId": "1421239606502-mfglq3",
    "pipelineId": "1419424647588-9osc91",
    "input": {
        "key": "uploads/0ad92625/ffb5d317/cef636ae/20150113101221.video.mp4"
    },
    "outputKeyPrefix": "video/uploads/0ad92625/ffb5d317/cef636ae",
    "outputs": [{
        "id": "1",
        "presetId": "1419429926952-dmb9yx",
        "key": "9946d18c.mp4",
        "thumbnailPattern": "9946d18c-{count}",
        "status": "Error",
        "statusDetail": "3002 2f870169-d5b7-4d5a-b042-a79498c8b428: The specified object could not be saved in the specified bucket because an object by that name already exists: bucket=ddnl-transcoding, key=video/uploads/0ad92625/ffb5d317/cef636ae9946d18c.mp4.",
        "errorCode": 3002
    }],
    "userMetadata": {
        "replyId": "5"
    }
}

Leave a Comment