Site Cleanup

I’ve upgraded, relocated, reskinned and repaired Nucleus. The previous skin was created when 1024×768 was a pretty typical resolution, and looked downright silly. RSS feeds are finally working. The last remains of the multiple-blog setup have been removed. (Now if only I had time to convert to WordPress)

Maybe somebody other than my Mom will read it now?

Ok, maybe not.

Outlook 2007 add-in shenanigans

Here are three things I was unable to find any guidance for on the internets regarding working with Outlook 2007 in Visual Basic, so I made it up.

1. How do you tell if a folder is a contacts folder?
I still dont know if this is the correct way – I may not have found the right search terms, but this works.

Check the DefaultItemType property. If it is Outlook.OlItemType.olContactItem, then the folder is a contacts folder.

2. How do you make a toolbar context aware / context sensitive? That is, how do I have a toolbar that is only displayed when viewing contacts, or the calendar, but not email items?

You will need to create an event handler for the FolderSwitch event on the active explorer. In this handler, check the DefaultItemType of the CurrentFolder on the active explorer.

A code block is worth a thousand words:

Public Class ThisAddIn
  Dim ToolBar As Office.CommandBar
  Dim WithEvents expl As Outlook.Explorer

  Private Sub ThisAddIn_Startup(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Startup
    expl = Me.Application.ActiveExplorer
    ToolBar = expl.CommandBars.Add("ToolBar", Office.MsoBarPosition.msoBarTop, False, True)
    ToolBar.enabled = true
  End Sub

  Private Sub expl_FolderSwitch() Handles expl.FolderSwitch
    If expl.CurrentFolder.DefaultItemType = Outlook.OlItemType.olContactItem Then
      ToolBar.Visible = True
    Else
      ToolBar.Visible = False
    End If
  End Sub
End Class

3. How do you create a Distribution List (aka DistListItem) in a non-default, custom folder? (Or how do you set the parent folder on a newly created Distribution List)?

All the examples I could find for creating Distribution lists programmatically suggest using Me.Application.CreateItem(Outlook.OlItemType.olDistributionListItem) to create the DistListItem object. When you do it this way, it always adds the Distribution list to the default contacts folder.

Turns out, you can also use <folder object>.Items.Add(Outlook.OlItemType.olDistributionListItem). You should be careful that this is only done in a contacts folder (can you see how this is all coming together?).

So, if you want to create a new distribution list in the current folder (instead of the default contacts folder), add a person to it, then present it to the user to save or disgard, you could do the following:

  Private Sub createDistList()
    Dim dlist As Outlook.DistListItem
    Dim recip As Outlook.Recipient
    dlist = Me.Application.ActiveExplorer.CurrentFolder.Items.Add(Outlook.OlItemType.olDistributionListItem)
    recip = Me.Application.Session.CreateRecipient("John Doe <jdoe@nowhere.com>")
    recip.Resolve()
    dlist.AddMember(recip)
    dlist.display
  End Sub

I’ll let you figure out how to add the button, and create a handler for said button.

Hopefully this saves somebody some time. I find it hard to believe I’m the first person to try it…

Installing Dynamics CRM on Server 2008

I am working on installing Microsoft Dynamics CRM 4.0 on Windows Server 2008 (using SQL Server 2008).

Installing CRM is not quite like your typical Microsoft installer, especially when installing on the ’08 servers. There are things you need to know, and do in advance to keep it from failing.

The information you need is in three places:
1. Microsoft Dynamics CRM Implementation Guide
This is a zip file containing a whole mess of project planning information and tools. “Microsoft_Dynamics_CRM_IG_Installing.doc” and “Microsoft_Dynamics_CRM_IG_Planning.doc” are the only documents you will need for installing. The planning document helps to establish the software requirements and various prerequisites.
2. Support for Microsoft Dynamics CRM 4.0 on Windows Server 2008-based computers
This explains what special steps must be taken to install CRM on Windows Server 2008.
3. Support for running Microsoft Dynamics CRM 4.0 together with Microsoft SQL Server 2008
This explains the step to install it with SQL Server 2008.

If you meditate over the instructions in these documents, you should be able to get it installed… almost. The instructions aren’t exactly clear in a few places, so I thought I’d mention the snags I encountered. Do these things BEFORE you run the CRM installer.

1. Make sure you are running the installer as a domain user that is a local administrator on the server
2. You will need an Active Directory OU to house the CRM groups, and the user with which you are installing needs full rights to that OU (using the delegate feature)
(alternatively, you could run the installer as a Domain Administrator)
3. If you use a port other than 80 when setting up SQL Reporting Services, you will need to create a dummy site in IIS with the same port, and start it BEFORE installing CRM.
If you forget it’s no biggie though – when you get the error (“The specified path is not a metabase path.”) you can create the site and click “Retry”.
I believe you can delete the site (or at least stop it) after CRM is installed.
4a. Copy the contents of the installation DVD to the hard disk (and use this to perform the installation, not the CD).
4b. Disable Internet Explorer Enhanced Security.
4c. Increase the Internet Explorer Cache size to 1024MB. (It defaults to 50MB).
When you install CRM, you MUST allow it to download updated setup files. If you do not make these changes, the installation will fail with the following error:
“Action Microsoft.Crm.Setup.Server.MsiInstallServerAction failed.
This update package could not be opened. Verify that the update package exists and that you can access it, or contact the application vendor to verify that this is a valid Windows Installer update package”
This is because the update file is larger than the default IE cache size of 50MB, and gets deleted right after being downloaded. The three parts of step 4 ensure that this will not happen.
You can, of course, change the IE settings back after the install is complete.

Finally, during the install, make sure you select “Network Service” and not a domain user for the security account.

This is all I can think of. The documentation is pretty thorough, albeit a bit verbose.

Google’s chrome browser finally gets it

Firefox is a really great browser and everything, but when I’m going to a website that I know might jack up my browser (such as using Oracle’s java web forms), I have to use Internet Explorer.
Why?

It’s not because IE is more stable. From my experience, IE is less stable, but when IE crashes – depending on how you use it – only one window is lost.

If you start a new instance of Internet Explorer from the quicklaunch or Start Menu, a shiny new process is created with no ties to any other windows. If it crashes, your other windows remain untouched.
Now, you only get this benefit when you launch a completely new browser. If you open a new window from the file Menu in IE, or open a new tab, or right-click -> open link in new window… you do not get the same protection. These are created as threads. When one thread crashes, any other windows / tabs created from the original IE window will be destroyed as well.

But at least Internet Explorer provides the ability to have separate browser processes. Firefox does not. It was rumored that they would enable this in Firefox 3, but they didn’t. In fact, if Firefox, if a browser process hangs and cannot be terminated, you have to restart the whole freaking computer.
The Firefox developers (and fanboys) ignored the many requests for running in separate processes, and even went so far as to tell the requesters off.

Well darn. There is no free software, decent web browser that you can trust to keep your gmail safe when some facebook app crashes.

Enter Google Chrome.
Web comic explaining tech behind Google Chrome
Seems the engineers at Google understand – web browsers crash (novel concept, right…). When one page crashes, it should not crash all of them. So, Google designed a new web browser that, among other things, isolates all browser tasks into separate processes.

I don’t necessarily want to have to switch to this new browser, although I am certainly going to give it a try. Eventually, I hope that Mozilla will take the hint, and fix Firefox.

Found a bug in Vista

I found a bug in windows Vista SP1, but now I have a problem – there is no way to report it. Apparently Microsoft is so audacious as to think their beta testers tried all possible input combinations. It’s just a bad philosophy, and the reason why Windows will eventually fail. Anyway, in the hope that maybe placing this online will accomplish something, here is my bug.

I tried to copy my iTunes library to a fat32 formatted external hard drive. I dragged and dropped, and Windows copied for a while and completed, but threw no errors.

When I tried to access it the next day, a good half of the library was missing!

What appears to have happened is that Vista hit an artist with an “international” character (just an accent over an e) and stopped copying. No complaints, no errors, no dialogs (lord knows Microsoft knows how to create dialogs).

So now I have no way of knowing what is getting skipped when I copy files. I think I may try using the command line xcopy, but seriously, this is ridiculous.

EDIT:

Found another bug.

I had a folder called “pictures”. I renamed this to “pictures_old” so that I could copy in a folder of the same name without merging them. What does Windows do? It says “a folder named pictures_old already exists, to I want to merge?” WTF??!? I had to copy the pictures to a totally different location.

Windows sucks. I hope Apple decides to let Mac OS X run on any PC, because they would easily destroy Microsoft. That or linux developers get their heads out of their respective butts and embrace standards in user interface design.

Installing oci8 for PHP 5 on SuSE 10

Filling in where the internets failed me again, here are step-by-step instructions for getting oci8 extensions running in php without having to recompile anything.

Prerequisites

First, you will need to download some stuff and make sure you have certain packages installed:

Oracle Instant Client
I used version 10.2.0.3 cause I know it works.
http://www.oracle.com/technology/tech/oci/instantclient/index.html

Do not download the rpm version, it is much easier to use the zip version. Trust me, I’ve tried them both.
There are three files you should snag:
* Instant Client Package – Basic (instantclient-basic-linux32-10.2.0.3-20061115.zip)
* Instant Client Package – SQL*Plus (instantclient-sqlplus-linux32-10.2.0.3-20061115.zip)
* Instant Client Package – SDK (instantclient-sdk-linux32-10.2.0.3-20061115.zip)

oci8 PECL package
I used version 1.3.2. If you have problems, try version 1.3.0. (1.3.1 didn’t work for me)
http://pecl.php.net/package/oci8

You will be grabbing one file – oci8-1.3.2.tgz

Packages
Obviously, all the necessary components to have php5 with apache2 working. The default install should have everything you need, but just in case, the ones you might be missing are:
* php5-devel
* php5-pdo (maybe – not sure)
* php5-pear
* php5-pear-log
* something with which to unzip things
Also, if you are running suse 10, throw in for good measure:
* orarun
(creates oracle user, and a few other oracle friendly things)

Procedure Part 1 – Install Instant Client

Note: I did all this as root because the oracle user on my box doesn’t have interactive login, and I’m too lazy to fix it.

(If the directory “/opt/oracle” doesn’t exist, create it and make oracle:oinstall the owner)

ftp the four files into /opt/oracle

On the server:
> cd /opt/oracle

unzip the three Instant Client files. A new directory called instantclient_10_2 should have been created.

If you are root, make sure oracle owns everything:
> chown -R oracle:oinstall instantclient_10_2

Now you need to create the symbolic link for libclntsh.so -> libclntsh.so.10.1
> cd /opt/oracle/instantclient_10_2
> ln -s libclntsh.so.10.1 libclntsh.so
Again, if you are root, make oracle own the symlink
> chown -h oracle:oinstall libclntsh.so

Finally, to make sure that your libraries are found correctly at runtime, edit the file “/etc/ld.so.conf” (as root) and add the path to your instantclient install (/opt/oracle/instantclient_10_2) to the list of paths (add it on a new line before any include statements)

Save the file, then run (as root)
> /sbin/ldconfig

The Instant Client is ready to go!

Procedure Part 2 – Install oci8 PEAR extension

This part should be super easy! Do this as root:

> cd /opt/oracle
> pear5 install oci8-1.3.0.tgz
(That’s right, you don’t even have to untar the oci8 archive!)

At the prompt, enter:
instantclient,/opt/oracle/instantclient_10_2

There shouldn’t be any errors. If there are, it probably relates to missing packages.

Almost done!

The last step is to add the following line to php.ini, and reboot apache.
extension=oci8.so

On SuSE, you will need to edit two files /etc/php5/apache2/php.ini and /etc/php5/cli/php.ini
I recommend adding the line after the comment block for “Dynamic Extensions”

reboot apache by running:
> apache2ctl -k stop
> apache2ctl -k start

Check to see if it worked. If apache doesn’t start, check your error logs(/var/log/apache2/error_log). You can always get apache running again by commenting out the line you added to php.ini.

Time

I found this bit of prose recorded in a bedside notebook of mine.

Time is not a tick-tock.
It is like a river -
      gentle or rapid it's pace is a whoosh
      or a rumble. a burble or a roar,
      a hum...

        time is taught from birth as nothing more than a tick-tock,
 a blink-blink, a tap-tap at a constant rate, impulsive, consistent.
Time passes in silence with mind shattering crash after crash - as the
clockwork interrups nature's flow with omnidirectional shockwaves of
sructure.
  Stop
  Go
  Stop
  Go      intermittant tasks are measured in the turning of a gear.

Time has been bottled up, refined, forified and sold to humanity
to be used one drop at a time -- the river tamed by the superiority of mankind.
The roar, the rush, the trickle  nothing but a Drip, Drip, Drip...

Security phrase and image

A lot of banks have started adding a security image and / or phrase to the login process in order to help prevent phishing.

It works like this. When you set up your account, you chose a picture from a list (usually things like puppies, kittens, bicycles, cars, etc), and you enter a phrase that will be displayed with this picture. This is stored with your account.

Later, when you login you first enter your username. You are presented with the picture and phrase to prove that you are at the bank’s true website and not a phishing site that just looks like your bank’s site. On this second page, you verify that the image and phrase are correct, then enter your password with confidence.

Sounds like a great idea, right? I thought so to at first, and a lot of people think that it is a very good security measure.

Unfortunately as currently implemented there is a serious flaw in the logic. What is to stop a phishing site from programmatically requesting this image and phrase on your behalf?
A Captcha would not help either. The phishing site could simply pass the captcha to the user, and the result back to the bank site.

No, this creates a false sense of security. By telling people that these features ensure the site is genuine, they will more readily believe it when a phishing site provides the same “security”.

I believe I could make a proof of concept, but with the current state of freedom in the US, I’d probably go to jail for it.

Programatically modify firefox settings

I refuse to believe that nobody has needed to silently push firefox setting / configuration in an unattended manner, but I was unable to find any directions on how to do so. In particular, I need to automatically, using a script, modify the no-proxy exclusion list.

Here is the way I eventually ended up doing it.

Firefox stores it’s configuration in prefs.js in the Profile folder for the user.
That is (on XP anyway) C:\Documents and Settings\[user]\Application Data\Mozilla\Firefox\Profiles\[randomtext].default\prefs.js
Which can be specified as %APPDATA%\Mozilla\Firefox\Profiles\[randomtext].default\prefs.js

Since it contains a random string, how the heck do you find it??
Well, you can parse the profiles.ini file in %APPDATA\Mozilla\Firefox. It looks like this:

[General]
StartWithLastProfile=1

[Profile0]
Name=default
IsRelative=1
Path=Profiles/cutfy0h4.default

Luckily, you can use a FOR loop within a winxp/2k batch file to grab the profile name(s).

FOR /F "delims==/ tokens=3 usebackq" %%i IN ("%APPDATA%\Mozilla\Firefox\profiles.ini") DO (
 echo %%i
)

This will echo just the “cutfy0h4.default”, and it will only return for lines of the file that contain 3 fields.
(For more information about the FOR loop, see here: http://www.robvanderwoude.com/ntfor.html.)

Now that we can locate the profile, how the heck do we modify the setting?

Turns out, firefox looks for a file called user.js, and applies those settings AFTER applying prefs.js. Any settings in user.js will be applied to prefs.js.
So you put your settings in user.js, copy it into the profile folder, start and stop firefox, then delete user.js. (If you don’t delete user.js, the user will be unable to modify the setting).

Warnings:
1. I am not responsible if this breaks anything. USE AT YOUR OWN RISK!!
2. If there are multiple profiles, it will not work right. In most cases there should only be one.
3. If firefox adds more stuff to profiles.ini, or fixes the direction of the slash in the profile path, this script will break.
4. This was developed with Firefox 2.0.0.13

Here is my final script:

You will need a file called “user.js.install” in the same folder as the batch file containing whatever settings you want to change. (Use prefs.js as your guide) Like this one:

user_pref("network.proxy.no_proxies_on", "localhost, 127.0.0.1, superserver, 192.168.0.1");

Here is the batch script:

taskkill /IM firefox.exe > javainst.log 2>&1
FOR /F "delims==/ tokens=3 usebackq" %%i IN ("%APPDATA%\Mozilla\Firefox\profiles.ini") DO (
  echo "%APPDATA%\Mozilla\Firefox\Profiles\%%i\prefs.js"  >> proclog.log 2>&1
  IF EXIST "%APPDATA%\Mozilla\Firefox\Profiles\%%i\prefs.js" (
    copy /Y user.js.install "%APPDATA%\Mozilla\Firefox\Profiles\%%i\user.js"  >> proclog.log 2>&1
    start firefox.exe
    rem wait 7 seconds for firefox to start
    ping 1.1.1.1 -n 1 -w 7000
    taskkill /IM firefox.exe  >> proclog.log 2>&1
    del "%APPDATA%\Mozilla\Firefox\Profiles\%%i\user.js"  >> proclog.log 2>&1
  )
)

Javascript gripe # 2

The add() function of the html select object functions totally different in IE and Firefox.

It is defined as :
selectObject.add(option,before)

Where option is an option object. Before is the tricky part.

In firefox, the second parameter is supposed to be a reference to the option object you want to place your new object in front of. In IE, it is the index to the object you want to remove.

These are fundamentally different.

In FF, you have to do this:
boxRef.add(newOpt,boxRef.options[i]);

in IE, you do this:
boxRef.add(newOpt,i);

Apparently, Firefox is correct according to the DOM specifications:
void add(in HTMLElement element, in HTMLElement before) raises(DOMException);
void remove(in long index);

But tell me, why does the add method use an object while the remove uses an index???. The standard is messed up, not IE.

Anyway…