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