Page 1 of 1
Forum

Welcome to the Tweaking4All community forums!
When participating, please keep the Forum Rules in mind!

Topics for particular software or systems: Start your topic link with the name of the application or system.
For example “MacOS X – Your question“, or “MS Word – Your Tip or Trick“.

Please note that switching to another language when reading a post will not bring you to the same post, in Dutch, as there is no translation for that post!



Share:
Notifications
Clear all

[Solved] Delphi 7 - Retrieve router info via HTTP Request

7 Posts
2 Users
0 Reactions
2,479 Views
 Hans
(@hans)
Famed Member Admin
Joined: 12 years ago
Posts: 2870
Topic starter  

This a repost of the post bij Maniic, please continue the topic here.


   
ReplyQuote
(@maniic)
Active Member
Joined: 10 years ago
Posts: 14
 

Dear Tweakers, 

I’m trying to create a delphi application that with a press of a button loads my cable modem statistics. The application uses HTTP request. The cable modem I own can be acces when connected by wifi or ethernet on ip: 192.168.178.1The admin login page has 2 forms, one for username and one for password. The source code of the web-interface :

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<link rel="stylesheet" type="text/css" href="main.css" />
<meta name="GENERATOR" content="Microsoft FrontPage 5.0">
<meta name="ProgId" content="FrontPage.Editor.Document">
<meta http-equiv="Content-Type" content="text/html; charset=windows-1252">
<title>Residential Gateway Login</title>

<script> function showTooltip(e,n) { var scrollT = document.body.scrollTop; var x = e.clientX; var y = e.clientY; document.getElementById('tooltipcontent').innerHTML = document.getElementById('tt'+n).innerHTML; document.getElementById('tooltip').style.left = (x+10)+'px'; document.getElementById('tooltip').style.top = ((y-20)+scrollT)+'px'; } function hideTooltip() { var t = document.getElementById('tooltip'); t.style.left = '-1000px'; t.style.top = '-1000px'; } </script> </head>
<body> <h2>Log in</h2> <form action=/goform/login method=POST name="login">
<td class="cell1"> <span class="txt"> Username: </span> </td> <td class="cell2"> <input type="text" name="loginUsername" value="" class="invoer"/> </td> </tr> <tr> <td class="cell1"> <span class="txt"> Password: </span> </td> <td class="cell2"> <input type="password" name="loginPassword" value="" class="invoer"/> <!--
--><input type="submit" value="Inloggen"><!--
--> </form> </body>
</html>

I have removed almost all markup/layout html tags from the code above to keep this post as short as possible. As you can see the username is entered in ‘loginUsername’ and the password is entered in ‘loginPassword’. The form action is set to /goform/login.

Once the user enters admin credentials he is then redirected to : http://192.168.178.1/RgHome.asp. On this page are the basic modem settings displayed. From here one can navigate to the following page: http://192.168.178.1/BasicCmState.asp. This page is my final destination. Here the user can find the modem’s up/downstream channel settings. The info is displayed in an html table, see code below: 

<html>

<head> <link rel="stylesheet" type="text/css" href="main.css" /> <meta name="GENERATOR" content="Microsoft FrontPage 5.0"> <meta name="ProgId" content="FrontPage.Editor.Document"> <meta http-equiv="Content-Type" content="text/html; charset=windows-1252"> <title>Residential Gateway Configuration: Basic - Docsis</title> </head>
<body>

<h1>Basic</h1> <h3>Docsis</h3> This page displays the docsis information.
<table> <tr><th colspan=2>Startup Procedure</th></tr> <tr bgcolor="#CCCCCC"><td>Acquired Downstream Status</td><td>Completed</td></tr> <tr bgcolor="#CCCCCC"><td>Upstream Ranging Status</td><td>Completed</td></tr> <tr bgcolor="#CCCCCC"><td>Docsis DHCP Status</td><td>Completed</td></tr> <tr bgcolor="#CCCCCC"><td>Docsis TFTP Status</td><td>Completed </td></tr> <tr bgcolor="#CCCCCC"><td>Docsis TOD Status</td><td>Completed</td></tr> <tr bgcolor="#CCCCCC"><td>Security Status</td><td>Enabled / BPI+</td></tr> </table>


<table style="font-family: Helvetica;font-size:14"> <tr bgcolor=#CE0000><th colspan=8>Downstream Bonded Channels</th></tr>
<tr bgcolor="#0088ce"><td>Channel</td><td>Lock Status</td><td>Modulation</td><td>Frequency</td><td>Power</td><td>SNR</td><td>Microreflections</td></tr> <tr bgcolor="#9999CC"><td>1</td><td>Locked</td><td>QAM256</td><td>276000000 Hz</td><td>-7.1 dBmV</td><td>39.0 dB</td><td>-40 dBc</td></tr> <tr bgcolor="#99CCFF"><td>2</td><td>Locked</td><td>QAM256</td><td>228000000 Hz</td><td>-6.9 dBmV</td><td>40.3 dB</td><td>-37 dBc</td></tr> <tr bgcolor="#9999CC"><td>3</td><td>Locked</td><td>QAM256</td><td>236000000 Hz</td><td>-7.1 dBmV</td><td>38.6 dB</td><td>-36 dBc</td></tr> <tr bgcolor="#99CCFF"><td>4</td><td>Locked</td><td>QAM256</td><td>244000000 Hz</td><td>-6.7 dBmV</td><td>39.9 dB</td><td>-37 dBc</td></tr> <tr bgcolor="#9999CC"><td>5</td><td>Locked</td><td>QAM256</td><td>252000000 Hz</td><td>-7.1 dBmV</td><td>39.5 dB</td><td>-37 dBc</td></tr> <tr bgcolor="#99CCFF"><td>6</td><td>Locked</td><td>QAM256</td><td>260000000 Hz</td><td>-7.2 dBmV</td><td>39.3 dB</td><td>-35 dBc</td></tr> <tr bgcolor="#9999CC"><td>7</td><td>Locked</td><td>QAM256</td><td>268000000 Hz</td><td>-7.5 dBmV</td><td>38.6 dB</td><td>-30 dBc</td></tr> <tr bgcolor="#99CCFF"><td>8</td><td>Locked</td><td>QAM256</td><td>284000000 Hz</td><td>-6.8 dBmV</td><td>39.9 dB</td><td>-36 dBc</td></tr> </table>
<table style="font-family: Helvetica;font-size:14"> <tr bgcolor="#0088ce"><td>Correctables</td><td>Uncorrectables</td></tr> <tr bgcolor="#CCCCCC"><td>69</td><td>1260</td></tr> </table>

<table style="font-family: Helvetica;font-size:14"> <tr bgcolor=#CE0000><th colspan=7>Upstream Bonded Channels</th></tr>
<tr bgcolor="#0088ce"><td>Channel</td><td>Lock Status</td><td>US Channel Type</td><td>Symbol Rate</td><td>Frequency</td><td>Power</td></tr> <tr bgcolor="#9999CC"><td>1</td><td>Locked</td><td>ATDMA</td><td>5120 Ksym/sec</td><td>52000000 Hz</td><td>39.8 dBmV</td></tr> <tr bgcolor="#99CCFF"><td>2</td><td>Locked</td><td>ATDMA</td><td>5120 Ksym/sec</td><td>44500000 Hz</td><td>38.3 dBmV</td></tr> <tr bgcolor="#9999CC"><td>3</td><td>Locked</td><td>ATDMA</td><td>5120 Ksym/sec</td><td>36000000 Hz</td><td>38.3 dBmV</td></tr> <tr bgcolor="#99CCFF"><td>4</td><td>Locked</td><td>ATDMA</td><td>5120 Ksym/sec</td><td>58800000 Hz</td><td>41.3 dBmV</td></tr> </table>

<table> <tr><th colspan=2>Counter</th></tr> <tr bgcolor="#CCCCCC"><td>T3 Timeout</td><td>0</td></tr> <tr bgcolor="#CCCCCC"><td>T4 Timeout</td><td>1</td></tr> </table>


<form action=/goform/BasicCmState method=POST name="CmState">
<!-- <center> <table border="1"> <tr> <td>Downstream Frequency Select (in KHz)</td> <td><input name="BasicLockFrequency" type="text" size=6 maxlength=6 value=></td> <td><input type="submit" value="TUNE" size="15"> </tr> </table> </center> --> </form>

This info is what I’m trying to retrieve with delphi using HTTP request. This is the delphi code I got so far: 

procedure TForm1.Button1Click(Sender: TObject);
 
var
 
POSTData : TStringList  ;
  
s,p:string;

begin
   
POSTData := TStringList.Create;
  
try
    
IdHTTP1.Request.Clear;
    
IdHTTP1.Request.BasicAuthentication:= true;
    
IdHTTP1.Request.UserName := 'admin';
    
IdHTTP1.Request.Password := 'password';
    
IdHTTP1.ReadTimeout := 5000;
    
POSTData.Add('loginUsername=defaultuser');
   

POSTData.Add('loginPassword=verysecretpassword');
  

s := IdHTTP1.Post('http://192.168.178.1', POSTData);
 p := idHTTP1.Get ('http://192.168.178.1/RgHome.asp'); //tried also without /RgHome.asp
    
Memo1.Lines.Add(p);
  
finally
   
 POSTData.Free;

end;
  
end;

As you can see from the delphi code above I havent even come to the part where I GET the up/down data, for some reason I cant send the login credentials and retrieve the RgHome.asp. I have tried many different variations of this code, but I’m missing something. 

I really really can use some help here, anything is welcome ! 

Sorry for the long post again.


   
ReplyQuote
 Hans
(@hans)
Famed Member Admin
Joined: 12 years ago
Posts: 2870
Topic starter  

While fighting some domain expiration issues, I've written this post 3 times now haha ... Anyhow ...

First of all, I haven't used Delphi 7 in a long time, I've switched to Lazarus Pascal now that I privately would have to pay the upgrade. Lazarus Pascal is free and sort-off a Delphi 7 clone. I think the code will be identical to Delphi 7 when it comes to this example.

For your purpose, Synapse would be the easier way to go. It's free and it works for Delphi and Lazarus.

Installation is not needed, simply unzip the file (attached below, or download it from the Synapse Download page) and copy the files in "source/lib" to your project directory.

For your purpose, we would need the following function (see HTTPSend Synapse Manual):

function HttpPostURL(const URL, URLData: string; const Data: TStream): Boolean;

A very useful function, and example of use can be found in the THTTPSend object. It implements the POST method of the HTTP protocol. This function is good for POSTing form data. It sends the POST method for a URL document to an HTTP server. You must prepare the form data in the same manner as you would the URL data, and pass this prepared data to "URLdata". The following is a sample of how the data would appear: 'name=Lukas&field1=some%20data'. The information in the field must be encoded by EncodeURLElement function. The returned document is in the "Data" stream. Returns boolean TRUE if all went well.

I took the effort to write a tiny program in Lazarus and tested it with my own modem.

I started with a new program, added a TButton (Button1), two TEdit boxes (edUsername and edPassword) and a TMemo (Memo1).
After that I added httpsend and synacode to the Uses clause.

On button click:

procedure TForm1.Button1Click(Sender: TObject);
var
  Response: TMemoryStream;
  Variables: string;
begin // STEP 1 - Try to login
  Response := TMemoryStream.Create;
  try
    // Encode to make sure special chars and spaces get converter properly
    Variables:=EncodeURL('Username1='+edUsername.Text+'&Password='+edPassword.Text);
    if not HttpPostURL('http://192.168.2.254/login', Variables, Response) then
      begin
        ShowMessage('Failed to login');
        exit;
      end;
  finally
    Response.Free;
  end;
// STEP 2 - Retrieve Data after successful login
  // This will be different for your router of course
  try
    HttpGetText('http://192.168.2.254/getpage.gch?pid=1002&nextpage=status_wan_connection_t.gch', Memo1.Lines);
  Except
    ShowMessage('Failed to retrieve data');
  end;
end;         

The steps are relatively easy once you know how:

First we will try to login. For this we create a TMemoryStream to catch the Response from HttpPostURL() - in my test, this did not return anything, but the function came back with a TRUE, so the POST did work. After that we encode the variables so characters like spaces will be converted properly (to %20). Then we call HttpPostURL. On failure: exit.

Once logged in, we use HttpGetText to retrieve the URL of the page that holds the data you need and load the HTML into the TMemo.

Obviously your URL's will be slightly different, and the variables used in the FORM will be different as well of course.

I did write the code a little "simple" to keep it readable. Obviously this can be done much cleaner and efficient.

Hope this helps ... 


   
ReplyQuote
(@maniic)
Active Member
Joined: 10 years ago
Posts: 14
 

Thanks a lot Hans !

I have lazarus on my mac however I have issues with the debugger. I did find a topic on this forum on how to use an older version of a debugger but haven't tried it yet. 

As for your code, i think this is exactly what I need. I will try this out tomorrow and will let you know if it worked or not. Once again thanks for the effort. 


   
ReplyQuote
 Hans
(@hans)
Famed Member Admin
Joined: 12 years ago
Posts: 2870
Topic starter  

Hi Maniic!

You're welcome!
Oh and I'm sure the code will work under Delphi 7 as well, if that's what you prefer to work with.
Synapse was originally developed for Delphi but has been made compatible with Lazarus as well.

The GDB debugger can be a bit of a pain, but once installed it will work fine.
Don't forget to install XCode and the commandline tools (but since you have Lazarus installed, I assume you already did that).

Hope this works for you ...


   
ReplyQuote
(@maniic)
Active Member
Joined: 10 years ago
Posts: 14
 

Hey there Hans, 

Yes I have installed all the necessary requirements, just the debugger is doing vervelend :) But I prefer delphi as it's already working just fine and it's a small project :) Nevertheless I will give Lazarus a try. 

Thanks


   
ReplyQuote
 Hans
(@hans)
Famed Member Admin
Joined: 12 years ago
Posts: 2870
Topic starter  

Hi Maniic!

Well, that the debugger is "vervelend" is a known issue after Apple dropped GDB.
The files (which can be found in this forum) should fix that - I and others have used it numerous times and it works perfectly fine (might want to disable the "timeout" error in the debugger settings).

On the other hand, for a small project like this, with code that should work under Delphi as well: just use Delphi ...


   
ReplyQuote
Share: