while loop in expect script - networking

I'm new to expect scripting, I want to write something like this:
set variable;
$variable = expect -exact "\/----Enter Password----\\"
while { != $variable } {
send -- {^[-}
}
I want to keep sending escape+hyphen character until I expect this prompt:
"\/----Enter Password----\\"
I have written the above code but it is not working. How do I do this?

You can make use of exp_continue to handle this situation. The command exp_continue allows expect itself to continue executing rather than returning as it normally would. This is useful for avoiding explicit loops or repeated expect statements. By default, exp_continue resets the timeout timer. The timer is not restarted, if exp_continue is called with the -continue_timer flag.
In expect, the default timeout is 10 seconds. i.e. the time till which expect will wait for the expected string to appear.
we used to give the expected string in expect as something like
expect "name"
which will wait for the string 'name' and proceed to next statement if timeout happened. To handle the timeout scenario, we are using the keyword timeout in expect itself.
expect {
"name" { # Some code here }
timeout { # timeout_hanlder_code_here }
}
You can change timeout value by using set command as shown below.
set timeout 60; # Timeout will happen after 60 seconds.
So, combining all together in one shot,
expect {
# If the phrase 'Enter Password' seen, then it will send the password
"Enter Password" {send "yourpassword\r"}
# If 'timeout' happened, then it will send some keys &
# 'expect' will be looped again.
timeout {send -- {^[-}; exp_continue}
}
Note : I am seeing a problem in your code. You have mentioned that you have to send escape + hyphen key together. But, you are sending only literal square bracket ([) and hyphen (-) symbol. If it is working then fine and you don't need to read this 'Note' section.Skip it. Else, proceed to read below.
You should send the actual Escape character to the program. It can be done as
send -- \033-; # Sending Escape + hyphen together
What is this \033 ? It is the octal code for Escape key. Then along with that we are just combining the hyphen with it's symbol as - which results in \033-. So our final code will be,
expect {
# If the phrase 'Enter Password' seen, then it will send the password
"Enter Password" {send "yourpassword\r"}
# If 'timeout' happened, then it will send some keys &
# 'expect' will be looped again.
timeout {send -- \033-; exp_continue}
}
Reference : Tcl's wiki & ASCII Char Table

Related

Trying to pass a JSON string with an em dash from Tcl to browser and it fails to parse?

I've been going in circles a bit the past two days with this simple task due to lack of knowledge in a couple areas; so, this may sound like a repeat of a question from yesterday but it is not.
I had the issue of having a string of plain text stored in SQLite containing an em dash represented by three bytes 226 128 148. I was trying to search the string for the dash by typing it in the text editor, and could not locate it.
After much help on SO, I learned that the plain text could easily be changed to UTF-8; and I did that and updated the SQLite table column. It now appears as code 8212 if run scan $c %c.
Now, the dash is displayed even in the command line interface when run SQLite from there for testing.
However, I can no longer send the record to a web browser to be displayed because of the following error. SyntaxError: JSON.parse: bad control character in string literal at line 1 column 49 of the JSON data localhost:8000:233:25 Of course, column 49 is the dash.
If I send back the previous version before updating the string from plain text to UTF-8, there is not an error in the browser and the string is displayed as expected.
Likely, this is a very stupid question but I don't know what I'm doing wrong or not doing. Thank you for any guidance you may be able to provide.
I updated one record using a SQLite function.
dbt function decodeUTF -argcount 1 -deterministic -directonly -returntype text { encoding convertfrom utf-8 }
set sql {select decodeUTF(text_content) from tablename where conditions...}
dbt eval $sql
And then retrieved the new value and sent it to a browser using some Tcl code as a very limited local server.
proc GetSQL {sock} {
chan flush $sock
set sql {select text_content from tablename where conditions ... }
dbt eval $sql {
set result "{\"result\":\"$text_content\"}"
}
set headers ""
append headers "HTTP/1.1 200 OK\n"
append headers "Content-Type: application/json; charset: utf-8\n"
append headers "Content-Length: [string length $result]\n"
append headers "Connection: Keep-Alive\n"
puts $sock $headers
chan configure $sock -translation binary
puts $sock $result
}
The GET request is made using fetch from the browser page script and return response.json() is where I think it fails.
The encoding convertfrom utf-8 when storing (your decodeUTF) needs to be matched by an encoding convertto utf-8 $result upon retrieval, before returning it to the client via your binary-only channel:
puts $sock [encoding convertto utf-8 $result]

Asterisk, Ignore DTMF special characters in GET DATA

I'm using phpagi $agi->get_data to read digit from user.
In some telephones, user didn't hit any key, but audio playback immediately stops and get result of "D" !!
I searched a lot about it, and looks like $agi-get_dat receives DTMF data that contains 0-9*#ABCD.
1st question is, why my users get "D" without hitting any key!
2nd question is, how can i ignore these characters to prevent interrupting my ivr.
phpagi getdata do this call
https://wiki.asterisk.org/wiki/display/AST/AGICommand_stream+file
so you can extend it by adding allowed digits param. PhpAGI lib is opensource and have source code.
Actualy you can just use stream_file call
stream_file (line 677)
Play the given audio file, allowing playback to be interrupted by a
DTMF digit. This command is similar to the GET DATA command but this
command returns after the first DTMF digit has been pressed while GET
DATA can accumulated any number of digits before returning.
return: see evaluate for return information. ['result'] is -1 on hangup or error, 0 if playback completes with no digit received,
otherwise a decimal value of the DTMF tone. Use chr() to convert to
ASCII.
link: http://www.voip-info.org/wiki-stream+file
example: Ping an IP address
array, stream_file (string $filename, [string $escape_digits = ''],
integer $offset)
string $filename: without extension, often in /var/lib/asterisk/sounds
string $escape_digits
integer $offset
you can check the logs by the following command :
asterisk -vvvvv
and you can check the value of the input for example in php code :
$val = $agi->get_data
exec("echo $val >> /tmp/output")
and then check this file : /tmp/output

Processing: How do I set a client to read multiple messages sent at once from a server as separate?

I am working on setting up a basic network system in Processing:
import processing.net.*;
Server myServer;
Client myClient;
However, I'm having trouble with my server and client side communication set up. My client is interpreting all incoming messages as Strings, and the issue is that whenever multiple messages are sent from the server in the same frame, they become added into a single string, which my program cannot interpret. After testing, I found that sending multiple messages from a single client to the server are given the same treatment.
My client reader looks like this:
while (myClient.available() > 0) {
String dataIn = myClient.readString();
As of now, I don't know if the problem is in the reader (combining the strings), or in the fact that I'm using write() multiple times in a single frame (and the data is being sent as a single string).
I am wondering if the messages can somehow be sent/read separately or, if not, there is some method to test if a message has already been sent (that works for both the client and server side) so that I can set up a queue to keep track of messages to be sent.
Well, I decided to forgo the idea of checking if a message had already been sent as I did not see any functions that would be able to help do that. Instead, I went ahead and created an arrayList of strings for the server called serverQ to act as a queue for messages to be sent:
ArrayList <String> serverQ = new ArrayList<String>();
I also added a function writeSQ(String) that would place any input string into the queue:
void writeSQ(String s) {
serverQ.add(s);
}
I then proceeded to replace every usage of myServer.write(String) with writeSQ(String s). At the end of my ServerUpdate function, I added a section that would empty the queue, sending the next string to all clients, one frame at a time:
// send data
if (serverQ.size() > 0) {
myServer.write(serverQ.get(0));
serverQ.remove(0);
}
}
However, for some reason, messages still got compounded, so I speculated that it may be due to the closeness (frequency) of the sent messages (each frame); so I set a boolean serverSent to alternate the messages sent to every other frame. The new code looks like this:
// send data
if (serverQ.size() > 0) {
if (!serverSent) {
myServer.write(serverQ.get(0));
serverQ.remove(0);
serverSent = true;
} else
serverSent = false;
}
This worked perfectly and the messages were interpreted individually by clients. I added that exact same support code to the clients (changing everything from server to client when needed) and after a good amount of testing, can confirm that this new support works properly both ways.

In asterisk, How can I restrict caller to press particular key as DTMFinstead of all?

I made a call flow using php AGI in asterisk. For getting DTMF from caller, I have user fastpass_get_data() function of AGI. In this function caller can press any key. As and when caller press any key, playing prompt will be stoped.
Now I want that when caller press "1" at that time only that playing prompt will stop. So while prompt file is playing and user press any digit except "1", it will not affect playing file. But if user press "1" playing prompt file file should be stopped and call flow continue onwards.
Thanks !!!
Use streamfile command
stream file Usage: STREAM FILE <filename> <escape digits> [sample offset]
Send the given file, allowing playback to be interrupted by the given digits, if any.
Use double quotes for the digits if you wish none to be permitted.
If sample offset is provided then the audio will seek to sample offset before play starts.
Remember, the file extension must not be included in the filename.
Returns: failure: 200 result=-1 endpos=<sample offset> failure on open: 200 result=0 endpos=0 success: 200 result=0 endpos=<offset> digit pressed: 200 result=<digit> endpos=<offset>
http://www.voip-info.org/wiki/view/stream+file

How to check if a POST submitted field exists in VBScript?

After a form is submitted, how does one check server-side if a particular field exists? For example:
If [Exists] Request("FieldName") Then
...
End If
If Request("FieldName").Count > 0 Then
...
End If
Or, for short:
If Request("FieldName").Count Then
...
End If
Background:
The Request collection is magic, in so far as it does not throw an error when you try to access a key that was not part of the request - but the .Count will be 0 for non-existing keys.
In a URL-encoded query string it's legal to send keys that don't have a value, like foo&bar&baz
It's also legal to send the same key multiple times, i.e. multiple values per key, like foo=value1&foo=value2.
Therefore, the reliable way to determine if a key has been sent by the client is to count how many times the client has sent it.
A special case of this test is checking whether there was a non-empty value for that key (If Request("FieldName") > ""). This may or may not be what you want in the end; just be aware that the underlying behavior of query strings is broader than that.
Check if it's not empty. There are a few different ways, but the one I've seen more frequently used is along the lines of:
If Request("FieldName") <> "" Then
'etc.
End If
I usually explicitly check the Form and QueryString collections with some variation of one of the code below if I may be getting the variable from one or the other depending on context:
Select Case True
Case Request.Form("FieldName") <> ""
'Run if the Form isn't empty
Case Request.QueryString("FieldName") <> ""
'Run if the QueryString isn't empty
Case Else
'Set a predefined default if they're both empty
End Select
Or a nested If ... Then:
If Request.Form("FieldName") <> "" Then
'Run if the Form isn't empty
ElseIf Request.QueryString("FieldName") <> "" Then
'Run if the QueryString isn't empty
Else
'Set a predefined default if they're both empty
End If
If I know exactly which collection it's coming from, I'll check that collection specifically. The reason is that I want to make sure it is pulling what I expect from where I expect it to come from. I don't want someone overriding a Form value by sending something in the QueryString when I'm not expecting it.
From MSDN:
If the specified variable is not in one of the preceding five
collections, the Request object returns EMPTY.
All variables can be accessed directly by calling Request(variable)
without the collection name. In this case, the Web server searches the
collections in the following order:
QueryString
Form
Cookies
ClientCertificate
ServerVariables
If a variable with the same name exists in more than one collection,
the Request object returns the first instance that the object
encounters.
It is strongly recommended that when referring to members of a
collection the full name be used. For example, rather than
Request.("AUTH_USER") use Request.ServerVariables("AUTH_USER"). This
allows the server to locate the item more quickly.
To check if the parameter was present (without caring about its value) it is also possible to write:
fieldValue = Request("FieldName")
if Not IsEmpty(fieldValue) ...
One advantage over Count method above is, that you can test the variable, without referring to the field name again.
Advantage over testing for "" is that if you pass &FieldName without assigning value, test for "" will yield true, but IsEmpty returns false.
Edit: Turns out this is not reliable in IIS.
For the url with ?param alone, or ?param=&param2, IsEmpty(param) returns false, but
For the url with ?param&param2, IsEmpty(param) weirdly returns true ...
I usually check the value of the SUBMIT button. If it was clicked, it's value is posted along with the form data. So, even if all your form data is blank, the submit button's value will not be. And if the submit button's value is blank, then it wasn't clicked.
if request("btn_Submit") <> "" Then
response.write "form was submitted"
end if
This is more difficult if you are using a javascript form.submit() call, in which case I usually opt for the hidden field.

Resources