AHK send URL commands with passwords Topic is solved

Get help with using AutoHotkey (v1.1 and older) and its commands and hotkeys
NFNNLN
Posts: 3
Joined: 28 Jan 2023, 22:38

AHK send URL commands with passwords

Post by NFNNLN » 28 Jan 2023, 22:49

I can control VLC via http.

Example:
I can paste this into the browser URL bar and it pauses/plays VLC
http://:[email protected]:8080/requests/status.xml?command=pl_pause

I cannot get AHK to submit the same URL successfully. It fails on the password:

Code: Select all

#Numpad8::
{
	cmd=127.0.0.1:8080/requests/status.xml?command=pl_pause
	info:=UrlDownloadToVar(cmd)
	MsgBox % "Response " . info
}

urlDownloadToVar(url,raw:=0,userAgent:="",headers:="",Username:="",Password:="vlcremote"){
	if (!regExMatch(url,"i)http?://"))
		url:="http://" url
	try {
		hObject:=comObjCreate("WinHttp.WinHttpRequest.5.1")
		hObject.open("GET",url)
		hObject.SetCredentials(Username,Password,0)
		if (userAgent)
			hObject.setRequestHeader("User-Agent",userAgent)
		if (isObject(headers)) {
			for i,a in headers {
				hObject.setRequestHeader(i,a)
			}
		}
		
		hObject.send()
		return raw?hObject.responseBody:hObject.responseText
	} catch e
		return % e.message
}
I get this output, as if it isn't getting the password.
<?xml version="1.0" encoding="ascii" ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml10/DTD/xhtml10strict.dtd">
<html lang="en">
<head>
<title>Unauthorized</title>
</head>
<body>
<h1>401 Unauthorized (/requests/status.xml)</h1>
<hr />
<a href="http://www.videolan.org">VideoLAN</a>
</body>
</html>
I tried passing the URL as http://:[email protected]:8080/requests/status.xml?command=pl_pause directly and I tried using .SetCredentials() but it is the same issue.

teadrinker
Posts: 4309
Joined: 29 Mar 2015, 09:41
Contact:

Re: AHK send URL commands with passwords  Topic is solved

Post by teadrinker » 29 Jan 2023, 10:54

Welcome to the AHK forum!
For me this works:

Code: Select all

pwd := "MyPassword"
len := StrPutBuff(":" . pwd, buf)
base64Pwd := CryptBinaryToString(&buf, len)
headers := {Authorization: "Basic " . base64Pwd}
url := "http://localhost:8080/requests/status.xml?command="

command := "pl_pause"
WebRequest(url . command,, headers)

StrPutBuff(str, ByRef buff, encoding := "UTF-8") {
	VarSetCapacity(buff, len := (StrPut(str, encoding) - 1) << (encoding ~= "i)^(UTF-16|cp1200)$"))
	StrPut(str, &buff, encoding)
	Return len
}

CryptBinaryToString(pData, size, formatName := "CRYPT_STRING_BASE64", NOCRLF := true)
{
   static formats := { CRYPT_STRING_BASE64: 0x1
                     , CRYPT_STRING_HEX:    0x4
                     , CRYPT_STRING_HEXRAW: 0xC }
        , CRYPT_STRING_NOCRLF := 0x40000000
   fmt := formats[formatName] | (NOCRLF ? CRYPT_STRING_NOCRLF : 0)
   if !DllCall("Crypt32\CryptBinaryToString", "Ptr", pData, "UInt", size, "UInt", fmt, "Ptr", 0, "UIntP", chars)
      throw "CryptBinaryToString failed. LastError: " . A_LastError
   VarSetCapacity(outData, chars << !!A_IsUnicode)
   DllCall("Crypt32\CryptBinaryToString", "Ptr", pData, "UInt", size, "UInt", fmt, "Str", outData, "UIntP", chars)
   Return outData
}

WebRequest(url, method := "GET", HeadersArray := "", body := "", ByRef error := "") {
   Whr := ComObjCreate("WinHttp.WinHttpRequest.5.1")
   Whr.Open(method, url, true)
   for name, value in HeadersArray
      Whr.SetRequestHeader(name, value)
   Whr.Send(body)
   Whr.WaitForResponse()
   status := Whr.status
   if (status != 200)
      error := "HttpRequest error, status: " . status
   Arr := Whr.responseBody
   pData := NumGet(ComObjValue(arr) + 8 + A_PtrSize)
   length := Arr.MaxIndex() + 1
   Return StrGet(pData, length, "UTF-8")
}

NFNNLN
Posts: 3
Joined: 28 Jan 2023, 22:38

Re: AHK send URL commands with passwords

Post by NFNNLN » 29 Jan 2023, 12:27

Thanks that worked right away.

As your code indicates, the password needs to be base64.

If I remove .SetCredentials() and add in the password as a base64 header then even the original code I have works. That makes me think .SetCredentials() isn't working as one would expect.

Code: Select all

urlDownloadToVar(url,raw:=0,userAgent:="",headers:="",Username:="",Password:="vlcremote"){

	len := StrPutBuff(":" . Password, buf)
	base64Pwd := CryptBinaryToString(&buf, len)
	headers := {Authorization: "Basic " . base64Pwd}

	try {
		hObject:=comObjCreate("WinHttp.WinHttpRequest.5.1")
		hObject.open("GET",url)
		;hObject.SetCredentials(Username,Password,0)
		if (userAgent)
			hObject.setRequestHeader("User-Agent",userAgent)
		if (isObject(headers)) {
			for i,a in headers {
				hObject.setRequestHeader(i,a)
			}
		}
		
		hObject.send()
		return raw?hObject.responseBody:hObject.responseText
	} catch e
		return % e.message
}



#Numpad8::
{
	;pwd := "vlcremote"
	;len := StrPutBuff(":" . pwd, buf)
	;base64Pwd := CryptBinaryToString(&buf, len)
	;headers := {Authorization: "Basic " . base64Pwd}
	;url := "http://localhost:8080/requests/status.xml?command="
	
	;command := "pl_pause"
	;WebRequest(url . command,, headers)

	cmd=http://127.0.0.1:8080/requests/status.xml?command=pl_pause
	info:=urlDownloadToVar(cmd)
	MsgBox % "Response " . info
}

StrPutBuff(str, ByRef buff, encoding := "UTF-8") {
	VarSetCapacity(buff, len := (StrPut(str, encoding) - 1) << (encoding ~= "i)^(UTF-16|cp1200)$"))
	StrPut(str, &buff, encoding)
	Return len
}

CryptBinaryToString(pData, size, formatName := "CRYPT_STRING_BASE64", NOCRLF := true)
{
   static formats := { CRYPT_STRING_BASE64: 0x1
                     , CRYPT_STRING_HEX:    0x4
                     , CRYPT_STRING_HEXRAW: 0xC }
        , CRYPT_STRING_NOCRLF := 0x40000000
   fmt := formats[formatName] | (NOCRLF ? CRYPT_STRING_NOCRLF : 0)
   if !DllCall("Crypt32\CryptBinaryToString", "Ptr", pData, "UInt", size, "UInt", fmt, "Ptr", 0, "UIntP", chars)
      throw "CryptBinaryToString failed. LastError: " . A_LastError
   VarSetCapacity(outData, chars << !!A_IsUnicode)
   DllCall("Crypt32\CryptBinaryToString", "Ptr", pData, "UInt", size, "UInt", fmt, "Str", outData, "UIntP", chars)
   Return outData
}

WebRequest(url, method := "GET", HeadersArray := "", body := "", ByRef error := "") {
   Whr := ComObjCreate("WinHttp.WinHttpRequest.5.1")
   Whr.Open(method, url, true)
   for name, value in HeadersArray
      Whr.SetRequestHeader(name, value)
   Whr.Send(body)
   Whr.WaitForResponse()
   status := Whr.status
   if (status != 200)
      error := "HttpRequest error, status: " . status
   Arr := Whr.responseBody
   pData := NumGet(ComObjValue(arr) + 8 + A_PtrSize)
   length := Arr.MaxIndex() + 1
   Return StrGet(pData, length, "UTF-8")
}

Post Reply

Return to “Ask for Help (v1)”