Scott Hanselman

Dictionary Password Generator in Powershell

July 26, 2006 Comment on this post [6] Posted in Programming
Sponsored By

A fellow at work wanted a script to generate strong passwords from a dictionary file. The "l337" hashtable in the first line is the list of characters that we'll be replacing. The $skip variable adds a little variance so we won't (likely) generate the same password twice given the same word.

$leet = @{e=3;o=0;l=1;a=4;i='!';t=7}
$rand = new-object System.Random
$words = import-csv dict.csv
$word = ($words[$rand.Next(0,$words.Count)]).Word
if ($args[0]) { $word = $args[0] }
$leet.Keys | foreach-object { $skip = $rand.Next(0,3); if ($skip -ne 0){ $word = $word.Replace($_,$leet[$_]) } }
$word

Here's the dictionary I used: File Attachment: dict.csv (6 KB)

> ./generate-password.ps1
1ass!7ude
!nterd!ct
c4j013
par!ah
ruff!4n
r3cant
pl3th0r4
> ./generate-password.ps1 "quixotic"
qu!x07!c
quixo7ic
quix0tic

UPDATE: Jeff opines (correctly) passphrases are where it's at, so...

$rand = new-object System.Random
$conjunction = "the","my","we","our","and","but","+"
$words = import-csv dict.csv
$word1 = ($words[$rand.Next(0,$words.Count)]).Word
$con = ($conjunction[$rand.Next(0,$conjunction.Count)])
$word2 = ($words[$rand.Next(0,$words.Count)]).Word
return $word1 + " " + $con + " " + $word2

Yielding:

> ./generate-passphrase.ps1'
foible my finesse
bolster but permeate
augury my dogmatic
surfeit the mercurial
reconcile but dexterity
acarpous our inveigh
perilous and bequest
cognizant we foible
calipers and vilify
trickle our enzyme
vigorous we ominous
ascertain + dubious
suborn but middling

I totally agree that passphrases are better. I've advocated them to family and friends and have a few long-ass passphrases myselfs

About Scott

Scott Hanselman is a former professor, former Chief Architect in finance, now speaker, consultant, father, diabetic, and Microsoft employee. He is a failed stand-up comic, a cornrower, and a book author.

facebook bluesky subscribe
About   Newsletter
Hosting By
Hosted on Linux using .NET in an Azure App Service

Hanselminutes Podcast 26 - Globalization/Internationalization with .NET

July 26, 2006 Comment on this post [2] Posted in Podcast | ASP.NET | Internationalization | XML | Bugs | Tools
Sponsored By

HanselminutesMy twenty-sixth Podcast is up. This episode is a discussion of Globalization/Internationalization with .NET. It ran a little longer than I'd have liked, but I didn't realize how big a topic it is. It's just hard to make things fit in 20 minutes sometimes!

We're listed in the iTunes Podcast Directory, so I encourage you to subscribe with a single click (two in Firefox) with the button below. For those of you on slower connections there are lo-fi and torrent-based versions as well.

This show was FULL of links, so here they are again. They are also always on the show site. Do also remember the archives are always up and they have PDF Transcripts, a little known feature.

Links from the Show

Localization in ASP.NET 2.0 (gve) Michael Kaplan (guw)
Global Development and Computing Portal (gv3)
How Do I? (gvb)
Microsoft TimeZone Utility (gux)
Microsoft Terminology Translations (gv4)
Microsoft .NET Internationalization (gup)
Directory of Localization Resources (guy)
W3C Language information and text direction (gv5)
Chris Sells' FormatDesigner (guq)
Basics of .NET Internationalization (guz)
The Absolute Minimum Every Software Developer Absolutely, Positively Must Know About Unicode and Character Sets (No Excuses!) (gv6)
Internationalization Overview (gus)
ASP.NET 2.0 Internationalization Diagram (gvo)
Authoring HTML for Middle Eastern Content (gv7)
Localizer for VS 2002/2003 (gut)
Locale Builder (VISTA) (gv1)
Michele Bustamante on Localization (gv8)
Using HTTP and meta for language information (guu)
NLS information page (gv2)
Enterprise Localization Toolkit - Todd Abel (gv9)
PsuedoInternationalization (guv)

Subscribe to my Podcast in iTunes

NEW COUPON CODE EXCLUSIVELY FOR HANSELMINUTES LISTENERS: The folks at XCeed are giving Hanselminutes listeners that is Coupon Code "hm-20-20." It'll work on their online shop or over the phone. This is an amazing deal, and I encourage you to check our their stuff. The coupon is good for 20% off any component or suite, with or without subscription, for 1 developer all the way up to a site license.

Our sponsors are XCeed, CodeSmith Tools, PeterBlum and the .NET Dev Journal. There's a $100 off CodeSmith coupon for Hanselminutes listeners - it's coupon code HM100. Spread the word, now's the time to buy.

As I've said before this show comes to you with the audio expertise and stewardship of Carl Franklin. The name comes from Travis Illig, but the goal of the show is simple. Avoid wasting the listener's time. (and make the commute less boring)

  • The basic MP3 feed is here, and the iPod friendly one is here. There's a number of other ways you can get it (streaming, straight download, etc) that are all up on the site just below the fold. I use iTunes, myself, to listen to most podcasts, but I also use FeedDemon and it's built in support.
  • Note that for now, because of bandwidth constraints, the feeds always have just the current show. If you want to get an old show (and because many Podcasting Clients aren't smart enough to not download the file more than once) you can always find them at http://www.hanselminutes.com.
  • I have, and will, also include the enclosures to this feed you're reading, so if you're already subscribed to ComputerZen and you're not interested in cluttering your life with another feed, you have the choice to get the 'cast as well.
  • If there's a topic you'd like to hear, perhaps one that is better spoken than presented on a blog, or a great tool you can't live without, contact me and I'll get it in the queue!

Enjoy. Who knows what'll happen in the next show?

About Scott

Scott Hanselman is a former professor, former Chief Architect in finance, now speaker, consultant, father, diabetic, and Microsoft employee. He is a failed stand-up comic, a cornrower, and a book author.

facebook bluesky subscribe
About   Newsletter
Hosting By
Hosted on Linux using .NET in an Azure App Service

New Release of WatirMaker now WatirRecorder

July 25, 2006 Comment on this post [5] Posted in Ruby | Watir
Sponsored By

Watirrecorder1Rutger Smit has given the original WatirMaker an overhaul and we're re-releasing it as WatirRecorder++. Here's the original screencast if you want to see what it does. A roadmap will follow soon. Thanks Rutger!

This version compiles and runs under 1.1, but it upgrades smoothly to 2.0, so we'll probably do that one day. We're in the process of setting up an Open Source BSD Project at CodePlex.com so if you've made changes yourself, or you want to join up, now's the time. We'll get the source uploaded as soon as the permissions are setup. If you become a developer or want the source, you'll be able to interact with the Team System source control system using a number of clients. Be sure to read the manual.

UPDATE: We had some trouble getting everyone access on CodePlex so we're putting WatirMaker/WatirRecorder up on OpenQA.org, where Watir itself is hosted.

You can check out the source anonymously using the Subversion URL http://svn.openqa.org/svn/watir-recorder/trunk You can get the source by doing the following:

svn co https://svn.openqa.org/svn/watir-recorder/trunk

If you've never installed Watir, here's the easiest possible thing to do:

  • Install the Ruby One-Click Installer.
  • Open cmd.exe and type "gem install watir"
  • Install WatirRecorder++, hit Start, do some stuff (do NOT use the keyboard to submit forms). Hit stop, and playback.
  • Now, STOP everything and remind yourself that this is a jump-starter, that's it.

Enjoy.

File Attachment: WatirRecorder_Setup_Lite.msi (2858 KB)

As an aside, keep an eye out for FireWatir. It's tricky to install and requires a number of bleeding edge things, but it's very shiny.

About Scott

Scott Hanselman is a former professor, former Chief Architect in finance, now speaker, consultant, father, diabetic, and Microsoft employee. He is a failed stand-up comic, a cornrower, and a book author.

facebook bluesky subscribe
About   Newsletter
Hosting By
Hosted on Linux using .NET in an Azure App Service

Internationalization and Classic ASP

July 25, 2006 Comment on this post [3] Posted in ASP.NET | Internationalization | XML | Bugs
Sponsored By

If you've ever done work in non-English languages with Classic ASP (ASP3) and gotten black squares in side of the characters you expected, your checklist should be something like this.

Remember: The Absolute Minimum Every Software Developer Absolutely, Positively Must Know About Unicode and Character Sets (No Excuses!)

Classic ASP Internationalization "Don't Lie" Checklist

  • Are your ASP pages saved as UTF-8? I recommend Notepad2 (or debug.exe ;) ) as a good editor that knows what a Unicode Byte-Order-Mark looks like.
  • There's two aspects to encoding with Classic ASP - there's the encoding of the page (the static stuff) and the encoding of the dynamically created content.
    • Add this little-known bit-o-goodness to your pages:
      Response.CodePage = 65001
      Response.CharSet = "utf-8"
  • Make sure that the strings/content you are consuming is also the correct encoding. A very common problem is having Unicode content in an XML file but the prolog might say:
    <?xml version="1.0" encoding="iso-1159-1" ?>.
    This mistake will go unnoticed until José shows up.
    • Make sure your XML encoding matches you actual encoding:
      <?xml version="1.0" encoding="UTF-8" ?>.
  • You might also ensure your Http Headers don't lie:
    Content-Type: text/html; charset=utf-8
  • You might also ensure your META tags don't lie:
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />

When all these things line up, things tend to just work. Again, this is old-school stuff, so you likely don't care. Move along, nothing to see here.

About Scott

Scott Hanselman is a former professor, former Chief Architect in finance, now speaker, consultant, father, diabetic, and Microsoft employee. He is a failed stand-up comic, a cornrower, and a book author.

facebook bluesky subscribe
About   Newsletter
Hosting By
Hosted on Linux using .NET in an Azure App Service

XSLT with Powershell

July 24, 2006 Comment on this post [5] Posted in PowerShell | XML
Sponsored By

UPDATE: I've put a snapshot of this code at https://github.com/shanselman/nxslt2 as Oleg's properties have disappeared from the net.

I was talking to Chris at Portland Codecamp 2.0 yesterday and he was wondering if there were any XML cmdlets for XSLT in Powershell. There sure should be.

I wrote a few scripts with XsltCommand and System.Xml.Xsl stuff, but then thought it'd be easier and cleaner to use the rocking cool (and far more flexible) NXSLT2, by the very smart Oleg Tkachenko. One could right a bunch of cool XML cmdlets and get them shiny, wonderful and all integrated in a few days. Or, one could channel MacGyver and slap something together. Of course, you could just call nxslt from the command-line in the regular way:

nxslt2 file.xml file.xslt

But since one is always working with XML in powershell in variables, why not a little hack to make it easier:

PS>$a = [xml](get-content foo.xml)
PS>$b = transform-xslt $a foo.xslt

And $b now contains the transformed document as an instances of a [xml] type (System.Xml.XmlDocument).

Other things that could be done to make this easier/cleaner/more-PowerShelly would be to have it allow pipeline input, but I find the syntax confusing (within scripts) to make a parameter bind to pipeline input.

Thought (assuming this doesn't already exist): It'd be cool if one could say something line [param pipeline] in a function to indicate which parameter was the default for pipelining.
This is was 'filters' are for...the let functions get at the current pipeline via $_.

So, go download NXSLT2 and put it in somewhere in your PATH. Then dot-source this function in your Microsoft.Powershell_profile.ps1:

. transform-xslt.ps1

...where transform-xslt is

UPDATE: Here's a better version with some changes suggested by Peter Wong. Note that it's a filter not a function so it supports pipelining using the $_ variable:

filter transform-xslt
{
 param ( [string]$xsltpath =$(read-host "Please specify the path to an XSLT") )
 $PRIVATE:tempString = $_
 if ($PRIVATE:tempString -is [System.String])
 {
  $PRIVATE:tempString = [xml]$PRIVATE:tempString
 }
 if ($_ -is [xml])
 {
  $PRIVATE:tempString = ([xml]$_).get_outerXml()
 }
 [xml]($PRIVATE:tempString | nxslt2 - $xsltpath)
}

...and DO improve it (as it's crap now), and post your improvements here!

UPDATE#2: Keith Hill has a great article on making functions/filters that behave like truly integrated cmdlets. The difference between a Cmdlets (typically written in .NET and compiled) and functions is the level of integration with the intrinsic cmdlets. If you can't tell the difference between your new behavior/function/cmdlet and the built-in ones, you've succeeded. Here is his version that supports piped in objects as well as arrays of input files.

function Transform-Xml {
  param([string]$stylesheetPath=$(throw '$stylesheetPath is required'),
        [string[]]$xmlPath)
      
  begin {
    function applyStylesheetToXml([xml]$xml) {
      $result = $xml.get_OuterXml() | nxslt2.exe - $stylesheetPath
      [string]::join([environment]::newline, $result)
    }
    function applyStylesheetToXmlFile($sourcePath) {
      $rpath = resolve-path $sourcePath
      $result = nxslt2.exe $rpath $stylesheetPath
      [string]::join([environment]::newline, $result)
    }
  }
 
  process {
    if ($_) {
      if ($_ -is [xml]) {
        applyStylesheetToXml $_
      }
      elseif ($_ -is [IO.FileInfo]) {
        applyStylesheetToXmlFile $_.FullName
      }
      elseif ($_ -is [string]) {
        if (test-path -type Leaf $_) {
            applyStylesheetToXmlFile $_
        }
        else {
            applyStylesheetToXml $_
        }
      }
      else {
        throw "Pipeline input type must be one of: [xml], [string] or [IO.FileInfo]"
      }
    }
  }
    
  end {
    if ($xmlPath) {
      foreach ($path in $xmlPath) {
        applyStylesheetToXmlFile $path
      }
    }
  }
}

Here's a simple example of usage:

PS[1] C:\Documents and Settings\shanselm\Desktop\xslt
> get-content foo.xml
<company>
        <name>XYZ Inc.</name>
        <address1>One Abc Way</address1>
        <address2>Some avenue</address2>
        <city>Tech city</city>
        <coun\try>Neverland</country>
</company>

PS[2] C:\Documents and Settings\shanselm\Desktop\xslt
> Get-Content foo.xslt
<xsl:stylesheet
      xmlns:xsl="
http://www.w3.org/1999/XSL/Transform"
      version="1.0">
<xsl:output method="xml" />
        <xsl:template match="company">
                <poo>
                        <c><xsl:value-of select="/company/name"/></c>
                        <a1><xsl:value-of select="/company/address1"/></a1>
                        <a2><xsl:value-of select="/company/address2"/></a2>
                        <c1><xsl:value-of select="/company/city"/></c1>
                        <c2><xsl:value-of select="/company/country"/></c2>
                </poo>
        </xsl:template>
</xsl:stylesheet>

PS[3] C:\Documents and Settings\shanselm\Desktop\xslt
> $a = (get-content foo.xml) -as [xml]
PS[4] C:\Documents and Settings\shanselm\Desktop\xslt
>
$b = transform-xslt $a foo.xslt
PS[5] C:\Documents and Settings\shanselm\Desktop\xslt
> $b
xml                                     poo
---                                     ---
                                        poo

PS[6] C:\Documents and Settings\shanselm\Desktop\xslt
> $b.poo
c  : XYZ Inc.
a1 : One Abc Way
a2 : Some avenue
c1 : Tech city
c2 : Neverland

By the way, an unrelated-to-Powershell-but-related-to-XML note, do check out DonXML's XPathMania, a nicely integrated "why wasn't it built-in" Visual Studio add-in (screenshot).

About Scott

Scott Hanselman is a former professor, former Chief Architect in finance, now speaker, consultant, father, diabetic, and Microsoft employee. He is a failed stand-up comic, a cornrower, and a book author.

facebook bluesky subscribe
About   Newsletter
Hosting By
Hosted on Linux using .NET in an Azure App Service

Disclaimer: The opinions expressed herein are my own personal opinions and do not represent my employer's view in any way.