Apple Aperture 2 Cop-out

January 1st, 2010

It seems Apple has a cop-out for the Aperture 2 problem I found (aside from slowness now):

Apple Aperture 2 Excuse

Wow. Are they serious? Note the date on that is October 14, 2009. Let me see if I get this straight. So, there’s a bug in your software (or OS, it used to work for me before just fine in Leopard), and the excuse is – “Oh, we never really supported grayscale!” Uh… then why does the UI seem to get it otherwise? Wait, was it that you just went that extra mile to make it work, but just not in a supported way?

Just in case that link ever goes away, let’s recap the excuse:

Aperture is designed to work with images from digital cameras which use an RGB color space. Non RGB images, such as grayscale TIFFs, grayscale PNGs, or RGB-A images (with alpha transparency) may not render correctly.

Are they serious? I sent in feedback and stated that I expected my money back.

Mac OS X

Aperture 2 For the Lose

December 30th, 2009

I’ve run into my first Apple application failure. I really like Aperture 2. I’ve spent a fair amount of time moving my photographs into it. I didn’t even try Adobe Lightroom 2 because I liked Aperture 2’s UI so much after trying it. I rushed out and bought it, and life was good – life was good in Leopard. Well, it wasn’t that good actually. I discovered a memory leak with Nikon RAW images. I say discovered because, from what I recall now, various other people discovered it well before me and it still was not fixed yet. Go /var/log/system.log file! At least that was something I could work around.

When the Leopard of a snowy nature (as someone asked me about it once) came out, I had it installed the next day. Aperture 2.1.4 is supposed to work in Snow Leopard. It does, but it’s slow when going full screen. I put in a bug report about that. Then I realized that I could no longer make adjustments to large grayscale TIFF files! The image never fully loads (color files are fine, but again – way too slow). This was not a problem in Leopard. I put in a bug report about that and questioned the quality control here. It’s like Aperture 2 is some kind of play thing and not a flagship product. This makes me question other products, like Final Cut. What if I were to move to that someday and have the same issues? I realize that Snow Leopard is new, but Aperture 2 has been updated to run in it. We are at 10.6.2 here people. What’s the problem? You guys fix that memory leak yet?

All right, I’ve had enough. I downloaded Adobe Lightroom 2, and guess what? It’s awesome. It works with my large grayscale TIFF files. It is not slow. Adobe now has my money, when I buy it anyway – and I am not sure if Apple fixing this before my 30 day trial ends will make a difference. I just spent hours correcting some photograph TIFF scans I mad previously fixed in Aperture 2.

Apple makes a great OS, and all of their other applications work fine. Aperture 2 sucks in my experience. It even ended up wasting a ton of my time already. What a huge disappointment.

Mac OS X

Apple Mail IMAP To Do Folder Fix

December 15th, 2009

I still use Mac OS X Leopard at work, but I have Snow Leopard at home. I am not sure when I noticed, but both machines did not see the same To Do items for my work email account that I access over IMAP. At one point my work client hung so bad that I had to go in and start deleting some files it stores in ~/Library/Mail, so that might have caused the problem – though I still would classify this as an Apple bug in the first place. I noticed that my client at home saw a new folder with a name like “ToDos.mbox”, but the work client did not. I looked at the files and they both contained To Do data.

First I thought that the name of the To Dos IMAP folder changed between versions of Apple Mail, but it’s not like you can tell from Apple Mail preferences (I guess we can’t be trusted to configure something so advanced or anything). I did some searching and figured out how to change the folder name that Apple Mail uses to find To Dos in mail accounts. First, open the Apple Mail preferences file:

open ~/Library/Preferences/com.apple.mail.plist

The property list editor can be used to navigate to Roots –> MailAccounts, which will show a number of entries starting at “0″ for different accounts:

Apple Mail Preferences

Apple Mail Preferences

Navigating down further in each mail account, look for entries with ToDosMailboxName set. You can set it to the default “Apple Mail To Do” if you wish (that’s what I suggest):

Apple Mail To Do IMAP Preference

Apple Mail To Do IMAP Preference

Note that I did not prefix that with “Mail/” like the other folder in the image. I store my IMAP mail folders in ~/Mail on the server. Apparently this does not matter. In any case, this solved my problem. The Apple Mail preferences should allow you to set this IMO, but that’s not going to stop me from using it because of its integration into iCal. I do have to say that Thunderbird 3.0 does look nice however :-)

Mac OS X

RADUM, Corel Painter 11, and Snow Leopard

August 30th, 2009

Yup. I installed Snow Leopard. I immediately tried testing RADUM with the new Ruby 1.8.7 install, and it just hung there forever. I thought maybe VMware had some issues since support for Snow Leopard (32 bit kernel only) is experimental. I tried all kinds of stuff. I installed Wireshark on the Active Directory server and kept seeing all these SYNs to port 80. I installed a Windows binary of netcat and caught this after adding a rule to allow port 80 traffic:

C:\Users\Administrator\Downloads\nc111nt>nc.exe -l -p 80
GET /CertEnroll/vmware-win2008.vmware.local_vmware-VMWARE-WIN2008-CA.crt HTTP/1.1
Host: vmware-win2008.vmware.local
User-Agent: ocspd (unknown version) CFNetwork/454.4 Darwin/10.0.0 (i386) (MacBookPro4%2C1)
Connection: close

This gave me a hint. I never considered that I might need the Certificate Authority Web Enrollment role service on the Active Directory server, but I installed it and that solved the problem:

GET /CertEnroll/vmware-win2008.vmware.local_vmware-VMWARE-WIN2008-CA.crt HTTP/1.1
Host: vmware-win2008.vmware.local
User-Agent: ocspd (unknown version) CFNetwork/454.4 Darwin/10.0.0 (i386) (MacBookPro4%2C1)
Connection: close

HTTP/1.1 200 OK
Content-Type: application/x-x509-ca-cert
Last-Modified: Wed, 20 May 2009 06:14:24 GMT
Accept-Ranges: bytes
ETag: "9c8df03812d9c91:0"
Server: Microsoft-IIS/7.0
Date: Sun, 30 Aug 2009 23:46:32 GMT
Connection: close
Content-Length: 899

0...0..g.......u.G..sf.M.z.....0..*.H.......0R1.0..
..&...,d....local1.0..
..&...,d....vmware1!0...U....vmware-VMWARE-WIN2008-CA0..090520060424Z.140520061423Z0R1.0..
<snip>

Of course, anyone who knows what they are doing with certificates probably knows more about why it would be a good idea to install that anyway. This never came up for me, and I am just a lowly UNIX guy trying to write a Ruby gem to handle users and groups, etc. Now I know, and knowing is half the battle.

Oh, I also had to fight with Corel Painter 11 like mad to get it to install. I succeeded with something like the following chain of events:

  • Failing to use “sudo” as if that might work.
  • Running Painter 11 with Rosetta and actually getting to the registration/activation window, which failed.
  • A failed attempt to install the previous data to /Library/Preferences for Painter.
  • Deleting those restored files.
  • Magic.
  • Somehow having the registration/activation window take my product key, even though it would not before.
  • Running successfully under Rosetta.
  • Turning off Rosetta, entering the product key in again successfully, and having everything work fine.

Of course, none of that probably had anything to do with getting this to work. The only thing I noted was that it prompted me for my user password after the registration/activation window when it worked instead of before when it failed. Oh, and when I installed it I left the disk image mounted, but what could that have to do with it? I don’t know, it works – so whatever.

Snow Leopard is awesome though. I am happy!

Mac OS X

Weekend Fun

August 3rd, 2009

I released RADUM 0.0.1 on RubyForge this weekend. The RubyForge project page contains more information. I have also placed RDoc information on this website. The wiki page has been updated with more links and a small example program. I am glad the first release is done, but apparently ruby-net-ldap does not work with Ruby 1.9, and I also discovered that String objects pulled out of the ENV hash are frozen as well. I think the next version of ruby-net-ldap will change my dependence on the NoMethodError being raised when an LDAP attribute has no value (instead returning an empty Array), but I am sure I can deal with that. Right now the SVN trunk for ruby-net-ldap does not seem to work with Ruby 1.9. I hope ruby-net-ldap is updated soon so that I don’t have to try and fix it myself.

I also had fun trying to copy an audio CD this weekend. I don’t like to use original CDs in my SUV because I leave them in there for months (some I’ve not taken out since I bought it actually, so a couple of years). I believe that this required third party software in Windows, but I figured this would be easy in Mac OS X. Well, it turns out that it is and it isn’t at the same time. I can’t use Disk Utility to do it because it claims not to know how to make an image of an audio CD. Really? Yeah, I doubt it. It turns out that when you insert an audio CD, it is mounted and all audio tracks are presented as .aiff files. This is what I did to burn an audio CD:

  1. Install Burn.
  2. Insert an audio CD you want to copy.
  3. Close iTunes as it won’t help you with this specific task unless you import as lossless, and who the heck does that for their iTunes library?
  4. Copy the mounted CD to a folder. Mac OS X happily mounts the audio CD and presents a folder with .aiff files that you can burn. How nice, right? How about letting me make an audio CD in Disk Utility?
    cd <destination folder>
    cp -R /Volumes/Audio\ CD\ You\ Own\ And\ Should\ Be\ Able\ To\ Copy .
    
  5. Start Burn, select the “Audio” tab, and drag the copied folder onto the window.
  6. Click the Burn button. Ignore any warnings about the data being too large to fit on the CD. Yeah, it fit on a CD before, so it’s fine. Just burn it anyway. I am not sure why I got that warning.
  7. Enjoy something that is way too much of a pain to accomplish. There’s no way I am spending money on Toast!

For a task I am trying to do on Mac OS X, this seems way to hard. I expected Disk Utility to deal with this, and I think in the past it could. Anyway, I don’t do this very often at all. All of my CD slots in the SUV are occupied.

Mac OS X, Ruby, Software

Robert L. Patrick

July 22nd, 2009

Robert LaVerne “Bus” Patrick was my grandfather. He passed away on July 18, 2009. I attended his funeral today. They did a great job. I collected six of the Patrick family photograph albums. There are wonderful black and white photographs in there. Some are very old. I don’t even know many of the people in them. I’ve decided to scan them all, categorize them, and get names where I can. This is the first photograph I scanned:

Robert L. Patrick

Robert L. Patrick

I spent an hour on it. Even though it was in great condition, there were scratches and dust that had to be fixed. I’ll have to streamline this process somewhat or I’ll never get done. I think it’s a great picture of him before he went off to the Pacific. He was a Gunner’s Mate on a fuel transport and crossed the Pacific a few times.

General

RADUM Testing

July 19th, 2009

I’ve been testing RADUM pretty hard this weekend. I spent the last two days working on testing. I didn’t even go to sleep until 5AM this morning :-) I had cases to test when not working with Active Directory, and they served me well for a while. I am nearly finished with the initial version’s feature set, though I recently added the ability to convert user and groups from Windows versions to UNIX versions and vice versa. Now I have what I am calling “live testing” against Active Directory itself, and I even go as far as to manually check raw LDAP attributes. I found that I needed to do various fixes. I was not looking forward to writing the live tests against Active Directory. I was just writing small programs to spot check things before I started this, but now I am glad I got started on Saturday. I’ve made a lot of progress! I think I’ll have a Gem by next Monday. I’ll figure out where to put that when it is done.

My last live testing run failed:

[rowland@rowland: test]$ ./live-test.rb
Loaded suite ./live-test
Started
.FE
Finished in 8.374693 seconds.

  1) Failure:
test_unix_windows_conversions(TC_Live) [./live-test.rb:668]:
user should have no UNIX attributes.
<false> is not true.

  2) Error:
test_user_attributes_groups(TC_Live):
RuntimeError: User is already in the directory.
    ../lib/radum/user.rb:100:in `initialize'
    ./live-test.rb:230:in `new'
    ./live-test.rb:230:in `test_user_attributes_groups'

3 tests, 58 assertions, 1 failures, 1 errors

because I did not remove one of the UNIX LDAP attributes (uidNumber) in Active Directory when converting a UNIX user to a regular Windows user. The first error caused the test program to not remove its testing container, which lead to the second test failing. I fixed that naturally:

[rowland@rowland: test]$ ./live-test.rb
Loaded suite ./live-test
Started
...
Finished in 15.825537 seconds.

3 tests, 98 assertions, 0 failures, 0 errors

Now it is all better :-) I have a lot more to test here, but now I think that I might be where I thought I was on Friday before I started testing with respect to status. I can’t wait to make this a Gem and get it out there. I am going to use it. Maybe someone else will find a use for it.

General

Creating User Accounts Using LDAP

May 23rd, 2009

I’ve expanded my RADUM sync() method to create Windows user accounts using LDAP alone. This means I won’t have to resort to using the Windows command line. I thought this would be possible, especially after successfully creating Windows groups. I found out that I was in for a world of pain (at least initially). I kept getting error code 53: “Unwilling to perform”. I figured that I was violating some Windows security rules somewhere. I searched online like mad, and I was able to get some hints on what the problems might be, though none of those solutions were Ruby related in any way :-)

So, how does one create a Windows user account using only LDAP? There are a couple of potential problems to deal with which I will discuss inline. The basic steps I am using are:

  1. Add the user account as a normal account, disabled, and with no password required.
  2. Replace the unicodePwd and userAccountControl AD attributes to at least remove the no password required attribute (and enable the account if it should be, which it should most of the time).
  3. Set the pwdLastSet AD attribute to 0 if the user must change his password on the first login.
  4. Fix the primaryGroupGID AD attribute if the primary Windows group is not Domain Users. Note that in the first step, the account was created with Domain Users as the primary Windows group. That seems like the easiest way to accomplish this because there is additional group logic needed if the primary Windows group is not the default Domain Users group. Most of the time this would not be required, but I want to make sure it is possible.

I am not going to post all the code from my create_user() method. It’s in the RADUM Git repository, and it is not production ready yet. It does work though. I will outline one sticky problem it took me a while to figure out though. The unicodePwd AD attribute can be set using LDAP to set the user’s Windows password. This attribute expects a UTF-16LE encoded value. This is actually Base64 encoded when it is handled over LDAP as well, but when specifying the value in the LDAP method you can just give it the UTF-16LE value. There are numerous sources online that point out the UTF-16LE format for this attribute. Microsoft has some documentation here. The first thing to note about the password value is that it has to be surrounded by explicit double quotes. Ruby has an NKF class that can easily encode values as UTF-16BE:

NKF.nkf('-w16m0', '"foo"')

But I could not get anything to work with respect to getting UTF-16LE using the NKF class. I did some digging and figured out that UTF-16LE for ASCII characters is simply the character itself followed by a NULL byte. That’s very convenient since I only care about handling ASCII characters for the password (sorry everyone who wants to use more characters :-). More information about this can be found on the UTF-16/UCS-2 Wikipedia page and in this extremely helpful email. This is how I encode the user’s password for the unicodePwd AD attribute:

# Convert a string to UTF-16LE. For ASCII characters, the result should be
# each character followed by a NULL, so this is very easy. Windows expects
# a UTF-16LE string for the unicodePwd attribute. Note that the password
# Active Directory is expecting for the unicodePwd attribute has to be
# explicitly quoted.
def str2utf16le(str)
  ('"' + str + '"').gsub(/./) { |c| "#{c}\0" }
end

Note that setting the unicodePwd AD attribute also requires using TLS as well or else error code 53 will be returned. I was able to do everything else except set the password unless I switched to TLS, so for now I’ve made my code require TLS. This means that a domain must have a certificate server. On my test server I added the role. Without a certificate server, connections to port 636 on my server would simply disconnect, even though the system was “listening”.

The second pain was dealing with setting the primaryGroupID AD attribute. Most of the time this would not be necessary. Users normally have Domain Users as their primaryGroupID, but as I’ve mentioned before, I want to be able to set this to whatever (there are restrictions that I check in the code). You can’t just set the primaryGroupID AD attribute to the right group. That also returned the dreaded error code 53. When using the GUI tools in Windows, I noted that you have to first add the user as a member of the target group, then you can set their primary Windows group to be that group. This also handles the magic where the user is removed from the member AD attribute for the target group and added to the member AD attribute for the previous primary Windows group. Recall that users are members of their primary Windows group by way of their primaryGroupID AD attribute alone. So, I simply did the same thing:

# The user already has the primary Windows group as Domain Users
# based on the default actions above. If the user has a different
# primary Windows group, it is necessary to add the user to that
# group first (as a member in the member attribute for the group)
# before attempting to set their primaryGroupID attribute or Active
# Directory will refuse to do it.
unless rid == find_group("Domain Users").rid
  ops = [
    [:add, :member, user.distinguished_name]
  ]

  puts ops.to_yaml
  @ldap.modify :dn => user.primary_group.distinguished_name,
               :operations => ops
  check_ldap_result

  ops = [
    [:replace, :primaryGroupID, rid.to_s]
  ]

  puts ops.to_yaml
  @ldap.modify :dn => user.distinguished_name, :operations => ops
  check_ldap_result
end

I am outputting the ops array to YAML format for now. That will be removed eventually of course, but it is useful for now.

My general algorithm for synchronizing with Active Directory seems to be something along the lines of: create all the groups that do not already exist (sans any user memberships since those users might not exist yet), create all user accounts that don’t already exist yet, then deal with group membership issues. I’ve not gotten to the last part yet, but at least I can now create a Windows user and set their password using LDAP alone. That’s great!

Oh yeah, I forgot that I also have to deal with any modified attributes for accounts that were not created by the first part of the algorithm. I am still working on this, but first I had to figure out if I could create users and groups using only LDAP.

Active Directory, Ruby

First Steps Toward RADUM sync() Method

May 19th, 2009

Since I bought the D90 and Aperture 2, I’ve not done much with my RADUM module. I decided I better get it up to speed and accomplish something. All along I thought that I’d need to use Windows commands (dsadd, dsmod, etc.) to create objects in Active Directory. I tried using the add() method of the Net::LDAP module to create a group and it worked! I am so happy. I might be able to do this as a pure Ruby module. I did not know if it would work since I can’t necessarily specify all the attributes, but I was hoping Active Directory would take care of the rest. So far it does. I couldn’t be happier about that.

I did have a little trouble at first because I did not catch that the attributes hash used with the add() method needs to contain string values. When creating a group so far, the code looks like this:

dn = group.distinguished_name

# Note that all the attributes need to be strings in this hash.
attr = {
  :cn => group.name,
  :groupType => group.type.to_s,
  :name => group.name,
  # All groups are of the objectclasses "top" and "group".
  :objectclass => ["top", "group"],
  :sAMAccountName => group.name
}

@ldap.add(:dn => dn, :attributes => attr)

unless @ldap.get_operation_result.code == 0
  puts "SYNC ERROR: " + @ldap.get_operation_result.message
end

That’s just the code I’ve checked in right now. Obviously it needs a lot of work. The group types I defined in the RADUM module have to be strings here. The numbers should be Bignums, but I can only pull them as Fixnums, so I was a little worried. Note that if you view these using GUI tools in Windows, they are represented as Fixnum types (large numbers are negative). I used those values here, and it works! Again, I am happy about that. So now I can create a group from nothing like this:

RADUM::UNIXGroup.new("newgroup", cn, ad.load_next_gid,
                     RADUM::GROUP_UNIVERSAL_SECURITY, "vmware")
puts "Looking for next UID: " + ad.load_next_uid.to_s
puts "Looking for next GID: " + ad.load_next_gid.to_s
ad.sync

and it actually creates the group:

Looking for next UID: 1010
Looking for next GID: 1004
newgroup not found - creating...

I also added the load_next_uid() and load_next_gid() methods to find the next usable UID and GID values by searching the entire Active Directory. This could be useful when creating UNIXUser and UNIXGroup objects if you do not already know the next available UID or GID. If all of your users and groups are in all the containers you load into the AD object, you can simply rely on the uids and gids attribute of the AD object itself, but I am trying to cover all the bases. Those methods truly do find the next UID and GID, not just the highest one not used. Of course, by the code above, I am not handling all the possible attributes. I just wanted to see if it could create the group in the first place. Now I have something to work with.

I hope this works for user accounts too. If so, that means I don’t have to make this Windows specific for actually creating new entities. That’d be great! I am excited. I never thought I’d be excited about Active Directory :-)

Active Directory, Ruby

We’ll Just Call It a Flower, With Raindrops…

May 13th, 2009

It rained all day. I got home late and the lighting wasn’t good, but I had to pull out the D90 and shoot the same mysterious flower which I cannot name. I am sure there are thousands of people who aren’t reading this who can name it easily. I probably could figure it out, but I am busy. Said flower again, now with RAIN™:

Flower with raindrops in the front yard.

Flower with raindrops in the front yard.

and:

Flower with raindrops in the front yard.

Flower with raindrops in the front yard.

I thought it was neat. I need to get out more :-)

Photographs