Home 0 SoundRaider 0 Director 0 Faust 0 Nectarine 9 0 Personal 0
 
 XObjects
 Shockwave Gallery
 Technical Guide for Director Developers
 Director Tips and Tricks
 
 Director Users Group
 DUG Members List

© Andy Wilson, 1998

Tips and Tricks: Secrets and Drives

Every month I’ve encouraged people to mail me with any questions they have about Director and Lingo. The odd thing is that I get a few questions asked over and over again. So, this month I thought I’d answer a couple of the FAQ’s that crop up regularly both in my post bag and on the UK Director Users Group (DUG) mailing list (see www.obsolete.com/dug/ for information on joining the User Group – it’s free and a wonderful source of information on all things connected with Director).

Basic Encryption

It seems to me that more and more people are using text files to store data from Director about users – user details, scores, preferences and the like. Even more commonly, people are using the Prefs file to store the same information when running Shockwave files. A common requirement is that you need to encrypt this information to keep away prying eyes.

I had this problem myself recently with a program I have been working on. I needed to store important information in an external file that I didn’t want the user to see. However, it was obvious that anyone who bothered looking at the program’s INI file, where I stored the information, would be able to read it easily and even edit it. I decided that the best way around this would be to encrypt the information before storing it.

It is important to say here that what we are talking about is a level of encryption that is strong enough to prevent the casual browser from being able to read the data in the file, nothing more. The encryption we are talking about here could be cracked by any serious hacker, so don’t use it for any information that needs to be kept truly confidential. Having said that, in the vast majority of cases this low level of encryption will suffice.

The key to this technique is that we are going to ‘shift’ all the letters in the string to be encrypted before saving it, then shifting it back again when we read it. What I’m talking about ‘shifting’ here is the ASCII number of the character to be encrypted. This is the number that is returned when you use the Lingo handler charToNum on a character – it tells you the ASCII number that is associated with that character.

All we need to do to encrypt a character is to get it’s ASCII number, offset this a little, then convert it back to another, different character. Decryption simply works in the opposite direction – you take the ASCII number of the encrypted character, offset it in the opposite direction to the encoding process, then convert it back to a character.

Actually there is a little catch here to do with the way that strings and characters work. A character cannot have an ASCII value greater than 255. If you try to set a character to a higher value it will wrap around, starting at 0 again. What this means is that you can’t offset the character’s ASCII value too much or it will go out of range. Since we are basically encoding alphanumeric characters, and since the ASCII value of "Z" is 90, and the code for "z" is 122, we don’t want to add an offset value that will take us out of range. Fortunately, we have plenty of room to play with.

Similarly, if you want to subtract the offset when encoding, you need to be careful not to extract too much. In this case the situation is worse. Not only will a value wrap round to 255, as before, but in fact you need to avoid any ASCII value below 32, since these are reserved for control characters which can cause you all sorts of bother. The best way to avoid this is not to use subtraction for your encoding. Take advantage of the greater room for manoeuvre at the top end of the ASCII table by adding the original offset rather than subtracting. Having said that, we can now see the code that will do the work. Of course you need to set the value of the offset, stored here in the global variable gOffset, before using either of the handlers.

global gOffset

on encryptString str
  set len = the length of str
  if len = 0 then return EMPTY
  set encryptedString = EMPTY
  repeat with chNum = 1 to len
    set thisChar = char chNum of str
    set thisCharASCII = charToNum (thisChar)
    set newCharASCII = thisCharASCII + gOffset
    set newChar = numToChar (newCharASCII)
    put newChar after encryptedString
  end repeat
  return encryptedString
end

on decryptString str
  set len = the length of str
  if len = 0 then return EMPTY
  set decryptedString = EMPTY
  repeat with chNum = 1 to len
    set thisChar = char chNum of str
    set thisCharASCII = charToNum (thisChar)
    set newCharASCII = thisCharASCII - gOffset
    set newChar = numToChar (newCharASCII)
    put newChar after decryptedString
  end repeat
  return decryptedString
end

As I warned earlier, this method only offers pretty low level encryption. But it works:

set goffset = 1
put encryptString ("HAL")
- - "IBM"
put decryptString ("IBM")
- - "HAL"

set goffset = 40
put encryptString ("Andy Wilson")
-- "Boez!Xjmtpo"
put decryptString ("Boez!Xjmtpo")
-- "Andy Wilson"

Next month I’ll be looking at another encryption algorithm, XOR encryption, that uses an encryption key to do it’s work and is far more powerful. As I mentioned before, though, this simple method outlined above will suffice for most purposes.

Where’s my CD Drive?

A common problem, at least in Windows projectors, is that you want to store resource files or other data on the CD you distribute your projector on, and need to know which drive is allocated to the CD on the user’s system so that you can get at the files.

The neatest way to do this is to put a dummy file in the root of your CD then go looking for it when your projector starts to run. The dummy file can be anything you like. A good idea is to simply create an empty text file, let’s call it CDLocate.txt, and save it in the root directory of the CD.

Now, when your projector is first run you can call the handler we’re about to write to look for the file. The best place to put any handler you want to call when a projector is first run is in the startMovie handler. Let’s call our new handler CDLocate. That means that our startMovie handler will look like this;

on startMovie
    global CDDrive
    ..
    set CDDrive = CDLocate ()
    ..
end

Now all we have to do is write the handler that’s going to do the work for us. The general idea of the handler is to examine all of our drives in turn and look for our dummy file in the root directory of each drive. When we’re reading directories like this the Lingo handler to use is getNthFilenameInFolder. This handler takes two arguments. The first is the name of the directory you want to read. In our case we want to read the root directory of a drive. So, for example, if we wanted to read the root directory of drive C we would pass "C:\" as the first argument. The second argument is the number of the file you want to find out about in the file allocation table. To continue with our hypothetical example, if we passed the number 1, getNthFilenameInFolder would return to us the first entry in the file allocation table (FAT) for the root directory of drive C.

put getNthFilenameInFolder ("C:\", 1)

The only thing we need to know now before writing our handler is that if there are no entries left in the FAT, getNthFilenameInFolder will return EMPTY. That means that, to look for a file, we can simply look at each successive entry in the FAT until we either find what we are looking for or get an EMPTY answer. The general method we are going to employ, then, is to look in the root directory of each drive in turn and search for our dummy file. When we find it, we know that we have found our CD on the user’s system.

on CDLocate
  set startDriveNum = charToNum ("A")
  set endDriveNum = charToNum ("Z")
  repeat with driveNum = endDriveNum down ¬
  		to startDriveNum
    set driveLetter = numToChar (driveNum)
    set searchDrive = driveLetter & ":"
    set searchDirectory = searchDrive & "\"
    repeat with fileNum = 1 to the maxInteger
      set fName = getNthFilenameInFolder ¬
	  		(searchDirectory, fileNum)
      if fName = EMPTY then exit repeat
      if fName = "CDLocate.txt" then ¬
	  		return searchDrive
    end repeat
  end repeat
  return #notFound
end

Notice that I’ve searched backwards, starting at drive Z and working back towards drive A. This is because the CD Drive is conventionally (though not always) allocated the last drive letter available on the system. By searching backwards we avoid the, admittedly small possibility that a file exists on one of the system’s hard drives with the same name as our dummy file.

That’s it. Now that you know the drive letter, you can find any resource on the CD in order to import it or read it. For example;

set drv = cdlocate()
put importFileInto (member 2, drv & ¬
		"\pictures\logo.gif")
-- 0

Comments and suggestions for suture articles can be mailed to me at andyw@dircon.co.uk.

 
There are currently users connected. You have viewed 1 pages. Unless otherwise stated, all content is ©1996-2003 Andy Wilson. If you have any questions or suggestions you can mail me: andyw at dircon dot co dot uk. This site is hosted by LShift Ltd.