Sign in to follow this  
Followers 0
Niblob

Sending Screen capture over port 80

10 posts in this topic

Hi there,

There are those who may claim this is not an AutoIT question, but I am using AutoIT to code it so a really hope someone can provide a solution.

I am trying to send screen captures at regular intervals from several PCs to a server. Because of firewall restrictions, I can only use port 80 - so it will have to be via HTTP. I have set up a CGI script on the server to handle the incoming jpegs. Here is the code for that:

CODE

#!/usr/bin/perl -w

use strict;

use CGI;

use CGI::Carp qw ( fatalsToBrowser );

use File::Basename;

$CGI::POST_MAX = 1024 * 5000;

my $safe_filename_characters = "a-zA-Z0-9_.-";

my $query = new CGI;

my $pc = $query->param("PC");

my $filename = "$pc.jpg";

my $upload_dir = 'C:/Inetpub/wwwroot/jpg';

my $upload_filehandle = $query->upload("TheFile");

open (UPLOADFILE, ">$upload_dir/$filename") or error("Can't open/create \"$upload_dir/$filename\": $!");

binmode UPLOADFILE;

while ( <$upload_filehandle> )

{

print UPLOADFILE;

}

close UPLOADFILE;

print $query->header ( );

print <<END_HTML;

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "DTD/xhtml1-strict.dtd">

<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">

<head>

<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />

<title>Thanks!</title>

<style type="text/css">

img {border: none;}

</style>

</head>

<body>

<p>Thanks for uploading your file!</p>

<p>Your photo:</p>

<p><img src="/jpg/$filename" alt="Photo" /></p>

</body>

</html>

END_HTML

sub error {

my $error = shift;

print $query->header(),

$query->start_html(-title=>'Error'),

$error,

$query->end_html;

exit(0);

}

Now I need AutoIT to take the Screen capture and send it to the server. I am doing this using multi-part form data. The problem is I don't know how to encode the binary data of the jpeg. Here's what I have so far:

CODE

#Include <ScreenCapture.au3>

;Capture the screen

_ScreenCapture_Capture("c:\temp\" & @ComputerName & ".jpg")

;set up the http object

$Http = ObjCreate("MSXML2.ServerXMLHTTP")

$url = "http://localhost/perlex/blob.pl"

$Http.open("POST", $url, true)

$Http.setRequestHeader ("Content-Type","multipart/form-data; boundary=---------------------------7d92383a340dea")

;open the jpeg as binary

$jpeg = fileopen("c:\temp\" & @ComputerName & ".jpg",16)

$strPost1="-----------------------------7d92383a340dea" & @crlf & _

"Content-Disposition: form-data; name=""PC""" & @crlf & _

"" & @crlf & _

@ComputerName & @crlf & _

"-----------------------------7d92383a340dea" & @crlf & _

"Content-Disposition: form-data; name=""TheFile""; filename=""c:\temp\" & @ComputerName & ".jpg""" & @crlf & _

"Content-Type: image/pjpeg" & @crlf & _

"" & @crlf

$binJPG = FileRead($jpeg)

$strPost2= @crlf & @crlf & "-----------------------------7d92383a340dea" & @crlf

$binPost1=stringtobinary($strPost1)

$binPost2=stringtobinary($strPost2)

$binPost = $binPost1 & $binJPG & $binPost2

$strPost = binarytostring($binPost)

msgbox("","",$strPost)

$Http.send($strPost)

$post = fileopen("c:\temp\post.txt",18)

filewrite($post,$strPost)

msgbox("","",$Http.responseText)

fileclose($post)

fileclose($jpeg)

$Http.abort()

$Http = 0

The string $strPost seems to be truncated when I use it. Strangely, when I display the length of the string it is very long, but the contents written to post.txt are very small.

If I can get this working it will be a nice little function!

Thanks in advance!

Share this post


Link to post
Share on other sites



ServerXMLHTTP has a .open() method...so maybe you should use that instead of autoit's FileOpen() function to get the binary data...

Humm just a guess though, i didn't look into it very throughly

Share this post


Link to post
Share on other sites

Thanks, but the .open method is what is used to send the post data.

Actually I should have specified the error I get. It is "Malformed Multipart POST". If I take the $binJPG and set it to some string (instead of the contents of the JPG file), then the string gets written to a jpg file on the server. So really seems like there's a problem handling the binary stuff.

I've been scratching my head for two days now - I would really appreciate someone taking a look!

Share this post


Link to post
Share on other sites

From what I can tell, these objects need files to be written as Byte arrays. I'm not sure how this is applies to AutoIt.

"winhttp.winhttprequest.5.1"

"MSXML2.XMLHTTP"

"MSXML2.ServerXMLHTTP"

http://www.vbforums.com/showthread.php?t=451836

http://groups.google.com/group/microsoft.p...91c66d695823322

http://www.ericphelps.com/scripting/sample...b/HTTP_POST.txt

Share this post


Link to post
Share on other sites

#6 ·  Posted (edited)

<snipped>

Edited by SmOke_N

Is There A Life BEFORE Death?im stupidSaved warn logs: cheateraSmOke_N Note Added 17 January 2009 - 02:54 PM Added to warn level Posting a way to hack the registry and force sending someones desktop via TCP. Jos Note Added 25 November 2008 - 02:52 PM Added to warn level for being an impolite rookie.once a year i go bad ... what will happen in 2010??[u]Its GOOD to be BAD ... (Warlock's Succubus - World of Warcraft)[/u]

Share this post


Link to post
Share on other sites

Thanks for the tips. I managed to get it working. Unfortunately only in VBScript. You really have to jump through some hoops to get the binary stuff working.

The problem with using VBScript is it has no self contained screen capture. I could of course call an AutoIT script to capture the screen to a file and then run the VBScript to send it to the server, but it's a little long-winded. The problem seems to be converting a string to binary. The function in VBScript looks like this:

Function StringToBinary(S)
 Dim i, ByteArray
 For i=1 To Len(S)
 ByteArray = ByteArray & ChrB(Asc(Mid(S,i,1)))
 Next
 StringToBinary = ByteArray
End Function

You would think the AutoIT equivalent would be:

Func myStringToBinary($S)
 Dim $i, $ByteArray
 For $i=1 To stringLen($S)
 $ByteArray = $ByteArray & chr(Binary(Asc(stringMid($S,$i,1))))
 Next
 return $ByteArray
Endfunc

or

Func myStringToBinary($S)
 Dim $i, $ByteArray
 For $i=1 To stringLen($S)
 $ByteArray = $ByteArray & Binary(Asc(stringMid($S,$i,1)))
 Next
 return $ByteArray
Endfunc

or just the StringToBinary function, but they don't do the same. Has anyone got any ideas?

In case anyone is interested, the VBScript code looks like this:

Const adLongVarBinary = 205 
dim adodb
set adodb=WScript.CreateObject("ADODB.Connection")
Set rs = WScript.CreateObject("ADODB.Recordset")
set inStream=WScript.CreateObject("ADODB.Stream")
inStream.Open
inStream.type=1
inStream.LoadFromFile("C:\blob.jpg")
binJPG=inStream.Read()
set objHttp = CreateObject("MSXML2.ServerXMLHTTP")
set fs = CreateObject("Scripting.FileSystemObject")
url = "http://localhost/perlex/blob.pl"
objHttp.open "POST", url, false
objHttp.setRequestHeader "Content-Type","multipart/form-data; boundary=---------------------------7d92383a340dea"

strPost1="-----------------------------7d92383a340dea" & vbcrlf & _
"Content-Disposition: form-data; name=""PC""" & vbcrlf & _
"" & vbcrlf & _
"Computer" & vbcrlf & _
"-----------------------------7d92383a340dea" & vbcrlf & _
"Content-Disposition: form-data; name=""TheFile""; filename=""c:\test.jpg""" & vbcrlf & _
"Content-Type: image/pjpeg" & vbcrlf & _
"Content-Transfer-Encoding: binary" & vbcrlf & _
"" & vbcrlf 
 
strPost2= vbcrlf & vbcrlf & "-----------------------------7d92383a340dea" & vbcrlf

rs.Fields.Append "FormData", adLongVarBinary, Len(strPost1) + LenB(binJPG) + Len(strPost2)
rs.Open
rs.AddNew 

rs("FormData").AppendChunk StringToBinary(strPost1) & ChrB(0)
binPost1 = rs("formData").GetChunk(Len(strPost1))
rs("FormData") = ""
rs("FormData").AppendChunk StringToBinary(strPost2) & ChrB(0)
binPost2 = rs("formData").GetChunk(Len(strPost2))
rs("FormData") = ""
rs("FormData").AppendChunk binPost1
rs("FormData").AppendChunk binJPG
rs("FormData").AppendChunk binPost2
binPost = rs("FormData")
rs.Close
'strPost = StringToBinary(strPost1) & binJPG & StringToBinary(strPost2)
'msgbox(binPost)
objHttp.send binPost
msgbox(objHttp.responseText)
objHttp.abort()
set objHttp = nothing

Function StringToBinary(S)
 Dim i, ByteArray
 For i=1 To Len(S)
 ByteArray = ByteArray & ChrB(Asc(Mid(S,i,1)))
 Next
 StringToBinary = ByteArray
End Function

Share this post


Link to post
Share on other sites

I attempted to convert the VBS file but it still has errors. It works fine in VB:

Line 96: No such interface supported

$oMyError = ObjEvent("AutoIt.Error","ComErrHandler") 

$filename = "C:\picture.jpg"

$result = upload('http://www.server.org/test.php', $filename, "uploaded_file")

ConsoleWrite("responseText: " & $result)

Func Upload($strUploadUrl, $strFilePath, $strFileField, $strDataPairs = "")
    ;Uses POST to upload a file and miscellaneous form data
    ;strUploadUrl is the URL (http://127.0.0.1/cgi-bin/upload.exe)
    ;strFilePath is the file to upload (C:\My Documents\test.zip)
    ;strFileField is the web page equivalent form field name for the file (File1)
    ;strDataPairs are pipe-delimited form data pairs (foo=bar|snap=crackle)
    Const $MULTIPART_BOUNDARY = "---------------------------0123456789012"
    Dim $ado, $rs
    Dim $lngCount
    Dim $bytFormData, $bytFormStart, $bytFormEnd, $bytFile
    Dim $strFormStart = "", $strFormEnd, $strDataPair
    Dim $web
    Const $adLongVarBinary = 205
    
    ;Read the file into a byte array
    Local $ado = ObjCreate("ADODB.Stream")
    $ado.Type = 1
    $ado.Open
    $ado.LoadFromFile ($strFilePath)
    $bytFile = $ado.Read
    $ado.Close
    
    ;Create the multipart form data. 
    ;Define the end of form
    $strFormEnd = @CRLF & "--" & $MULTIPART_BOUNDARY & "--" & @CRLF
    
    ;First add any ordinary form data pairs
    If $strDataPairs <> "" Then
        For $strDataPair In StringSplit($strDataPairs, "|", 2)
            $strFormStart &= "--" & $MULTIPART_BOUNDARY & @CRLF
            $strFormStart &= "Content-Disposition: form-data; "
            $aTemp = StringSplit($strDataPair, "=", 2)
            $strFormStart &= 'name="' & $aTemp[0] & '"'
            $strFormStart &= @CRLF & @CRLF
            ;$aTemp = StringSplit($strDataPair, "=", 2)
            $strFormStart &= $aTemp[1]
            $strFormStart &= @CRLF
        Next
    EndIf
    
    ;Now add the header for the uploaded file
    $strFormStart &= "--" & $MULTIPART_BOUNDARY & @CRLF
    $strFormStart &= "Content-Disposition: form-data; "
    $strFormStart &= 'name="' & $strFileField & '"; '
    $strFormStart &= 'filename="' & StringMid($strFilePath, StringInStr($strFilePath, "\",0,-1) + 1) & '"'
    $strFormStart &= @CRLF
    $strFormStart &= "Content-Type: application/upload" ;'bogus, but it works
    $strFormStart &= @CRLF & @CRLF
    
    ;Create a recordset large enough to hold everything
    Local $rs = ObjCreate("ADODB.Recordset")
    $rs.Fields.Append ("FormData", $adLongVarBinary, StringLen($strFormStart) + BinaryLen($bytFile) + StringLen($strFormEnd)) ;LenB FIXED
    $rs.Open
    $rs.AddNew
    
    ;Convert form data so far to zero-terminated byte array
    For $lngCount = 1 To StringLen($strFormStart)
        $bytFormStart &= ChrB(Asc(StringMid($strFormStart, $lngCount, 1))) ;ChrB
    Next
    
    $rs("FormData").AppendChunk ($bytFormStart & ChrB(0)) ;ChrB
    $bytFormStart = $rs("formData").GetChunk(StringLen($strFormStart))
    $rs("FormData") = ""
    
    ;Get the end boundary as a zero-terminated byte array
    For $lngCount = 1 To StringLen($strFormEnd)
        $bytFormEnd &= ChrB(Asc(StringMid($strFormEnd, $lngCount, 1))) ;ChrB
    Next
    $rs("FormData").AppendChunk ($bytFormEnd & ChrB(0)) ;ChrB
    $bytFormEnd = $rs("formData").GetChunk(StringLen($strFormEnd))
    $rs("FormData") = ""
    
    ;Now merge it all
    $rs("FormData").AppendChunk ($bytFormStart)
    $rs("FormData").AppendChunk ($bytFile)
    $rs("FormData").AppendChunk ($bytFormEnd)
    $bytFormData = $rs("FormData")
    $rs.Close
    
    ;ConsoleWrite($bytFormData)
    ;Return
    
    ;Upload it
    Local $web = ObjCreate("winhttp.winhttprequest.5.1")
    ;Local $web = ObjCreate("MSXML2.XMLHTTP")
    $web.Open ("POST", $strUploadUrl, false)
    $web.SetRequestHeader ("Content-Type", "multipart/form-data; boundary=" & $MULTIPART_BOUNDARY)
    $web.Send($bytFormData) ;FAILURE
    
    Return $web.ResponseText
EndFunc

Func ChrB($iCode)
    ;Return StringToBinary(Chr($iCode))
    ;Return Binary(Chr($iCode))
    Return Chr($iCode)
EndFunc

Func ComErrHandler()
    $HexNumber = Hex($oMyError.number, 8)
    MsgBox(0, "COM Error", "COM Error Details:" & @CRLF & @CRLF & _
            "err.description is: " & @TAB & $oMyError.description & @CRLF & _
            "err.windescription:" & @TAB & $oMyError.windescription & @CRLF & _
            "err.number is: " & @TAB & $HexNumber & @CRLF & _
            "err.lastdllerror is: " & @TAB & $oMyError.lastdllerror & @CRLF & _
            "err.scriptline is: " & @TAB & $oMyError.scriptline & @CRLF & _
            "err.source is: " & @TAB & $oMyError.source & @CRLF & _
            "err.helpfile is: " & @TAB & $oMyError.helpfile & @CRLF & _
            "err.helpcontext is: " & @TAB & $oMyError.helpcontext _
            )
    SetError(1)
EndFunc  ;==>ComErrHandler

Share this post


Link to post
Share on other sites

The same result as me. I really appreciate you having at look at it though. I was a bit surprised that when I put the following line in before the send:

msgbox("","",BinaryLen($bytFormData))

I get zero returned.

Could it be some kind of bug in the way AutoIT is handling the binary data? I'm not that up on binary stuff so it's a bit tricky for me to diagnose. Anyway, it looks as if I will install Snagit on all the PCs and run the VBScript version on them. Ho Hum!

Thanks again for taking a look at it.

Jean-Pierre

Share this post


Link to post
Share on other sites

You could always POST using the IE functions.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!


Register a new account

Sign in

Already have an account? Sign in here.


Sign In Now
Sign in to follow this  
Followers 0