An Open Letter to Steve Jobs and the iPad iOS Design Team

July 28th, 2010

Steve

I’ll get right down to business. I’m a bit perplexed by some of the User Interface inconsistencies I’ve been finding in many of the Apple-written iOS applications on my iPad. I’ll give you a few examples:

I want to uninstall an App. I hold my finger over the App for a few seconds, it wobbles, I can either drag it somewhere else or click the X to delete it. Makes perfect sense to me. What happens if I want to remove an iBook from my Bookshelf, like the graciously provided Winnie The Pooh book? Naturally, I hold my finger on the book for a few seconds, expecting that I can delete it. Nope! All that allows me to do is drag it around. To delete the book, I must click on Edit on the top right of the screen. Interesting.

Swiping left and right to move forward/back. On the App screens, I can swipe left and right to change from one page of apps to another. On the iBook App I can operate similarly to change pages in books. But in Safari, if I want to go to the previous page I visited, why can I not swipe right to left? Instead I must awkwardly reach from the natural position I was holding the iPad (which is NEVER near the top of the device, where those pesky buttons hide!) and click the Back button. Now I realize there is probably some reason why this is the case, but you must admit, it feels far too Desktop-y. You built this great OS with these touch interfaces, but the reliance on buttons instead of gestures is simply astounding!

Now, my last example for the night. Contacts. Why on earth doesn’t this App take up the full screen? Would it really be that much worse in Portrait mode for it to be a bit taller? Certainly doesn’t look that way to me. I’m sure there’s some better way of doing this.

In any case, I hope you, or someone of the appropriate ability, can take these comments and do something useful with them. I can’t imagine I’m the only one noticing these things.

Take care,
Joe

Sent from my iPad ;)

Creating a Script-Wrapping HTA – Part 1

May 10th, 2010

Microsoft has an interesting How-To on wrapping your Automation/Administration scripts in an HTA. Let’s take their example and develop it a little further.
Read the rest of this entry »

Fun with Tokens

April 22nd, 2010

I manage to find all sorts of fun problems for myself with scripting. The latest is needing to set some security privileges on the “Support_######” account on a wide range of systems. As you may know, the Support account has a randomized username, different with every installation. This posed what seemed at first to be quite a tricky problem, and once I had solved it the hard way, the easy way quickly became apparent.

So first off, the quickest way to get a list of the local user accounts on a system is by way of the NET USER command. Unfortunately, this command puts its output in a table rather than one username per row. So already I know we’re going to have some fun with this one.

So we take net user and want to run a find against it, to find the row with the correct user account: NET USER ^| FIND /I "SUPPORT" . Now how do we break out the one piece that we need? FOR can help us out here.

FOR has the option to run on a variety of input, and has quite a few options. The options we’re concerning ourselves with right now are tokens and delims. Delims specify what seperates the input, typically a TAB or a Space, and tokens specifies what number of the delimited input you want. Let’s take a look at an example:

FOR /F "tokens=2 delims= " %%A IN ("sample input text") DO @ECHO %%A

The output is input since input is the second token in the input. Now how does this help with my problem? I can’t determine where the SUPPORT account is in the list, it could be the first, second, or even third space-delimited output. But there is one thing that sets SUPPORT apart from the other user accounts, and we can use that to our advantage.

FOR /F "tokens=2 delims=_" %%A IN ('net user ^| FIND /I "SUPPORT"') DO SET NETUSER=%%A

We set the delimiter to an underscore, and the token to 2 since what we want immediately follows the underscore, the unique portion of the SUPPORT account’s username. However if the SUPPORT account is listed first or second in the output, we’ll have a bunch of garbage following it, including spaces and other user accounts. Luckily, there’s an answer to this.

SET SUPPORT=SUPPORT_%NETUSER:~0,8%

We take the variable we just created, NETUSER, and do some magic to it. We’re looking for only the first 8 characters, so we break the string up with the :~0,8 and add the text “SUPPORT” to the front of it, to a new variable called SUPPORT.

Voila, we have our output! Here’s the final script:
FOR /F "tokens=2 delims=_" %%A IN ('net user ^| FIND /I "SUPPORT"') DO SET NETUSER=%%A
SET SUPPORT=SUPPORT_%NETUSER:~0,8%

Now we can use the SUPPORT variable in any command in the script, such as:

NTRIGHTS.EXE +r SeDenyBatchLogonRight -u %SUPPORT%
NTRIGHTS.EXE +r SeDenyInteractiveLogonRight -u %SUPPORT%
NTRIGHTS.EXE +r SeDenyNetworkLogonRight -u %SUPPORT%

Now if you recall at the beginning, I mentioned there was an easy way I could have accomplished this. As it turns out, the SUPPORT user belongs to a group, which the Support user is the only member of. NTRIGHTS.EXE can take Groups as well as individual accounts for its target, and the name of the group is consistent across all platforms. Oh well, at least I learned a lot about FOR loops and Tokens!

NTRIGHTS.EXE +r SeDenyBatchLogonRight -g HelpServicesGroup

Quick and Dirty Method to Determine Windows Architecture

April 22nd, 2010

There are many ways to determine the architecture of your Windows Server via script, but many involve multiple lines and comparing strings in the registry. One that I don’t see much mention of is the very simple %processor_architecture% variable.

Easy enough to use, here’s a BATCH script example:

IF NOT %processor_architecture% == x86 GOTO 64
GOTO 32

:32
echo do this if x86
goto end

:64
echo do this if x64
goto end

:end

Can’t beat that, right?

Using DenyHosts to Automatically Block Failed Login Attempts

April 21st, 2010

Anyone with a Linux server running SSH and has taken the time to look at their auth.log has surely noticed at one time or another someone or something trying to brute force their way into your server. The signs are obvious, a list of common usernames one after the other failing to login. However, combing through logs to find troublesome hosts to block quickly becomes a nuisance and a time-waster. Luckily, there are tools that can be used to help you with this: DenyHosts.

DenyHosts is a script intended to be run by Linux system administrators to help thwart SSH server attacks (also known as dictionary based attacks and brute force attacks).

DenyHosts is a package that can easily be installed on various Linux Distributions by their package manager, ie: apt-get install denyhosts. From there, to monitor SSH logins all you need to do is edit /etc/denyhosts.conf with the settings you desire. Personally, I have mine set to ban any IP that tries to login as ‘root’ after one attempt, as I disallow SSH Root Login. Any existing user account is granted three login attempts before a temporary ban, any non-existing account is banned after two attempts. To prevent locking myself out, I have added my own IP address to /etc/hosts.allow, just in case.

One great feature of DenyHosts is the ability for the software to connect to a central repository of other DenyHosts users. When I catch an attacker, my client can report up to the server and notify others running this application that they should block this address too. To prevent invalid entries, you can configure that a minimum of X number of other ‘reports’ must be known regarding that IP address before you accept it into your block list as well. At the time of this writing, my /etc/hosts.deny has over 10,000 blocked IP addresses. As addresses go stale, from no more attack sightings, they get removed from the list.

Definitely something I add to any linux server running SSH that has access to the internet, and I hope you take this into consideration for your own systems as well.

BATCH Scripting: Using the Event Log

December 21st, 2009

While working on my Uber-script to automate the steps I take when bringing a Windows Server 2003 system online, I started to think about the ability to verify that steps were completed successfully. This can be done fairly easily using %errorlevel% by checking the exit status of each step:


xcopy file1 C:\Path\To\Copy\To\
IF "%errorlevel%" == "0" (
echo "xcopy file1 succeeded" >> C:\Temp\build.log
) ELSE (
echo "xcopy file1 failed" >> C:\Temp\build.log
)

If the copy succeeds, xcopy exits with an errorcode of 0 and we write a success message to the log. If it fails, a different errorlevel is produced and we write a failure.

But what if you have thousands of things to check on? Like checking each of the 100 patches in the previous post’s Update? A log file might work great for some people, but knowing my target audience I wanted something a little more obvious, and the Event Log is what I turned to.

Right off the bat I decided we wanted to use our own custom Event Log rather than one of the existing logs, so that we can keep everything separated and easy to audit. Creating a new event log can be done easily enough in VBScript:

Const NO_VALUE = Empty
Set WshReg = WScript.CreateObject("WScript.Shell")
WshReg.RegWrite "HKLM\System\CurrentControlSet\Services\EventLog\NewLogName\", NO_VALUE

Which gets called from the Uber-Batch-Script by:
cscript CreateEvtLog.vbs

So now that we have our new event log, what can we do with it? Let’s build off the previous xcopy example:

xcopy file1 C:\Path\To\Copy\To\
IF "%errorlevel%" == "0" (
EVENTCREATE /ID 1 /L NewLogName /T INFORMATION /SO "Server Build" /D "file1 was copied successfully" > NUL
) ELSE (
EVENTCREATE /ID 1 /L NewLogName /T INFORMATION /SO "Server Build" /D "file1 was not copied successfully" > NUL
)

So now, rather than echoing to a log that the copy succeeded or failed, we create an entry in our new Event Log. And if the copy fails, we get a nice red X. Quickly scanning for failed steps just got a whole lot quicker.

BATCH Scripting FOR Loops

December 21st, 2009

Lately I have been working on automating a huge amount of work that gets done manually to each Windows Server 2003 machine before it is allowed to touch the network. This includes Windows Updates, Registry Edits, and installing a lot of software. This can take hours depending on who is doing the work. So I started investigating how to automate this, one piece at a time.

Starting off with Windows Updates, I came to the realization that if I were to write a script with all 100 or so updates, I’d end up with a script that was annoying to maintain. Manually removing Superceded updates from the folder, then removing the reference to it from the script, and then adding the new updates in. Surely, there must be a better way!

And along comes the idea of using a simple FOR Loop.

PUSHD X86\UPDATES

FOR /F %%i IN ('"dir /b /o:n *.exe"') DO CALL :install %%i

QCHAIN.EXE
POPD
GOTO :EOF

:install
%1 /Z /Q /U

Pretty straightforward, the script goes into the X86\UPDATES directory, and get a directory listing of all of the files sorted alphabetically. Then, for each of the files in the directory, it calls :install, which says to run the file with the arguments /Z /Q /U.

Once all of the files have been run, it escapes the for loop to run QCHAIN.EXE, return to the original directory, and then exit the script.

Now when I need to remove an update, I simply delete the .exe from the UPDATES directory, and adding new updates is just as simple – just copy it in!

Rate Limiting scp

September 8th, 2009

Broadband internet connections keep getting faster and faster, but as soon as you flood your pipe by uploading too quickly, everything grinds to a halt. At least that’s the case with Comcast. Maybe you FiOS people are luckier than I am.

My home router (a D-Link DIR 655) is supposed to do some fancy QoS and automatically determine how fast is too fast for my upload speed, but it never seems to work right, flooding my pipe and making browsing the internet feel worse than it did back in my 14400baud AOL days.

In any case, this afternoon I was working on uploading some 2GB of resized photos to my webserver and came across a handy setting in scp that allows you to control the speed at which your upload takes place.

Not a whole lot to explain here, so here’s all you need to know:
scp -l 512 filename user@host:

The -l flag limits the transfer speed, in Kbit/s.

ImageMagick Batch Image Resizing

September 7th, 2009

I like to have photos I take available to family members online, but with modern cameras taking pictures at 10 Megapixels and up, these photos quickly consume lots of the limited space I have on the webserver. Since most of these photos are only going to be viewed on the screen, it makes sense to resize them before publishing them to the Gallery2 photo album I use. This helps cut the amount of time it takes to upload them, as well as save space on the server. The best method for accomplishing this in my setup, is to batch resize them using ImageMagick.

There are a few different methods by which you can use ImageMagick to resize photos. Here are a few quick examples:

mogrify -resize 800 *
Simply enough, this will resize all files to a width of 800 pixels, maintaining aspect ratio

mogrify -resize 800x800! *
This will break the aspect ratio, and force all images to exactly 800×800 pixels.

And finally, a method by which you can recursively resize all of your photos:
find ./ -name "*" -exec mogrify -resize 800 {} \;