Gotoif how to set it to allow a 3 or 4 digit response to meet the condition - asterisk

Was wondering if anyone can help me currently I only accept 3 cvv numbers and I need to chage this to 4 but I can't find any where online how to put a range in this statement.
exten => s,n,GotoIf($[${LEN(${vrCC_CCV})}=3]?wait:cc_ccvinv)
Visa/Mastercard are fine with 3 didits but American Express requires the four digits on front of the card.
Any assistance would be greatful.

Like any other language asterisk support AND/OR in expressions.
https://www.voip-info.org/asterisk-cmd-gotoif/
Example 2
; Are the first three digits of the returned value of ${ENUM} are
; either SIP or IAX? If not, we ignore and pass to normal
; dialing path at priority 4.
;
exten => _011X.,2,GotoIf($[$["${ENUM:0:3}" = "SIP"] | $["${ENUM:0:3}" = "IAX"]]?3:4)
More info about expressions in dialplan
https://www.voip-info.org/asterisk-expressions/

Related

How do i pass multiple variables to writing ODBC function?

I need to insert some data to SQL ftom Asterisk dialplan. I am using ODBC connection and func_odbc.conf file. There are good way to READ several values from SQl, but apparently, i can't find any working solution for inserting several variables to func_odbc function.
I already tried to use NoOp(ODBC_FunctionName(${ARG1},${ARG2},${ARG3})) and it does not work with 'writesql'. Set(${ODBC_Function()={${ARG1},${ARG2},${ARG3}}) is not working either due to Set limited for one name/value pair.
Here is my func_odbc:
[putClientEvaluation]
;${ARG1} - uniqueid
;${ARG2} - operator
;${ARG3} - client
;${ARG4} - rating
;${ARG5} - queue
dsn=voip
writesql=INSERT INTO cc_service_rating(timestamp,callid,operator,client,rating,queue) values(now(),'${SQL_ESC(${ARG1})}','${SQL_ESC(${ARG2})}','${SQL_ESC(${ARG3})}','${SQL_ESC(${ARG4})}','${SQL_ESC(${ARG5})}')
So i need a working way to pass several arguments at once to odbc writesql function.
UPDATE:
Looks like i just have to use VAL instead of ARG:
writesql=INSERT INTO cc_service_rating(timestamp,callid,operator,client,rating,queue) values(now(),'${SQL_ESC(${VAL1})}','${SQL_ESC(${VAL2})}','${SQL_ESC(${VAL3})}','${SQL_ESC(${VAL4})}','${SQL_ESC(${VAL5})}')
But i still get warning from Set:
WARNING[1227][C-00000020]: pbx_variables.c:1155 pbx_builtin_setvar: Set requires one variable name/value pair.
So, how do i do this without using Set?
UPD:
Did this, no warnings now:
macro extension
exten => s,n,Set(operator=${ARG1})
exten => s,n,Set(quename=${ARG2})
exten => s,n,Set(client=${ARG3})
;timestamp,callid,operator,client,rating,queue
exten => s,n,Set(ODBC_putClientEvaluation()=${UNIQUEID},${operator},${client},${MACRO_EXTEN},${quename})
function
writesql=INSERT INTO cc_service_rating(timestamp,callid,operator,client,rating,queue) values(now(),'${VAL1}','${ARG1}','${ARG3}','${VAL2}','${ARG3}')
Not shure why does this work, obviousely i don't understand how ARG and VAL works here, and why putting args in function brackets does not work at all (even with comma screening).
You are using variables incorrect. Please read book article about variables.
Set(ODBC_Function(${ARG1},${ARG2})=${VAL1},"fixed_param",${VAL3})
I think you should try like this:
Set(ODBC_Function()=${VAR1},"fixed_param",${VAL3});

Insert character Cisco IOS EEM Script

I am extracting the ip address of an interface and using that address' 3rd octet as part of the BGP AS number. I need to insert a 0 before the number if the 3rd octet is < 10.
For example, if 3rd octet = 8 then BGP AS = 11108
Here is my current and unfinished applet.
event manager applet replace
event none
action 1.0 cli command "conf t"
action 1.1 cli command "do show ip int brief vlan 1"
action 1.2 regexp " [0-9.]+ " $_cli_result ip match
action 2.0 regexp {([0-9]+\.[0-9]+\.[0-9]+\.[0-9]+)} $_cli_result match ip
action 2.1 regexp {([0-9]+)\.([0-9]+)\.([0-9]+)\.([0-9]+)} $ip match first second third forth
action 2.2 set vl1 $first.$second.$third.$forth
action 2.3 cli command "router bpg 111$third"
The simplest method here is to use format with the right formatting sequence. (If you've ever used sprintf() in C, you'll understand what the format command does straight off. Except the Tcl command doesn't have any problems with buffer overruns or other tricky bits like that.)
# Rest of your script unchanged; I'm lazy so I'll not repeat it here
set bpg [format "652%02d" $third]
action 2.3 cli command "router bpg $bpg"
The key here is that %02d does formatting (%) of a decimal number (d) in a zero-padded (0) field of width two (2). And there's a literal 652 in front of it (no % there so literal).
You can roll the above into a single line if you want, but I think it is much clearer to write it in two (there's really no good excuse for writing unclear code, as it just makes your life harder later and it doesn't really take much less time to write clearly in the first place):
action 2.3 cli command "router bpg [format 652%02d $third]"

Writing the total request time in seconds to an nginx access log, possibly using a calculated variable

I'm trying to modify my nginx access log format to include the request duration, in seconds.
I see two possible variables I could use:
1) $request_time
2) $upstream_response_time
However both of these variables are expressed in microseconds, and I need this value to be rendered in seconds. Is there any way to specify the output as an expression (i.e. $request_time * 1000) or accomplish this in some other way?
Thanks
The webserver is not a calculator or statistical program. It's logging function is to provide the raw data you can do your analysis with. If you analysis program is incapable of converting microseconds to seconds you should shop around for other software. In any case, it us unrealistic to expect a program's logging function to perform unit conversions for you. The goal of logging is not to format, yet to record what it has done without impacting the performance of it's core functionality.
If you use a reporter like LogStash (ELK stack) you can do some calculation when parsing the log. Here is my example to convert second into millisecond in my Logstash filter for Nginx:
grok {
match => {
"message" => "%{IPORHOST:clientip} %{USER:ident} %{USER:auth} \[%{HTTPDATE:timestamp}\] \"%{WORD:verb} %{URIPATHPARAM:logMessage} HTTP/%{NUMBER:httpversion}\" %{NUMBER:response} (?:%{NUMBER:bytes}|-) (?:\"(?:%{URI:referrer}|-)\"|%{QS:referrer}) %{QS:agent} rt=%{NUMBER:duration_sec} cid=%{GREEDYDATA:correlationId}"
}
}
mutate { convert => [ "duration_sec", "float" ] }
ruby { code => "event['duration_ms'] = event['duration_sec'].to_f * 1000" }
Hope this helps.
As noted in the comments $request_time is already in seconds, however it is possible to convert to another unit purely in nginx config as follows.
I realise this is an old question but it seems to get a lot of traffic so perhaps the below will help someone else who, like me, might want to convert to a different unit, in my case nanoseconds (though if you want milliseconds then simply omit the 6 trailing zeros).
This is useful for sending to the Elastic event.duration field - to avoid the faff of an ingest pipeline or similar on the Elastic end (to multiply by 1000000) you can instead do some hideous regex as below.
The fact that $request_time is always zero-padded to 3 decimal places helps, so in the common cases you can append 6 zeros - but you also have to handle leading zeros (before & after the decimal point) to make sure the result doesn't end up with any leading zeros:
map $request_time $request_time_nanos {
# Simple case for 0.000
~^0\.000$ 0;
# If 0 before decimal place, must remove leading zeros after it, before adding 6 zeros
~^0\.(?:0*)([^0].*)$ $1000000;
# Otherwise just concatenate the full pre- & post-decimal parts, before adding 6 zeros
~^([^0][^.]*)\.(.*)$ $1$2000000;
}
Example transformations (commas inserted for readability only):
[sec] [nanoseconds]
0.000 => 0
0.110 => 110,000,000
0.010 => 10,000,000
1.010 => 1,010,000,000

Function that returns a value in extensions.conf - asterisk

I want to do the following in my extensions.conf in asterisk:
Read in a number entered by a user. - easy
Feed that number into a script which returns a wav file.
This wav file is then played.
I know the system command, but have not been able to figure out a way for it to return a value.
Any help is most welcome,
Thanks,
Sriram.
For such things I use Asterisk AGI. Idea is similar to CGI scripts for Web servers. You can use various languages, but I use Python with pyst: Python for Asterisk library. Such AGI script/program can read or set channel variable and this way communicate with Asterisk dialplan.
Example of such code with pyst agilib:
wav_to_play = 'other.wav'
user_nr = agilib.get_variable('user_entered_number')
if not user_nr:
wav_to_play = 'nothing.wav'
elif user_nr.endswith('0'):
wav_to_play = 'zero.wav'
# ...
agilib.set_variable('wav_selected', wav_to_play)
After saving such code in wav_selector.agi (you must add normal Python header, libs etc) you can use it in dialplan like:
exten => s,n,Set(user_entered_number=5)
exten => s,n,AGI(wav_selector.agi)
exten => s,n,Background((${wav_selected})
One can have the program/script write the value to a file and then use the functions within asterisk such as ReadFile to get the value. This can be done like so:
Within the script:
echo -n ${value} > ${fileName}
From within asterisk:
exten => 0,n,ReadFile(ValueReadFromFile=${fileName},${MAX_FILE_CHAR})
where: ${MAX_FILE_CHAR} is the max. characters that need to be read from the file ${fileName}. The value you want read will be stored in ValueReadFromFile.

Can I determine if the terminal interprets the C1 control codes?

ISO/IEC 2022 defines the C0 and C1 control codes. The C0 set are the familiar codes between 0x00 and 0x1f in ASCII, ISO-8859-1 and UTF-8 (eg. ESC, CR, LF).
Some VT100 terminal emulators (eg. screen(1), PuTTY) support the C1 set, too. These are the values between 0x80 and 0x9f (so, for example, 0x84 moves the cursor down a line).
I am displaying user-supplied input. I do not wish the user input to be able to alter the terminal state (eg. move the cursor). I am currently filtering out the character codes in the C0 set; however I would like to conditionally filter out the C1 set too, if terminal will interpret them as control codes.
Is there a way of getting this information from a database like termcap?
The only way to do it that I can think of is using C1 requests and testing the return value:
$ echo `echo -en "\x9bc"`
^[[?1;2c
$ echo `echo -e "\x9b5n"`
^[[0n
$ echo `echo -e "\x9b6n"`
^[[39;1R
$ echo `echo -e "\x9b0x" `
^[[2;1;1;112;112;1;0x
The above ones are:
CSI c Primary DA; request Device Attributes
CSI 5 n DSR; Device Status Report
CSI 6 n CPR; Cursor Position Report
CSI 0 x DECREQTPARM; Request Terminal Parameters
The terminfo/termcap that ESR maintains (link) has a couple of these requests in user strings 7 and 9 (user7/u7, user9/u9):
# INTERPRETATION OF USER CAPABILITIES
#
# The System V Release 4 and XPG4 terminfo format defines ten string
# capabilities for use by applications, .... In this file, we use
# certain of these capabilities to describe functions which are not covered
# by terminfo. The mapping is as follows:
#
# u9 terminal enquire string (equiv. to ANSI/ECMA-48 DA)
# u8 terminal answerback description
# u7 cursor position request (equiv. to VT100/ANSI/ECMA-48 DSR 6)
# u6 cursor position report (equiv. to ANSI/ECMA-48 CPR)
#
# The terminal enquire string should elicit an answerback response
# from the terminal. Common values for will be ^E (on older ASCII
# terminals) or \E[c (on newer VT100/ANSI/ECMA-48-compatible terminals).
#
# The cursor position request () string should elicit a cursor position
# report. A typical value (for VT100 terminals) is \E[6n.
#
# The terminal answerback description (u8) must consist of an expected
# answerback string. The string may contain the following scanf(3)-like
# escapes:
#
# %c Accept any character
# %[...] Accept any number of characters in the given set
#
# The cursor position report () string must contain two scanf(3)-style
# %d format elements. The first of these must correspond to the Y coordinate
# and the second to the %d. If the string contains the sequence %i, it is
# taken as an instruction to decrement each value after reading it (this is
# the inverse sense from the cup string). The typical CPR value is
# \E[%i%d;%dR (on VT100/ANSI/ECMA-48-compatible terminals).
#
# These capabilities are used by tac(1m), the terminfo action checker
# (distributed with ncurses 5.0).
Example:
$ echo `tput u7`
^[[39;1R
$ echo `tput u9`
^[[?1;2c
Of course, if you only want to prevent display corruption, you can use less approach, and let the user switch between displaying/not displaying control characters (-r and -R options in less). Also, if you know your output charset, ISO-8859 charsets have the C1 range reserved for control codes (so they have no printable chars in that range).
Actually, PuTTY does not appear to support C1 controls.
The usual way of testing this feature is with vttest, which provides menu entries for changing the input- and output- separately to use 8-bit controls. PuTTY fails the sanity-check for each of those menu entries, and if the check is disabled, the result confirms that PuTTY does not honor those controls.
I don't think there's a straightforward way to query whether the terminal supports them. You can try nasty hacky workarounds (like print them and then query the cursor position) but I really don't recommend anything along these lines.
I think you could just filter out these C1 codes unconditionally. Unicode declares the U+0080.. U+009F range as control characters anyway, I don't think you should ever use them for anything different.
(Note: you used the example 0x84 for cursor down. It's in fact U+0084 encoded in whichever encoding the terminal uses, e.g. 0xC2 0x84 for UTF-8.)
Doing it 100% automatically is challenging at best. Many, if not most, Unix interfaces are smart (xterms and whatnot), but you don't actually know if connected to an ASR33 or a PC running MSDOS.
You could try some of the terminal interrogation escape sequences and timeout if there is no reply. But then you might have to fall back and maybe ask the user what kind of terminal they are using.

Resources