Overview

This article is the third in a series of articles about my open source TCPUtil code which enables socket programming from withing the Windows Scripting Host. If you have not already done so I recommend that you have a look at the first two articles before attempting this one, as I will skip some of the basic explainations here that I made there. The first article discussed Scripting Internet Connections Under Window$ and the second demonstrated the use of the code with a Search Engine submission 'exploit' .

This time I'm going to show how to use socket programming to create a command line translation tool using the translation service from Google.

Web Based Translation Services

You will have seen many web based translation services springing up around the Internet. The one that I am going to use here will be the one on Google however, as most of us will be familiar with this site. (See langauge tool on the top right of their page). Google offers a translation service that consists of a form posting to a script and displaying the outputted translation on a html page.

So with the TCPutil control I can write a socket application that POSTs the appropriate variables to the script and parses the returned HTML for the translation. Simple

Ethics

This is a proof of concept. DON'T try writing a commercial application with this code - that would be a theft of service from Google. I'm posting this because I can't imagine many commercial applictions that would require command line translation and I am certainly not about to write an ActiveX control to explot this loophole from within an application. So the code, as far as it goes here, is a nice little curiosity with little actual value. But with a bit of spit and polish a less ethical programmer could integrate this into almost anything - maybe have auto translated web pages for international customers - whatever.

How it works

You can enter the text you want translating in two ways:
1...Typed at a command line using standard input streams
(Three carrige returns closes the session)
2...From an external text file using the -f option
(See usage)

The script also needs to know what language to translate to (I have assumed for the purposes of this article that the language to be translated from is English). The language is set using the -l or -langauge switch, and accepts the following parameters:

german - de
italian - it
french - fr
portuguese - pt
spanish - es
Usage

Usage: Babel.vbs <--Langauge|-l [Translate to de|fr|it|es|pt]>"
[--Delay|-d] Page Time Out delay (in seconds) Default: 5 Seconds"
[--file|-f] Translate from a text file."
[--Verbose|-v]"
[--debug|-vv]"
[--Help|/?]>"
An Example

So this is what it does when you run it...

C:\tcputil>babel -l es
Microsoft (R) Windows Script Host Version 5.1 for Windows
Copyright (C) Microsoft Corporation 1996-1999. All rights reserved.

--Babel Fish Utility.
--July 2002 by NTSA.
--www.ntsa.org.uk

Type the text you wish to be translated:
:>this is a test
:>for all of the good
:>people at AntiOnline
:>
:>I can include carrige returns.
:>I finish input with 3 <returns>.
:>
:>
esto es una prueba para toda la buena gente en AntiOnline que puedo incluir vuel
tas del carrige. Acabo la entrada con 3 &lt; vueltas &gt;.
The Code

NOTE: There may be a few unused routines in here (left over from the main TCPUtil code) but I only had a couple of hours to write the code and the tutorial so this'll just have to do.

Code:
dim buffer,blncon,blnSkip,wtresp,secwait,blnLastcmdnull 'Program Vars
DIM blnbuff,blnifile,lang,sdelay,Verbose,debug,iFile,Ofile,str 'User Vars
Dim oArgs, ArgNum 'Argument vars

Const sckTCPProtocol=0 
Const sckUDPProtocol=1

const FlgDebug =1
const flgVerbose =2
const flgEcho =3

Const ForReading = 1
const ForWriting = 2

WScript.Echo "--Babel Fish Utility."
WScript.Echo "--July 2002 by NTSA."
WScript.Echo "--www.ntsa.org.uk"
WScript.Echo ""

'Create a FSO for file I/O operations
Set fso = CreateObject("Scripting.FileSystemObject")

GetUserParams

'Create the winsock object and pass the event handler tp wsPop_
on error resume next
Set tcpClient=WScript.CreateObject("sbWinsck.winsock","wsPop_")
if err.number > 0 then 
out "Could not create an instance of the SBWinsck control.",flgEcho
out "You need to register SBWinsck.ocx using the regsvr32",flgEcho
out "command. (ie regsvr32 c:\path\sbWinsck.ocx where c:\path",flgEcho
out "is the full path to the ocx file.",flgEcho
end if

tcpClient.Protocol = sckTCPProtocol
tcpClient.RemoteHost = "216.239.37.120" 
tcpClient.RemotePort =  80

str = ""

'No input file set so retreive the str 
'translation string from the command line.
if iFile & "" = "" then

twice = 0
cmd = ""
str = ""
wscript.echo "Type the text you wish to be translated:"
do 

	cmd = input("")
	if cmd = "" then 
		twice = twice + 1
	else
		twice = 0
	end if

	str = str & replace(cmd," ","+")
	if twice < 2 then str = str & "%0D%0A"
	out "cmd=" & cmd & " | twice=" & twice & " | " & "str=" & str,flgdebug

loop until cmd = "" and twice > 1

'Load the str value from a file
else

Set f = fso.OpenTextFile(ifile, ForReading)
while not f.atendofstream			 
	t = f.readline
	str = str & t & "%0D%0A"
wend

end if

str = "text="& str &"&langpair=en%7C"& lang &_
"&hl=en&ie=ASCII&oe=ASCII"

tcpClient.Connect

tio = 0
do until blncon = true or blnskip = true or tio = sdelay *2
WSCRIPT.SLEEP 500
out "Waiting for connection...",FlgDebug
tio = tio + 1
LOOP

'Timed out - Could not connect
if tio = sdelay *2 and blnskip =false then 
out "Could not connect to: " & tcpClient.RemoteHost & _
" on port: " & tcpClient.RemotePort & ".",FlgEcho
wscript.quit(1)
end if

tio = 0
do until blncon = false or tio = sdelay *2
WSCRIPT.SLEEP 500
out "Waiting for disconnection...",FlgDebug
tio = tio + 1
loop

h = split(buffer,"<textarea name=q")
ht = split(h(1),"</textarea>")
htm = split(ht(0),">")

if blnbuff = true then
'Output buffer to screen
out htm(1),FlgEcho
end if

Sub wsPop_DataArrival(Byval b)

dim strdata
out "Data Arrival...",flgverbose	
'/* Get the data and add it to the buffer...
'*/
tcpClient.GetData strData,vbstring

if blnbuff = true then
buffer = buffer &  strdata
else
out strdata,Flgverbose
end if

'Data has just arrived - wait some 
'more to see if anything further comes
secwait = 100
blnskip = true

end sub

Sub wsPop_Connected()

blncon = true
blnskip = true
out "Connected...",flgverbose
'sending data to the host
out "Sending data...",flgverbose

sendandlog "POST /translate_t HTTP/1.1"
sendandlog "Accept: image/gif, image/x-xbitmap, image/jpeg, " & _
"image/pjpeg, application/vnd.ms-powerpoint, " & _
"application/vnd.ms-excel, application/msword, */*"
sendandlog "Accept-Language: en-gb"
sendandlog "Content-Type: application/x-www-form-urlencoded"
sendandlog "Accept-Encoding: gzip, deflate"
sendandlog "User-Agent: Mozilla/4.0 " & _ 
(compatible; MSIE 5.01; Windows NT 5.0)"
sendandlog "Host: translate.google.com"
sendandlog "Content-Length: " & cstr(len(str))
sendandlog "Connection: Keep-Alive"
sendandlog ""
sendandlog str

out "Data sent.",flgverbose

End Sub

sub sendandlog(data)

tcpclient.SendData data & vbCrLf
LogDataSend(data)

end sub

sub scriptInput

'##################################
'# Script Interpreter
'# Lines with * begin interactive user input session
'# Interactive sessions are ended with a !
'# Lines beginning with # are comments
'# Values in [name] format will be requested from user

'Open Script file
Set f = fso.OpenTextFile(ifile, ForReading)
while not f.atendofstream			 
	t = f.readline
	if t <> "*" then
		if left(trim(t),1) = "#" then
			'Comment - Ignore.
			out t,flgDebug
		else
			'Request User Input
			if instr(t,"[") > 0 then t = BuildStr(t)
			tcpclient.SendData t & vbCrLf 
			LogDataSend(t)
		end if
	else
		'Drop out to command line
		getinput
	end if
wend

end sub

function BuildStr(t)

a = split(t,"[")
b = split(a(1),"]")
Intxt = b(0)

buildstr = a(0) & input("Enter " & intxt) & b(1)

end function

sub GetInput

do 
	'If there has already been a reponse to the
	'Last request (blnskip) then set smaller wait.
	'value.
	if blnskip = true then 
		n = sdelay * 50
	else
		n = sdelay * 1000
	end if

	if blnLastcmdnull = false and port <> 43 then
		for secwait = n to 0 step -1
			out "wait to see if any more data is coming "& _
			secwait &"...",flgverbose
			'before returning to cmd promt
			wscript.sleep(1)
		next
	end if

	out "Data stream from remote host terminated (probably!).",flgVerbose
	cmd = input("Send Data (Quit with '!')")
	
	IF cmd <> "" or port = 80 then
		if lcase(cmd) <> "!" and blncon = true then 
			on error resume next
			tcpclient.SendData cmd & vbcrlf
			if err.number >0 then
				out "Connection Failed.",flgEcho
				wscript.quit(1)
			end if

			LogDataSend(cmd)
		end if
	end if

	if cmd = "" then 
		blnLastcmdnull = true
	else
		blnLastcmdnull = false
	end if

	'Wait 1/2 second to see if server quits
	wscript.sleep(500)

IF CMD = "" and port = 80 then cmd = "!"
loop until lcase(cmd) = "!" or blncon = false	

end sub

sub LogDataSend(poststr)

if port = 80 then
	out "Sending:> " & poststr,Flgverbose
else 
	'out "Sending:> " & poststr,FlgEcho
end if

end sub

Sub wsPop_Close()

blncon = false
out "Disconnected...",flgverbose

End Sub

function RemoveDel(str)

RemoveDel = replace(str,"/","")
RemoveDel = replace(RemoveDel,"-","")
RemoveDel = replace(RemoveDel,"--","")

end function

function IsEmpty(str)

if str & "" = "" then 
	isempty = true
else
	isempty = false
end if

end function

function iCount(str,del)

icount =0

for i = 1 to len(str)
	if mid(str,i,1) = del then
		icount = icount +1
	end if
next

icount = icount - 1

end function

function input(quest)

WScript.StdOut.Write(quest & ":>")
input = WScript.StdIn.ReadLine()

end function

sub out(str,flg)

select case flg
	case flgEcho
		wscript.echo str
	case flgVerbose
		if verbose = true or debug = true then
			wscript.echo str
		end if
	case FlgDebug
		if debug = true then
			wscript.echo str
		end if
end select
end sub

sub GetUserParams

buffset = 0

Set oArgs = WScript.Arguments
ArgNum = 0
While ArgNum < oArgs.Count

	Select Case RemoveDel(LCase(oArgs(ArgNum)))
		case "language","lang","l":
			ArgNum = ArgNum + 1
			select case lcase(oArgs(ArgNum))
				case "german","de":
					lang = "de"
				case "italian","it":
					lang = "it"
				case "french","fr":
					lang = "fr"
				case "portuguese","pt":
					lang = "pt"
				case "spanish","es":
					lang = "es"
			end select
		Case "file","f":
			ArgNum = ArgNum + 1
			If (fso.FileExists(oArgs(ArgNum))) Then
				iFile = oArgs(ArgNum)
				blnIfile = true
			else
				out "Error! The file " & oArgs(ArgNum) & _
				" was not found.",FlgEcho
				out "",FlgEcho
				displayusage
				wscript.quit(1)
			end if
		Case "delay","d":
			ArgNum = ArgNum + 1
			sdelay = oArgs(ArgNum)
		Case "help","?":
			Call DisplayUsage
		Case "verbose", "v":
			Verbose = true
		Case "debug","vv":
			debug = true
		Case Else:
			WScript.Echo "Unknown argument "& oArgs(ArgNum)
			Call DisplayUsage
			wscrip.quit(1)
	End Select	

	ArgNum = ArgNum + 1
Wend

if buffset = 0 then
	select case port 
		case 80,43
			blnbuff = true
		case else
			blnbuff = false
	end select
end if

blnbuff = true
buffset = 1

if isempty(sdelay) then
	'Set default as 3 second delay before breaking connection
	sdelay = 5
end if

if isempty(lang) then
	out "You must specify a language.",flgecho
	DisplayUsage
	wscript.quit(1)
end if

end sub

Sub DisplayUsage

WScript.Echo "Usage: Babel.vbs <--Langauge|-l [Translate to de|fr|it|es|pt]>"
WScript.Echo "        [--Port|-p [Port Number or www|ftp|smtp|pop3|whois] Default: 80"
WScript.Echo "        [--Delay|-d] Page Time Out delay (in seconds) Default: 3 Seconds"
WScript.Echo "        [--file|-f] Translate from a text file."
WScript.Echo "        [--Verbose|-v]"
WScript.Echo "        [--debug|-vv]"
WScript.Echo "        [--Help|/?]>"
WScript.Echo ""
WScript.Quit (1)	

End Sub
Just in case my line ends have died I have included the code (and sbwinsock control) in the zip file below.

If you enjoyed this thread you may also enjoy these others:
Open Source FTP Control
Web based classes
Backing up the IIS metabase.
What port is that?
Building your own IDS tripwire.
Credit card security
Dumping SQL data to a text file
Hunting down skript kiddies
Search Engine submission 'exploit'
Forced shutdown of a remote nt/2k server
Securing an installation of IIS 4. (No, seriously)
Remote DSN Connections, using WinAPIs and the registry
Scripting Internet Connections Under Window$