AMD for CSS

I am using a lot of Javascript plugins these days and managing them has become a fairly big deal. Recently, I have adopted Asynchronous Module Definition. I am using Require JS (http://requirejs.org) and like it a lot.

The problem is, Require JS does not work with CSS and it turns out that loading CSS is as much of a hassle as loading Javascript.

I think that the basic solution is to put a link to the CSS file into their page. But, I work with a framework and I do not want to pollute it with content-specific code. Some of the pages/sites that use the framework do not need plugin X and should not be having the CSS for it any more than they should have the JS.

Require JS says that they don't support CSS files because there isn't any good way to know when they arrive. It offers a tidbit of code for those, they say, who don't care about the timing of the arrival of the file.

This is nonsense. Following is code that does exactly that. Unfortunately, since it's not built into Require JS, I have to wrap stuff up for callback, but, c'est la vie.


var loadCssFile = function(filePath, callback){

  var link = document.createElement("link");
  link.type = "text/css";
  link.rel = "stylesheet";
  link.href = filePath;
  document.getElementsByTagName("head")[0].appendChild(link);

  var count=0,
  tryAgain=function(){
    for (var i=0, len=document.styleSheets.length; i<len; i++){
      var element=document.styleSheets[i];
      if (element.href && element.href.match(filePath)){
        callback();
        return;
      }
    }
        if (count<10){
          count++;
          setTimeout(tryAgain, 100);
        }
        else{
          throw "loadCssFile() failed on to find "+filePath;
        }
  }

  setTimeout(tryAgain, 100);

}

PHP Pretty Print with bbedit

PHP is old and ubiquitous. It is completely bizarre that there are almost no options to format your PHP. Javascript has eighteen formatters and evaluaters and lint-ers. PHP is really lame by comparison.

In fact, other than online versions, I only found one. (Your comments will be appreciated!)

http://www.phpformatter.com/ is the only one I could find that I can run on my own computer. It is a pear component. I hate pear. It has all the worst aspects of php - inconsistent calls, structures and everything else.

But, I'm desperate. After a year of primarily NodeJS, I'm returning to PHP having developed a strong reliance on being able to clean up my code at the press of a button. Further, the project I'm returning to did not benefit from that technology so it's got a million lines of code that is only as pretty as I had energy that particular day. Since I'm also trying to read an old project, this is an urgent need.

Since I have hated pear for much longer than I've had my current computer, I had to install it. That was infinitely more hassle than it should have been (I know there are people who dislike NPM but it works infinitely better than anything PHP, including composer). But, done.

After that, installing php_formatter was no big deal. It works, too. Except...

1) Php_formatter actually sets the PHP error_level explictly. The PHP authors, in another example of what's bad about PHP, has changed the meaning of E_ALL. Now it includes E_STRICT. This is really stupid.

2) Php_formatter strips all empty lines from the code. I use empty lines. A lot.

So, here's the thing. I had to edit the php_formatter files to comment out their error specification. Amateurs. It was two files. I don't remember which so do a multi-file search.

I use bbedit by Bare Bones Software (a great program). I want this to operate as a Text Filter. That's not so hard. bbedit passes the contents of the window (or selection) to the program and, bingo!, you are in business. In fact, php_formatter worked correctly once I got it working at all.

The problem is the stripping of blank lines. Turns out that php_formatter supposedly has a filter that preserves them but I could not make that work.

I made a NodeJS program that turns blank lines into comments. Then I beautify. Then I remove the comment characters. Voila! Blank lines are retained.

For the record, here's the Text Filter:

#!/bin/bash

~/Scripts/bin/js/commentUnComment.js -c | php  /Users/tqwhite/Documents/webdev/pear/bin/php_beautifier -t | ~/Scripts/bin/js/commentUnComment.js -u


And here's commentUncomment.js:

[NOTE: This is updated as of 5/29/15. The second regex failed in some circumstances.]

//=========================================================
#!/usr/local/bin/node

var inString='';

var cmdLineParameters={};
for (var i = 0, len = process.argv.length; i < len; i++) {
            var element = process.argv[i];
            if (element=='-c'){
                cmdLineParameters.c=true;
            }
            if (element=='-u'){
                cmdLineParameters.u=true;
            }
        }
       
var writeStuff = function() {
        var outString='';
       
        if (cmdLineParameters.c){
        outString=inString.replace(/\n\s*\n/gm, '\r//\r');
        }
        if (cmdLineParameters.u){
        outString=inString.replace(/^\s*\/\/\s*$/gi, '');
        outString=inString.replace(/^\t*\/\/\s*$/gmi, '');
        }
       
       
        process.stdout.write(outString);
       

    };

//the rest ========================================================

process.stdin.resume();
process.stdin.setEncoding('utf8');
process.stdin.on('data', function(data){
        inString+=data;
    });
process.stdin.on('end', writeStuff);

Apple OSX Mail Program Changes the Port on Its Own

I use Mandrill for my outbound SMTP. For SSL, it operates through port 587.

I have had many occasions where my connection fails for no apparent reason. I'm just living my life and sending email and then, poof!, an email tells me it can't send with that server. I go through debugging and re-enter the credentials and it would work.

I started thinking "last time it happened, wasn't it the port number that was different then, too?" So, I changed the name of the server to "Mandrill, s/b port 587" so I would know.

It happened again today. I went to look at it the settings and there was a change to port 486. WTF?


I changed it back to 587 and it worked.

I have changed the setting "Automatically detect and maintain account settings" to be off. I'm going to be that stops the problem. If not, I'll update here. If it's been a long time since 5/15/15, you are safe in seeing that as a solution.

Dave Winer Strikes a Blow for Freedom

I started my web career with this guy's software. He's an original blogger and podcaster whom I've been reading since the nineties. He's done a lot of interesting things but now he's doing something important.

He has put together a Javscript/Browser blog editing environment that is not tied to any predefined external service. He's making a big point of keeping all open source. One of his major ideas is creating ecosystems. I think this will establish an important niche.

The reason it's important is that it will allow us to establish a web presence without relying on some big company's software. For the most part, anyone who wants to blog or otherwise express him or herself on the web has to use Facebook, Twitter, Blogger, hosted Wordpress, Tumblr, etc. That is, you put yourself at the mercy of their terms and conditions. Worse, your information is stored on their servers where it is probably hard to retrieve for posterity, reuse or backup - if you can get it at all.

Dave's thing is intended to counter that. As I understand it, pre-release, he has defined a protocol for storing data from the browser that can be implemented on any server you want. He also has created a NodeJS component that implements the protocol. All open source.

With his other Javascript things (he calls them "snacks"), he has made configuring and using them an entirely browser-based experience. It sounds like this might require creating a storage location this time. We will see.

However, he has often expressed a philosophical viewpoint with which I agree heartily that being free requires that we be able to communicate on our own terms with technology that is sufficiently decentralized that we cannot be shut down. I'm looking forward to his release of his MyWord Editor Project.

http://tqwhite.org/?89E805

Dave provides additional explanation.

http://tqwhite.org?41A5AE

MSSQL Service Broker Does Not Work

It's time for a project I've not seen in awhile to get some love. It's .NET MVC running against SQL Server.

I fire it up. After some really annoying compiler reference issues (how does this happen on a project that has not been touched?), I get a dev version up and running.

I want to work on a copy of the database but I also want to leave the original up for reference as I move forward. So, I back up, make a new database and restore into it. I run my initialization script that, mainly, establishes a service broker. Edit the connection string to point at the new database, and, drum roll. . . . .

No love. The service broker is not configured properly.

This stuff worked just fine last time I used it and for years before that. I check a billion things. I recreate the database making sure I didn't screw anything up. I turn on the debugger and look at it from the program's viewpoint. Nothing does any good.

I am beat. After another round of dejected facebook or twitter or something, I am just staring at Management Studio. I, once again, look at the properties of the database. Goddam, Service Broker is turned on. I look at the original database again, Service Broker is turned on.

But I notice the GUID for the first time.

Bottom line, the Service Broker GUID was restored along with the rest of the database. For no particular reason (probably a guy who worked here years ago), I was setting ENABLE_BROKER.

A little google later and I learned about NEW_BROKER. Done. Works.

If you have a service broker that doesn't work, won't respond or otherwise gives you a big pain, check the database property/options and scroll down to service broker. If the GUID is the same as in another database, there's your problem.

OR, you could immediately try, ...

ALTER DATABASE [database name] SET NEW_BROKER WITH ROLLBACK IMMEDIATE;

And go to lunch.

Secure Email - OSX and IOS

(I never went back and edited this. That means it's probably a little rough and may be confusing.)

Secure email requires encryption. Encryption requires two keys. One is called a public key, a sender can use this to encrypt a message. The other is called a private key. It can be used to decrypt a message that was encrypted with the corresponding public key.

When you send secure email, there are two functions. One is called 'signing'. In a signed message, the mail program uses the recipient's public key to create something called a digest. The recipient can open the digest (with their private key) and verify that the email is exactly the one that was sent. The other security function is called encrypting. In this case, the sender uses a public key to put an encrypted form of the message into the email and send that instead. The recipient uses his or her private key to decrypt the message into a readable form that security people call plaintext.

When you send an encrypted or signed email to a list of people, a different key is used for each person. A different encrypted package is sent to each. Each uses his or her personal private key to open the message. You cannot send an encrypted message to a list of people that includes someone for whom you do not have a public key.

Managing the keys is done with something called certificates. The certificate contains both the public and the private key and information that allows the mail program (in cases where its important enough to pay the certificate company) to verify that you are you and that this is your key.

To start, get a free certificate at:

https://www.comodo.com/home/email-security/free-email-certificate.php

After executing the signup, it will email your the certificate.
- Double click on the attachment in the email from Comodo tol open Keychain Access.

It will automatically install the certificate.

To verify that it all works, quit Mail.app and restart it. Create a new email and you will see new icons on the left of the subject line.



That blue check means your emails are now signed. If some hacker messes with the message before it gets to me, I will get a notification that the message is not the one you sent. The grayed out lock symbol says that you are not yet able to send an encrypted email, yet.

To be able to send encrypted email, your email program has to have the other person’s public key. Mail.app collects these when it gets a signed email. To send an encrypted email, ask the person (I have one so I'm a good option) to send you a signed one and reply (or Mail.app may already have it). The lock should turn blue in a new message to that person.

But, when you receive an encrypted message (eg, when I reply to your first encrypted message), you will see that you cannot read it on your iPhone. The problem is that your iPhone needs to have your certificate as well.


NOTE: YOU DO NOT NEED TO DO THIS. THE EXPORT FROM KEYCHAIN CAN BE SENT. I DON'T REMEMBER EXACTLY WHAT I DID, SO I AM LEAVING THIS PART IN.

To update your iPhone with a certificate, you need a new program called the iPhone Configuration Utility.

Download it from  

http://support.apple.com/kb/DL1465

Install it like any other program. It gets installed into "Applications/Utility/IPhone Configuration Utility".

Open Keychain Access
- Find the certificate that was installed before in the ‘login’ keychain. It is named as your email address. If you have old ones, it will probably be the one with the latest expiration date.
- Select it and choose Export Items from the File menu.

You will see a file dialog. In addition to files, it will show a popup men under the file list.
- Choose “Personal Information Exchange (p12)”
- Save the file someplace easy to find again (Desktop is good. You can throw it away after this is done.)

Open iPhone Configuration Utility.
- Select “Configuration Profiles” from the palette in the left column
- Click the New icon on the top left.

This will show a new set of controls in the lower left window.

Select the General item.
-` Make up an informative name .
- Then make up a unique Identifier. For this purpose, I suggest something like com.domain.emailCert.yourEmailName.

Leave Description and Security as they are (blank, or whatever you want to type, and Always).

Next, scroll down from General and find Credentials.
- Click on the Configure button that shows and you will see a file dialog. Choose the p12 file you made before and Open.

The final act in Configuration Utility is to click Share, next to the New icon.
- Select None from the Security popup and Share…. This will take you to Mail.app.

There you will see a new mail message with a file attached. Email this to yourself.

The last step is to open the email on your iPhone and tap the certificate.

It will open.
- Click the button, top left, that says Install. It will ask for your phone’s password.
- Enter your password and click Done. It will tell you that the profile is not signed.
- Click Install. It will ask you to do it again to confirm.
- Click Install again (this time red and at the bottom).

It will return you to your email message and you are done.

(You can look at it or delete it by going to Settings->General->Profile. It’s way down at the bottom).

Now you can find the email that you couldn’t read before and you will be able to read it.


SSL Certificate for Apache

I just renewed the certificate for a client web store. This is a task that drives me crazy because I do it so infrequently that I can never remember the details. It's made worse by the fact that I use InstantSSL, a company whose documentation and practices are incredibly confusing. Also, cheap.

Here's what happened.

I followed the usual instructions for generating a Certificate Signing Request. This generated two files, a .csr and a .key (for later).
I used a command line like this:

openssl req -new -newkey rsa:2048 -nodes -keyout myDomainName.key -out myDomainName.csr

It is entirely unclear to me if the name of the files makes any difference. Also, in the dialog that openssl conducts to construct the CSR, it asks for "your name". It means 'your domain name'. May be obvious but I thought that maybe it was picking up the domain name from the command line.

The purchase process for InstantSSL is pretty easy. They are really good at taking money.

Since I screwed up the domain name thing, I had to interact with tech support and give them a new CSR. This was annoying since it just said I needed to do it, not how. Eventually I had looked around long enough that I felt like I had to call. Turns out you have to construct a support account and treat send it through the support website along with your order number.

The next step was validation. It does two things. It looks up the company phone number (in this case using Dunn & Bradstreet). I had to work with the client to be there to answer the phone and gather the 'validation code'. Entering this into the phone call tool triggers another email (this came to me, as the email address on the purchase) with another, longer validation code. This had to be put into the order control panel.

While there, I saw that it still wanted to send email to admin@, an address that does not exist, for additional validation. Turns out that, in the order control panel, you can change this to one of several other options. I don't know where they come from but, one of them was me. That sent another validation code to put into the order control panel.

And then I got an email with a .zip full of certification. Expanding this got me two files, a .crt and a .ca-bundle. I also needed the .key file made along with the CSR.

These were put into folders specified in the Apache config file. In my case, this was a virtual host file for that site.

There are three files and they need three entries for Apache configuration:

    SSLCertificateFile /etc/ssl/certs/sales/myDomain.crt
    SSLCertificateChainFile /etc/ssl/certs/sales/myDomain.ca-bundle


    SSLCertificateKeyFile /etc/ssl/private/myDomain.key

On my system, these are root files with permission 644. I do not know if this is ideal. There might be some more secure arrangement. (That's what comments are for.)

After a server restart, the browser security violation went away and things look pretty good.

Now you know.





Debugging a Web Type Font Served from a Different Domain

A client came up with a type face that she found on some site. The supplied file type was .ttf (truetype).

Because I treat my public_html folder as source code, I always keep a third level domain for static file server, eg, static.someDomain.com, to hold files that need to be directly served. I expect that this might have worked more easily if I had been able to/chosen to serve the type file from the site's public_html folder instead of the different domain.

I put the .ttf on the static domain and added this coding to the web page:

@font-face {
  font-family: 'demoFont';
  src: local('demoFont'), url(http://static.someDomain.com/demoFont.ttf) format('ttf');
}

Even though the internet said that Firefox wants .ttf , it didn't work.

I have used Google fonts before so I checked that out for comparison.
@font-face {
  font-family: 'demoFont';
  font-style: normal;
  font-weight: 400;
  src: local('demoFont'), url(http://static.someDomain.com/demoFont.woff) format('woff');
}

I find a site that does ttf-woff conversion ([1] below). It works great but, after I copy it in and edit to use the google version of @font-face. No dice.

Reading the internet ([2] below), I got the idea to look at the headers ('curl -I domain.com') coming back from google and my static domain specifically to see about 'Access-Control-Allow-Origin'. I found that google's header included "Access-Control-Allow-Origin: *" and mine did not.

The website suggested using .htaccess to add the goodies to the header:

<FilesMatch "\.(ttf|otf|eot|woff)$">
    <IfModule mod_headers.c>
        Header set Access-Control-Allow-Origin "*"
    </IfModule>
</FilesMatch>

(Actually, I added the '|woff')

Checking the header... No dice. The line does not appear.

I notice mod_headers.c and check my Apache config. Not there. Navigate to /etc/apache2/sites-enabled:

ln -s ../mods-available/headers.load headers.load

service apache2 restart

Bada Bing. Bada Boom!

The header is there and the the typeface shows. Win! And, for good measure, it works in Chrome, Safari and late model Internet Explorer.


[1] - http://everythingfonts.com/ttf-to-woff
[2] - http://stackoverflow.com/questions/2856502/css-font-face-not-working-with-firefox-but-working-with-chrome-and-ie