Topics


Blogs


Forums


Samples


Media


Labs


Resources

 




DevCentral > Weblogs > Joe Pruitt - A Software Architect's take on Network Security
  Wednesday, December 23, 2009 #
  
X-Forwarded-For HTTP Module For IIS7, Source Included!

iis7-highlight For those who of you that are having problems with logging client addresses in their server logs because you are running your web servers behind a proxy of some sort, never fear, your solution is here.  For those that don't, I already discussed in my previous posts about what the X-Forwarded-For header is so feel free to click back into those to read about it.

History

Back in September, 2005 I wrote and posted a 32-bit ISAPI filter that extracted the X-Forwarded-For header value and replaced the c-ip value (client ip) that is stored in the server logs.  Lots of folks have found this useful over time and I was eventually asked for a 64-bit version which I posted about in August, 2009

The Question

question_mark_3d Well, it looks like it's time for the next generation for this filter…  I received an email from a colleague here at F5 telling me that his customer didn't want to deploy any more ISAPI filters in their IIS7 infrastructure.  IIS7 introduced the concept of IIS Modules that are more integrated into the whole pipeline and was told that Microsoft is recommending folks move in that direction.  I was asked if I had plans to port my ISAPI filter into a HTTP Module. 

The Answer

Well, the answer was "probably not", but now it's changed to a "yes"!

The Solution

In reading about IIS Module, I found that you can develop in managed (C#/VB) or Native (C++) code.  I loaded up the test C# project to see if I could get it working.  In a matter of minutes I had a working module that intercepted the event when logging occurs.  The only problem was that from managed code, I could find no way to actually modify the values that were passed to the logging processor.  This was a problem so I scrapped that and moved to a native C++ module.  After a little while of jumping through the documentation, I found the things I needed and pretty soon I had a working HTTP module that implemented the same functionality as the ISAPI filter.

Download

The new Http Module hasn't had much testing done so please test it out before you roll it out into production.  I've made the source available as well if you find an issue and care to fix it.  Just make sure you pass back the fixes to me B-).

The filter will require installation into IIS in order for you to be able to add it to your applications.  Both distributions include a readme.txt file with an example installation procedure.  Make sure you use the Release builds for the appropriate platform (x86 or x64) unless you are in need of some troubleshooting as the Debug build will dump a lot of data to a log file.  The module supports customizable headers if you are using something other than X-Forwarded-For.  Instructions for using that are in the readme.txt file as well.

If you have any issues with using this, please let me know on this blog.  Keep in mind that this is an unsupported product, but I'll do my best to fix any issues that come up.  I'm even open to enhancements if you can think of any.

Enjoy!

-Joe


Add Comment |
 
      

  Monday, October 05, 2009 #
  
Introducing Posh-FourSquare - The PowerShell library for FourSquare.com

PoshFourSquare_thumb[2]Those who know me, can attest that I'm a early adopter when it comes to social networking systems.  The latest one I've been getting into lately is FourSquare.com

FourSquare.com describes itself as 50% friend finder, 30% social city guide, and 20% nightlife game.  They include ways to keep up with what your friends are doing as well as offering up some fun challenges to have you explore cities in different ways.

Once I've played around with a social networking site for a bit, my next step is to see what kind of API's they have exposed and see if I can build my own app to integrate with the site.  It turns out that the FourSquare.com has exposed a public API in their FourSquare-API Google Group.

So, as I did with my Posh-Tweet, Posh-Bing, Posh-TwitPic, and Posh-Delicious libraries, I went ahead and wrote a PowerShell library of functions to access the FourSquare APIs.

The API is broken down into these categories:

Credentials

  • Get-FourSquare.Credentials - Get the credentials for your FourSquare.com account.
  • Set-FourSquare.Credentials - Set the credentials for your FourSquare.com account.

GEO Methods

  • Get-FourSquare.Citites - Returns a list of currently active cities.
  • Check-FourSquare.City - When given a lat/long, returns the closest foursquare city.
  • Switch-FourSquare.City - When given a valid foursquare cityid, changes the user's default city.
  • Get-FourSquare.Checkins - Returns a list of recent checkins from friends.
  • New-FourSquare.Checkin - Allows you to check-in to a place.
  • Get-FourSquare.History - Returns a history of checkins for the authenticated user (across all cities).

User Methods

  • Get-FourSquare.User - Returns profile information (badges, etc) for a given user.
  • Get-FourSquare.Friends - Returns a list of the authenticated user's friends.
  • Get-FourSquare.Venues - Returns a list of venues near the area specified or that match the search term.
  • Get-FourSquare.Venue - Returns venue data, including mayorship, tips/to-dos and tags
  • Add-FourSquare.Venue - Allows you to add a new venue.

Tip Methods

  • Get-FourSquare.Tips - Returns a list of tips near the area specified.
  • Add-FourSquare.Tip - Allows you to add a new tip or to-do at a venue.

Other Methods

  • Get-FourSquare.Status - Returns the string "ok".

Usage:

To use the API's you must first register on FourSquare.com.  The username and password you use to create the account will be used in this API with the Set-FourSquare.Credentials method.  After setting your credentials, you can call any of the other methods and start updating your status from the comfort of your PowerShell prompt.  The following example will register the functions in the current runspace, set the credentials, query the available citites, and then checkin at the Cafe next door for lunch.

PS C:\> . .\Posh-FourSquare.ps1
PS C:\> Set-FourSquare.Credentials -user myuser -pass mypass
PS C:\> Get-FourSquare.Cities | Format-Table id timezone name geolat geolong -- -------- ---- ------ ------- 56 Europe/Amsterdam Amsterdam 52.3789 4.90067 46 America/New_York Atlanta 33.7525 -84.3888 42 America/Chicago Austin 30.2669 -97.7428 58 America/Denver Black Rock City 40.7693 -119.22 24 America/New_York Boston 42.3583 -71.0603 32 America/Chicago Chicago 41.8858 -87.6181 43 America/Chicago Dallas / Fort Worth 32.7887 -96.7676 25 America/Denver Denver 39.734 -105.026 47 America/New_York Detroit 42.3333 -83.0484 48 America/Chicago Houston 29.7594 -95.3594 49 America/Los_Angeles Las Vegas 36.1721 -115.122 34 America/Los_Angeles Los Angeles 34.0443 -118.251 39 America/New_York Miami 25.7323 -80.2436 51 America/Chicago Minneapolis / St. Paul 44.9609 -93.2642 22 America/New_York New York City 40.7255 -73.9983 33 America/New_York Philadelphia 39.8694 -75.2731 53 America/Phoenix Phoenix 33.4483 -112.073 37 America/Los_Angeles Portland 45.527 -122.685 38 America/Los_Angeles San Diego 32.7153 -117.156 23 America/Los_Angeles San Francisco 37.7587 -122.433 41 America/Los_Angeles Seattle 47.6036 -122.326 59 America/Vancouver Vancouver 49.259515 -123.103867 31 America/New_York Washington, DC 38.8964 -77.0447 PS C:\> New-FourSquare.Checkin -venue "Urban Cafe" -shout "It's lunch time!" message : OK! We've got you @ Urban Cafe. This is your 4th checkin here! id : 1398385 created : Mon, 05 Oct 09 12:50:00 +0000 venue : venue mayor : mayor

Get The Source

The full source for the script is available from my blog at Posh-FourSquare.ps1

Enjoy!

-Joe


2 Comments |
 
      

  Friday, September 25, 2009 #
  
Turn Your Podcast Into A Interactive Live Streaming Experience

image The folks here on the DevCentral team have been producing a weekly podcast for a while now.  Trying to keep our budget low, we opted to copy what some other podcasters were doing by making use of Skype for our audio communication and found a great little Skype add-on called Pamela which creates high-quality WAV files from Skype conversations. 

We created a dedicated Skype account on an old machine here in the office that will auto-record whenever that account is added to a conversation. We would occasionally have differences in audio levels between the callers so we incorporated the awesome The Levelator (from the Conversations Network) into the post production and we were set.

A few weeks ago we broke through our one hundredth podcast and along with that milestone we decided to expand things a bit by making the podcast more interactive.  I spent a few weeks investigating how to best accomplish this and I ultimately decided on a setup.  I figured that I'd go ahead and share it with you all so you can see how we do it on our end.  Here's the high-level diagram:

podcast-architecture

 

I experimented with a mixing board but ended up with a software only solution that anyone can implement.  Everything besides the top left three items in the image were added to enable us to record our Skype podcast as well as stream it to UStream and allow callers with TalkShoe. 

The Components

Here's a list of the following components and how we used them.

Skype - http://www.skype.com - $0

Skype, for those that don't know, is a software program that allows you to make video and voice calls across the internet.  Calls are free to other skype users and you can purchase the ability to call out to land line numbers or to get your own number so you can accept phone calls.

We have a dedicated server with Skype and Pamela running to do the recording and each person on the podcast is connected through the main Skype instance on our publishing system.

Pamela Skype Recorder - http://www.pamela.biz/en/ - $24

Pamela is an add-on program for Skype that will allow you to record your Skype conversations.  It features Skype call, video, and chat recording, answering machine, video mail, and skype based publishing.  We use it primarily for the ability to automatically record skype calls to either our skype account or our Skype dial-in number.  .WAV files are created and we are emailed when a recording is completed.

Windows Media Player - $0

Windows Media Player is the default music/video player on the Windows platforms.  We use it to play background music into our skype and UStream sessions.  You could just as easily use another audio player as long as it supports the ability to customize which output audio device it uses.

Virtual Audio Cable - http://software.muzychenko.net/eng/vac.html - $30

This little gem really saved the day with our setup.  There are various Mac programs that allow you to map audio streams from one program to another one but this is the best one I could find for Windows.  Virtual Audio Cable allows you to transfer audio (wave) streams between applications and/or devices.  In our setup, it allows us to map windows media player back into Skype and our multiple audio streams back into our live video processing through VidBlaster.

VidBlaster - http://vidblaster.com/ - $0

VidBlaster is a powerful, economic way to record, stream, and produce high quality videos.  VidBlaster comes in three versions: Home, Pro, and Studio with the only difference being the number of "modules" you can use at one time.  What's best about this product is that you can use it for free if you can live with a "VidBlaster" add in the top right corner of your video stream.  We'll likely put the couple hundred bucks down for the Pro version but as of now it hasn't costed us a cent.

Adobe Flash Media Encoder - http://www.adobe.com/products/flashmediaserver/flashmediaencoder/ - $0

The Adobe Flash Media Encoder allows you to capture live audio and video while streaming it in real time to a flash media server.  While we could stream directly from VidBlaster to UStream, the quality is not as good as moving some of the processing down to the client.

UStream - http://www.ustream.tv - $0

UStream is the live interactive video broadcast platform that enables anyone with a camera (or VidBlaster!) and an internet connection to quickly and easily broadcast to a global audience of unlimited size.  Best of all, it's free!

TalkShoe - http://www.talkshoe.com - $0

We struggled for a while trying to figure out the best way to include a "live" audience in our recording.  TalkShoe is a service that enables anyone to easily create, join, or listen to live interactive discussions, conversations, podcasts, and audioblogs.  It fit the bill of just what we needed and since we already had our Skype conversation going, bolting on TalkShoe was as simple as adding the conference number to our group Skype conversation.  TalkShoe also has some pretty nifty user controls allowing the moderator to control muting of each of the participants.  Another great free service!

Production Setup Walkthrough

Here's the steps I go through in preparation for our weekly podcast.

  1. Create 3 Virtual Audio Cables with the Virtual Audio Cable Control Panel (VAC #1, VAC #2, VAC #3)
  2. Start up 2 instances of the Virtual Audio Cable Audio Repeater.  Set the first one (R1) from VAC #3 to VAC #1 and the second from VAC #3 to VAC #2.
  3. Start and login to Skype.  Go into the Audio settings and change the audio input to VAC #1 and the output to VAC #2.
  4. Start Windows Media Player and change the speaker device settings to output to VAC #3.
  5. Start VidBlaster and setup various screen captures, set the video resolution to 640x480 and the frame rate to 15fps (much higher than that drives the CPU way up).  Finally click "Start" on the Streamer module.
  6. Start the Adobe Flash Media Encoder.  Load the stream configuration that you can download from your UStream show's advanced settings and then Select VidBlaster for the Video Device and "Line 2 (Virtual Audio Cable)" (ie. VAC #2) for the Audio device.  Click "Start" to begin streaming.
  7. Login to our UStream.tv account and click "Broadcast Now" for your show.  Another browser window will come up detecting the media stream.  Click "Start Broadcast" to start the stream and click "Start Record" to being recording your stream on the server.
  8. Bring up the Skype window and create a conference with the podcast members including our account that auto-records the conversations.  Then finally, call the TalkShoe conference bridge and initiate the meeting on their side.
  9. Login to the TalkShoe account on their website and click the option to join the meeting.  When the admin console is loaded, you can optionally select "Record" from the top left to have TalkShoe make an alternate recording.

At this point we are recording our Skype session in audio, UStream is recording the video stream and TalkShoe is recording a secondary audio recording.  At this point, I cue up the intro music in Windows Media Player and start into the podcast.

When we are finished, I reverse the process above by stopping and saving the various recordings.  I take our Pamela based recording, run it through The Levelator, convert it to a mp3 with Audacity, edit the ID3 tags, and publish it to our media server.  At this point, the blog post is created and we are done for the week.

Reflections

There are a few things that are still causing some issues.  The main issue is that of horsepower on my media system.  The desktop I'm using for all of this was not meant to run these types of CPU intensive applications.  While it works, my dual-core CPU system is hovering at 99-100% CPU usage during the podcast which is a bit worrisome.  Depending on the success of the podcast, we may invest in a new desktop to run this on.  But, seeing how we've spent well under $100 for the entire software suite, I don't think we'll have much trouble justifying it!

Hopefully this helps some of you out there with some ideas and I'd love to hear feedback on how I could do things better!

-Joe


2 Comments |
 
      

  Monday, September 21, 2009 #
  
Introducing Posh-Delicious - The PowerShell Library For The Delicious Bookmark Service

poshdelicious

For those of you who don't know what Delicious.com is (yes it's the same as del.icio.us), I'll just borrow their overview from their getting started page:

Delicious is a social bookmarking service that allows you to tag, save, manage, and share Web pages all in one place.  With emphasis on the power of the community, Delicious greatly improves how people discover, remember and share on the Internet.

Here on DevCentral, when new content is added, we regularly add it to various social networking sites, including Delicious.  There are some great browser plugins that help you with sharing content and I regularly use the Shareaholic Firefox plug-in.  But, it's still too much manual work for me so I figured I'd try to automate it a bit.

I previously published a PowerShell library for Twitter (PoshTweet), for TwitPic (PoshTwitPic) as well as one for the Bing Search API (PoshBing) so I figured I'd build on those and write one for Delicious.  The Delicious API documentation is defined here

The API is broken down into the following functions:

Credentials

  • Set-Delicious.Credentials - set the client credentials for the delicious.com account.
  • Get-Delicious.Credentials - get the client credentials for the delicious.com account.

Posts

Tags

Tag Bundles

Usage:

The usage is fairly straight forward.  First you must load the functions into your runspace.  This is most easily done by "dot sourcing" the script.  Then you will call the Set-Delicious.Credentials function with your delicious credentials.  At this point you should be all set to submit bookmarks with PowerShell.  The following code creates a new bookmark for my blog with the Add-Delicious.Post function and then retrieves the entries from the last day you posted with Get-Delicious.Posts.

PS C:\> . .\Posh-Delicious.ps1
PS C:\> Set-Delicious.Credentials -user "joeuser" -pass "joepass"
PS C:\> Add-Delicious.Post -url "http://devcentral.f5.com/weblogs/joe" -extended "An awesome blog!" -tags "weblogs"
ResultCode
----------
done
PS C:\> Get-Delicious.Posts
href : http://devcentral.f5.com/weblogs/joe
hash : ed2760db92010aad2c6a1008afa6ce2b
description : http://devcentral.f5.com/weblogs/joe
tag : weblogs
time : 2009-09-21T15:34:06Z
extended : An awesome blog!

Get The Source

If you want to automate the posting of links to Delicious, feel free to check out the source that can be downloaded from here: Posh-Delicious.ps1

Enjoy!

-Joe


Add Comment |
 
      

  Thursday, August 27, 2009 #
  
Listen To DevCentral Live!

This week marks a major milestone for us here at DevCentral: we have reached our 100th weekly Podcast!  To celebrate, we are going to try some new formats and the first one of these is user interaction!  Starting today, we will be streaming our podcasts live on UStream.tv so you can listen in while we are recording.  Don't worry, we will still be archiving the audio versions on DevCentral, iTunes, etc.

UStream.tv gives us a few benefits.  First, we can broadcast video along with the audio.  At this point we are unable to syndicate everyone's webcam from our team but this gives us some options for the future.  Another benefit here is that you are welcome to comment in our chat session as well if you feel the need to chime in or ask a question. 

We really want to move our podcast into more of a "virtual round table" with the DevCentral community and this is our first step.  We are always looking for guests as well so if you feel like you have something to share with the community, we'd love to have you on.  Just leave a comment on this blog and we'll get back to you to schedule you in.

We've setup a permanent link that will get you to our live show, including previous recordings).

Live_Logo
http://devcentral.f5.com/live

We record our podcast on Thursday's at 2PM PST.  I'm sure as the popularity grows on this, we'll expand our times so make sure you "follow" us on our UStream.tv channel http://www.ustream.tv/channel/dcpodcast for any upcoming recordings.

-Joe


Add Comment |
 
      

  Thursday, August 20, 2009 #
  
The Encryption Dance

 safety-danceOk, so Pete did his best Weird Al impersonation the other day by throwing up his take-off on Men Without Hat’s “Safety Dance”.  His version “Encryption Dance” is brilliant and we decided to highlight it in this weeks podcast with a challenge out to Pete to give us a live recording of his parody.

Well, it didn’t take Pete long to answer to our call and he sent along his recording of “Encryption Dance”.   For those who aren’t familiar with Men Without Hats, here’s their Safety Dance Video for you to check out first.

And here’s Pete’s “Encryption Dance” performed A Cappella".

Get the Flash Player to see this player.

I know which one I prefer!  Thanks Pete!!!

-Joe


2 Comments |
 
      

  Wednesday, August 19, 2009 #
  
X-Forwarded-For Log Filter for Windows Servers

For those that don't know what X-Forwarded-For is, then you might as well close your browser because this post likely will mean nothing to you…

A Little Background

Now, if you are still reading this, then you likely are having issues with determining the origin client connections to your web servers.  When web requests are passed through proxies, load balancers, application delivery controllers, etc, the client no longer has a direct connection with the destination server and all traffic looks like it's coming from the last server in the chain.  In the following diagram, Proxy2 is the last hop in the chain before the request hits the destination server.  Relying on connection information alone, the server thinks that all connections come from Proxy2, not from the Client that initiated the connection.

TrafficFlow The only one in the chain here who knows who the client really is (as determined by it's client IP Address, is Proxy1.  The problem is that application owners rely on source client information for many reasons ranging from analyzing client demographics to targeting Denial of Service attacks.

That's where the X-Forwarded-For header comes in.  It is non-RFC standard HTTP request header that is used for identifying the originating IP address of a client connecting to a web server through a proxy.  The format of the header is:

X-Forwarded-For: client, proxy1, proxy, …

X-Forwarded-For header logging is supported in Apache (with mod_proxy) but Microsoft IIS does not have a direct way to support the translation of the X-Forwarded-For value into the client ip (c-ip) header value used in its webserver logging.

Back in September, 2005 I wrote an ISAPI filter that can be installed within IIS to perform this transition.  This was primarily for F5 customers but I figured that I might as well release it into the wild as others would find value out of it.

Recently folks have asked for 64 bit versions (especially with the release of Windows 2008 Server).  This gave me the opportunity to brush up on my C skills.  In addition to building targets for 64 bit windows, I went ahead and added a few new features that have been asked for.

Proxy Chain Support

The original implementation did not correctly parse the "client, proxy1, proxy2,…" format and assumed that there was a single IP address following the X-Forwarded-For header.  I've added code to tokenize the values and strip out all but the first token in the comma delimited chain for inclusion in the logs.

Header Name Override

Others have asked to be able to change the header name that the filter looked for from "X-Forwarded-For" to some customized value.  In some cases they were using the X-Forwarded-For header for another reason and wanted to use iRules to create a new header that was to be used in the logs.  I implemented this by adding a configuration file option for the filter.  The filter will look for a file named F5XForwardedFor.ini in the same directory as the filter with the following format:

[SETTINGS]
HEADER=Alternate-Header-Name

The value of "Alternate-Header-Name" can be changed to whatever header you would like to use. 

Download

I've updated the original distribution file so that folks hitting my previous blog post would get the updates.  The following zip file includes 32 and 64 bit release versions of the F5XForwardedFor.dll that you can install under IIS6 or IIS7.download_buttonInstallation

Follow these steps to install the filter.

  1. Download and unzip the F5XForwardedFor.zip distribution.
  2. Copy the F5XForwardedFor.dll file from the x86\Release or x64\Release directory (depending on your platform) into a target directory on your system.  Let's say C:\ISAPIFilters.
  3. Ensure that the containing directory and the F5XForwardedFor.dll file have read permissions by the IIS process.  It's easiest to just give full read access to everyone.
  4. Open the IIS Admin utility and navigate to the web server you would like to apply it to.
  5. For IIS6, Right click on your web server and select Properties.  Then select the "ISAPI Filters" tab.  From there click the "Add" button and enter "F5XForwardedFor" for the Name and the path to the file "c:\ISAPIFilters\F5XForwardedFor.dll" to the Executable field and click OK enough times to exit the property dialogs.  At this point the filter should be working for you.  You can go back into the property dialog to determine whether the filter is active or an error occurred.
  6. For II7, you'll want to select your website and then double click on the "ISAPI Filters" icon that shows up in the Features View.  In the Actions Pane on the right select the "Add" link and enter "F5XForwardedFor" for the name and "C:\ISAPIFilters\F5XForwardedFor.dll" for the Executable.  Click OK and you are set to go.

I'd love to hear feedback on this and if there are any other feature request, I'm wide open to suggestions. The source code is included in the download distribution so if you make any changes yourself, let me know!

Good luck and happy filtering!

-Joe


22 Comments |
 
      

  Wednesday, August 12, 2009 #
  
Big Prizes and Accolades Await You With The 2009 iRule. Do You? Contest

iRuleDoYouv1Come one, come all to our third edition of the iRule. Do You? Contest.  For those that don't know, an iRule is F5's embedded packet scripting language allowing you to gain full control over how your applications flow across the network.

There are hundreds of iRules in our iRule CodeShare and thousands of them running out in the wild.  It's time for you iRule geeks out there to show us, and our community, your stuff.  Whether you are an avid developer or just someone who wants to dabble in new technologies, this contest is for you.

The rules are pretty simple:

01  Read the contest rules.
02  Write a working
iRule.
03  Tell us about it by submitting it on our
Contest Entry form.
04  Goto 02 as many times as you want.
05  Sit back and wait for the judges to pick you as a winner and receive some awesome prizes.

We are judging on several criteria so don't worry if your iRule isn't the most complex.  Sometimes it's the simplest ones that provide the most value that will ultimately make it to the winners circle.  The entries will be judged on Business Merit (innovation, business value, and breadth of applicability) as well as Technical Merit (Elegance, Potential for extensibility, and Cool factor) so there are lots of ways to win.

As if the accolades of winning are not enough, we've sweetened the pot with some pretty awesome prizes, if I do say for myself.  How's a 17" MacBook Pro sound?  No, well then, how about a Canon 5D Mark II?  If you win the gold, you'll be taking one of these home with you.  There are also plenty of consolation prizes including a MacBook Air, Apple 30" Cinema display, HP TouchSmart, Amazon Kindle DX, ASUS EeePC, XBox 360, and even a bunch of iRule branded Flip Mino HD video cameras (I've got to get me one of these!). 

So, hurry up and get started submitting your iRules!

-Joe


One Comment |
 
      

  Wednesday, August 05, 2009 #
  
There’s a New iRule Editor in Town

AboutTheiRuleEditorIt’s been a while since I posted an update for the iRule Editor so I figured I’d spend some time this week polishing off some of the bugs and enhancements reported on the iRule Editor forum over the past year or so.

So, I can go on and on about the history, but I figure you all just want to bypass that and go straight to what’s been fixed/added since the last version.  We’ll here’s what I’ve got for you in the latest v0.10.0.0 distribution that I released today.

FIX:  Hyperlink click crashes iRule Editor

This was reported in this thread titled iRule Crash.  In the text editor window, the iRule Editor has some special tokens that allow you to click on them and launch a browser to take you to the appropriate documentation webpage for that token.  On some windows system, the registry settings for the default browser were not where I expected them to be.  I removed this registry lookup and relied on the system to determine for me the default browser application.  This works much nicer now!

FIX: Disable auto-configuration saving if the user is in a roll that doesn’t allow it.

Manager roles do now have access to the ConfigSync.save_configuration() iControl method to flush the running configuration to disk.  In the past, an error dialog would display on every save command.  The iRule Editor will now assume you have privileges to do so and if it encounters an error saving the configuration, it will use a new “Auto-Save” flag configurable in the “Tools.BIG-IP Config” menu item.

FIX: iRule Property Virtual Server assignment not persisted to disk.

For some reason, I omitted the call to ConfigSync.save_configuration() on the iRule Property dialog when assigning virtual servers.  Now, on an OK in the dialog, a save operation occurs.

ENH: New “Tools.BIG-IP Config” menu to control BIG-IP configuration saving.

On this menu, you can trigger a manual config save and control the auto-save option.

ENH: HTTP Proxy Server support for Connection Dialog

As implemented in the iControl Assembly, the connection dialog now supports a HTTP proxy for iControl connections to your BIG-IP’s management port.  I had a hard time testing this so please let me know if it works B-).

ENH: Application Self Updates

Since removing the ClickOnce deployment from the iRule Editor setup, there hasn’t been an easy way to check for new versions of the Editor.  With this release, there is an new program installed with the Editor called iRulerUpdater.exe that is called by the iRule Editor’s “Check For Updates” command.  You should never see this unless a new update is available on the site.  BTW, if you want to check for the latest version yourself, you can do so by querying http://devcentral.f5.com/labs/iRuleEditor/iRulerCurrentVersion.txt.

ENH: New GTM syntax tokens in the editing window.

Thanks to Jason, we’ve got an updated list of GTM iRule tokens in the lexer configuration for the Editor.

There’s also a few hidden Easter eggs in there that I didn’t want to enable for the general population.  Let me know if you find out how to enable them. B-).

So, enough said…  Head over to the iRule Editor Labs page and download the latest version and let me know what you think.

Oh, and don’t forget, the source is available as well if you want to dig in and add some features yourself.  I’m always happy to receive changes and incorporate them into the main distribution.

-Joe


9 Comments |
 
      

  Friday, June 19, 2009 #
  
Shrink-Url – Use PowerShell To Shrink Your Urls

poshShrinkShrinking your Url’s is all the rage nowadays.  If you are on Twitter, then odds are you have used one.  Despite CodingHorror’s distaste for them in his recent blog post on Url Shorteners: Destroying the Web since 2002, they are a fact of life when we live in a world of 140 character status updates.

So what’s a URL shrinking service anyway?  Well, to put it simply, you supply them with a URL, they then supply you with a shorter URL containing a lookup “key”.  When future requests are made to this shorter URL, connections are routed to that services website where they convert the short URL to the original URL and issue a HTTP Redirect back to your browser to send you off to the original long url website.

So, what’s a guy, or gal, to do if they want to set their status programmatically on Twitter, Facebook, FriendFeed, or the other gazillion social networking sites out there today and need to post a very long URL?  Most of these shrinking services offer API’s to access their “shrinking” services so it’s just a matter of digging into the various APIs to get them implemented.  In my original PowerShell Twitter library PoshTweet, I included support for a couple for shrinking URL’s through a couple of shrinking services but I figured it would be good to separate that functionality out into it’s own library. 

So, here’s my first stab at a generic URL shortening library for PowerShell.  I’ve included the following services:

Some of these services have advanced features such as statistical reporting on all your submitted links.  Those services require users to create accounts and register for API keys.  Bit.ly is one of them, so if you want to use that service, you will have to supply this script with your bit.ly username and API key with the Set-BitlyServiceInfo function.

So, here’s the script, hope you all enjoy!

 

   1: param(
   2:   [string]$longurl = $null,
   3:   [string]$provider = "tinyurl"
   4: );
   5:  
   6: $script:DIGG_APPKEY = "http://devcentral.f5.com/PoshShrink";
   7: $script:BITLY_LOGIN = "";
   8: $script:BITLY_KEY = "";
   9:  
  10: #----------------------------------------------------------------------------
  11: # function Set-BitlyServiceInfo
  12: #----------------------------------------------------------------------------
  13: function Set-BitlyServiceInfo()
  14: {
  15:   param(
  16:     [string]$login = $null,
  17:     [string]$key = $null
  18:   );
  19:   if ( $login -and $key )
  20:   {
  21:     $script:BITLY_LOGIN = $login;
  22:     $script:BITLY_KEY = $key;
  23:   }
  24:   else
  25:   {
  26:     Write-Error "Usage: Set-BitlyServiceInfo -login login -key key";
  27:   }
  28: }
  29:  
  30: #----------------------------------------------------------------------------
  31: # function Shrink-Url
  32: #----------------------------------------------------------------------------
  33: function Shrink-Url()
  34: {
  35:   param(
  36:     [string]$longurl = $null,
  37:     [string]$provider = "tinyurl"
  38:   );
  39:   
  40:   $shorturl = $null;
  41:   if ( $longurl )
  42:   {
  43:     switch ($provider.ToLower())
  44:     {
  45:       "is.gd" {
  46:         $shorturl = Execute-HTTPGetCommand "http://is.gd/api.php?longurl=$longurl";
  47:       }
  48:       "tinyurl" {
  49:         $shorturl = Execute-HTTPGetCommand "http://tinyurl.com/api-create.php?url=$longurl";
  50:       }
  51:       "snurl" {
  52:         $shorturl = Execute-HTTPGetCommand "http://snipr.com/site/snip?r=simple&link=$longurl";
  53:       }
  54:       "digg" {
  55:         [xml]$results = Execute-HTTPGetCommand `
  56:           "http://services.digg.com/url/short/create?url=${longurl}&appkey=${script:DIGG_APPKEY}";
  57:         $shorturl = $results.shorturls.shorturl.short_url;
  58:       }
  59:       "tr.im" {
  60:         [xml]$results = Execute-HTTPGetCommand "http://api.tr.im/api/trim_url.xml?url=$longurl";
  61:         $shorturl = $results.trim.url;
  62:       }
  63:       "bit.ly" {
  64:         if ( !$BITLY_LOGIN -or !$BITLY_KEY )
  65:         {
  66:           Write-Error "ERROR: You must configure your bit.ly LOGIN and APIKEY!"
  67:           exit;
  68:         }
  69:         else
  70:         {
  71:           $results = Execute-HTTPGetCommand `
  72:             "http://api.bit.ly/shorten?version=2.0.1&longUrl=$longurl&login=$script:BITLY_LOGIN&apiKey=$script:BITLY_KEY";
  73:           $shorturl = $results.Split("`n")[7].Split("""")[3];
  74:         }
  75:       }
  76:       default {
  77:         $shorturl = Execute-HTTPGetCommand "http://tinyurl.com/api-create.php?url=$longurl";
  78:       }
  79:     }
  80:   }
  81:   else
  82:   {
  83:     Write-Host "ERROR: Usage: Shrink-Url -longurl http://www.foo.com";
  84:   }
  85:   $shorturl;
  86: }
  87:  
  88: #----------------------------------------------------------------------------
  89: # function Execute-HTTPGetCommand
  90: #----------------------------------------------------------------------------
  91: function Execute-HTTPGetCommand()
  92: {
  93:   param([string] $url = $null);
  94:   
  95:   $user_agent = "PoshShrink";
  96:   
  97:   if ( $url )
  98:   {
  99:     $request = [System.Net.HttpWebRequest]::Create($url);
 100:     $request.UserAgent = $user_agent;
 101:     $request.Credentials = [System.Net.CredentialCache]::DefaultCredentials;
 102:     if ( $request.Proxy )
 103:     {
 104:       $request.Proxy.Credentials = [System.Net.CredentialCache]::DefaultNetworkCredentials;
 105:     }
 106:     $response = $request.GetResponse();
 107:     $rs = $response.GetResponseStream();
 108:     [System.IO.StreamReader]$sr = New-Object System.IO.StreamReader -argumentList $rs;
 109:     $sr.ReadToEnd();
 110:   }
 111: }
 112:  
 113: Shrink-Url -longurl $longurl -provider $provider;

 

You can download the full contents for this script here: Shrink-Url.ps1


8 Comments |
 
      

  Wednesday, June 17, 2009 #
  
Introducing PoshTwitPic – Use PowerShell To Post Your Images To Twitter Via TwitPic

PowerShell-twitpicTwitter, for those who don’t know about it, is a status updating service that is all the rage nowadays.  It’s popularity is primarily due to it’s simplistic nature.  You post a 140 character status (known as a “tweet”) about what you are doing.  You can also friend other folks to see what they are doing.  If you are still lost, read up on the entry in Wikipedia and you should get the gist of it. 

The downside to this minimalistic approach is that it does not allow for rich multimedia content such as images or videos to be associated with your “tweets”.  Let’s face it, posting a tweet about an awesome dinner you just had isn’t as good as posting a picture you took of it.  To account for this, various services have arisen to offload the image or video storage for twitter and many of the Twitter clients out there have incorporated these services into their apps.  TwitPic was an early entry into this category of services.  They allow you to post an image to their site while posting a “tweet” to Twitter including a link to the image.  Fortunately for us, TwitPic exposes their API to allow applications to integrate their features.

Since I’ve already tackled the PowerShell Twitter functionality with my PoshTweet library, I figured the next logical step would be to write a TwitPic library to enable posting images to TwitPic through their API.

The biggest challenge in writing this library was getting the multipart/form-data POST format working correctly.  Luckily I stumbled across a post by Martin Normark on his blog containing a C# TwitPic API client.  It was fairly straightforward coming up with a PowerShell conversion of his C# code.

My library includes the following functions

  • Get-EncodedDataFromFile – Encode a local image file into a string.
  • Get-ImageContentType – Get the Content Type for a given image file (ie. image/jpeg).
  • Execute-HTTPPostCommand – Send a HTTP POST command containing the multipart/form-data request.
  • Post-TwitPic – The main function that takes an image, posts it to TwitPic and optionally posts a Tweet to Twitter.

Without further ado, here’s the code:

   1: param(
   2:   [System.IO.FileInfo]$file = $null,
   3:   [string]$twitteruser = $null,
   4:   [string]$twitterpass = $null,
   5:   [string]$message = $null
   6: );
   7:  
   8: $CODEPAGE = "iso-8859-1";
   9:  
  10: $TWITPIC_API_UPLOAD = "http://twitpic.com/api/upload";
  11: $TWITPIC_API_UPLOADANDPOST = "http://twitpic.com/api/uploadAndPost";
  12:  
  13: #--------------------------------------------------------------------------------------------
  14: # function Get-EncodedDataFromFile
  15: #--------------------------------------------------------------------------------------------
  16: function Get-EncodedDataFromFile()
  17: {
  18:   param(
  19:     [System.IO.FileInfo]$file = $null,
  20:     [string]$codePageName = $CODEPAGE
  21:   );
  22:   
  23:   $data = $null;
  24:  
  25:   if ( $file -and [System.IO.File]::Exists($file.FullName) )
  26:   {
  27:     $bytes = [System.IO.File]::ReadAllBytes($file.FullName);
  28:     if ( $bytes )
  29:     {
  30:       $enc = [System.Text.Encoding]::GetEncoding($codePageName);
  31:       $data = $enc.GetString($bytes);
  32:     }
  33:   }
  34:   else
  35:   {
  36:     Write-Host "ERROR; File '$file' does not exist";
  37:   }
  38:   $data;
  39: }
  40:  
  41: #--------------------------------------------------------------------------------------------
  42: # function Get-ImageContentType
  43: #--------------------------------------------------------------------------------------------
  44: function Get-ImageContentType()
  45: {
  46:   param([System.IO.FileInfo]$file = $null);
  47:   $contentType = $null;
  48:   $contentTypeMap = @{
  49:     ".jpg"  = "image/jpeg";
  50:     ".jpeg" = "image/jpeg";
  51:     ".gif"  = "image/gif";
  52:     ".png"  = "image/png";
  53:     ".tiff" = "image/tiff";
  54:   }
  55:   
  56:   if ( $file )
  57:   {
  58:     $contentType = $contentTypeMap[$file.Extension.ToLower()];
  59:   }
  60:   $contentType;
  61: }
  62:  
  63: #----------------------------------------------------------------------------
  64: # function Execute-HTTPPostCommand
  65: #----------------------------------------------------------------------------
  66: function Execute-HTTPPostCommand()
  67: {
  68:   param(
  69:     [string] $url = $null,
  70:     [string] $data = $null,
  71:     [System.Net.NetworkCredential]$credentials = $null,
  72:     [string] $contentType = "application/x-www-form-urlencoded",
  73:     [string] $codePageName = "UTF-8",
  74:     [string] $userAgent = $null
  75:   );
  76:  
  77:   if ( $url -and $data )
  78:   {
  79:     [System.Net.WebRequest]$webRequest = [System.Net.WebRequest]::Create($url);
  80:     $webRequest.ServicePoint.Expect100Continue = $false;
  81:     if ( $credentials )
  82:     {
  83:       $webRequest.Credentials = $credentials;
  84:       $webRequest.PreAuthenticate = $true;
  85:     }
  86:     $webRequest.ContentType = $contentType;
  87:     $webRequest.Method = "POST";
  88:     if ( $userAgent )
  89:     {
  90:       $webRequest.UserAgent = $userAgent;
  91:     }
  92:     
  93:     $enc = [System.Text.Encoding]::GetEncoding($codePageName);
  94:     [byte[]]$bytes = $enc.GetBytes($data);
  95:     $webRequest.ContentLength = $bytes.Length;
  96:     [System.IO.Stream]$reqStream = $webRequest.GetRequestStream();
  97:     $reqStream.Write($bytes, 0, $bytes.Length);
  98:     $reqStream.Flush();
  99:     
 100:     $resp = $webRequest.GetResponse();
 101:     $rs = $resp.GetResponseStream();
 102:     [System.IO.StreamReader]$sr = New-Object System.IO.StreamReader -argumentList $rs;
 103:     $sr.ReadToEnd();
 104:   }
 105: }
 106:  
 107: #--------------------------------------------------------------------------------------------
 108: # function Post-TwitPic
 109: #--------------------------------------------------------------------------------------------
 110: function Post-TwitPic()
 111: {
 112:   param
 113:   (
 114:     [System.IO.FileInfo]$file = $null,
 115:     [string]$twitteruser = $null,
 116:     [string]$twitterpass = $null,
 117:     [string]$message = $null
 118:   );
 119:   
 120:   if ( $file -and $twitteruser -and $twitterpass )
 121:   {
 122:     $boundary = [System.Guid]::NewGuid().ToString();
 123:     $header = "--{0}" -f $boundary;
 124:     $footer = "--{0}--" -f $boundary;
 125:   
 126:     [System.Text.StringBuilder]$contents = New-Object System.Text.StringBuilder;
 127:     [void]$contents.AppendLine($header);
 128:  
 129:     $filedata = Get-EncodedDataFromFile -file $file -codePageName $CODEPAGE;
 130:     if ( $filedata )
 131:     {
 132:       $fileContentType = Get-ImageContentType -file $file;
 133:       $fileHeader = "Content-Disposition: file; name=""{0}""; filename=""{1}""" -f "media", $file.Name;
 134:  
 135:       [void]$contents.AppendLine($fileHeader);
 136:       [void]$contents.AppendLine("Content-Type: {0}" -f $fileContentType);
 137:       [void]$contents.AppendLine();
 138:       [void]$contents.AppendLine($fileData);
 139:  
 140:       [void]$contents.AppendLine($header);
 141:       [void]$contents.AppendLine("Content-Disposition: form-data; name=""username""");
 142:       [void]$contents.AppendLine();
 143:       [void]$contents.AppendLine($twitteruser);
 144:       
 145:       [void]$contents.AppendLine($header);
 146:       [void]$contents.AppendLine("Content-Disposition: form-data; name=""password""");
 147:       [void]$contents.AppendLine();
 148:       [void]$contents.AppendLine($twitterpass);
 149:       
 150:       $url = $TWITPIC_API_UPLOAD;
 151:       if ( $message )
 152:       {
 153:         [void]$contents.AppendLine($header);
 154:         [void]$contents.AppendLine("Content-Disposition: form-data; name=""message""");
 155:         [void]$contents.AppendLine();
 156:         [void]$contents.AppendLine($message);
 157:         
 158:         $url = $TWITPIC_API_UPLOADANDPOST;
 159:       }
 160:       
 161:       [void]$contents.AppendLine($footer);
 162:       
 163:       $contents.ToString() > ".\out.txt";
 164:       
 165:       $postContentType = "multipart/form-data; boundary={0}" -f $boundary;
 166:       
 167:       [xml]$resp = Execute-HTTPPostcommand -url $url -data $contents.ToString() `
 168:         -contentType $postContentType -codePageName $CODEPAGE -userAgent "PoshTwitPic";
 169:       
 170:       if ( $resp )
 171:       {
 172:         switch ($resp.rsp.stat)
 173:         {
 174:           "ok" {
 175:             $obj = 1 | select mediaid, mediaurl;
 176:             $obj.mediaid = $resp.rsp.mediaid;
 177:             $obj.mediaurl = $resp.rsp.mediaurl;
 178:             $obj;
 179:           }
 180:           "fail" {
 181:             $errcode = $resp.rsp.err.code;
 182:             $errmsg = $resp.rsp.err.msg;
 183:             Write-Host "Post Error: Code = '$errcode'; Message = '$errmsg'";
 184:           }
 185:         }
 186:       }
 187:     }
 188:   }
 189:   else
 190:   {
 191:     Write-Host "USAGE: Post-TwitPic.ps1 -file file -twitteruser user -twitterpass pass";
 192:   }
 193: }
 194:  
 195: if ( $file -and $twitteruser -and $twitterpass )
 196: {
 197:   Post-TwitPic -file $file -twitteruser $twitteruser -twitterpass $twitterpass -message $message;
 198: }
 199: else
 200: {
 201:   Write-Host "USAGE: Post-TwitPic.ps1 -file file -twitteruser user -twitterpass pass";
 202: }

The entire script can be downloaded from here: Post-TwitPic.ps1

Happy Tweeting!


2 Comments |
 
      

  Monday, June 08, 2009 #
  
Introducing AskBing – The PowerShell Bing Twitter Proxy

TwitterBingLast week I posted a PowerShell function library for Microsoft’s newly introduced search engine at Bing.com.  The function library was appropriately named PoshBing. There was a log of interest in the script so I quickly moved it off my blog and onto a CodePlex project under PoshBing.

Working on the command line is fun and all, but since I spend a good portion of my time accessing my twitter account, I figured it would be a bit of fun to integrate it with my previously released PoshTweet PowerShell twitter library.

So, after an hour or so of coding it up and creating the @askbing twitter account, I’ve got it up and running. 

Using it is as simple as posting a message mentioning the @askbing account.  The Usage is as follows:

@askbing [sourcetype [options]] question_or_search_terms

If you omit the sourcetype it will default to “web”.  The following sourcetypes and options are currently available:

  • @askbing image iPod
  • @askbing instantanswer feet in a mile
  • @askbing news FFIV
  • @askbing mobileweb games
  • @askbing phonebook “F5 Networks”
  • @askbing relatedsearch “Xbox”
  • @askbing spell Is this missspelled?"
  • @askbing web Apple
  • @askbing translation en:es Hi, how are you?
  • @askbing video The Pick of Destiny

The only source type that includes a separate option is “translation”  By default it will translate from English to Spanish.  If you want to override these languages, you can use the “from:to” option to override these defaults.  The values for the from and to languages

  • Ar = Arabic
  • zh-CHS = Simplified Chinese
  • zh-CHT = Traditional Chinese
  • Nl = Dutch
  • En = English
  • Fr = French
  • De = German
  • It = Italian
  • Ja = Japanese
  • Ko = Korean
  • Pl = Polish
  • Pt = Portuguese
  • Ru = Russian
  • Es = Spanish

After you post an @reply to @askbing, you should expect a @reply to your account within a minute or so.

Since I’ve only spent an hour or so on this, there are bound to be some issues so please let me know if you find any.  Here' are a few known issues:

  1. It queries it’s @replies every 60 seconds and only queries 100 entries so if this ever gets more popular that that, I’ll need to enhance the request logic.
  2. It only returns the first entry returned from the bing services.  I might change this to a random entry later on.
  3. It has little error handling so if you get a garbled response, then that’s likely the reason.
  4. It uses tinyurl for Url shortening which is sometimes fairly flaky.
  5. Probably more…

So, when you’ve got some time, Send a @reply to @askbing and see how it works for you.  I’d love to hear any and all feedback.

-Joe


10 Comments |
 
      

  Wednesday, June 03, 2009 #
  
Introducing PoshBing – The PowerShell library for Microsoft’s Bing Search Engine

PoshBing Microsoft released their new search engine called “Bing” at, aptly named, http://www.bing.com.  Microsoft is getting positive reviews from the likes of CNET, The Wall Street Journal, and TechCrunch.  Instead of posting my review of the site, I’ll let you browse the above links to find out what the services is all about.

What interested me about Bing is that Microsoft has released a full API to allow you to use their services in your applications.  The Bing API is documented at Microsoft’s developer site and I thought to myself how I could test it out.  The obvious answer was PowerShell of course.  My previous PoshTweet Twitter Library has been fairly popular so I figured I’d give a “library” type project another go around and tackle the Bing APIs.

The Bing API has the concept of “SourceTypes” which are essentially data sources that you can search into.  My script library provides access to the Image, InstantAnswer, News, MobileWeb, Phonebook, RelatedSearch, Spell, Web, Translation, and Video SourceTypes with the following functions:

  • Get-BingImage – Search the Image SourceType for a list of images including properties about the media files.
  • Get-BingInstantAnswer – Get single, authoritative answers to questions.
  • Get-BingNews – Provide news specific to a topic, a location, or breaking news.
  • Get-BingMobileWeb – Returns mobile web results, primarily relevant XHTML or WML pages.
  • Get-BingPhonebook – Enables you to view details about a business for which you are searching as if they were a phonebook entry.
  • Get-BingRelatedSearch – View searches that provide information in which you might be interested, based on your current search.
  • Get-BingSpell – Query alternative spellings for a given word or phrase.
  • Get-BingWeb – Get pages relevant to the queried terms.
  • Get-BingTranslation – Translate a term from one language to another.
  • Get-BingVideo – return a list of videos and their properties relevant to the query terms.

I’ve included parsing for the response streams for the above SourceTypes, but if you would like to get the raw XML back, all of the above functions include a “-raw” parameter to allow you to bypass the response processing.

 

*Update* 

This little script has taken on a life of it’s own.  As a consequence, I’ve created a project on CodePlex.com to manage the distributions.  You can access it now at the following link:

http://poshbing.codeplex.com

Enjoy!


39 Comments |
 
      

  Monday, May 18, 2009 #
  
Unix To PowerShell - Md5

PowerShell_unix PowerShell is definitely gaining momentum in the windows scripting world but I still hear folks wanting to rely on Unix based tools to get their job done.  In this series of posts I’m going to look at converting some of the more popular Unix based tools to PowerShell.

md5

The Unix “md5” command (aliased to “openssl dgst –md5” or “md5sum”) calculates and verifies 128-bit MD5 hashes as described in RFC 1321.  The MD5 hash (or checksum) functions as a compact digital fingerprint of a file.  It is extremely unlikely that any two non-identical files existing in the real world will have the same MD5 hash.

The “openssl dgst –md5” option, there is a “-c” option to include colons between the two digit groups in the digest.  The “md5sum” command does not.  I’ve opted to use the output format of the “openssl” version of the command for my PowerShell function.

Unix PowerShell Description
-c -colons Print the digest in two-digit groups
separated by colons.

 

   1: #----------------------------------------------------------------
   2: # Md5.ps1
   3: #----------------------------------------------------------------
   4: param
   5: (
   6:   [string]$filespec = $null,
   7:   [bool]$colons = $false
   8: );
   9:  
  10: #----------------------------------------------------------------
  11: # function Do-Md5
  12: #----------------------------------------------------------------
  13: function Do-Md5()
  14: {
  15:   param
  16:   (
  17:     [string]$filespec = $null,
  18:     [bool]$colons = $false
  19:   );
  20:   
  21:   $hashAlgorithm = new-object -TypeName "System.Security.Cryptography.MD5CryptoServiceProvider";
  22:   
  23:   $files = @(Get-ChildItem -Path $filespec -ErrorAction SilentlyContinue);
  24:   foreach ($file in $files)
  25:   {
  26:     $stream = $file.OpenRead();
  27:     $hashByteArray = $hashAlgorithm.ComputeHash($stream);
  28:     $stream.Close();
  29:     
  30:     $md5StringBuilder = New-Object System.Text.StringBuilder
  31:     
  32:     $hashByteArray | % {
  33:       if ( $colons )
  34:       {
  35:         if ( $md5StringBuilder.Length -gt 0 ) { [void] $md5StringBuilder.Append(":") }
  36:       }
  37:       [void] $md5StringBuilder.Append($_.ToString("x2"))
  38:     }
  39:     
  40:     "MD5($($file.Name))= $($md5StringBuilder.ToString())";
  41:  
  42:     # Ensure stream is closed if exceptions occurred.
  43:     trap
  44:     {
  45:         if ($stream -ne $null) { $stream.Close(); }
  46:         break;
  47:     }
  48:   }
  49: }
  50:  
  51: Do-Md5 -filespec $filespec -colons $colons;

You can download the source for this script here: Md5.ps1


3 Comments |
 
      

  Thursday, May 07, 2009 #
  
Unix To PowerShell - Touch

PowerShell_unix PowerShell is definitely gaining momentum in the windows scripting world but I still hear folks wanting to rely on Unix based tools to get their job done.  In this series of posts I’m going to look at converting some of the more popular Unix based tools to PowerShell.

touch

The Unix “touch” command is used to change a file’s access and modification timestamps.  It can also be used to create a new empty file.

The options to the Unix touch command are implemented with the following PowerShell parameters:

Unix PowerShell Description
FILE -filespec The files to modify.
-d -datetime Parse STRING and use it instead of current time.
-F -forward Modify the time by going forward SECONDS seconds.
-r -reference Use this file as a reference instead of the current time.
-m -only_modification Change only the modification time.
-a -only_access Change only the access time.

 

   1: #----------------------------------------------------------------
   2: # Touch.ps1
   3: #----------------------------------------------------------------
   4: param
   5: (
   6:   [string]$filespec = $null,         # Files to touch
   7:   [DateTime]$datetime = ([DateTime]::Now), # Use DateTime STRING instead of current time.
   8:   [int]$forward = 0,                 # Modify the time by going forward SECONDS s.
   9:   [string]$reference = $null,        # Use this file's time instead of current time.
  10:   [bool]$only_modification = $false, # Change only the modification time.
  11:   [bool]$only_access = $false        # Change only the access time
  12: );
  13:  
  14: #----------------------------------------------------------------
  15: # Function Do-Touch
  16: #----------------------------------------------------------------
  17: function Do-Touch {
  18:   param(
  19:     [string]$filespec = $null,
  20:     [datetime]$datetime = ([DateTime]::Now),
  21:     [int]$forward = 0,
  22:     [string]$reference = $null,
  23:     [bool]$only_modification = $false,
  24:     [bool]$only_access = $false
  25:   );
  26:   
  27:   $touch = $null;
  28:   
  29:   if ( $filespec )
  30:   {
  31:     $files = @(Get-ChildItem -Path $filespec -ErrorAction SilentlyContinue)
  32:     if ( !$files )
  33:     {
  34:       # If file doesn't exist, attempt to create one.
  35:       # A wildcard patter will fail silently.
  36:       Set-Content -Path $filespec -value $null;
  37:       $files = @(Get-ChildItem -Path $filespec -ErrorAction SilentlyContinue);
  38:     }
  39:     
  40:     if ( $files )
  41:     {
  42:       if ( $reference )
  43:       {
  44:         $reffile = Get-ChildItem -Path $reference -ErrorAction SilentlyContinue;
  45:         if ( $reffile )
  46:         {
  47:           [datetime]$touch = $reffile.LastAccessTime.AddSeconds($forward);
  48:         }
  49:       }
  50:       elseif ( $datetime )
  51:       {
  52:         [datetime]$touch = $datetime.AddSeconds($forward);
  53:       }
  54:       
  55:       if ( $touch )
  56:       {
  57:         [DateTime]$UTCTime = $touch.ToUniversalTime();
  58:         foreach ($file in $files)
  59:         {
  60:           if ( $only_access )
  61:           {
  62:             $file.LastAccessTime=$touch
  63:             $file.LastAccessTimeUtc=$UTCTime
  64:           }
  65:           elseif ( $only_modification )
  66:           {
  67:             $file.LastWriteTime=$touch
  68:             $file.LastWriteTimeUtc=$UTCTime
  69:           }
  70:           else
  71:           {
  72:             $file.CreationTime = $touch;
  73:             $file.CreationTimeUtc = $UTCTime;
  74:             $file.LastAccessTime=$touch
  75:             $file.LastAccessTimeUtc=$UTCTime
  76:             $file.LastWriteTime=$touch
  77:             $file.LastWriteTimeUtc=$UTCTime
  78:           }
  79:           $file | select Name, *time*
  80:         }
  81:       }
  82:     }
  83:   }
  84: }
  85:  
  86: Do-Touch -filespec $filespec -datetime $datetime -forward $forward -reference $reference `
  87:   -only_modification $only_modification -only_access $only_access;

You can download the full script here: Touch.ps1


2 Comments |