søndag 30. desember 2012

Automatically block RDP attacks on your Windows Server 2008

Having your Windows Server 2008 exposed on the internet is a security risk. The minimum requried actions is to rename your "administrator" account, make sure you have a secure password and change the default RDP-port.

A guide on how to change the RDP port and firewall rules can be found here: http://www.iteezy.com/change-rdp-3389-port-on-windows-2008-server/qc/10098

Commercial tools for preventing RDP attacks also exists, like RdpGuard or Syspeace. Lately, a free alternative named EvlWatcher has been released.

I wanted to take a different approach. In Windows Server 2008 you can attach tasks to be executed on particular logged events. Adding an attacking IP to the Windows firewall is actually an easy task. I had Windows execute this script whenever event ID 4625 occured:

fail2ban.vbs:

  1. If wscript.arguments.count = 2 then  
  2.     Dim firewall, rule, rulename, ip, re, account  
  3.     'Change this value! This rule must already exist in your inbound firewall rules  
  4.     rulename = "Fail2Ban"  
  5.       
  6.     account = wscript.arguments.item(0)  
  7.     ip = wscript.arguments.item(1)  
  8.     'MsgBox "Debug message: Invalid login with account " & account & " from IP " & ip  
  9.     Set re = new regexp  
  10.     re.Pattern = "\b(([01]?\d?\d|2[0-4]\d|25[0-5])\.){3}([01]?\d?\d|2[0-4]\d|25[0-5])\b"  
  11.   
  12.     If re.Test(ip) And Not IsException(account, ip) Then  
  13.         Set firewall  = CreateObject("HNetCfg.FwPolicy2")  
  14.         Set rule = firewall.Rules.Item(rulename)  
  15.         If Not (rule Is NothingThen  
  16.             If InStr(1,rule.RemoteAddresses,ip,1) = 0 Then  
  17.                 rule.RemoteAddresses = rule.RemoteAddresses & "," & ip  
  18.             End If  
  19.         End If  
  20.         Set firewall = Nothing  
  21.     Else  
  22.         'Invalid IP or excemption from rule  
  23.     End If  
  24. end If  
  25.   
  26. 'Handle exception cases here, you don't want to ban your own IP, for instance...Customize to your needs  
  27. Function IsException(account, ip)  
  28.     
  29.   Dim exip   
  30.   exip = "My.IP"  
  31.   IsException = False  
  32.     
  33.   If ip = exip Then  
  34.     IsException = True  
  35.   End If  
  36. End Function   

For creating the script above I used this blog for inspiration.
  
For creating the event based task I used this blog for reference. Essential parts of the task xml configuration I changed to fit my needs:

  1. <Triggers>  
  2.     <EventTrigger>  
  3.         <Enabled>true</Enabled>  
  4.         <Subscription>...omitted for layout purposes...</Subscription>  
  5.         <ValueQueries>  
  6.             <Value name="AccountDomain">Event/EventData/Data[@Name='TargetDomainName']</Value>  
  7.             <Value name="AccountName">Event/EventData/Data[@Name='TargetUserName']</Value>  
  8.             <Value name="ClientAddress">Event/EventData/Data[@Name='IpAddress']</Value>  
  9.             <Value name="Computer">Event/System/Computer</Value>  
  10.             <Value name="EventID">Event/System/EventID</Value>  
  11.         </ValueQueries>  
  12.     </EventTrigger>  
  13. </Triggers>   
  14.   
  15. ...  
  16.   
  17. <Actions Context="Author">  
  18.     <Exec>  
  19.       <Command>D:\Scripts\fail2ban.vbs</Command>  
  20.       <Arguments>"$(AccountName)" "$(ClientAddress)"</Arguments>  
  21.     </Exec>  
  22.   </Actions>   
Edit: Powershell has some more functionality allowing a little more flexibility that can detect hammering instead of ocasional failed logins. This script let's you decide that an IP address must exceed X number of failed logins within a Y hour time span before the IP is added to the Windows firewall.
Fail2Ban.vbs:
  1. Dim objShell, scriptpath, args, ip, acc  
  2.   
  3. scriptpath = "D:\Scripts\fail2ban.ps1"  
  4. acc = wscript.arguments.item(0)  
  5. ip = wscript.arguments.item(1)  
  6.   
  7. args = chr(34) & acc & chr(34) & " " & chr(34) & ip & chr(34)  
  8.   
  9. Set objShell = CreateObject("WScript.Shell")  
  10. 'Run powershell hidden  
  11. objShell.Run ("powershell " & scriptpath & " " & args), 0, true  
  12. Set objShell = Nothing  
Fail2ban.ps1:
  1. $targetaccount = $args[0]  
  2. $sourceip = $args[1]  
  3.   
  4. #Filter/Threshold options  
  5. $datefilter = [DateTime]::Now.AddHours(-1) # check only last x hours  
  6. $countfilter = 3  
  7. $rulename ="MyRule" #Firewall rule name  
  8.   
  9. $TargetUserName = @{n='TargetUserName';e={$_.ReplacementStrings[5]}}  
  10. $IpAddress = @{n='IpAddress';e={$_.ReplacementStrings[19]}}  
  11.   
  12. #return IP if number of failed logins for specifed IP has exceeded x tries within specified timeframe  
  13. $IP2Ban = Get-Eventlog security -InstanceId 4625 -After $datefilter | where {$_.ReplacementStrings[19] -eq $sourceip} | select-object $IpAddress | Group-Object -Property IPAddress | where Count -gt $countfilter | Select-Object -Property Name  
  14.   
  15. if ( $IP2Ban -ne $null)  
  16. {  
  17.     #Add IP to firewall  
  18.     #$IP2Ban.Name is same as $sourceip  
  19.   
  20.     $fw = New-object –comObject HNetCfg.FwPolicy2  
  21.     $myrule = $fw.Rules | where {$_.Name -eq $rulename}  
  22.   
  23.     if (-not ($myrule.RemoteAddresses -match $sourceip) -and -not ($sourceip -like "my.ip"))  
  24.     {  
  25.         $myrule.RemoteAddresses += (","+$sourceip)  
  26.     }  
  27.     $fw = $null  
  28. }  

lørdag 22. september 2012

Make µTorrent execute ftp script to upload files back to your home computer

Not a Powershell script this time, but still a useful one. Let's say you have a MS Windows based server and µTorrent running. How to get the files back to your home computer as fast as possible?

I'm usually more interested in event based programming/scripting, then schedule based. I had some requirements:
  • Command line based, 
  • All info must be passable in a single command
  • Parallel transfers to take full use of bandwidth.
A cygwin compiled lftp was my solution. Along with a bit of VB Scripting to take care of some syntax issues, I arrived with the script below. It supports single file torrents as well as multifile torrents.

Run this program when a torrent finishes:
C:\Utils\Scripts\ftp.vbs %K "%D" "%N" %L "%F"

ftp.vbs:

Dim path,label,cmd,nm,file,tp,host,user,pass,dir,drive,login,lftp,wd, context
host = "myHostOrIP"
user = "myUsername"
pass = "myPassword"
login = user & ":" & pass & "@" & host
lftp = "C:\Utils\lftp\lftp.exe"
wd = "C:\"

tp = WScript.Arguments.Item(0) 'single/multi
dir = WScript.Arguments.Item(1)
drive = LCase(Mid(dir, 1, 1))
path = "/cygdrive/" & drive & Right(dir,Len(dir)-2)
path = Replace(Replace(path,"\","/")," ","\ ")
nm = Replace(Replace(WScript.Arguments.Item(2),"\","/")," ","\ ")
file = path & "/" & Replace(Replace(WScript.Arguments.Item(4),"\","/")," ","\ ")
label = WScript.Arguments.Item(3)

If tp = "single" Then
context = "cd /" & label & "; put " & file
Else
'multifile
context = "mirror -R -v --parallel=3 --depth-first " & path & " /" & label & "/" & nm
End If

cmd = "ftp://" & login & " -e " & chr(34) & "set ftp:nop-interval 1; set net:timeout 5; "& context & "; quit" & chr(34)

Set objShell = CreateObject("Shell.Application")
objShell.ShellExecute lftp, cmd, wd, "runas", 1
Set objShell = Nothing


Note: This solution requires that you have a FTP Server running on your home computer. FileZilla for example.

tirsdag 11. september 2012

Powershell v3.0: Invoke-WebRequest

With Powershell v3.0, a handy cmdlet Invoke-WebRequest is available. Kind of like curl/wget for PowerShell. Here are some examples on how to use. I have used httpbin.org which is excellent for testing request and server response: http://www.httpbin.org/

  1. cls  
  2. function basic()  
  3. {  
  4.     #preemtive authentication  
  5.     $uri = New-Object System.Uri ($baseuri+"basic-auth/" + $username + "/" + $password)  
  6.     $encoded =  [System.Convert]::ToBase64String([System.Text.Encoding]::UTF8.GetBytes($username+":"+$password ))  
  7.     $headers = @{Authorization = "Basic "+$encoded}  
  8.     $r = Invoke-WebRequest -Uri $uri.AbsoluteUri -Headers $headers  
  9.     $r.Content  
  10. }  
  11. function basic2()  
  12. {  
  13.     #server will respond with 401 on first attempt, then Powershell will add the credentials and retry  
  14.     $uri = New-Object System.Uri ($baseuri+"basic-auth/" + $username + "/" + $password)  
  15.     $secpasswd = ConvertTo-SecureString $password -AsPlainText -Force  
  16.     $mycreds = New-Object System.Management.Automation.PSCredential ($username$secpasswd)  
  17.     $r = Invoke-WebRequest -Uri $uri.AbsoluteUri -Credential $mycreds  
  18.     $r.Content  
  19. }  
  20. function digest()  
  21. {  
  22.     #server will respond with 401 on first attempt, then Powershell will add the credentials   
  23.     #and retry based on header info from first attempt  
  24.     $uri = New-Object System.Uri ($baseuri+"digest-auth/auth/" + $username + "/" + $password)  
  25.     $secpasswd = ConvertTo-SecureString $password -AsPlainText -Force  
  26.     $mycreds = New-Object System.Management.Automation.PSCredential ($username$secpasswd)  
  27.     $r = Invoke-WebRequest -Uri $uri.AbsoluteUri -Credential $mycreds  
  28.     $r.Content  
  29. }  
  30. function response()  
  31. {  
  32.     #Make server send back a custom header  
  33.     $myheader = "myheader"  
  34.     $myvalue = "myvalue"  
  35.     $uri = New-Object System.Uri ($baseuri+"response-headers")  
  36.     $headers = @{$myheader = $myvalue}  
  37.     $r = Invoke-WebRequest -Uri $uri.AbsoluteUri -Body $headers  
  38.     $r.Headers  
  39. }  
  40. function ip()  
  41. {  
  42.     #returns IP address of calling client  
  43.     $uri = New-Object System.Uri ($baseuri+"ip")  
  44.     $r = Invoke-WebRequest -Uri $uri.AbsoluteUri  
  45.     $parsed = ConvertFrom-Json -InputObject $r.Content  
  46.     $parsed.origin  
  47. }  
  48. function headers()  
  49. {  
  50.     #httpbin will in this case return headers as payload  
  51.     $uri = New-Object System.Uri ($baseuri+"headers")  
  52.     $r = Invoke-WebRequest -Uri $uri.AbsoluteUri  
  53.     $parsed = ConvertFrom-Json -InputObject $r.Content  
  54.     $parsed.headers  
  55. }  
  56. function setcookies()  
  57. {  
  58.     #receive Set-Cookies header from servver  
  59.     $cookiename = "mycookie"  
  60.     $cookievalue = "myvalue"  
  61.     $cookies = @{$cookiename = $cookievalue}  
  62.     $uri = New-Object System.Uri ($baseuri+"cookies/set")  
  63.     $r = Invoke-WebRequest -Uri $uri.AbsoluteUri -Body $cookies  
  64.     $session.Cookies.GetCookies($uri) | Select-Object Name,Value  
  65. }  
  66. function getcookies()  
  67. {  
  68.     #check that we send cookies correctly  
  69.     $cookiename1 = "mycookie"  
  70.     $cookievalue1 = "myvalue"  
  71.   
  72.     $cookiename2 = "anothercookie"  
  73.     $cookievalue2 = "anothervalue"  
  74.   
  75.     $cookies = @{$cookiename1 = $cookievalue1$cookiename2 = $cookievalue2}  
  76.   
  77.     Add-Type -AssemblyName Microsoft.PowerShell.Commands.Utility  
  78.   
  79.     #Cookies  
  80.     $uri = New-Object System.Uri ($baseuri+"cookies")  
  81.     $cc = New-Object System.Net.CookieContainer  
  82.     foreach ($c in $cookies.Keys)  
  83.     {  
  84.         $cookie = New-Object System.Net.Cookie $c$cookies[$c], $uri.AbsolutePath, $uri.Host  
  85.         $cc.Add($cookie)  
  86.     }  
  87.       
  88.   
  89.     #Sessionvariable  
  90.     $session = New-Object Microsoft.PowerShell.Commands.WebRequestSession  
  91.     $session.Cookies = $cc  
  92.   
  93.     $r = Invoke-WebRequest -Uri $uri.AbsoluteUri -WebSession $session  
  94.     $session.Cookies.GetCookies($uri) | Select-Object Name,Value  
  95.       
  96.     #change cookievalue and send it back  
  97.     $session.Cookies.GetCookies($uri)[$cookiename1].Value = "valuehaschanged"  
  98.     $r = Invoke-WebRequest -Uri $uri.AbsoluteUri -WebSession $session  
  99.     $session.Cookies.GetCookies($uri) | Select-Object Name,Value  
  100. }  
  101. function post()  
  102. {  
  103.     #sends data with http post  
  104.     $uri = New-Object System.Uri ($baseuri+"post")  
  105.     $postvars = @{post1 = "value1";post2 = "value2";post3 = "value3";}  
  106.     #or $postvars = "post1=value1&post2=value2&post3=value3"  
  107.     $r = Invoke-WebRequest -Uri $uri.AbsoluteUri -Method Post -Body $postvars  
  108.     $parsed = ConvertFrom-Json -InputObject $r.Content  
  109.     $parsed.form  
  110. }  
  111. function get()  
  112. {  
  113.     #sends data with http get  
  114.     $uri = New-Object System.Uri ($baseuri+"get?get1=value1&get2=value2&get3=value3")  
  115.     $r = Invoke-WebRequest -Uri $uri.AbsoluteUri  
  116.     $parsed = ConvertFrom-Json -InputObject $r.Content  
  117.     $parsed.args  
  118. }  
  119. function get2()  
  120. {  
  121.     #sends data with http get  
  122.     $uri = New-Object System.Uri ($baseuri+"get")  
  123.     $getvars = @{get1 = "value1";get2 = "value2";get3 = "value3";}  
  124.     $r = Invoke-WebRequest -Uri $uri.AbsoluteUri -Body $getvars  
  125.     $parsed = ConvertFrom-Json -InputObject $r.Content  
  126.     $parsed.args  
  127. }  
  128. function status([int16] $status)  
  129. {  
  130.     $uri = New-Object System.Uri ($baseuri+"status/"+$status.ToString())  
  131.     $r = Invoke-WebRequest -Uri $uri.AbsoluteUri  
  132.     $r.Content  
  133. }  
  134. function useragent([string] $ua)  
  135. {  
  136.     $uri = New-Object System.Uri ($baseuri+"user-agent")  
  137.     $r = Invoke-WebRequest -Uri $uri.AbsoluteUri -UserAgent $ua  
  138.     $parsed = ConvertFrom-Json -InputObject $r.Content  
  139.     $parsed | Select-Object user-agent  
  140. }  
  141. $username = "myuser"  
  142. $password = "mypass"  
  143. $useragent = "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:15.0) Gecko/20100101 Firefox/15.0"  
  144. #httpbin(1): HTTP Request & Response Service  
  145. $baseuri = "http://www.httpbin.org/"  
  146.   
  147. #useragent $useragent  
  148. #post  
  149. #get  
  150. #get2  
  151. #getcookies  
  152. #setcookies  
  153. #headers  
  154. #basic  
  155. #basic2  
  156. #status 404  
  157. #digest  
  158. #response  
  159. #ip  

mandag 7. mai 2012

Uploading images to ImageBam using PowerShell and cURL


Do you need to automate a task to upload images to a free host with gallery functionality? Then this script could be your solution.

This script uses following tools:
- cURL, http://curl.haxx.se
- HtmlAgilityPack, http://htmlagilitypack.codeplex.com
- PowerShell 2.0, http://support.microsoft.com/kb/968929
- ImageBam API, http://code.google.com/p/imagebam-api/ (To access API, register here: http://www.imagebam.com/sys/API/clients)

This script takes care of OAuth authentication and authorization (the dirty way, without user consent, lol)


  1. $basedrive ="C:"  
  2. $basedir = "imagebam/"  
  3. $basepath = ($basedrive + "/" + $basedir)  
  4.   
  5. Add-Type -Assembly System.ServiceModel.Web,System.Runtime.Serialization  
  6. Add-Type -AssemblyName System.Web  
  7. add-type -Path ($basepath+"\HtmlAgilityPack.dll")  
  8.   
  9.   
  10. $responsefile = "response.txt"  
  11. $headerfile = "headers.txt"  
  12. $ib_nick = "MyImageBamNick"  
  13. $ib_pw = "MyImageBamPW"  
  14. $api_key = "FILL_IN"  
  15. $api_secret = "FILL_IN"  
  16. $oauth_token = "FILL_IN_AFTER_AUHTORIZED"  
  17. $oauth_token_secret = "FILL_IN_AFTER_AUHTORIZED"  
  18.   
  19. $oauth_nonce = 0  
  20. $oauth_timestamp = 0  
  21. $oauth_signature_method = "MD5";  
  22. $random = New-Object -type Random  
  23. $htmldoc = New-Object HtmlAgilityPack.HtmlDocument  
  24.   
  25. $basedrive  
  26. cd\  
  27. cd $basepath  
  28. cls  
  29.   
  30. function MD5($inputstring)  
  31. {  
  32.   
  33.     #Borrowed this snippet from Daniel Damen http://www.out-web.net/?p=334  
  34.   
  35.     $result = ""  
  36.     $cryptoServiceProvider = [System.Security.Cryptography.MD5CryptoServiceProvider];  
  37.     $hashAlgorithm = new-object $cryptoServiceProvider  
  38.     $hashByteArray = $hashAlgorithm.ComputeHash([Char[]]$inputString);  
  39.     foreach ($byte in $hashByteArray) { $result += “{0:X2}” -f $byte}  
  40.     return $result.ToLower()  
  41. }  
  42. function GetUnixTimeStamp()  
  43. {  
  44.   
  45.     #Borrowed this piece of code from: http://dev.healthx.com/Home/powershell-NET   
  46.   
  47.     $epoch = New-Object -type DateTime(1970, 1, 1)  
  48.     $unixts = [int] ([System.DateTime]::Now.ToUniversalTime() - $epoch).TotalSeconds  
  49.     return $unixts.ToString()  
  50. }  
  51.   
  52. function Login()  
  53. {  
  54.     $login = "action=true&nick=" + $ib_nick + "&pw=" + $ib_pw  
  55.     & curl -L -c cookie.txt -D loginheaders.txt -o login.html -d $login http://www.imagebam.com/login  
  56. }  
  57.   
  58. function Authenticate()  
  59. {  
  60.     $url = "http://www.imagebam.com/sys/oauth/request_token"  
  61.     $dataresponse = ""  
  62.     $data = ""  
  63.       
  64.     $oauth_timestamp = GetUnixTimeStamp  
  65.     $oauth_nonce = $random.Next().ToString()  
  66.       
  67.     #build signature string  
  68.     $oauth_signature_string = $api_key + $api_secret + $oauth_timestamp + $oauth_nonce  
  69.     #write-host "oauth_signature_string: " -nonewline   
  70.     #write-host $oauth_signature_string -foregroundcolor Blue  
  71.       
  72.     #compute md5 hash of signature string  
  73.     $oauth_signature = MD5($oauth_signature_string)  
  74.     #write-host "oauth_signature: " -nonewline  
  75.     #write-host $oauth_signature -foregroundcolor Blue  
  76.       
  77.     #build http POST data string  
  78.     $data =   "oauth_consumer_key=" + $api_key  
  79.     $data += "&oauth_signature_method=" + $oauth_signature_method  
  80.     $data += "&oauth_signature=" + $oauth_signature  
  81.     $data += "&oauth_timestamp=" + $oauth_timestamp  
  82.     $data += "&oauth_nonce=" + $oauth_nonce  
  83.     #write-host "auth_params: " -nonewline   
  84.     #write-host $data -foregroundcolor Blue  
  85.       
  86.     #delete exisiting response files  
  87.     if( Test-path ($basepath + $responsefile) ) { del $responsefile }  
  88.     if( Test-path ($basepath + $headerfile) ) { del $headerfile }  
  89.       
  90.     #send request  
  91.     & curl -s -d $data -D $headerfile -o $responsefile $url  
  92.       
  93.     #read response data  
  94.     $dataresponse =  (Get-Content $responsefile)  
  95.     $httpresponse =  (Get-Content $headerfile)[0].Replace("HTTP/1.1 ","").Substring(0,3)  
  96.     #write-host $httpresponse  
  97.       
  98.     #write-host "oauth response: "  -nonewline   
  99.     #write-host $response -foregroundcolor Blue  
  100.       
  101.     #parse response data: variable1=value1&variable2=value2  
  102.     $authdata = [regex]::split($dataresponse"&")  
  103.     $ot = [regex]::split($authdata[0], "=")[1]  
  104.     $ots = [regex]::split($authdata[1], "=")[1]  
  105.     Set-Variable -Name oauth_token -Value $ot -Scope global  
  106.     Set-Variable -Name oauth_token_secret -Value $ots -Scope global  
  107.     write-host "oauth_token: "  -nonewline   
  108.     write-host $oauth_token -foregroundcolor Blue  
  109.     #write-host "oauth_token_secret: "  -nonewline   
  110.     #write-host $oauth_token_secret -foregroundcolor Blue  
  111. }  
  112. function Authorize()  
  113. {  
  114.     $url = "http://www.imagebam.com/sys/oauth/authorize_token"  
  115.     $urla = ($url + "?oauth_token=" + $oauth_token)  
  116.     #login to get cookies  
  117.     Login  
  118.     #Give this script access to your ImageBam account  
  119.     & curl -s -b cookie.txt -c cookie.txt -o "authorize.html" $urla  
  120.     $htmldoc.Load(($basepath + "authorize.html"))  
  121.     $oa = $htmldoc.DocumentNode.SelectSingleNode("//input[@name='oauth_token']").Attributes["value"].Value  
  122.     $oas = $htmldoc.DocumentNode.SelectSingleNode("//input[@name='token_auth_sec']").Attributes["value"].Value  
  123.   
  124.     $data = "submit=yes&authorize=true&oauth_token=" + $oa + "&token_auth_sec=" + $oas  
  125.     & curl -s -b cookie.txt -c cookie.txt -D $headerfile -d $data -o "authorizepin.html" $url  
  126.     $htmldoc.Load(($basepath + "authorizepin.html"))  
  127.     $oauth_verifier = $htmldoc.DocumentNode.SelectSingleNode("//div[@style='font-size:22px; margin-top:20px;']").InnerHtml.Trim()  
  128.     write-host "shared secret: "  $oauth_verifier  
  129.     $oauth_timestamp = GetUnixTimeStamp  
  130.     $oauth_nonce = $random.Next().ToString()  
  131.       
  132.     $oauth_signature_string = $api_key + $api_secret + $oauth_timestamp + $oauth_nonce + $oauth_token + $oauth_token_secret  
  133.     #write-host "oauth_signature_string: " -nonewline   
  134.     #write-host $oauth_signature_string -foregroundcolor Blue  
  135.       
  136.     #compute md5 hash of signature string  
  137.     $oauth_signature = MD5($oauth_signature_string)  
  138.     #write-host "oauth_signature: " -nonewline  
  139.     #write-host $oauth_signature -foregroundcolor Blue  
  140.       
  141.     #build http POST data string  
  142.     $data  = " oauth_consumer_key=" + $api_key  
  143.     $data += "&oauth_token=" + $oauth_token  
  144.     $data += "&oauth_signature_method=" + $oauth_signature_method  
  145.     $data += "&oauth_signature=" + $oauth_signature  
  146.     $data += "&oauth_timestamp=" + $oauth_timestamp  
  147.     $data += "&oauth_nonce=" + $oauth_nonce  
  148.     $data += "&oauth_verifier=" + $oauth_verifier  
  149.       
  150.     $url = "http://www.imagebam.com/sys/oauth/request_access_token"  
  151.     #send request  
  152.     & curl -s -b cookie.txt -c cookie.txt -d $data -D $headerfile -o $responsefile $url  
  153.       
  154.     #read response data  
  155.     $dataresponse =  (Get-Content $responsefile)  
  156.     $httpresponse =  (Get-Content $headerfile)[0].Replace("HTTP/1.1 ","").Substring(0,3)  
  157.     #write-host $httpresponse  
  158.       
  159.     #write-host "oauth response: "  -nonewline   
  160.     #write-host $response -foregroundcolor Blue  
  161.       
  162.     #parse response data: variable1=value1&variable2=value2  
  163.     $authdata = [regex]::split($dataresponse"&")  
  164.     $ot = [regex]::split($authdata[0], "=")[1]  
  165.     $ots = [regex]::split($authdata[1], "=")[1]  
  166.     Set-Variable -Name oauth_token -Value $ot -Scope global  
  167.     Set-Variable -Name oauth_token_secret -Value $ots -Scope global  
  168.     write-host "new oauth_token: "  -nonewline   
  169.     write-host $oauth_token -foregroundcolor Blue  
  170.     write-host "oauth_token_secret: "  -nonewline   
  171.     write-host $oauth_token_secret -foregroundcolor Blue  
  172.           
  173. }  
  174. function UploadImage([string]$imagepath, [string]$contenttype, [string]$galleryid)  
  175. {  
  176.     $url = "http://www.imagebam.com/sys/API/resource/upload_image"  
  177.     $dataresponse = ""  
  178.     $data = ""  
  179.       
  180.     $oauth_timestamp = GetUnixTimeStamp  
  181.     $oauth_nonce = $random.Next().ToString()  
  182.       
  183.     #build signature string  
  184.     $oauth_signature_string = $api_key + $api_secret + $oauth_timestamp + $oauth_nonce + $oauth_token + $oauth_token_secret  
  185.     #write-host "oauth_signature_string: " -nonewline   
  186.     #write-host $oauth_signature_string -foregroundcolor Blue  
  187.       
  188.     #compute md5 hash of signature string  
  189.     $oauth_signature = MD5($oauth_signature_string)  
  190.     #write-host "oauth_signature: " -nonewline  
  191.     #write-host $oauth_signature -foregroundcolor Blue  
  192.       
  193.     #build http POST data string  
  194.     #authentication params  
  195.     $d1 = "oauth_consumer_key=" + $api_key  
  196.     $d2 = "oauth_signature_method=" + $oauth_signature_method  
  197.     $d3 = "oauth_signature=" + $oauth_signature  
  198.     $d4 = "oauth_timestamp=" + $oauth_timestamp  
  199.     $d5 = "oauth_nonce=" + $oauth_nonce  
  200.     $d6 = "oauth_token=" + $oauth_token  
  201.       
  202.     #image params  
  203.     $ct = ""  
  204.     if($imagepath.ToLower().EndsWith("jpg")){ $ct = ";type=image/jpeg"}  
  205.     elseif($imagepath.ToLower().EndsWith("png")) { $ct = ";type=image/png" }  
  206.     elseif($imagepath.ToLower().EndsWith("gif")) { $ct = ";type=image/gif" }  
  207.       
  208.     if ($contenttype -eq "") { $contenttype = "family"}  
  209.       
  210.     $d7 = "content_type=" + $contenttype  
  211.     $d8 = "gallery_id=" + $galleryid  
  212.     $d9 = "image=@" + $imagepath + $ct  
  213.       
  214.     #delete exisiting response files  
  215.     if( Test-path ($basepath + $responsefile) ) { del $responsefile }  
  216.     if( Test-path ($basepath + $headerfile) ) { del $headerfile }  
  217.     if( Test-path ($basepath + "trace.log") ) { del "trace.log" }  
  218.       
  219.     #send multipart form post request, disable Expect 100 continue header  
  220.     & curl -s -H "Expect:" -F $d1 -F $d2 -F $d3 -F $d4 -F $d5 -F $d6 -F $d7 -F $d8 -F $d9 -D $headerfile --trace-ascii trace.log -o $responsefile $url  
  221.       
  222.     #read response data  
  223.     $dataresponse =  (Get-Content $responsefile) -join "`n"  
  224.     $httpresponse =  (Get-Content $headerfile)[0].Replace("HTTP/1.1 ","").Substring(0,3)  
  225.     if ($httpresponse -ne "200")  
  226.     {  
  227.         write-host "Error: " -nonewline -foregroundcolor Black  
  228.         write-host $dataresponse -foregroundcolor Red  
  229.         $dataresponse = ""  
  230.     }  
  231.     #$jsondata = (Get-Content ($basepath + $responsefile)) -join "`n"  
  232.     return  Convert-JsonToXml $dataresponse  
  233.     #return $dataresponse  
  234.       
  235. }  
  236.   
  237. function CreateGallery([string]$title, [string]$description)  
  238. {  
  239.     $url = "http://www.imagebam.com/sys/API/resource/create_gallery"  
  240.     $dataresponse = ""  
  241.     $data = ""  
  242.       
  243.     $oauth_timestamp = GetUnixTimeStamp  
  244.     $oauth_nonce = $random.Next().ToString()  
  245.       
  246.     #build signature string  
  247.     $oauth_signature_string = $api_key + $api_secret + $oauth_timestamp + $oauth_nonce + $oauth_token + $oauth_token_secret  
  248.     #write-host "oauth_signature_string: " -nonewline   
  249.     #write-host $oauth_signature_string -foregroundcolor Blue  
  250.       
  251.     #compute md5 hash of signature string  
  252.     $oauth_signature = MD5($oauth_signature_string)  
  253.     #write-host "oauth_signature: " -nonewline  
  254.     #write-host $oauth_signature -foregroundcolor Blue  
  255.       
  256.     #build http POST data string  
  257.     #authentication params  
  258.     $data = "oauth_consumer_key=" + $api_key  
  259.     $data += "&oauth_signature_method=" + $oauth_signature_method  
  260.     $data += "&oauth_signature=" + $oauth_signature  
  261.     $data += "&oauth_timestamp=" + $oauth_timestamp  
  262.     $data += "&oauth_nonce=" + $oauth_nonce  
  263.     $data += "&oauth_token=" + $oauth_token  
  264.       
  265.     #gallery params  
  266.       
  267.     $data += "&title=" + [System.Uri]::EscapeDataString($title)  
  268.     $data += "&description=" + [System.Uri]::EscapeDataString($description)  
  269.       
  270.     #delete exisiting response files  
  271.     if( Test-path ($basepath + $responsefile) ) { del $responsefile }  
  272.     if( Test-path ($basepath + $headerfile) ) { del $headerfile }  
  273.     if( Test-path ($basepath + "trace.log") ) { del "trace.log" }  
  274.       
  275.     #send request, disable Expect 100 continue header  
  276.     & curl -s -H "Expect:" -d $data -D $headerfile --trace-ascii trace.log -o $responsefile $url  
  277.       
  278.     #read response data  
  279.     $dataresponse =  (Get-Content $responsefile) -join "`n"  
  280.     $httpresponse =  (Get-Content $headerfile)[0].Replace("HTTP/1.1 ","").Substring(0,3)  
  281.     if ($httpresponse -ne "200")  
  282.     {  
  283.         write-host "Error: " -nonewline -foregroundcolor Black  
  284.         write-host $dataresponse -foregroundcolor Red  
  285.         $dataresponse = ""  
  286.     }  
  287.     #$jsondata = (Get-Content ($basepath + $responsefile)) -join "`n"  
  288.     return  Convert-JsonToXml $dataresponse  
  289.     #return $dataresponse  
  290. }   
  291.   
  292. function Convert-JsonToXml([string]$json)  
  293. {  
  294.   
  295.     #Thanks to Joel Bennett: http://huddledmasses.org/json-from-powershell-but-why/    
  296.   
  297.     $bytes = [byte[]][char[]]$json  
  298.     $quotas = [System.Xml.XmlDictionaryReaderQuotas]::Max  
  299.     $jsonReader = [System.Runtime.Serialization.Json.JsonReaderWriterFactory]::CreateJsonReader($bytes,$quotas)  
  300.     try  
  301.     {  
  302.         $xml = new-object System.Xml.XmlDocument  
  303.    
  304.         $xml.Load($jsonReader)  
  305.         $xml  
  306.     }  
  307.     finally  
  308.     {  
  309.         $jsonReader.Close()  
  310.     }  
  311. }  
  312. #These are only needed first time, but you may have to re-authenticate if the authentication tokens exprire  
  313. #Authenticate  
  314. #Authorize  
  315.   
  316. #Create gallery ID, optional  
  317. $gallryxml = CreateGallery "My First Gallery"  
  318. $galleryid = $gallryxml.SelectSingleNode("//GID").InnerXml  
  319. write-host "Gallery ID:" $galleryid  
  320. $contenttype = "family" #family/adult  
  321. $files = dir C:\mypics |   Select-Object FullName, Directory, Name, Length | Sort-Object Name  
  322. foreach($file in $files)  
  323. {  
  324.       
  325.     write-host "Uploading " $file.FullName  
  326.  $xml = UploadImage $file.FullName $contenttype $galleryid    
  327.     $imagelink = $xml.SelectSingleNode("//URL").InnerXml  
  328.     $xml = $null  
  329.     write-host "Link: " $imagelink  
  330.     #[diagnostics.process]::start($imagelink)  
  331. }