ucf.jar gotchas

Note 16-Oct-2017: For High Sierra users: you need to install Oracle JDK 7 or suchlike and then switch to JDK 7, otherwise ucf.jar won’t run because of missing security providers.
The link below works at this time, but Oracle’s links seem to move stuff around frequently so you might need to poke around a bit to find JDK 1.7u80. Grab it when/while you can.
On the command line, something like

/usr/libexec/java_home -V

shows you what Java versions you have. I then use

export JAVA_HOME=`/usr/libexec/java_home -v 1.7.0_80`

or similar to switch to the JRE 7 before running ucf.jar

Lately I made some automated build setup for an Extension to one of the apps in the Adobe Creative Cloud, and I decided to use ucf.jar for signing (see https://www.adobeexchange.com/resources/7).

In the process, I bumped into some gotchas and interesting tidbits.

I suspect the info below could be old news to many people, or ‘duh’-level stuff that is spelled out in the documentation, but just in case it is not, it’s documented here.

I’ll document my findings here, in the hope they come in handy for someone struggling through a similar ordeal.

Funny side story: it’s already happened multiple times to me that I go out on a Google hunt to resolve some weird issue, and eventually bump into some info I wrote up somewhere, and then forgot about (in the most recent time it happened to me was on the Adobe forums – https://forums.adobe.com/thread/959112).

So, really, this article about ucf.jar is mostly about allowing Google to supplement my own memory. In a few years time I’ll no doubt will be struggling with ucf.jar and will end up on this page. Hi, Kris from the future!

.debug in ZXP, yes we can

First thingy: ucf.jar normally strips out .debug files. This was something I never checked or verified before now, but it looks like ucf.jar does The Right Thing, and strips out .debug

That is a good thing: you don’t want to deploy a ZXP that has a .debug file in it: it opens up a potential back door and some malicious person might try to break in via one of the open ports.

However, my extension was exhibiting different behavior after being packed up into a ZXP, so I really, really wanted to get a ZXP with a .debug file included.

After some poking I found it is possible to force the .debug file to come across by explicitly listing it on the command line.

Something akin to:

 java -jar ./signingtoolkit/ucf.jar  -package -storetype PKCS12 -keystore "$certfile" -storepass "$certpassword" -tsa http://timestamp.digicert.com com.rorohiko.harebrained.zxp -C ../build/dist/com.rorohiko.harebrained . -e ../build/dist/com.rorohiko.harebrained/.debug .debug

seems to do the trick ($certfile and $certpassword are bash environment variables). The trick is to explicitly add in the .debug file.

After that, Anastasiy’s Extension Manager (http://install.anastasiy.com/) happily installs the ZXP with the .debug file included.

Kill cfprefsd

My next head-scratcher came when I was mucking around on my Mac with PlayerDebugMode and LogLevel and the changes I made did not ‘take’.

Turns out there is some caching of preferences going on on Mac OS X, and you need to force the cache to be cleared.

The simplest method I found is to kill cfprefsd.

I now use a few simple double-clickable command-line bash scripts on my Mac to enable and disable the debug mode.

This is my ‘enable PlayerDebugMode’ script. Store it in a command-line script whose file name ends in ‘.command’ and it will be double-clickable from the Finder. Don’t forget to chmod +x !

defaults write com.adobe.CSXS.7.plist PlayerDebugMode 1
defaults write com.adobe.CSXS.7.plist LogLevel 5
killall -u `whoami` cfprefsd

And this is my ‘disable PlayerDebugMode’ script. Same deal.

defaults write com.adobe.CSXS.7.plist PlayerDebugMode 0
defaults write com.adobe.CSXS.7.plist LogLevel 0
killall -u `whoami` cfprefsd

PlayerDebugMode could be something else

The next thing that I figured out is that PlayerDebugMode seemed to only affect the signature verification of the ZXP, at least for the app I was working with.

My incorrect assumption was that PlayerDebugMode would also be turning on or off the debug mode.

That seems not to be the case: as far as I could tell I could leave PlayerDebugMode set to 0, and was still be able to debug the (signed and installed) ZXP, as long as it contains a .debug file.

I have not checked whether this is true for all Creative Cloud applications, but it sure was for the one I was working with.

ucf.jar don’t like no spaces

At some point in time, my fresh ZXPs failed to install due to signature issues.

As it turns out, that was because one of the files in my ZXP had a file name with a space in it.

That throws ucf.jar. I suspect it accounts for the file in the signature, but fails to include the file into the ZXP.

Unlike ucf.jar, ZxpSignCmd does not seem to have this issue.

Once I changed that file name all was well again.

Hope this helps!

Hacking cefclient for lazy CEP debugging

When working on extensions for the Adobe Creative Suite, you can use Chrome as a debugger.

When debugging is enabled, your extension will open up a port, and then you point your browser to http://localhost:<whateverport> to get to the debug interface.

Sadly enough, this stuff is kind of ‘broken-ish’ (see http://raspi.rwf.co/brokenish.html).

For example, you cannot type in the console to inspect stuff, so debugging is a bit frustrating.

Ole Kvern mentioned on the Slack group (adobedevs.slack.com) that a lot of this pain and suffering can be alleviated by using a slightly older cefclient instead of Chrome. See http://opensource.spotify.com/cefbuilds/index.html and look around in the older builds.

I did that and it works a treat.

I prodded and poked around a bit in the available builds, and found that version 51.0.2704.47 works OK for me. There might be more recent versions that work too, but I called ‘good enough’ on this one, and I did not put in any more time.

However, I am lazy. So here’s a little hack I performed. It’s nasty, but it works. I am using a Mac. I assume a closely related similar hack would be possible on Windows.

I only use this cefclient app to do CEP debugging, so I have no qualms making a hacked mongrel version to suit my needs.

For it to work, your debug URL must be exactly 21 characters long (e.g. http://localhost:8070 or suchlike. That means: you want to use a 4-digit port number in your .debug file).

Open the cefclient binary with a Hex Editor (on Mac, it is at …/cefclient.app/Contents/MacOS/cefclient ).

Search for the text ‘http://www.google.com’. It occurs twice – you want the one around position 0x552288.



Replace the text with whatever your debug URL. Make sure to not add or remove bytes. You need to overwrite the URL with something of the same length.

Save and Quit.

And now, each time I launch cefclient, it immediately goes to http://localhost:8070.

The clean way to do this would be to make a variant of cefclient that accepts command-line parameters. I might do that at some point; it would allow me to easily add a ‘debug’ button to my extensions and have it launch the debugger. Together with my old ‘dive into it’ hack (https://coppieters.nz/?p=63) that might make for a more seamless debugging experience. For now, this nasty hack will have to do…

GetURL for InDesign, Revisited (now with https)

Note 1-Nov-2020: Make sure to check out my novel approach to GetURL: making curl available in ExtendScript. Not just for InDesign – any Adobe app that supports ExtendScript can use this. More info here:


Note 16-Dec-2019: Latest installer which also supports InDesign 2020 and macOS Catalina:


GetURL: some history

A long, long time ago, I wrote a bit of sample code to demonstrate state machines.

On a whim, I decided to implement a bit of the HTTP protocol in ExtendScript and InDesign.

It was never intended to be a full HTTP socket implementation, but in the end, it turned out that the sample served a purpose for many people, as it allowed them to interact with HTTP-based services from ExtendScript.

It was not very fast, and could not handle many HTTP features.


Over time, I added a few little tweaks to help people out, but by now GetURL.jsx must be a contender for the longest living stopgap measure ever.


Recently, more and more people started asking me for HTTPS support.

Sadly enough, crusty old GetURL.jsx is not up to the task: for efficient HTTPS support, things get a lot more complicated.

Doing it all in pure ExtendScript would be nearly certainly too slow.

So, I decided to find a different solution.

What I am presenting here is ‘work-in-progress’, or maybe better ‘mucking-around-in-progress’.

I am playing around, and try things out. I will probably be tweaking this for some time to come, but it currently works fairly well as-is, so for people in need, they can grab what I have, as-is, and try to make sense of it.

In the following post, I’ll show a solution that allows the ExtendScript coder to write something as simple as

#targetengine TestSomewhere
#include "JSInterface.jsx"


// or...
function handleData(data) { 


// or...

var url = "https://www.rorohiko.com/welcome.msg";

Bear with me…


For a while now, InDesign and other Creative Cloud apps have been including the Adobe Common Extensibility Platform (CEP) and Extensions.

Essentially, an Extension is akin to a browser (Chrome) with a server (Node.js) all rolled into one, all running as an ancillary process inside of InDesign.

As a result, an InDesign scripter now has two totally separate programming environments at their disposal.

These environments share very similar languages (ExtendScript and JavaScript), which is often a bit confusing.

The ExtendScript (ES) programming environment is ‘inward facing’: it is tightly integrated with InDesign and can interact with the InDesign Document Object Model (DOM).

The JavaScript (JS) programming environment is ‘outward facing’: it can drive user-interfaces that are contained within floating panels and dialog boxes.

Because the JS environment has a complete Node.js available, writing things like an https-capable GetURL replacement is trivial on the JS side.

But that is not a proper solution for the ExtendScripter. A bit of extra work is needed.

Communicating between ES and JS

The ES and JS environments are quite separate, and run independently of one another. They don’t have a direct connection.

Instead, there is a ‘callback’-based interface. From the JS environment, one can initiate some operation in the ES environment. When the ES environment completes the task, it calls back to the JS environment with the results.

To compound the issue, the JS environment provides multiple independent runtimes (i.e. you can run multiple extensions concurrently), whereas the ES environment is a single-tasking shared resource: when an operation is launched from any of the active JS environments in ES, the ES environment gets busy in mumble mode, and any subsequent ES operation request from any other JS will stall until the previous ES operation is finished.

Lots more info about all this can be found here:



One thing that always annoyed me a bit was the asymmetrical nature of the interface between JS and ES.

In JS you have a ‘CSInterface’ thingy and you can call sumtin’ like

csInterface.evalScript(<some script>, <some callback>)

to execute a script in ES, and be woken by the callback when it is done.

JSInterface: Evening The Score

To even the score a bit, I first set out to create a similar ‘JSInterface’, as a component of my ‘GetURL.jsx’-replacement.

JSInterface allows you to call JS from ES.  You can receive a callback when it is done.

The extension includes a CSXS manifest file that covers CC 2015 and CC 2017. I suspect it might run with lower versions after a bit of tweaking in the manifest, but I have not tried that.

For this to work, you also need to run your ES script in a persistent engine.

If you were to run in the ‘main’ (default) engine, the callback would not work because the whole engine vanishes out of existence as soon as the JS call returns and the ES script can run to completion.

Most of the time, a JS call will return before it completes, and a non-persistent ES engine will have gone by the time the JS call wants to perform a callback.

The main idea behind JSInterface is to allow developers to be ‘ExtendScript’-centric – i.e. concentrate on ExtendScript and ignore most of the JS details.

Often, you want to write some simple ExtendScript code, and don’t have any need for all the bells and whistles JS offers… except for one or two small features.

That’s where JSInterface comes in: you write all your code in ES, and occasionally call out to JS when you need something special.

JSInterface has a plug-in architecture. It currently comes with a single plugin, called ‘getURLPlugin’ which implements the coveted getURL method that can handle HTTPS.

Additional plug-ins can be added as needed: the idea is that you write little functions using JS/Node.js and expose them to ES via the plug-in architecture. You can then easily call them from ES, and JSInterface takes care of the glue.


Note: all material as-is: there is not much documentation. Use at your own risk.

You have a few options:

  • Simple Installer:
  • If you want to delve a bit deeper: ZXP file and source code:

    This source code folder contains
    – a subfolder call ‘dist’ containing a ZXP file
    – a subfolder called ‘com.rorohiko.extendExtendScript’ with all source code

  • Run the installer, or install the com.rorohiko.extendExtendScript.zxp, or install manually.
    For installing the ZXP file, you use something like Anastasiy’s Extension Manager (http://install.anastasiy.com/), or ZXPInstaller (http://zxpinstaller.com).
    You can also set the CEP debug flag, then copy the ExtendExtendScript extension manually from the source code folder into one of the Adobe extensions folders.
    Restart InDesign for good measure.
  • To see it in action: grab the following three files from the

    and put them in the InDesign scripts folder or a subfolder thereof:


    CallGetURL.jsx is the actual sample code; the other two files are modules that CallGetURL.jsx depends on.

  • Double-click CallGetURL.jsx. A dialog with some data retrieved from an HTTPS-based URL should display.


If you want to delve into JSInterface or add plug-ins or suchlike, you’ll need to read a bit of code. Not much documentation there, but the code should be more or less straightforward.

Errata and Notes

Note 16-Dec-2019: There is now an easy installer for ExtendExtendScript which supports macOS Catalina and InDesign 2020.

Note 13-Mar-2018: There is now an easy installer for ExtendExtendScript. See https://coppieters.nz/?p=220

Note 11-Oct-2017: there was a bug in node_modules/GetURL/index.js. Around line 105 a line is missing:

 protocol.get(parsedURL, function(response) { protocol.get(parsedURL, function(response) {
 response.setEncoding('binary'); // <<< THIS IS MISSING
 function checkForCompletion() {

I’ve updated the downloadable .zip file

I’ll be at the Creative Developers Summit in Atlanta in May 2017 – anyone in need of more info or assistance, feel free to catch up with me there!

Things To Come

Silly thoughts: I want to do some debugging/monitoring support in the panel (e.g. allow console.log from ExtendScript). Maybe get started on a ES Toolkit replacement or ScriptUI replacement as a panel?

Creative Developers Summit

From InDesign To Scribus, An Automator’s Perspective – part 1 of many.

(writing in progress)

I bit the bullet – I am going to dig into Scribus, and add it to my toolkit.


Adobe is not what it used to be. The company becomes increasingly erratic and difficult to work with for a third-party developer. As far as I can tell, Adobe is ‘doing a Quark’ on a large subset of its users.

So, after ten years of neglecting it, I’m getting back up to speed on automation with QuarkXPress 2015, and I am also looking at Scribus.

I looked at Scribus a while back and did not get very far before I lost interest. As far as I could tell, Scribus was nowhere near as powerful as InDesign, so it would not be an option for many people.

This time around I decided to look mainly at what it can do, rather than concentrate on what it cannot do. Scribus will only improve if more people start using it; it’s a chicken-and-egg situation.

I want to make sure I can help automate projects where Scribus is an option. And Scribus is definitely powerful enough to be useful for a range of real-life projects.

Getting into Scribus

Getting into Scribus will be different for everyone.

I’m looking for things that I’m familiar with. As I go, I try to map things I know from other environments onto things I discover in Scribus.

I just spent half an hour with Scribus and its documentation, and as far as I can tell, the available documentation is not a good resource for the kinds of questions I have as an system designer and automator.

What I intend to do here is keep track of my questions and the answers I found.

Anyone else in the automation game is bound to have similar questions and might find my notes useful.

I’ll be using a Mac most of the time, but I’ll also take sneak peeks at the Windows and Linux versions along the way.

I’ll be looking at both Scribus 1.4.5 and Scribus 1.5.0. According to the web page, 1.4.x is a stable version, whereas 1.5.x is a development version.

1.5.x has some interesting things in its feature list, like IDML import. I’ll be trying that out!

What about scripts?

Being in automation, this is an important point for me.

Scribus can be scripted, and the ‘native’ scripting language is Python, rather than ExtendScript. That’s cool.

Ok, let’s try to do a few ‘Hello World’ scenarios and see if we learn anything.

First, I did a bit of snooping, stole some sample code left and right, and came up with the following script:

#!/usr/bin/env python
# -*- coding: utf-8 -*-

import sys
import scribus
scribus.messageBox('Python Version', sys.version, icon=scribus.ICON_NONE, button1=scribus.BUTTON_OK)

I saved this file to my desktop as Version.py, and then used the Script – Execute Script… menu item to run this script from Scribus 1.4.5 and 1.5.0.

From Scribus 1.4.5 on Mac OS X 10.11:

Screen Shot 2015-10-08 at 6.04.05 PM

From Scribus 1.5.0 on Mac OS X 10.11:

Screen Shot 2015-10-08 at 7.11.07 PM

This tells me that Scribus uses Python 2.x, and that it uses an embedded Python interpreter, rather than relying on the Python interpreter provided by the Mac OS. Otherwise I would expect the two Python interpreter versions to be identical.

On Windows 7 x64 with Scribus 1.4.5:

Screen Shot 2015-10-08 at 7.00.02 PM

And with Scribus 1.5.0:

Screen Shot 2015-10-08 at 7.13.02 PM

Looks like the Windows versions both embed the same version of Python.

It looks like I’ll need to install Ghostscript separately to enable some of the Scribus functionality relating to Postscript and EPS. I’ll look into that later.

Where are the scripts?

The second thing I want to know: where are the scripts? When you look at the Scribus Script (in 1.4.5) or Scripter (in 1.5.0) menu, it shows a whole range of sample scripts.

I’ll refer to the menu item as the Script menu item, even though it is called Scripter in 1.5.0. For example, when you see me mention a menu item Script – Show Console, it might actually be called Scripter – Show Console.

On the Mac, the scripts shown in the menu are located inside the Scribus app. On my system that’d be:


On Windows I found them here:

C:\Program Files\Scribus\share\scripts

This list of scripts shown in the menu seems to be refreshed only on restart of Scribus. If you add or modify any scripts while it’s running, the menu won’t update. This is unlike InDesign, where the Scripts Palette is dynamic and updates as scripts are added or modified.

Separate from that, there is also a configurable path to a scripts folder, which can be accessed via the Scribus – Preferences – Paths  (in 1.5.0) or Scribus – Preferences – General (in 1.4.5) menu item.

This folder can be set to something like, say,

/Users/kris/Documents/Scribus Scripts

Somewhat surprising: this folder is only used when you use the Script – Execute Script… menu item: it is the default folder location your dialog will open to.

It does not affect the list of scripts shown in the Script menu; that folder location seems to be hard-coded.

How does the console work?

For my first test, I used the scribus.messageBox function to plunk something into a dialog. However, for debugging and so on, I’d love to get some continuous text output.

My next question is: how can I write to a console from a script?

There is a console under the Script – Show Console menu item, but that was not really what I was looking for.

It took me a bit of searching, and as it turns out, the secret to the Scribus Console window seems to be function key <F9>.

Enter or copy-paste a script in the top half of the Console, then press <F9>.

Depending on how your Mac is configured you might need to change the System Preferences, or possibly press <fn>-<F9> or something like that.

Screen Shot 2015-10-09 at 2.45.53 PM

Check your System Preferences – Keyboard and System Preferences – Mission Control setup.

But that’s not really what I was after. I am looking for a way to get debugging info out from my scripts into a scrolling window.

The first method that worked for me was to start a Terminal window, and then navigate into the Scribus.app.

Then launch Scribus from the command line. After that, I get to see any output from Python in the Terminal window.

First I launch Scribus via the Terminal:

cd /Applications/Scribus.app/Contents/MacOS/

It spits out some information:

Path = /Applications/Scribus.app
"scpaths: bundle at /Applications/Scribus.app"
"scpaths: doc dir=/Applications/Scribus.app/Contents/share/doc/scribus/"
"scpaths: icon dir=/Applications/Scribus.app/Contents/share/scribus/icons/"
"scpaths: font dir=/Applications/Scribus.app/Contents/share/scribus/fonts/"
"scpaths: sample dir=/Applications/Scribus.app/Contents/share/scribus/samples/"
"scpaths: script dir=/Applications/Scribus.app/Contents/share/scribus/scripts/"
"scpaths: template dir=/Applications/Scribus.app/Contents/share/scribus/templates/"
"scpaths: lib dir=/Applications/Scribus.app/Contents/lib/"
"scpaths: plugin dir=/Applications/Scribus.app/Contents/lib/"
"scpaths: QML dir=/Applications/Scribus.app/Contents/share/scribus/qml/"
"scpaths: qtplugins=/Applications/Scribus.app/Contents/PlugIns:/Applications/Scribus.app/Contents/MacOS"
Fontconfig error: Cannot load default config file

Then I run a little ‘Hello World’ Python script via the Script -Execute Script… menu item.

#!/usr/bin/env python
# -*- coding: utf-8 -*-

import sys
print "Hello World"

That makes ‘Hello World’ appear in my terminal window.

Another way that works is to use the Python syslog. The script

import syslog
syslog.syslog(syslog.LOG_ALERT, 'Hello in syslog')

makes a log entry appear in the /var/log/system.log file.

What about the scribus module

I started Scribus from the command line as shown before, and then ran the following script:

#!/usr/bin/env python
# -*- coding: utf-8 -*-

import scribus


That made it spit out oodles of documentation in the Terminal window.

You can also simply type


into the Console window, then hit <F9>.

To come

Here’s a bunch of stuff I still want to look into:

Scribus console mode

C++ plug-ins:




Extension Scripts vs. regular scripts?

UTF-8 and stuff? How does it handle file names with non-ASCII characters? And text with non-ASCII characters?

Database publishing. Maybe tie a FileMaker and/or MySQL database to Scribus, just to try it out?

Must use Symbolic Links Instead of Alias for InDesign CC 2015 on OS X

Here’s a little tidbit. It’s not much, but it’s a little annoyance in InDesign CC 2015, and how I’m working around it.

It’s particular to my workflow. As everyone has their own preferred way to do things, and I suspect not many people have the same workflow as I do, this might be a worthless tip, but I am putting it out nevertheless, just in case. I hope this helps someone!

In previous versions of InDesign, you could add stuff to the Scripts Panel by means of a Mac OS X alias. With InDesign CC 2015, that does not work any more, and you must use a symbolic link instead.

Some more detail:

I do most of my InDesign script development with InDesign on a Mac. My workflow is often as follows:

– I have some Git repository with ‘stuff’ under development

– For InDesign scripts, I’ll have a project folder with the script under development and some other ‘subservient stuff’ – helper files, read me files, PHP scripts, XSLT files,…

– To test my script, I like to add it to the InDesign Scripts Panel, so I can run it from InDesign by double-clicking the script on the Scripts Panel.

I have this ‘habitual process’ to create a reference to my script on the Scripts Panel; I perform the following steps:

1) Start InDesign CC 2014 or earlier, and go to the Scripts Panel

2) Right-click (or Control-click) the User folder, and select Reveal in Finder. The Scripts folder opens in the Finder

3) Go find my source code folder in the Git repository

4) Drag the project folder containing the script and the helpers while holding Command+Option, and drop it inside the Scripts Panel folder.

That creates an alias which references the project folder inside the Git repository.

In InDesign CC 2014 and earlier, the alias works like ‘the real thing’: you get a disclosure triangle, etc…

(click to see larger version):
Screen Shot 2015-10-07 at 5.01.11 PM

Enter InDesign CC 2015. This approach does not work any more. Yay.

The workaround is to use a symbolic link rather than an alias.

It’s not as quick, but it works, at least for now.

Here’s my new procedure:

I often use a tool called cd to… which helps me a bit:


This tool allows you to click a button in a Finder window for a particular folder, and it automatically opens a Terminal window that has been ‘cd’-ed to that folder.

So, now my procedure is:

1) Start InDesign CC 2015, go to the Scripts Panel.

2) Right-click (or Control-click) the User folder, and select Reveal in Finder. The Scripts folder opens.

3) Go find my source code in the Git repository

4) Select the Scripts Panel folder icon in the Finder window. Then click the cd to… button, so a Terminal window opens inside the Scripts Panel folder.

5) Start typing


Now drag the script source folder from the repository and drop into the open terminal window, so it auto-types the full path for you. Then continue typing


Don’t forget the trailing period-character. The end result is the command to create a symbolic link, e.g. something like:

ln -s /Users/kris/Documents/Controlled/Rorohiko/Crawler .

Hit <Enter>.

The folder now appears on InDesign scripts panel and works as expected.

(click to see larger version):
Screen Shot 2015-10-07 at 5.24.57 PM

Adobe CEP Debugging – Diving Right Into It

(Note June 16, 2017: I updated CEFPakPatcher.zip  again – previous fix did not work, and also to provide better error messages).

(Note June 2, 2017: I updated CEFPakPatcher.zip to work with more recent versions of Mac OS).

Download link: https://www.rorohiko.com/downloads/CEFPakPatcher.1.0.2.zip

Or – how to avoid wasting time when debugging an Adobe Creative Suite Extension.

If you’re developing extensions for an Adobe Creative Suite app like InDesign or Illustrator, you’re probably familiar with the debugging facilities.

Essentially, while your extension is running ‘inside’ the Creative Suite, you launch Chrome, and visit a special URL to access the Chrome Developer Tools.

More info about all that can be found here:


One thing that cramped my style was this:

Screen Shot 2015-02-04 at 1.44.33 pm


Each time I wanted to get into the debugger, I had to first access the correct URL, then click index.html.

In the heat of cutting code, that click is really one click too many.

What I really wanted was to access this URL and get the debugger. I very, very much dislike that extra click.

So, I figured out a way to get rid of it. My trick is to patch up a file called cef.pak.

Before anything else: if you want to try this out, you do it at your own risk. I do not accept any responsibility of this thing blows up. All I can say is that it works for me. Caveat emptor.

This cef.pak file can be found in various locations ‘below’ the various Adobe Creative Suite apps.

The first step is to find the copy, or copies, of this file that you want to patch.

On Mac, it’s inside some framework.

On Windows it’s in a subfolder of the Creative Suite App.

You need to patch cef.pak for each individual application (e.g. if you only do it for InDesign, Illustrator won’t be affected).

I’ll leave locating these files as an exercise to the reader.

As an example, here I am showing you the Mac location inside InDesign CC 2014.

Screen Shot 2015-02-04 at 1.49.49 pm

And a second example: the location of the file inside Illustrator CC 2014:

Screen Shot 2015-02-04 at 1.56.29 pm


Now that you’ve found the file, you can grab my little patch program.

It’ll go searching for a little bit of JavaScript, then overwrite it with a different bit of JavaScript inside cef.pak.

Now, I am assume you’re a developer, and you can live with a few rough edges.

Hence, the patcher program is not idiot-proof, so please make sure to read carefully what follows.

First of all, you can download my patcher here:


Before anything else: do not double-click the application you’ll find inside.

It’s meant to be used in a drag/drop fashion, and merely double clicking simply launches it, doing nothing until you hard-kill it.

If you could not help yourself, and double-clicked anyway, you’ll have to find the CEFPakPatcher task in the task list and kill it. This is one of the rough edges I referred to before.

Once downloaded, decompress things; you’ll find Mac and Windows versions – there’s a bit of zip-in-zip going on.

IMPORTANT: The cef.pak file might have restricted permissions (e.g. only root can write): you’ll probably have to loosen the permission restrictions on the containing folder and on the file before using the patcher tool.

E.g. on Mac with CC 2015, I have to do a ‘chmod 666 cef.pak’ before I run the tool, then revert back with a ‘chmod 644 cef.pak’ afterwards. With more recent Creative Cloud updates, I find I also need to loosen the permissions on the enclosing directory – otherwise it cannot make a backup.

Note the two files cef_patcher_original.txt and cef_patcher_replacement.txt.

Inside these text files you’ll find two snippets of JavaScript.

function onReady() {
  if(this.readyState == 4 && this.status == 200) {
    if(this.response != null)
      var responseJSON = JSON.parse(this.response);
      for (var i = 0; i < responseJSON.length; ++i)


function onReady() {
  if(this.readyState == 4 && this.status == 200) {
    if (this.response != null) {
     var responseJSON = JSON.parse(this.response);
     window.location.href = 

In cef_patcher_original.txt  you find the original script that currently lives inside cef.pak.

Side note:  this script has a bug in it: there are some curly braces missing and the if (this.response != null) only applies to the first line behind it. The for is not part of the if, but it should be.

This script is used by the CEP debugger runtime to generate the initial web page with the clickable index.html link on it.

The second script is my patched replacement.

Instead of building a menu, I simply, and impatiently, redirect the window.location.href to the first ‘secret’ debugger URL I can get my hands on (this URL is different every time).

The patcher I made is ‘white-space-smart’: it ignores inconsistencies and mismatches in white space when searching or patching.

Because we’re patching in-place, the patched script must be exactly the same length as the original.

My patcher program achieves that by first ‘collapsing’ all spaces in the replacement script (so all multi-white-space become single spaces), then appending extra spaces until the replacement is exactly the same length as the match it found in cef.pak.

When you drag/drop the icon for the file cep.pak onto the icon for CEFPakPatcher, the patcher program will search for a match against the cef_patcher_original.txt and replace it with the contents of cef_patcher_replacement.txt (making sure the replacement is the exact same length).

It will also make a copy of cep.pak in the file cep.pak.original so you can always ‘undo’ what the patcher did.

For the Windows version, you have to change the properties so CEFPakPatcher.exe can run as an administrator, and have the necessary privileges to overwrite part of cef.pak.

Screen Shot 2015-02-04 at 2.30.15 pm


On Mac, you need to have an account with administrative privileges. Also make sure the permissions on cef.pak allow you to overwrite it; temporarily do a chmod 666 if need be.

Drag-dropping cef.pak onto the icon for CEFPakPatcher.app or CEFPakPatcher.exe makes a copy of the file, then patches the file.

Screen Shot 2015-02-04 at 2.33.18 pm

If you accidentally try to re-patch the file, nothing will happen (as the original text won’t be found).

I expect that in future versions of the Creative Suite, the JavaScript in cef.pak will change (e.g. Adobe might fix the JavaScript bug).

In that case, you’ll probably have to adjust the contents of cef_patcher_original.txt accordingly, and possibly also cef_patcher_replacement.txt.

(That is, unless I find the time and inclination to do it and update my patcher).

If and when that happens, the easiest is to inspect the source for the debugging web page in your browser, then make an adjusted version of cef_patcher_original.txt and cef_patcher_replacement.txt.

Google ChromeScreenSnapz001

Make sure that the script in cef_patcher_replacement.txt is not larger than the script it replaces!

You also might want to inspect cef.pak with a hex editor to make sure all is as it should be.



wxMaxima on Mac OS X Yosemite 10.10 with MacPorts

How I got wxMaxima to work on Yosemite.

I recently switched from fink to MacPorts on one of my computers – an ageing 17″ MacBook Pro, because it seemed MacPorts would allow me easier access to GNU Radio.

One of the softwares I occasionally use is wxMaxima (a GUI shell around maxima). MacPorts can provide wxMaxima, and in theory all you need to do is

sudo port install wxmaxima

to get wxMaxima installed. However, that did not work: the GUI would not connect to the command-line program maxima.

From there things got bad, worse, disastrous as I got caught in MacPorts update loops and other problems as I tried to fix things.

Now, the machine carried a lot of history and crud, so I decided to start from scratch: clean install of Mac OS X 10.10.

After a few days of reinstalling, I finally came back to the same point: installing wxMaxima. Dismay: it did the same.

Maxima process terminated” in the status line, and “Not connected to Maxima!” when I tried to evaluate an expression.

So, I dug in. First I made sure wxMaxima was referring to the proper command line maxima.

I changed the wxMaxima preferences so it referred to /opt/local/bin/maxima (rather than the default maxima). No go.

Nothing in the various logs that could shed any light on the issue.

So I created a command line script called maxima in my personal bin folder, which resides in ~/bin. 

Then I changed the preferences in wxMaxima to refer to /Users/kris/bin/maxima instead of /opt/local/bin/maxima. 

(P.S. ‘kris’ is the name of my home directory. wxMaxima does not like the use of the tilde ~ as a shorthand for the home directory, so I had to spell it out: /Users/kris/bin/maxima instead of ~/bin/maxima).

In my script I had the following temporary hack:

/opt/local/bin/maxima "$@" > /tmp/t.1 2>&1

This in an attempt to get a bit more info.

The contents of /tmp/t.1 gave me the necessary clue: maxima could not find sbcl.

sbcl is installed in /opt/local/bin by MacPorts, so it looked like a simple path problem.

My workaround: I now use a script /Users/kris/bin/maxima that contains

PATH=$PATH:/opt/local/bin; export PATH
/opt/local/bin/maxima "$@"

(Don’t forget to chmod +x ~/bin/maxima or something similar).

Then I changed the wxMaxima preferences to refer to /Users/kris/bin/maxima instead of to /opt/local/bin/maxima

That made it work!

Programming Baofeng UV82 (and possibly others) on Mac OS X 10.10

I purchased a few Baofeng UV82 radios to play around with.

I am using the chirp 0.4.1 software (see http://chirp.danplanet.com) to program the radios, and that proved sometimes elusive. I am using a Prolific-based USB programming cable I got from AliExpress.

I installed a Prolific driver for Mac OS X which I downloaded from http://www.miklor.com/COM/UV_Drivers.php and sometimes things would work, sometimes not.

A possibly important note: my Mac is currently running with a boot flag that allows improperly signed extensions to load on OS X 10.10. I needed to execute the command line

sudo nvram boot-args="kext-dev-mode=1"

and then reboot in order to allow my USB-to-HDMI adapters to work.

This setting might or might not affect the loading of the Prolific drivers – so if the procedure below does not work, try setting the ‘kext-dev-mode’ boot flag, reboot, then try again.

Often the chirp software would refuse to upload or download with a ‘Radio did not respond’ error message.

I think I’ve found a way to make it work for me:

1) Quit chirp if running.

2) Disconnect the programming cable. Turn radio off.

3) Start a Terminal session and navigate to /System/Library/Extensions

4) Unload the driver:

sudo kextunload ./osx-pl2303.kext

5) Start chirp

6) Connect the programming cable to the radio (but not to the computer). Turn the radio on.

7) Connect the USB of the programming cable to the computer

8) Reload the driver

sudo kextload ./osx-pl2303.kext

9) In chirp, now upload or download

By no means do I want to imply this is the only proper sequence. Maybe some of the steps above are unnecessary, or can be executed in a different sequence. I’ve not experimented that much. But this is what seems to work for me. Hopefully it helps someone else struggling with the same issues!

365 Pictures – A Year’s Worth

During 2014 (more precisely, from 30 December 2013 till 29 December 2014) I did a ‘365’ – i.e. made at least one photo each day. This is mainly an exercise to get better at photography.

It was hard at times. A fair number of the photos are what I call ‘desperation photos’. Like, it’s 5 to midnight, and I haven’t taken my photo yet, so I’d grab anything and make a picture. Hence, you’ll find pictures of bookshelves, bathroom cabinets, ukuleles… Also, most of the pictures are from around Plimmerton.

I do feel the experience as a whole improved my technique – I can recommend the exercise! The picture below is actually a slide show from Flickr; you can click on the left or right side of the image to go backwards and forwards.

It starts and ends with the same landscape shot, taken 365 days apart.

On 30 December 2013:

On 29 December 2014:

Here’s the complete 365 on Flickr:


Normally, you will not see all 365 pictures: I restricted viewing of the family pictures in the set to only ‘Family & Friends’.

Unless you register yourself on https://www.flickr.com and then request to be listed in my group of ‘Friends an Family’, you’ll see slightly less than 365 pictures…

More bit stuff

Out of curiosity, I worked out the carry bit for the addition of two 8-bit symbolic words, a[7]…a[0] and b[7]…b[0].

I intend to work out some method of intelligently re-collapsing common subexpressions.

For all I know, that’ll be a non-effective, circular endeavor; i.e. what I started with might be no more complex than whatever end result I come up with.

I am currently mucking around with what I call ‘tree expressions’: a complex expression gets reduced to a tree of

expression = symbol . primarySubTree | secondarySubtree

where symbol is an atomic symbolic bit (e.g. either ‘x’ or ‘!x’), and both primarySubTree and secondarySubTree don’t contain that symbol.

I.e. I first simplify the expression to a list of terms, each term a ‘flat’ list of symbolic factors.

a.b.c | a.b.!c | a.!b.d … | b.c.d | … or whatever

then find the most common symbol (e.g. a), and convert the expression to

a.(b.c | b.!c | !b.d…) | (b.c.d | …)

then repeat recursively on both subtree, until everything is either expressed as a tree or of a simpler form.

To get a feel for how re-collapsing would work: I let my program express the carry as a tree expression, then manually reduced the carry expression to (using lower case x, y, … for intermediate results):

x = a[7].!b[7] | !a[7].b[7]
y = x.(a[6] | b[6])
z = y.(a[5] | b[5])
t = z.(a[4] | b[4])
u = t.(a[3] | b[3])
v = u.(a[2] | b[2])
w = v.(a[1] | b[1])
carry = a[0].b[0].w | a[1].b[1].v | a[2].b[2].u | a[3].b[3].t | a[4].b[4].z | a[5].b[5].y | a[6].b[6].x | a[7].b[7]

which has a nice symmetry to it.

The ‘normal’ carry expressions work out as follows (using upper case X, Y,… for intermediate results):

X = a[0].b[0]
Y = a[1].b[1] | X.(a[1].!b[1] | !a[1].b[1])
Z = a[2].b[2] | Y.(a[2].!b[2] | !a[2].b[2])
T = a[3].b[3] | Z.(a[3].!b[3] | !a[3].b[3])
U = a[4].b[4] | T.(a[4].!b[4] | !a[4].b[4])
V = a[5].b[5] | U.(a[5].!b[5] | !a[5].b[5])
W = a[6].b[6] | V.(a[6].!b[6] | !a[6].b[6])
carry = a[7].b[7] | W.(a[7].!b[7] | !a[7].b[7])

which seems to be about the same complexity.

Note: If we write the XOR operator as ^, then a ^ b == (a.!b | !a.b)

This is the same, using the XOR operator:

x = a[7] ^ b[7]
y = x.(a[6] | b[6])
z = y.(a[5] | b[5])
t = z.(a[4] | b[4])
u = t.(a[3] | b[3])
v = u.(a[2] | b[2])
w = v.(a[1] | b[1])
carry = a[0].b[0].w | a[1].b[1].v | a[2].b[2].u | a[3].b[3].t | a[4].b[4].z | a[5].b[5].y | a[6].b[6].x | a[7].b[7]

The ‘normal’ carry expressions:

X = a[0].b[0]
Y = a[1].b[1] | X.(a[1] ^ b[1])
Z = a[2].b[2] | Y.(a[2] ^ b[2])
T = a[3].b[3] | Z.(a[3] ^ b[3])
U = a[4].b[4] | T.(a[4] ^ b[4])
V = a[5].b[5] | U.(a[5] ^ b[5])
W = a[6].b[6] | V.(a[6] ^ b[6])
carry = a[7].b[7] | W.(a[7] ^ b[7])

What I like about the new form is that it starts down from the high bits. If we read it in pseudocody words, it says:

– if both a[7] and b[7] are set there is a carry (a[7].b[7] in the carry expression)
– else if a[7] and b[7] are clear there is no carry (x is 0, hence y, z,.. are all 0)
– else if a[6] or b[6] are set there is a carry (y is 1)
– else if a[5] or b[5] are set there is a carry (z is 1)

It’s not very exciting, and I don’t see any practical uses for it, but it’s satisfying to see that the program came up with a nice, symmetrical alternate expression for the carry.