diff --git a/agc_2-X/trunk/UPGRADE b/agc_2-X/trunk/UPGRADE index 64ee58b3..16519604 100644 --- a/agc_2-X/trunk/UPGRADE +++ b/agc_2-X/trunk/UPGRADE @@ -582,6 +582,18 @@ OTHER CHANGES: Campaign/List/In-Group, new reporting and more. See the docs/QC_PROCCES.txt document for more information. +165. Added the BUTTON Field Type option to Custom List Fields. Allows you to add + a button to the form that will commit any changes made in the form and + automatically reload the form. + +166. Added Two-Factor Authentication(2FA) as an option for the admin web screens + This adds a required second step to the admin web screen login process + through a method other than a password, such as: an Email, Phone Call or + Text-Message(SMS). This 2FA auth also lasts only a set amount of time + (defined in System Settings[number of hours, from 1-9999 hours]), or + until the user logs out. For more information, read the + 2FA_TWO_FACTOR_AUTHENTICATION.txt document. + diff --git a/agc_2-X/trunk/agi/cm_speak_var.agi b/agc_2-X/trunk/agi/cm_speak_var.agi index 8c219b87..c4dee466 100644 --- a/agc_2-X/trunk/agi/cm_speak_var.agi +++ b/agc_2-X/trunk/agi/cm_speak_var.agi @@ -1,23 +1,25 @@ #!/usr/bin/perl # -# cm_speak_var.agi version 2.10 +# cm_speak_var.agi version 2.14 # # runs after a call has lead_id assigned to it, speaks letters/numbers # # You need to put lines similar to those below in your Custom Dialplan: # # exten => 8412,1,Answer -# exten => 8412,n,AGI(cm_speak_var.agi,say_digits---security_phrase) +# exten => 8412,n,AGI(cm_speak_var.agi,say_digits---security_phrase---DB) # exten => 8412,n,Hangup # # CLI FLAG OPTIONS: # 1. function: (say_digits, say_number, say_alpha, say_datetime, say_phonetic, stream_file) # 2. field: (any vicidial_list field) +# 3. variable type: DB(default) or DP(Asterisk Dialplan Variable) # -# Copyright (C) 2014 Matt Florell LICENSE: AGPLv2 +# Copyright (C) 2021 Matt Florell LICENSE: AGPLv2 # # changes: # 140619-2005 - first build +# 210311-1710 - Added variable type option, and ability to use Asterisk dialplan variables # $script = 'cm_speak_var.agi'; @@ -122,7 +124,10 @@ if (length($ARGV[0])>1) @ARGV_vars = split(/---/, $ARGV[0]); $CLI_function = $ARGV_vars[0]; $CLI_field = $ARGV_vars[1]; + $CLI_var_type = $ARGV_vars[2]; } +if ( ($CLI_var_type != 'DB') && ($CLI_var_type != 'DP') ) + {$CLI_var_type='DB';} $|=1; while() @@ -180,93 +185,98 @@ $CIDlead_id = ($CIDlead_id + 0); if ( ($CLIlead_id > 0) && ($CIDlead_id < 1) ) {$CIDlead_id = $CLIlead_id;} $VD_lead_id = $CIDlead_id; -if ($AGILOG) {$agi_string = "+++++ cm_speak_var START : |$CLI_function|$CLI_field|$CIDlead_id|$now_date|$AST_ver|$priority|$calleridname|"; &agi_output;} +if ($AGILOG) {$agi_string = "+++++ cm_speak_var START : |$CLI_function|$CLI_field|$CLI_var_type|$CIDlead_id|$now_date|$AST_ver|$priority|$calleridname|"; &agi_output;} if ($CM_LOG) { open(Lout, ">>$CMLOGfile") || die "Can't open $CMLOGfile: $!\n"; - print Lout "$now_date|$VD_lead_id| |$CLI_function|$CLI_field|$calleridnum|$callerid|\n"; + print Lout "$now_date|$VD_lead_id| |$CLI_function|$CLI_field|$CLI_var_type|$calleridnum|$callerid|\n"; close(Lout); } $AGI->stream_file('sip-silence'); $AGI->stream_file('sip-silence'); - -$stmtA = "SELECT lead_id,entry_date,modify_date,status,user,vendor_lead_code,source_id,list_id,phone_number,title,first_name,middle_initial,last_name,address1,address2,address3,city,state,province,postal_code,country_code,gender,date_of_birth,alt_phone,email,security_phrase,comments,called_count,last_local_call_time,rank,owner FROM vicidial_list where lead_id='$VD_lead_id';"; -$sthA = $dbhA->prepare($stmtA) or die "preparing: ",$dbhA->errstr; -$sthA->execute or die "executing: $stmtA ", $dbhA->errstr; -$sthArows=$sthA->rows; -if ($sthArows > 0) +if ($CLI_var_type == 'DP') { - @aryA = $sthA->fetchrow_array; - $CM_lead_id = $aryA[0]; - $CM_entry_date = $aryA[1]; - $CM_modify_date = $aryA[2]; - $CM_status = $aryA[3]; - $CM_user = $aryA[4]; - $CM_vendor_lead_code = $aryA[5]; - $CM_source_id = $aryA[6]; - $CM_list_id = $aryA[7]; - $CM_phone_number = $aryA[8]; - $CM_title = $aryA[9]; - $CM_first_name = $aryA[10]; - $CM_middle_initial = $aryA[11]; - $CM_last_name = $aryA[12]; - $CM_address1 = $aryA[13]; - $CM_address2 = $aryA[14]; - $CM_address3 = $aryA[15]; - $CM_city = $aryA[16]; - $CM_state = $aryA[17]; - $CM_province = $aryA[18]; - $CM_postal_code = $aryA[19]; - $CM_country_code = $aryA[20]; - $CM_gender = $aryA[21]; - $CM_date_of_birth = $aryA[22]; - $CM_alt_phone = $aryA[23]; - $CM_email = $aryA[24]; - $CM_security_phrase = $aryA[25]; - $CM_comments = $aryA[26]; - $CM_called_count = $aryA[27]; - $CM_last_local_call_time = $aryA[28]; - $CM_rank = $aryA[29]; - $CM_owner = $aryA[30]; + $field_value = $AGI->get_variable("$CLI_field"); } -$sthA->finish(); - -if ($CLI_field =~ /lead_id/) {$field_value = $CM_lead_id;} -if ($CLI_field =~ /entry_date/) {$field_value = $CM_entry_date;} -if ($CLI_field =~ /modify_date/) {$field_value = $CM_modify_date;} -if ($CLI_field =~ /status/) {$field_value = $CM_status;} -if ($CLI_field =~ /user/) {$field_value = $CM_user;} -if ($CLI_field =~ /vendor_lead_code/) {$field_value = $CM_vendor_lead_code;} -if ($CLI_field =~ /source_id/) {$field_value = $CM_source_id;} -if ($CLI_field =~ /list_id/) {$field_value = $CM_list_id;} -if ($CLI_field =~ /phone_number/) {$field_value = $CM_phone_number;} -if ($CLI_field =~ /title/) {$field_value = $CM_title;} -if ($CLI_field =~ /first_name/) {$field_value = $CM_first_name;} -if ($CLI_field =~ /middle_initial/) {$field_value = $CM_middle_initial;} -if ($CLI_field =~ /last_name/) {$field_value = $CM_last_name;} -if ($CLI_field =~ /address1/) {$field_value = $CM_address1;} -if ($CLI_field =~ /address2/) {$field_value = $CM_address2;} -if ($CLI_field =~ /address3/) {$field_value = $CM_address3;} -if ($CLI_field =~ /city/) {$field_value = $CM_city;} -if ($CLI_field =~ /state/) {$field_value = $CM_state;} -if ($CLI_field =~ /province/) {$field_value = $CM_province;} -if ($CLI_field =~ /postal_code/) {$field_value = $CM_postal_code;} -if ($CLI_field =~ /country_code/) {$field_value = $CM_country_code;} -if ($CLI_field =~ /gender/) {$field_value = $CM_gender;} -if ($CLI_field =~ /date_of_birth/) {$field_value = $CM_date_of_birth;} -if ($CLI_field =~ /alt_phone/) {$field_value = $CM_alt_phone;} -if ($CLI_field =~ /email/) {$field_value = $CM_email;} -if ($CLI_field =~ /security_phrase/) {$field_value = $CM_security_phrase;} -if ($CLI_field =~ /comments/) {$field_value = $CM_comments;} -if ($CLI_field =~ /called_count/) {$field_value = $CM_called_count;} -if ($CLI_field =~ /last_local_call_time/) {$field_value = $CM_last_local_call_time;} -if ($CLI_field =~ /rank/) {$field_value = $CM_rank;} -if ($CLI_field =~ /owner/) {$field_value = $CM_owner;} +else + { + $stmtA = "SELECT lead_id,entry_date,modify_date,status,user,vendor_lead_code,source_id,list_id,phone_number,title,first_name,middle_initial,last_name,address1,address2,address3,city,state,province,postal_code,country_code,gender,date_of_birth,alt_phone,email,security_phrase,comments,called_count,last_local_call_time,rank,owner FROM vicidial_list where lead_id='$VD_lead_id';"; + $sthA = $dbhA->prepare($stmtA) or die "preparing: ",$dbhA->errstr; + $sthA->execute or die "executing: $stmtA ", $dbhA->errstr; + $sthArows=$sthA->rows; + if ($sthArows > 0) + { + @aryA = $sthA->fetchrow_array; + $CM_lead_id = $aryA[0]; + $CM_entry_date = $aryA[1]; + $CM_modify_date = $aryA[2]; + $CM_status = $aryA[3]; + $CM_user = $aryA[4]; + $CM_vendor_lead_code = $aryA[5]; + $CM_source_id = $aryA[6]; + $CM_list_id = $aryA[7]; + $CM_phone_number = $aryA[8]; + $CM_title = $aryA[9]; + $CM_first_name = $aryA[10]; + $CM_middle_initial = $aryA[11]; + $CM_last_name = $aryA[12]; + $CM_address1 = $aryA[13]; + $CM_address2 = $aryA[14]; + $CM_address3 = $aryA[15]; + $CM_city = $aryA[16]; + $CM_state = $aryA[17]; + $CM_province = $aryA[18]; + $CM_postal_code = $aryA[19]; + $CM_country_code = $aryA[20]; + $CM_gender = $aryA[21]; + $CM_date_of_birth = $aryA[22]; + $CM_alt_phone = $aryA[23]; + $CM_email = $aryA[24]; + $CM_security_phrase = $aryA[25]; + $CM_comments = $aryA[26]; + $CM_called_count = $aryA[27]; + $CM_last_local_call_time = $aryA[28]; + $CM_rank = $aryA[29]; + $CM_owner = $aryA[30]; + } + $sthA->finish(); + if ($CLI_field =~ /lead_id/) {$field_value = $CM_lead_id;} + if ($CLI_field =~ /entry_date/) {$field_value = $CM_entry_date;} + if ($CLI_field =~ /modify_date/) {$field_value = $CM_modify_date;} + if ($CLI_field =~ /status/) {$field_value = $CM_status;} + if ($CLI_field =~ /user/) {$field_value = $CM_user;} + if ($CLI_field =~ /vendor_lead_code/) {$field_value = $CM_vendor_lead_code;} + if ($CLI_field =~ /source_id/) {$field_value = $CM_source_id;} + if ($CLI_field =~ /list_id/) {$field_value = $CM_list_id;} + if ($CLI_field =~ /phone_number/) {$field_value = $CM_phone_number;} + if ($CLI_field =~ /title/) {$field_value = $CM_title;} + if ($CLI_field =~ /first_name/) {$field_value = $CM_first_name;} + if ($CLI_field =~ /middle_initial/) {$field_value = $CM_middle_initial;} + if ($CLI_field =~ /last_name/) {$field_value = $CM_last_name;} + if ($CLI_field =~ /address1/) {$field_value = $CM_address1;} + if ($CLI_field =~ /address2/) {$field_value = $CM_address2;} + if ($CLI_field =~ /address3/) {$field_value = $CM_address3;} + if ($CLI_field =~ /city/) {$field_value = $CM_city;} + if ($CLI_field =~ /state/) {$field_value = $CM_state;} + if ($CLI_field =~ /province/) {$field_value = $CM_province;} + if ($CLI_field =~ /postal_code/) {$field_value = $CM_postal_code;} + if ($CLI_field =~ /country_code/) {$field_value = $CM_country_code;} + if ($CLI_field =~ /gender/) {$field_value = $CM_gender;} + if ($CLI_field =~ /date_of_birth/) {$field_value = $CM_date_of_birth;} + if ($CLI_field =~ /alt_phone/) {$field_value = $CM_alt_phone;} + if ($CLI_field =~ /email/) {$field_value = $CM_email;} + if ($CLI_field =~ /security_phrase/) {$field_value = $CM_security_phrase;} + if ($CLI_field =~ /comments/) {$field_value = $CM_comments;} + if ($CLI_field =~ /called_count/) {$field_value = $CM_called_count;} + if ($CLI_field =~ /last_local_call_time/) {$field_value = $CM_last_local_call_time;} + if ($CLI_field =~ /rank/) {$field_value = $CM_rank;} + if ($CLI_field =~ /owner/) {$field_value = $CM_owner;} + } if ($CLI_function =~ /say_digits/) { diff --git a/agc_2-X/trunk/bin/ADMIN_keepalive_ALL.pl b/agc_2-X/trunk/bin/ADMIN_keepalive_ALL.pl index e3e51cd5..29c8551e 100644 --- a/agc_2-X/trunk/bin/ADMIN_keepalive_ALL.pl +++ b/agc_2-X/trunk/bin/ADMIN_keepalive_ALL.pl @@ -145,9 +145,10 @@ # 201123-1651 - Added reset of vicidial_lead_call_daily_counts table # 201218-2054 - Added reset of vicidial_agent_dial_campaigns table # 210207-1200 - Added purging of vicidial_shared_log log entries +# 210311-2229 - Added purging of old records from vicidial_two_factor_auth # -$build = '210207-1200'; +$build = '210311-2229'; $DB=0; # Debug flag $teodDB=0; # flag to log Timeclock End of Day processes to log file @@ -1935,6 +1936,24 @@ if ($timeclock_end_of_day_NOW > 0) ##### END vicidial_shared_log end of day process removing records older than 7 days ##### + ##### BEGIN vicidial_two_factor_auth end of day process removing expired and older records ##### + $stmtA = "DELETE from vicidial_two_factor_auth where (auth_exp_date < NOW()) or ( (auth_code_exp_date < NOW()) and (auth_stage != '1') );"; + if($DBX){print STDERR "\n|$stmtA|\n";} + $affected_rows = $dbhA->do($stmtA); + if($DB){print STDERR "\n|$affected_rows vicidial_two_factor_auth expired or older records purged|\n";} + if ($teodDB) {$event_string = "vicidial_two_factor_auth expired or older records purged: |$stmtA|$affected_rows|"; &teod_logger;} + + $stmtA = "optimize table vicidial_two_factor_auth;"; + if($DBX){print STDERR "\n|$stmtA|\n";} + $sthA = $dbhA->prepare($stmtA) or die "preparing: ",$dbhA->errstr; + $sthA->execute or die "executing: $stmtA ", $dbhA->errstr; + $sthArows=$sthA->rows; + @aryA = $sthA->fetchrow_array; + if ($DB) {print "|",$aryA[0],"|",$aryA[1],"|",$aryA[2],"|",$aryA[3],"|","\n";} + $sthA->finish(); + ##### END vicidial_two_factor_auth end of day process removing records older than 7 days ##### + + ##### BEGIN vicidial_lead_messages end of day process removing records older than 1 day ##### $stmtA = "DELETE FROM vicidial_lead_messages WHERE call_date < \"$RMSQLdate\";"; $sthA = $dbhA->prepare($stmtA) or die "preparing: ",$dbhA->errstr; diff --git a/agc_2-X/trunk/docs/2FA_TWO_FACTOR_AUTHENTICATION.txt b/agc_2-X/trunk/docs/2FA_TWO_FACTOR_AUTHENTICATION.txt new file mode 100644 index 00000000..f464263e --- /dev/null +++ b/agc_2-X/trunk/docs/2FA_TWO_FACTOR_AUTHENTICATION.txt @@ -0,0 +1,75 @@ +2FA - TWO FACTOR AUTHENTICATION Updated: 2021-03-12 + +This document covers the 2FA(Two-Factor-Authentication) features in VICIdial as +of admin.php build 210312-1239(svn/trunk revision 3373). + + + +What is 2FA (Two-Factor-Authentication)? + +Two-Factor-Authentication adds a required second step to the admin web screen login process through a method other than a password, such as: an Email, Phone Call or Text-Message(SMS). This 2FA auth also lasts only a set amount of time(defined in System Settings[number of hours, from 1-9999 hours]), or until the user logs out. Currently, 2FA is not available or affected by agent screen logins. + + +To use 2FA on your system, you will need to have at least one of the following enabled on your VICIdial system: +1. The ability for your webserver to send email through PHP +2. The ability to place phone calls from one of your dialers +3. An SMS service that can send text messages by an HTTP or HTTPS API + + +To enable and configure 2FA in VICIdial, there are two settings in the Admin -> System Settings web configuration page, and one override setting in the User Modify page: + +SYSTEM SETTINGS: +1. 2FA Auth Expire Hours - Must be set to a number higher than 0 to enable +2. 2FA Settings Container - Must be a valid 2FA_SETTINGS Container Type, with the following configuration options(example is below the field definitions): + +auth_code_expire_minutes = The number of minutes the Authorization code will be valid for, default is 30 minutes +auth_code_attempts = The number of attempts a person has to enter an auth code before their account is locked for 15 minutes, default is 10 +auth_code_length = The number of digits in the Authorization code(can be from 4 to 10), default is 6 +email_auth = If set to YES, then "Email" is given as an option to people logging in when choosing a 2FA method, default is NO +email_from = The email address that the webserver will use to send Auth-code emails from +email_subject = The subject of the Auth-code emails +email_message = The message content of the Auth-code emails, default is: "Here is your VICIdial Login Authorization Code: --A--auth_code--B--" +phone_auth = If set to YES, then "Phone Call" is given as an option to people logging in when choosing a 2FA method, default is NO +phone_prefix = The dial prefix used when placing Auth-code phone calls(if using 10-digit numbers in USA-Canada, and campaign prefix is 9, then use '91') +phone_server_ip = The Server IP of the dialer to be used to place Auth-code phone calls +phone_cid_number = The callerID number to be used when placing Auth-code phone calls +phone_message_override = A Settings Container with alternative Call Menu ID to be used to play(your access code is "--A--auth_code--B--"), default is 2FA_say_auth_code +sms_auth = If set to YES, then "SMS(Text-Message)" is given as an option to people logging in when choosing a 2FA method, default is NO +sms_cid_number = The callerID number to be used when placing Auth-code SMS text-messages +sms_url = The URL used to send SMS messages, the agent Mobile Number and Auth-Code variables are "--A--mobile_number--B--" and "--A--auth_code--B--" + + +EXAMPLE "2FA_SETTINGS" SETTINGS CONTAINER: + +auth_code_expire_minutes => 30 +auth_code_attempts => 10 +auth_code_length => 5 +email_auth => YES +email_from => no-reply@vicidial.org +email_subject => VICIdial Login Authentication +email_message => Here is your VICIdial Login Authorization Code: --A--auth_code--B-- +phone_auth => YES +phone_prefix => 91 +phone_server_ip => 10.10.10.15 +phone_cid_number => 3125551212 +phone_message_override => +sms_auth => YES +sms_cid_number => 3125551212 +sms_url => https://http-api.d7networks.com/send?to=1--A--mobile_number--B--&from=17275551212&username=USERNAME_HERE&password=PASSWORD_HERE&content=Here%20is%20your%20VICIdial%20login%20authorization%20code%3A%20--A--auth_code--B-- + + +USER MODIFY: +3. There is also a User option "Two Factor Auth Override" which allows an administrator to disable 2FA for a specific user account. + + + + + +QUICK TUTORIAL FOR HOW TO SET UP AN SMS ACCOUNT WITH D7NETWORKS.COM: +1. Go to https://d7networks.com +2. Click to "Login/Sign-Up" and fill out the form to set up a new account +3. Click on the "SMS Api" link at the top, then the "HTTP API" link in the main panel +4. Copy the Username and Password that it has generated for you and populate it in the below URL to test: + NOTE: Both the 'to' and 'from' assume the country code is included, so in NANPA countries(like the USA and Canada) you will need the '1' prefix before the 10-digit phone numbers. + +https://http-api.d7networks.com/send?to=1--A--mobile_number--B--&from=17275551212&username=USERNAME_HERE&password=PASSWORD_HERE&content=Here%20is%20your%20VICIdial%20login%20authorization%20code%3A%20--A--auth_code--B-- diff --git a/agc_2-X/trunk/extras/MySQL_AST_CREATE_tables.sql b/agc_2-X/trunk/extras/MySQL_AST_CREATE_tables.sql index f39fe350..5c84c42a 100644 --- a/agc_2-X/trunk/extras/MySQL_AST_CREATE_tables.sql +++ b/agc_2-X/trunk/extras/MySQL_AST_CREATE_tables.sql @@ -685,7 +685,9 @@ max_inbound_filter_enabled ENUM('0','1') default '0', max_inbound_filter_statuses TEXT, max_inbound_filter_ingroups TEXT, max_inbound_filter_min_sec SMALLINT(5) default '-1', -status_group_id VARCHAR(20) default '' +status_group_id VARCHAR(20) default '', +mobile_number VARCHAR(20) default '', +two_factor_override ENUM('NOT_ACTIVE','ENABLED','DISABLED') default 'NOT_ACTIVE' ) ENGINE=MyISAM; CREATE UNIQUE INDEX user ON vicidial_users (user); @@ -1894,7 +1896,9 @@ allow_shared_dial ENUM('0','1','2','3','4','5','6') default '0', agent_search_method ENUM('0','1','2','3','4','5','6') default '0', phone_defaults_container VARCHAR(40) default '---DISABLED---', qc_claim_limit TINYINT UNSIGNED DEFAULT '3', -qc_expire_days TINYINT UNSIGNED DEFAULT '3' +qc_expire_days TINYINT UNSIGNED DEFAULT '3', +two_factor_auth_hours SMALLINT(5) default '0', +two_factor_container VARCHAR(40) default '---DISABLED---' ) ENGINE=MyISAM; CREATE TABLE vicidial_campaigns_list_mix ( @@ -2821,7 +2825,7 @@ field_name VARCHAR(5000), field_description VARCHAR(100), field_rank SMALLINT(5), field_help VARCHAR(1000), -field_type ENUM('TEXT','AREA','SELECT','MULTI','RADIO','CHECKBOX','DATE','TIME','DISPLAY','SCRIPT','HIDDEN','READONLY','HIDEBLOB','SWITCH','SOURCESELECT') default 'TEXT', +field_type ENUM('TEXT','AREA','SELECT','MULTI','RADIO','CHECKBOX','DATE','TIME','DISPLAY','SCRIPT','HIDDEN','READONLY','HIDEBLOB','SWITCH','SOURCESELECT','BUTTON') default 'TEXT', field_options VARCHAR(5000), field_size SMALLINT(5), field_max SMALLINT(5), @@ -4495,6 +4499,20 @@ last_modified TIMESTAMP NOT NULL DEFAULT current_timestamp() ON UPDATE current_t PRIMARY KEY (qc_scorecard_id) ) ENGINE=MyISAM; +CREATE TABLE vicidial_two_factor_auth ( +auth_date DATETIME, +auth_exp_date DATETIME, +user VARCHAR(20) default '', +auth_stage ENUM('0','1','2','3','4','5','6') default '0', +auth_code VARCHAR(20) default '', +auth_code_exp_date DATETIME, +auth_method VARCHAR(20) default 'EMAIL', +auth_attempts SMALLINT(5) default '0', +index (user), +index (auth_date), +index (auth_exp_date) +) ENGINE=MyISAM; + ALTER TABLE vicidial_email_list MODIFY message text character set utf8; @@ -4599,9 +4617,11 @@ INSERT INTO vicidial_process_triggers SET trigger_id='LOAD_LEADS',server_ip='10. INSERT INTO vicidial_call_menu SET menu_id='defaultlog',menu_name='logging of all outbound calls from agent phones',menu_prompt='sip-silence',menu_timeout='20',menu_timeout_prompt='NONE',menu_invalid_prompt='NONE',menu_repeat='0',menu_time_check='0',call_time_id='',track_in_vdac='0',custom_dialplan_entry='exten => _X.,1,AGI(agi-NVA_recording.agi,BOTH------Y---Y---Y)\nexten => _X.,n,Goto(default,${EXTEN},1)',tracking_group=''; INSERT INTO vicidial_call_menu SET menu_id='default---agent',menu_name='agent phones restricted to only internal extensions',menu_prompt='sip-silence',menu_timeout='20',menu_timeout_prompt='NONE',menu_invalid_prompt='NONE',menu_repeat='0',menu_time_check='0',call_time_id='',track_in_vdac='0',custom_dialplan_entry='include => vicidial-auto-internal\ninclude => vicidial-auto-phones\n',tracking_group=''; +INSERT INTO vicidial_call_menu (menu_id,menu_name,menu_prompt,menu_timeout,menu_timeout_prompt,menu_invalid_prompt,menu_repeat,menu_time_check,call_time_id,track_in_vdac,custom_dialplan_entry,tracking_group,dtmf_log,dtmf_field,user_group,qualify_sql,alt_dtmf_log,question,answer_signal) values('2FA_say_auth_code','2FA_say_auth_code','sip-silence|hello|your|access-code|is|cm_speak_var.agi,say_digits---access_code---DP',1,'NONE','NONE',1,'0','24hours','1','','CALLMENU','0','NONE','---ALL---','','0',0,'Y'); INSERT INTO vicidial_call_menu_options SET menu_id='defaultlog',option_value='TIMEOUT',option_description='hangup',option_route='HANGUP',option_route_value='vm-goodbye',option_route_value_context=''; INSERT INTO vicidial_call_menu_options SET menu_id='default---agent',option_value='TIMEOUT',option_description='hangup',option_route='HANGUP',option_route_value='vm-goodbye',option_route_value_context=''; +INSERT INTO vicidial_call_menu_options (menu_id,option_value,option_description,option_route,option_route_value,option_route_value_context) values('2FA_say_auth_code','TIMEOUT','','HANGUP','',''); INSERT INTO vicidial_scripts (script_id,script_name,script_comments,active,script_text) values('CALLNOTES','Call Notes and Appointment Setting','','Y',''); @@ -4829,4 +4849,4 @@ INSERT INTO vicidial_settings_containers(container_id,container_notes,container_ UPDATE system_settings set vdc_agent_api_active='1'; -UPDATE system_settings SET db_schema_version='1619',db_schema_update_date=NOW(),reload_timestamp=NOW(); +UPDATE system_settings SET db_schema_version='1620',db_schema_update_date=NOW(),reload_timestamp=NOW(); diff --git a/agc_2-X/trunk/extras/upgrade_2.14.sql b/agc_2-X/trunk/extras/upgrade_2.14.sql index cea042d8..97ba9d93 100644 --- a/agc_2-X/trunk/extras/upgrade_2.14.sql +++ b/agc_2-X/trunk/extras/upgrade_2.14.sql @@ -624,7 +624,7 @@ ALTER TABLE vicidial_inbound_groups ADD park_file_name VARCHAR(100) default ''; UPDATE system_settings SET db_schema_version='1543',db_schema_update_date=NOW() where db_schema_version < 1543; -ALTER TABLE vicidial_lists_fields MODIFY field_type ENUM('TEXT','AREA','SELECT','MULTI','RADIO','CHECKBOX','DATE','TIME','DISPLAY','SCRIPT','HIDDEN','READONLY','HIDEBLOB','SWITCH','SOURCESELECT') default 'TEXT'; +ALTER TABLE vicidial_lists_fields MODIFY field_type ENUM('TEXT','AREA','SELECT','MULTI','RADIO','CHECKBOX','DATE','TIME','DISPLAY','SCRIPT','HIDDEN','READONLY','HIDEBLOB','SWITCH','SOURCESELECT','BUTTON') default 'TEXT'; UPDATE system_settings SET db_schema_version='1544',db_schema_update_date=NOW() where db_schema_version < 1544; @@ -1431,7 +1431,7 @@ index (drop_time) UPDATE system_settings SET db_schema_version='1616',db_schema_update_date=NOW() where db_schema_version < 1616; -ALTER TABLE vicidial_lists_fields MODIFY field_type ENUM('TEXT','AREA','SELECT','MULTI','RADIO','CHECKBOX','DATE','TIME','DISPLAY','SCRIPT','HIDDEN','READONLY','HIDEBLOB','SWITCH','SOURCESELECT') default 'TEXT'; +ALTER TABLE vicidial_lists_fields MODIFY field_type ENUM('TEXT','AREA','SELECT','MULTI','RADIO','CHECKBOX','DATE','TIME','DISPLAY','SCRIPT','HIDDEN','READONLY','HIDEBLOB','SWITCH','SOURCESELECT','BUTTON') default 'TEXT'; UPDATE system_settings SET db_schema_version='1617',db_schema_update_date=NOW() where db_schema_version < 1617; @@ -1531,3 +1531,31 @@ ALTER TABLE system_settings ADD qc_expire_days TINYINT UNSIGNED DEFAULT '3'; INSERT INTO vicidial_settings_containers(container_id,container_notes,container_type,user_group,container_entry) VALUES ('QC_STATUS_TEMPLATE','Sample QC Status Template','QC_TEMPLATE','---ALL---','# These types of containers are simply used for creating a list of \r\n# QC-enabled statuses to apply to campaigns, lists, and ingroups.\r\n# Simply put all the statuses that this template should allow in\r\n# a comma-delimited string, as below:\r\n\r\nSALE,DNC,NI'); UPDATE system_settings SET db_schema_version='1619',db_schema_update_date=NOW() where db_schema_version < 1619; + +ALTER TABLE vicidial_lists_fields MODIFY field_type ENUM('TEXT','AREA','SELECT','MULTI','RADIO','CHECKBOX','DATE','TIME','DISPLAY','SCRIPT','HIDDEN','READONLY','HIDEBLOB','SWITCH','SOURCESELECT','BUTTON') default 'TEXT'; + +ALTER TABLE vicidial_users ADD mobile_number VARCHAR(20) default ''; +ALTER TABLE vicidial_users ADD two_factor_override ENUM('NOT_ACTIVE','ENABLED','DISABLED') default 'NOT_ACTIVE'; + +ALTER TABLE system_settings ADD two_factor_auth_hours SMALLINT(5) default '0'; +ALTER TABLE system_settings ADD two_factor_container VARCHAR(40) default '---DISABLED---'; + +INSERT INTO vicidial_call_menu (menu_id,menu_name,menu_prompt,menu_timeout,menu_timeout_prompt,menu_invalid_prompt,menu_repeat,menu_time_check,call_time_id,track_in_vdac,custom_dialplan_entry,tracking_group,dtmf_log,dtmf_field,user_group,qualify_sql,alt_dtmf_log,question,answer_signal) values('2FA_say_auth_code','2FA_say_auth_code','sip-silence|hello|your|access-code|is|cm_speak_var.agi,say_digits---access_code---DP',1,'NONE','NONE',1,'0','24hours','1','','CALLMENU','0','NONE','---ALL---','','0',0,'Y'); + +INSERT INTO vicidial_call_menu_options (menu_id,option_value,option_description,option_route,option_route_value,option_route_value_context) values('2FA_say_auth_code','TIMEOUT','','HANGUP','',''); + +CREATE TABLE vicidial_two_factor_auth ( +auth_date DATETIME, +auth_exp_date DATETIME, +user VARCHAR(20) default '', +auth_stage ENUM('0','1','2','3','4','5','6') default '0', +auth_code VARCHAR(20) default '', +auth_code_exp_date DATETIME, +auth_method VARCHAR(20) default 'EMAIL', +auth_attempts SMALLINT(5) default '0', +index (user), +index (auth_date), +index (auth_exp_date) +) ENGINE=MyISAM; + +UPDATE system_settings SET db_schema_version='1620',db_schema_update_date=NOW() where db_schema_version < 1620; diff --git a/agc_2-X/trunk/www/agc/functions.php b/agc_2-X/trunk/www/agc/functions.php index 852f55cd..203d0319 100644 --- a/agc_2-X/trunk/www/agc/functions.php +++ b/agc_2-X/trunk/www/agc/functions.php @@ -51,6 +51,7 @@ # 200406-1204 - Fix for gender default field population # 210211-0145 - Added SOURCESELECT field type, added basic Math equations to SCRIPT custom field types # 210211-1916 - Disable SCRIPT custom fields Math functions on older PHP versions +# 210310-1322 - Added BUTTON field type # # $mysql_queries = 26 @@ -442,7 +443,7 @@ function custom_list_fields_values($lead_id,$list_id,$uniqueid,$user,$DB,$call_i } if ( (!preg_match("/\|$A_field_label[$o]\|/i",$vicidial_list_fields)) and (!preg_match("/\|$A_master_field[$o]\|/i",$vicidial_list_fields)) ) { - if ( ($A_field_type[$o]=='DISPLAY') or ($A_field_type[$o]=='SCRIPT') or ($A_field_type[$o]=='SWITCH') ) + if ( ($A_field_type[$o]=='DISPLAY') or ($A_field_type[$o]=='SCRIPT') or ($A_field_type[$o]=='SWITCH') or ($A_field_type[$o]=='BUTTON') ) { $select_SQL .= "8,"; $A_field_select[$o]='----EMPTY----'; @@ -809,6 +810,19 @@ function custom_list_fields_values($lead_id,$list_id,$uniqueid,$user,$DB,$call_i if ($A_field_default[$o]=='NULL') {$A_field_default[$o]='';} $field_HTML .= _QXZ("$A_field_default[$o]")."\n"; } + if ($A_field_type[$o]=='BUTTON') + { + $field_options_array = explode("\n",$A_field_options[$o]); + if (preg_match("/^SubmitRefresh/i",$field_options_array[0])) + { + if ($A_multi_position[$o]=='VERTICAL') + {$field_HTML .= "   ";} + if (strlen($A_field_default[$o]) < 1) {$A_field_default[$o] = _QXZ("Commit Changes and Refresh Form");} + $field_HTML .= " \n"; + if ($A_multi_position[$o]=='VERTICAL') + {$field_HTML .= "
\n";} + } + } if ($A_field_type[$o]=='READONLY') { if ($A_field_default[$o]=='NULL') {$A_field_default[$o]='';} diff --git a/agc_2-X/trunk/www/agc/vdc_form_display.php b/agc_2-X/trunk/www/agc/vdc_form_display.php index 24da32df..41c484bc 100644 --- a/agc_2-X/trunk/www/agc/vdc_form_display.php +++ b/agc_2-X/trunk/www/agc/vdc_form_display.php @@ -47,10 +47,11 @@ # 201117-2056 - Changes for better compatibility with non-latin data input # 210211-0146 - Added SOURCESELECT field type # 210304-1612 - Added READONLY submit_button option +# 210310-1115 - Added BUTTON field type with SubmitRefresh function # -$version = '2.14-37'; -$build = '210304-1612'; +$version = '2.14-38'; +$build = '210310-1115'; $php_script = 'vdc_form_display.php'; require_once("dbconnect_mysqli.php"); @@ -203,6 +204,10 @@ if (isset($_GET["did_custom_five"])) {$did_custom_five=$_GET["did_custom_five" elseif (isset($_POST["did_custom_five"])) {$did_custom_five=$_POST["did_custom_five"];} if (isset($_GET["hide_gender"])) {$hide_gender=$_GET["hide_gender"];} elseif (isset($_POST["hide_gender"])) {$hide_gender=$_POST["hide_gender"];} +if (isset($_GET["button_action"])) {$button_action=$_GET["button_action"];} + elseif (isset($_POST["button_action"])) {$button_action=$_POST["button_action"];} +if (isset($_GET["orig_URL"])) {$orig_URL=$_GET["orig_URL"];} + elseif (isset($_POST["orig_URL"])) {$orig_URL=$_POST["orig_URL"];} if (isset($_GET["DB"])) {$DB=$_GET["DB"];} elseif (isset($_POST["DB"])) {$DB=$_POST["DB"];} @@ -228,6 +233,30 @@ $agents='@agents'; $script_height = ($script_height - 20); if (strlen($bgcolor) < 6) {$bgcolor='FFFFFF';} $startMS = microtime(); +$ip = getenv("REMOTE_ADDR"); +$query_string = getenv("QUERY_STRING"); +$REQUEST_URI = getenv("REQUEST_URI"); +$POST_URI = ''; +foreach($_POST as $key=>$value) + {$POST_URI .= '&'.$key.'='.$value;} +if (strlen($POST_URI)>1) + {$POST_URI = preg_replace("/^&/",'',$POST_URI);} +$REQUEST_URI = preg_replace("/'|\"|\\\\|;/","",$REQUEST_URI); +$POST_URI = preg_replace("/'|\"|\\\\|;/","",$POST_URI); +if ( (strlen($query_string) < 1) and (strlen($POST_URI) > 2) ) + {$query_string = $POST_URI;} +if ( (strlen($query_string) > 0) and (strlen($POST_URI) > 2) ) + {$query_string .= "&GET-AND-POST=Y&".$POST_URI;} +$CL=':'; +$script_name = getenv("SCRIPT_NAME"); +$server_name = getenv("SERVER_NAME"); +$server_port = getenv("SERVER_PORT"); +if (preg_match("/443/i",$server_port)) {$HTTPprotocol = 'https://';} + else {$HTTPprotocol = 'http://';} +if (($server_port == '80') or ($server_port == '443') ) {$server_port='';} +else {$server_port = "$CL$server_port";} +$vdcPAGE = "$HTTPprotocol$server_name$server_port$script_name"; +$vdcURL = $vdcPAGE . '?' . $query_string; $vicidial_list_fields = '|lead_id|entry_date|vendor_lead_code|source_id|list_id|gmt_offset_now|called_since_last_reset|phone_code|phone_number|title|first_name|middle_initial|last_name|address1|address2|address3|city|state|province|postal_code|country_code|gender|date_of_birth|alt_phone|email|security_phrase|comments|called_count|last_local_call_time|rank|owner|'; @@ -280,6 +309,7 @@ $agent_log_id = preg_replace('/[^0-9]/', '', $agent_log_id); $server_ip = preg_replace("/\'|\"|\\\\|;/","",$server_ip); $session_id = preg_replace('/[^0-9]/','',$session_id); $call_id = preg_replace('/[^-_\.0-9a-zA-Z]/','',$call_id); +$button_action = preg_replace('/[^-_0-9a-zA-Z]/','',$button_action); if ($non_latin < 1) { @@ -438,9 +468,9 @@ if ($stage=='SUBMIT') $A_field_value[$o] = $form_field_value; - if ( ($A_field_type[$o]=='DISPLAY') or ($A_field_type[$o]=='SCRIPT') or ($A_field_type[$o]=='SWITCH') or ($A_field_type[$o]=='HIDDEN') or ($A_field_type[$o]=='HIDEBLOB') or ($A_field_type[$o]=='READONLY') ) + if ( ($A_field_type[$o]=='DISPLAY') or ($A_field_type[$o]=='SCRIPT') or ($A_field_type[$o]=='SWITCH') or ($A_field_type[$o]=='HIDDEN') or ($A_field_type[$o]=='HIDEBLOB') or ($A_field_type[$o]=='READONLY') or ($A_field_type[$o]=='BUTTON') ) { - if (($A_field_type[$o]=='DISPLAY') or ($A_field_type[$o]=='SCRIPT') or ($A_field_type[$o]=='SWITCH') or ($A_field_type[$o]=='READONLY')) + if (($A_field_type[$o]=='DISPLAY') or ($A_field_type[$o]=='SCRIPT') or ($A_field_type[$o]=='SWITCH') or ($A_field_type[$o]=='READONLY') or ($A_field_type[$o]=='BUTTON')) { $SUBMIT_output .= "$A_field_name[$o]: $A_field_value[$o]
"; } @@ -562,14 +592,26 @@ if ($stage=='SUBMIT') } else { - echo _QXZ("Custom Form Output:")."\n
\n"; + if ( (strlen($orig_URL)> 10) and ($button_action == 'SubmitRefresh') ) + { + echo "\n"; + echo "\n"; + echo "\n"; + echo ""._QXZ("Committing changes and reloading form")."...\n

\n"; + echo ""._QXZ("click here if form is not reloading")."\n"; + } + else + { + echo _QXZ("Custom Form Output:")."\n
\n"; - echo "$SUBMIT_output"; + echo "$SUBMIT_output"; + } echo "
\n"; echo "\n"; echo "\n"; echo "
\n"; + } } ### END parse submission of the custom fields form ### @@ -589,6 +631,7 @@ if ($SUBMIT_only < 1) echo " \n"; echo " \n"; echo " \n"; @@ -666,6 +718,7 @@ if ($SUBMIT_only < 1) echo "\n"; echo "\n"; echo "\n"; + echo "\n"; echo "\n"; echo "\n"; echo "\n"; @@ -673,6 +726,7 @@ if ($SUBMIT_only < 1) echo "\n"; echo "\n"; echo "\n"; + echo "\n"; echo "\n"; if ($submit_button=='READONLY') { diff --git a/agc_2-X/trunk/www/vicidial/AST_timeonVDADall.php b/agc_2-X/trunk/www/vicidial/AST_timeonVDADall.php index 7dabfbff..d2bd4096 100644 --- a/agc_2-X/trunk/www/vicidial/AST_timeonVDADall.php +++ b/agc_2-X/trunk/www/vicidial/AST_timeonVDADall.php @@ -418,8 +418,16 @@ $auth=0; $reports_auth=0; $admin_auth=0; $auth_message = user_authorization($PHP_AUTH_USER,$PHP_AUTH_PW,'REPORTS',0,0); -if ($auth_message == 'GOOD') - {$auth=1;} +if ( ($auth_message == 'GOOD') or ($auth_message == '2FA') ) + { + $auth=1; + if ($auth_message == '2FA') + { + header ("Content-type: text/html; charset=utf-8"); + echo _QXZ("Your session is expired").". "._QXZ("Click here to log in").".\n"; + exit; + } + } if ($auth > 0) { diff --git a/agc_2-X/trunk/www/vicidial/AST_timeonVDADall_mobile.php b/agc_2-X/trunk/www/vicidial/AST_timeonVDADall_mobile.php index c65024d2..f3f460e7 100644 --- a/agc_2-X/trunk/www/vicidial/AST_timeonVDADall_mobile.php +++ b/agc_2-X/trunk/www/vicidial/AST_timeonVDADall_mobile.php @@ -263,8 +263,16 @@ $auth=0; $reports_auth=0; $admin_auth=0; $auth_message = user_authorization($PHP_AUTH_USER,$PHP_AUTH_PW,'REPORTS',0,0); -if ($auth_message == 'GOOD') - {$auth=1;} +if ( ($auth_message == 'GOOD') or ($auth_message == '2FA') ) + { + $auth=1; + if ($auth_message == '2FA') + { + header ("Content-type: text/html; charset=utf-8"); + echo _QXZ("Your session is expired").". "._QXZ("Click here to log in").".\n"; + exit; + } + } if ($auth > 0) { diff --git a/agc_2-X/trunk/www/vicidial/KHOMP_admin.php b/agc_2-X/trunk/www/vicidial/KHOMP_admin.php index b5af28b2..df92f4df 100644 --- a/agc_2-X/trunk/www/vicidial/KHOMP_admin.php +++ b/agc_2-X/trunk/www/vicidial/KHOMP_admin.php @@ -107,8 +107,16 @@ $ip = getenv("REMOTE_ADDR"); $browser = getenv("HTTP_USER_AGENT"); $auth_message = user_authorization($PHP_AUTH_USER,$PHP_AUTH_PW,'QC',1,0); -if ($auth_message == 'GOOD') - {$user_auth=1;} +if ( ($auth_message == 'GOOD') or ($auth_message == '2FA') ) + { + $user_auth=1; + if ($auth_message == '2FA') + { + header ("Content-type: text/html; charset=utf-8"); + echo _QXZ("Your session is expired").". "._QXZ("Click here to log in").".\n"; + exit; + } + } if ($user_auth > 0) { diff --git a/agc_2-X/trunk/www/vicidial/admin.php b/agc_2-X/trunk/www/vicidial/admin.php index e5a89b38..8418b1ad 100644 --- a/agc_2-X/trunk/www/vicidial/admin.php +++ b/agc_2-X/trunk/www/vicidial/admin.php @@ -5,6 +5,7 @@ # $startMS = microtime(); +$php_script='admin.php'; require("dbconnect_mysqli.php"); require("functions.php"); @@ -2576,6 +2577,17 @@ if (isset($_GET["allow_shared_dial"])) {$allow_shared_dial=$_GET["allow_shared elseif (isset($_POST["allow_shared_dial"])) {$allow_shared_dial=$_POST["allow_shared_dial"];} if (isset($_GET["shared_dial_rank"])) {$shared_dial_rank=$_GET["shared_dial_rank"];} elseif (isset($_POST["shared_dial_rank"])) {$shared_dial_rank=$_POST["shared_dial_rank"];} +if (isset($_GET["mobile_number"])) {$mobile_number=$_GET["mobile_number"];} + elseif (isset($_POST["mobile_number"])) {$mobile_number=$_POST["mobile_number"];} +if (isset($_GET["two_factor_auth_hours"])) {$two_factor_auth_hours=$_GET["two_factor_auth_hours"];} + elseif (isset($_POST["two_factor_auth_hours"])) {$two_factor_auth_hours=$_POST["two_factor_auth_hours"];} +if (isset($_GET["two_factor_container"])) {$two_factor_container=$_GET["two_factor_container"];} + elseif (isset($_POST["two_factor_container"])) {$two_factor_container=$_POST["two_factor_container"];} +if (isset($_GET["two_factor_override"])) {$two_factor_override=$_GET["two_factor_override"];} + elseif (isset($_POST["two_factor_override"])) {$two_factor_override=$_POST["two_factor_override"];} +if (isset($_GET["auth_entry"])) {$auth_entry=$_GET["auth_entry"];} + elseif (isset($_POST["auth_entry"])) {$auth_entry=$_POST["auth_entry"];} + if (isset($script_id)) {$script_id= mb_strtoupper($script_id,'utf-8');} if (isset($lead_filter_id)) {$lead_filter_id = mb_strtoupper($lead_filter_id,'utf-8');} @@ -2589,7 +2601,7 @@ if (strlen($dial_status) > 0) ############################################# ##### START SYSTEM_SETTINGS LOOKUP ##### -$stmt = "SELECT use_non_latin,enable_queuemetrics_logging,enable_vtiger_integration,qc_features_active,outbound_autodial_active,sounds_central_control_active,enable_second_webform,user_territories_active,custom_fields_enabled,admin_web_directory,webphone_url,first_login_trigger,hosted_settings,default_phone_registration_password,default_phone_login_password,default_server_password,test_campaign_calls,active_voicemail_server,voicemail_timezones,default_voicemail_timezone,default_local_gmt,campaign_cid_areacodes_enabled,pllb_grouping_limit,did_ra_extensions_enabled,expanded_list_stats,contacts_enabled,alt_log_server_ip,alt_log_dbname,alt_log_login,alt_log_pass,tables_use_alt_log_db,call_menu_qualify_enabled,admin_list_counts,allow_voicemail_greeting,svn_revision,allow_emails,level_8_disable_add,pass_key,pass_hash_enabled,disable_auto_dial,country_code_list_stats,frozen_server_call_clear,active_modules,allow_chats,enable_languages,language_method,meetme_enter_login_filename,meetme_enter_leave3way_filename,enable_did_entry_list_id,enable_third_webform,default_language,user_hide_realtime_enabled,log_recording_access,alt_ivr_logging,admin_row_click,admin_screen_colors,ofcom_uk_drop_calc,agent_screen_colors,script_remove_js,manual_auto_next,user_new_lead_limit,agent_xfer_park_3way,agent_soundboards,web_loader_phone_length,agent_script,enable_auto_reports,enable_pause_code_limits,enable_drop_lists,allow_ip_lists,system_ip_blacklist,hide_inactive_lists,allow_manage_active_lists,expired_lists_inactive,did_system_filter,enable_gdpr_download_deletion,mute_recordings,user_admin_redirect,list_status_modification_confirmation,sip_event_logging,call_quota_lead_ranking,enable_second_script,enable_first_webform,recording_buttons,opensips_cid_name,require_password_length,user_account_emails,outbound_cid_any,entries_per_page,browser_call_alerts,inbound_answer_config,enable_international_dncs,daily_call_count_limit,allow_shared_dial,agent_search_method,admin_home_url,qc_claim_limit,qc_expire_days FROM system_settings;"; +$stmt = "SELECT use_non_latin,enable_queuemetrics_logging,enable_vtiger_integration,qc_features_active,outbound_autodial_active,sounds_central_control_active,enable_second_webform,user_territories_active,custom_fields_enabled,admin_web_directory,webphone_url,first_login_trigger,hosted_settings,default_phone_registration_password,default_phone_login_password,default_server_password,test_campaign_calls,active_voicemail_server,voicemail_timezones,default_voicemail_timezone,default_local_gmt,campaign_cid_areacodes_enabled,pllb_grouping_limit,did_ra_extensions_enabled,expanded_list_stats,contacts_enabled,alt_log_server_ip,alt_log_dbname,alt_log_login,alt_log_pass,tables_use_alt_log_db,call_menu_qualify_enabled,admin_list_counts,allow_voicemail_greeting,svn_revision,allow_emails,level_8_disable_add,pass_key,pass_hash_enabled,disable_auto_dial,country_code_list_stats,frozen_server_call_clear,active_modules,allow_chats,enable_languages,language_method,meetme_enter_login_filename,meetme_enter_leave3way_filename,enable_did_entry_list_id,enable_third_webform,default_language,user_hide_realtime_enabled,log_recording_access,alt_ivr_logging,admin_row_click,admin_screen_colors,ofcom_uk_drop_calc,agent_screen_colors,script_remove_js,manual_auto_next,user_new_lead_limit,agent_xfer_park_3way,agent_soundboards,web_loader_phone_length,agent_script,enable_auto_reports,enable_pause_code_limits,enable_drop_lists,allow_ip_lists,system_ip_blacklist,hide_inactive_lists,allow_manage_active_lists,expired_lists_inactive,did_system_filter,enable_gdpr_download_deletion,mute_recordings,user_admin_redirect,list_status_modification_confirmation,sip_event_logging,call_quota_lead_ranking,enable_second_script,enable_first_webform,recording_buttons,opensips_cid_name,require_password_length,user_account_emails,outbound_cid_any,entries_per_page,browser_call_alerts,inbound_answer_config,enable_international_dncs,daily_call_count_limit,allow_shared_dial,agent_search_method,admin_home_url,qc_claim_limit,qc_expire_days,two_factor_auth_hours,two_factor_container FROM system_settings;"; $rslt=mysql_to_mysqli($stmt, $link); if ($DB) {echo "$stmt\n";} $qm_conf_ct = mysqli_num_rows($rslt); @@ -2693,6 +2705,8 @@ if ($qm_conf_ct > 0) $SSadmin_home_url = $row[94]; $SSqc_claim_limit = $row[95]; $SSqc_expire_days = $row[96]; + $SStwo_factor_auth_hours = $row[97]; + $SStwo_factor_container = $row[98]; } ##### END SETTINGS LOOKUP ##### ########################################### @@ -3051,6 +3065,7 @@ $allow_shared_dial = preg_replace('/[^0-9]/','',$allow_shared_dial); $shared_dial_rank = preg_replace('/[^0-9]/','',$shared_dial_rank); $qc_claim_limit = preg_replace('/[^0-9]/','',$qc_claim_limit); $qc_expire_days = preg_replace('/[^0-9]/','',$qc_expire_days); +$auth_entry = preg_replace('/[^0-9]/','',$auth_entry); $user_new_lead_limit = preg_replace('/[^-0-9]/','',$user_new_lead_limit); $drop_call_seconds = preg_replace('/[^-0-9]/','',$drop_call_seconds); @@ -3065,6 +3080,7 @@ $daily_reset_limit = preg_replace('/[^-0-9]/','',$daily_reset_limit); $auto_active_list_rank = preg_replace('/[^-0-9]/','',$auto_active_list_rank); $max_inbound_filter_min_sec = preg_replace('/[^-0-9]/','',$max_inbound_filter_min_sec); $no_agent_delay = preg_replace('/[^-0-9]/','',$no_agent_delay); +$two_factor_auth_hours = preg_replace('/[^-0-9]/','',$two_factor_auth_hours); ### DIGITS and COLONS $shift_length = preg_replace('/[^\:0-9]/','',$shift_length); @@ -3223,6 +3239,7 @@ $auto_hopper_multi = preg_replace('/[^\.0-9]/','',$auto_hopper_multi); # Settings alphanumeric, dash, underscore $daily_limit_manual = preg_replace('/[^-_0-9a-zA-Z]/','',$daily_limit_manual); $transfer_button_launch = preg_replace('/[^-_0-9a-zA-Z]/','',$transfer_button_launch); +$two_factor_override = preg_replace('/[^-_0-9a-zA-Z]/','',$two_factor_override); if ($non_latin < 1) { @@ -3635,6 +3652,7 @@ if ($non_latin < 1) $inbound_drop_voicemail = preg_replace('/[^-_0-9a-zA-Z]/','',$inbound_drop_voicemail); $inbound_after_hours_voicemail = preg_replace('/[^-_0-9a-zA-Z]/','',$inbound_after_hours_voicemail); $pause_max_exceptions = preg_replace('/[^-_0-9a-zA-Z]/','',$pause_max_exceptions); + $two_factor_container = preg_replace('/[^-_0-9a-zA-Z]/','',$two_factor_container); ### ALPHA-NUMERIC and underscore $qc_statuses_id = preg_replace('/[^_0-9a-zA-Z]/','',$qc_statuses_id); @@ -3740,6 +3758,7 @@ if ($non_latin < 1) $did_pattern = preg_replace('/[^:\+\*\#\.\_0-9a-zA-Z]/','',$did_pattern); $web_loader_phone_strip = preg_replace('/[^:\+\*\#\.\_0-9a-zA-Z]/','',$web_loader_phone_strip); $manual_dial_phone_strip = preg_replace('/[^:\+\*\#\.\_0-9a-zA-Z]/','',$manual_dial_phone_strip); + $mobile_number = preg_replace('/[^:\+\*\#\.\_0-9a-zA-Z]/','',$mobile_number); ### ALPHA-NUMERIC and spaces dots, commas, dashes, underscores $adaptive_dl_diff_target = preg_replace('/[^- \.\,\_0-9a-zA-Z]/','',$adaptive_dl_diff_target); @@ -4320,6 +4339,7 @@ else $inbound_drop_voicemail = preg_replace('/[^-_0-9\p{L}]/u','',$inbound_drop_voicemail); $inbound_after_hours_voicemail = preg_replace('/[^-_0-9\p{L}]/u','',$inbound_after_hours_voicemail); $pause_max_exceptions = preg_replace('/[^-_0-9\p{L}]/u','',$pause_max_exceptions); + $two_factor_container = preg_replace('/[^-_0-9\p{L}]/u','',$two_factor_container); ### ALPHA-NUMERIC and underscore and dash and slash and dot $menu_timeout_prompt = preg_replace('/[^-\/\|\._0-9\p{L}]/u','',$menu_timeout_prompt); @@ -4422,6 +4442,7 @@ else $did_pattern = preg_replace('/[^:\+\*\#\.\_0-9\p{L}]/u','',$did_pattern); $web_loader_phone_strip = preg_replace('/[^:\+\*\#\.\_0-9\p{L}]/u','',$web_loader_phone_strip); $manual_dial_phone_strip = preg_replace('/[^:\+\*\#\.\_0-9\p{L}]/u','',$manual_dial_phone_strip); + $mobile_number = preg_replace('/[^:\+\*\#\.\_0-9\p{L}]/u','',$mobile_number); ### ALPHA-NUMERIC and spaces dots, commas, dashes, underscores $adaptive_dl_diff_target = preg_replace('/[^- \.\,\_0-9\p{L}]/u','',$adaptive_dl_diff_target); @@ -5506,12 +5527,13 @@ if ($SSscript_remove_js > 0) # 210305-2159 - Added Default Phone Fields, Changed CLEAR LIST to remove custom fields for removed leads # 210306-0840 - Added new QC module with QC scorecards, Quality Control Report, Settings Compare Utility # 210309-2207 - Added Inbound main panel sub-links, fixed System Settings modify SQL +# 210312-1239 - Added Two-Factor Authentication system, Added mobile_number to User Modify screen # # make sure you have added a user to the vicidial_users MySQL table with at least user_level 9 to access this page the first time -$admin_version = '2.14-794a'; -$build = '210309-2207'; +$admin_version = '2.14-795a'; +$build = '210312-1239'; $STARTtime = date("U"); $SQLdate = date("Y-m-d H:i:s"); @@ -5573,6 +5595,11 @@ if ($force_logout) { if( (strlen($PHP_AUTH_USER)>0) or (strlen($PHP_AUTH_PW)>0) ) { + if ($SStwo_factor_auth_hours > 0) + { + $stmt="UPDATE vicidial_two_factor_auth SET auth_stage='2' where user='$PHP_AUTH_USER' and auth_stage='1';"; + $rslt=mysql_to_mysqli($stmt, $link); + } echo "\n"; echo "\n"; echo "\n"; @@ -5782,7 +5809,7 @@ if ( ($qc_auth > 0) and ($auth < 1) ) $qc_only_user=1; } -$stmt="SELECT user_id,user,pass,full_name,user_level,user_group,phone_login,phone_pass,delete_users,delete_user_groups,delete_lists,delete_campaigns,delete_ingroups,delete_remote_agents,load_leads,campaign_detail,ast_admin_access,ast_delete_phones,delete_scripts,modify_leads,hotkeys_active,change_agent_campaign,agent_choose_ingroups,closer_campaigns,scheduled_callbacks,agentonly_callbacks,agentcall_manual,vicidial_recording,vicidial_transfers,delete_filters,alter_agent_interface_options,closer_default_blended,delete_call_times,modify_call_times,modify_users,modify_campaigns,modify_lists,modify_scripts,modify_filters,modify_ingroups,modify_usergroups,modify_remoteagents,modify_servers,view_reports,vicidial_recording_override,alter_custdata_override,qc_enabled,qc_user_level,qc_pass,qc_finish,qc_commit,add_timeclock_log,modify_timeclock_log,delete_timeclock_log,alter_custphone_override,vdc_agent_api_access,modify_inbound_dids,delete_inbound_dids,active,alert_enabled,download_lists,agent_shift_enforcement_override,manager_shift_enforcement_override,shift_override_flag,export_reports,delete_from_dnc,email,user_code,territory,allow_alerts,callcard_admin,force_change_password,modify_shifts,modify_phones,modify_carriers,modify_labels,modify_statuses,modify_voicemail,modify_audiostore,modify_moh,modify_tts,modify_contacts,modify_same_user_level,alter_admin_interface_options,modify_custom_dialplans,modify_languages,selected_language,user_choose_language,modify_colors,api_only_user,modify_auto_reports,modify_ip_lists,export_gdpr_leads from vicidial_users where user='$PHP_AUTH_USER';"; +$stmt="SELECT user_id,user,pass,full_name,user_level,user_group,phone_login,phone_pass,delete_users,delete_user_groups,delete_lists,delete_campaigns,delete_ingroups,delete_remote_agents,load_leads,campaign_detail,ast_admin_access,ast_delete_phones,delete_scripts,modify_leads,hotkeys_active,change_agent_campaign,agent_choose_ingroups,closer_campaigns,scheduled_callbacks,agentonly_callbacks,agentcall_manual,vicidial_recording,vicidial_transfers,delete_filters,alter_agent_interface_options,closer_default_blended,delete_call_times,modify_call_times,modify_users,modify_campaigns,modify_lists,modify_scripts,modify_filters,modify_ingroups,modify_usergroups,modify_remoteagents,modify_servers,view_reports,vicidial_recording_override,alter_custdata_override,qc_enabled,qc_user_level,qc_pass,qc_finish,qc_commit,add_timeclock_log,modify_timeclock_log,delete_timeclock_log,alter_custphone_override,vdc_agent_api_access,modify_inbound_dids,delete_inbound_dids,active,alert_enabled,download_lists,agent_shift_enforcement_override,manager_shift_enforcement_override,shift_override_flag,export_reports,delete_from_dnc,email,user_code,territory,allow_alerts,callcard_admin,force_change_password,modify_shifts,modify_phones,modify_carriers,modify_labels,modify_statuses,modify_voicemail,modify_audiostore,modify_moh,modify_tts,modify_contacts,modify_same_user_level,alter_admin_interface_options,modify_custom_dialplans,modify_languages,selected_language,user_choose_language,modify_colors,api_only_user,modify_auto_reports,modify_ip_lists,export_gdpr_leads,mobile_number,two_factor_override from vicidial_users where user='$PHP_AUTH_USER';"; $rslt=mysql_to_mysqli($stmt, $link); $row=mysqli_fetch_row($rslt); $LOGfull_name =$row[3]; @@ -5819,6 +5846,7 @@ $LOGdelete_dids =$row[57]; $LOGmanager_shift_enforcement_override=$row[61]; $LOGexport_reports =$row[64]; $LOGdelete_from_dnc =$row[65]; +$LOGemail =$row[66]; $LOGcallcard_admin =$row[70]; $LOGforce_change_password =$row[71]; $LOGmodify_shifts =$row[72]; @@ -5842,6 +5870,8 @@ $LOGapi_only_user =$row[89]; $LOGmodify_auto_reports =$row[90]; $LOGmodify_ip_lists =$row[91]; $LOGexport_gdpr_leads =$row[92]; +$LOGmobile_number =$row[93]; +$LOGtwo_factor_override =$row[94]; $stmt="SELECT allowed_campaigns,allowed_reports,admin_viewable_groups,admin_viewable_call_times,qc_allowed_campaigns,qc_allowed_inbound_groups from vicidial_user_groups where user_group='$LOGuser_group';"; $rslt=mysql_to_mysqli($stmt, $link); @@ -5936,6 +5966,28 @@ if ( (!preg_match('/\-ALL/i', $LOGqc_allowed_inbound_groups)) ) $first_login_link=0; +$VALID_2FA=1; + +# check for 2FA being active, and if so, see if there is a non-expired 2FA auth +if ( ($SStwo_factor_auth_hours > 0) and ($LOGtwo_factor_override != 'DISABLED') ) + { + $stmt="SELECT count(*) from vicidial_two_factor_auth where user='$PHP_AUTH_USER' and auth_stage='1' and auth_exp_date > NOW();"; + $rslt=mysql_to_mysqli($stmt, $link); + if ($DB) {echo "$stmt\n";} + $auth_check_to_print = mysqli_num_rows($rslt); + if ($auth_check_to_print < 1) + {$VALID_2FA=0;} + else + { + $row=mysqli_fetch_row($rslt); + $VALID_2FA = $row[0]; + } + } +if ($VALID_2FA < 1) + { + $ADD=99999701; + $reports_only_user=1; + } if ($LOGforce_change_password=='Y') { @@ -5944,7 +5996,6 @@ if ($LOGforce_change_password=='Y') } if ($SSfirst_login_trigger=='Y') { - if ($ADD==999996) {$reports_only_user=1;} else @@ -6517,6 +6568,7 @@ if ($ADD==99999) {$hh='users'; echo _QXZ("HELP");} if ($ADD==999999) {$hh='reports'; echo _QXZ("REPORTS");} if ($ADD==999998) {$hh='admin'; echo _QXZ("ADMIN");} if ($ADD==999997) {$hh='reports'; echo _QXZ("CHANGE PASSWORD");} +if ($ADD==99999701) {$hh='reports'; echo _QXZ("TWO-FACTOR-AUTHENTICATION");} if ($ADD==999996) {$hh='reports'; echo _QXZ("INITIAL INSTALL WELCOME");} if ($ADD==999995) {$hh='reports'; echo _QXZ("COPYRIGHT TRADEMARK LICENSE");} if ($ADD==999994) {$hh='reports'; echo _QXZ("ADMIN UTILITIES");} @@ -10587,6 +10639,7 @@ if ($ADD==192111111111) + $NWB#settings_containers-container_type$NWE\n"; echo ""._QXZ("Admin User Group").": $NWB#users-force_change_password$NWE\n"; - echo ""._QXZ("Last Login Info").": $last_login_date - $failed_login_count - $last_ip$NWB#users-last_login_date$NWE\n"; + echo ""._QXZ("Last Login Info").": $last_login_date - $failed_login_count - $last_ip $last_auth$NWB#users-last_login_date$NWE\n"; echo ""._QXZ("Full Name").": $NWB#users-full_name$NWE\n"; echo ""._QXZ("User Level").": $NWB#users-active$NWE\n"; echo ""._QXZ("Voicemail ID").": "._QXZ("voicemail chooser")."$NWB#users-voicemail_id$NWE\n"; - echo ""._QXZ("Email").": $NWB#users-optional$NWE\n"; + echo ""._QXZ("Email").": $NWB#users-email$NWE\n"; + echo ""._QXZ("Mobile Number").": $NWB#users-mobile_number$NWE\n"; echo ""._QXZ("User Code").": $NWB#users-optional$NWE\n"; echo ""._QXZ("Main Territory").": $NWB#users-optional$NWE\n"; echo ""._QXZ("User Nickname").": $NWB#users-user_nickname$NWE\n"; @@ -24228,6 +24298,8 @@ if ($ADD==3) echo ""._QXZ("SECURITY OPTIONS, Only enable if needed").":\n"; echo ""._QXZ("Modify IP Lists").": $NWB#users-modify_ip_lists$NWE\n"; echo ""._QXZ("Ignore IP List").": $NWB#users-ignore_ip_lists$NWE\n"; + # + echo ""._QXZ("Two Factor Auth Override").": $NWB#users-two_factor_override$NWE\n"; } else { @@ -38947,6 +39019,7 @@ if ($ADD==392111111111) + $NWB#settings_containers-container_type$NWE\n"; @@ -39960,7 +40033,7 @@ if ($ADD==311111111111111) $ALLagent_count = $rowx[2]; } - $stmt="SELECT version,install_date,use_non_latin,webroot_writable,enable_queuemetrics_logging,queuemetrics_server_ip,queuemetrics_dbname,queuemetrics_login,queuemetrics_pass,queuemetrics_url,queuemetrics_log_id,queuemetrics_eq_prepend,vicidial_agent_disable,allow_sipsak_messages,admin_home_url,enable_agc_xfer_log,db_schema_version,auto_user_add_value,timeclock_end_of_day,timeclock_last_reset_date,vdc_header_date_format,vdc_customer_date_format,vdc_header_phone_format,vdc_agent_api_active,qc_last_pull_time,enable_vtiger_integration,vtiger_server_ip,vtiger_dbname,vtiger_login,vtiger_pass,vtiger_url,qc_features_active,outbound_autodial_active,outbound_calls_per_second,enable_tts_integration,agentonly_callback_campaign_lock,sounds_central_control_active,sounds_web_server,sounds_web_directory,active_voicemail_server,auto_dial_limit,user_territories_active,allow_custom_dialplan,db_schema_update_date,enable_second_webform,default_webphone,default_external_server_ip,webphone_url,enable_agc_dispo_log,custom_dialplan_entry,queuemetrics_loginout,callcard_enabled,queuemetrics_callstatus,default_codecs,admin_web_directory,label_title,label_first_name,label_middle_initial,label_last_name,label_address1,label_address2,label_address3,label_city,label_state,label_province,label_postal_code,label_vendor_lead_code,label_gender,label_phone_number,label_phone_code,label_alt_phone,label_security_phrase,label_email,label_comments,custom_fields_enabled,slave_db_server,reports_use_slave_db,webphone_systemkey,first_login_trigger,default_phone_registration_password,default_phone_login_password,default_server_password,admin_modify_refresh,nocache_admin,generate_cross_server_exten,queuemetrics_addmember_enabled,queuemetrics_dispo_pause,label_hide_field_logs,queuemetrics_pe_phone_append,test_campaign_calls,agents_calls_reset,default_voicemail_timezone,default_local_gmt,noanswer_log,alt_log_server_ip,alt_log_dbname,alt_log_login,alt_log_pass,tables_use_alt_log_db,did_agent_log,campaign_cid_areacodes_enabled,pllb_grouping_limit,did_ra_extensions_enabled,expanded_list_stats,contacts_enabled,call_menu_qualify_enabled,admin_list_counts,allow_voicemail_greeting,svn_revision,queuemetrics_socket,queuemetrics_socket_url,enhanced_disconnect_logging,allow_emails,level_8_disable_add,pass_hash_enabled,pass_key,pass_cost,disable_auto_dial,queuemetrics_record_hold,country_code_list_stats,reload_timestamp,queuemetrics_pause_type,frozen_server_call_clear,callback_time_24hour,allow_chats,chat_url,chat_timeout,enable_languages,language_method,meetme_enter_login_filename,meetme_enter_leave3way_filename,enable_did_entry_list_id,enable_third_webform,agent_debug_logging,default_language,agent_whisper_enabled,user_hide_realtime_enabled,usacan_phone_dialcode_fix,cache_carrier_stats_realtime,oldest_logs_date,log_recording_access,report_default_format,alt_ivr_logging,default_phone_code,admin_row_click,admin_screen_colors,ofcom_uk_drop_calc,agent_screen_colors,script_remove_js,manual_auto_next,user_new_lead_limit,agent_xfer_park_3way,rec_prompt_count,agent_soundboards,web_loader_phone_length,agent_script,agent_chat_screen_colors,enable_auto_reports,enable_pause_code_limits,enable_drop_lists,allow_ip_lists,system_ip_blacklist,agent_push_events,agent_push_url,hide_inactive_lists,allow_manage_active_lists,expired_lists_inactive,did_system_filter,anyone_callback_inactive_lists,enable_gdpr_download_deletion,source_id_display,agent_logout_link,manual_dial_validation,mute_recordings,user_admin_redirect,list_status_modification_confirmation,sip_event_logging,call_quota_lead_ranking,enable_second_script,enable_first_webform,recording_buttons,opensips_cid_name,require_password_length,user_account_emails,outbound_cid_any,entries_per_page,browser_call_alerts,queuemetrics_pausereason,inbound_answer_config,enable_international_dncs,web_loader_phone_strip,manual_dial_phone_strip,daily_call_count_limit,allow_shared_dial,agent_search_method,phone_defaults_container,qc_claim_limit,qc_expire_days from system_settings;"; + $stmt="SELECT version,install_date,use_non_latin,webroot_writable,enable_queuemetrics_logging,queuemetrics_server_ip,queuemetrics_dbname,queuemetrics_login,queuemetrics_pass,queuemetrics_url,queuemetrics_log_id,queuemetrics_eq_prepend,vicidial_agent_disable,allow_sipsak_messages,admin_home_url,enable_agc_xfer_log,db_schema_version,auto_user_add_value,timeclock_end_of_day,timeclock_last_reset_date,vdc_header_date_format,vdc_customer_date_format,vdc_header_phone_format,vdc_agent_api_active,qc_last_pull_time,enable_vtiger_integration,vtiger_server_ip,vtiger_dbname,vtiger_login,vtiger_pass,vtiger_url,qc_features_active,outbound_autodial_active,outbound_calls_per_second,enable_tts_integration,agentonly_callback_campaign_lock,sounds_central_control_active,sounds_web_server,sounds_web_directory,active_voicemail_server,auto_dial_limit,user_territories_active,allow_custom_dialplan,db_schema_update_date,enable_second_webform,default_webphone,default_external_server_ip,webphone_url,enable_agc_dispo_log,custom_dialplan_entry,queuemetrics_loginout,callcard_enabled,queuemetrics_callstatus,default_codecs,admin_web_directory,label_title,label_first_name,label_middle_initial,label_last_name,label_address1,label_address2,label_address3,label_city,label_state,label_province,label_postal_code,label_vendor_lead_code,label_gender,label_phone_number,label_phone_code,label_alt_phone,label_security_phrase,label_email,label_comments,custom_fields_enabled,slave_db_server,reports_use_slave_db,webphone_systemkey,first_login_trigger,default_phone_registration_password,default_phone_login_password,default_server_password,admin_modify_refresh,nocache_admin,generate_cross_server_exten,queuemetrics_addmember_enabled,queuemetrics_dispo_pause,label_hide_field_logs,queuemetrics_pe_phone_append,test_campaign_calls,agents_calls_reset,default_voicemail_timezone,default_local_gmt,noanswer_log,alt_log_server_ip,alt_log_dbname,alt_log_login,alt_log_pass,tables_use_alt_log_db,did_agent_log,campaign_cid_areacodes_enabled,pllb_grouping_limit,did_ra_extensions_enabled,expanded_list_stats,contacts_enabled,call_menu_qualify_enabled,admin_list_counts,allow_voicemail_greeting,svn_revision,queuemetrics_socket,queuemetrics_socket_url,enhanced_disconnect_logging,allow_emails,level_8_disable_add,pass_hash_enabled,pass_key,pass_cost,disable_auto_dial,queuemetrics_record_hold,country_code_list_stats,reload_timestamp,queuemetrics_pause_type,frozen_server_call_clear,callback_time_24hour,allow_chats,chat_url,chat_timeout,enable_languages,language_method,meetme_enter_login_filename,meetme_enter_leave3way_filename,enable_did_entry_list_id,enable_third_webform,agent_debug_logging,default_language,agent_whisper_enabled,user_hide_realtime_enabled,usacan_phone_dialcode_fix,cache_carrier_stats_realtime,oldest_logs_date,log_recording_access,report_default_format,alt_ivr_logging,default_phone_code,admin_row_click,admin_screen_colors,ofcom_uk_drop_calc,agent_screen_colors,script_remove_js,manual_auto_next,user_new_lead_limit,agent_xfer_park_3way,rec_prompt_count,agent_soundboards,web_loader_phone_length,agent_script,agent_chat_screen_colors,enable_auto_reports,enable_pause_code_limits,enable_drop_lists,allow_ip_lists,system_ip_blacklist,agent_push_events,agent_push_url,hide_inactive_lists,allow_manage_active_lists,expired_lists_inactive,did_system_filter,anyone_callback_inactive_lists,enable_gdpr_download_deletion,source_id_display,agent_logout_link,manual_dial_validation,mute_recordings,user_admin_redirect,list_status_modification_confirmation,sip_event_logging,call_quota_lead_ranking,enable_second_script,enable_first_webform,recording_buttons,opensips_cid_name,require_password_length,user_account_emails,outbound_cid_any,entries_per_page,browser_call_alerts,queuemetrics_pausereason,inbound_answer_config,enable_international_dncs,web_loader_phone_strip,manual_dial_phone_strip,daily_call_count_limit,allow_shared_dial,agent_search_method,phone_defaults_container,qc_claim_limit,qc_expire_days,two_factor_auth_hours,two_factor_container from system_settings;"; $rslt=mysql_to_mysqli($stmt, $link); $row=mysqli_fetch_row($rslt); $version = $row[0]; @@ -40161,6 +40234,8 @@ if ($ADD==311111111111111) $phone_defaults_container = $row[195]; $qc_claim_limit = $row[196]; $qc_expire_days = $row[197]; + $two_factor_auth_hours = $row[198]; + $two_factor_container = $row[199]; if ($pass_hash_enabled > 0) {$pass_hash_enabled = 'ENABLED';} else {$pass_hash_enabled = 'DISABLED';} @@ -40575,12 +40650,26 @@ if ($ADD==311111111111111) echo ""._QXZ("Allow Mute Recordings").": $NWB#settings-mute_recordings$NWE\n"; - echo ""._QXZ("Enable Automated Reports").": $NWB#settings-enable_auto_reports$NWE\n"; - echo ""._QXZ("First Login Trigger").": "._QXZ("$first_login_trigger")."   $NWB#settings-first_login_trigger$NWE\n"; echo ""._QXZ("User Password Minimum Length").": $NWB#settings-require_password_length$NWE\n"; + echo "\"Two-Factor-Authentication\" "._QXZ("Two-Factor Auth Hours").": $NWB#settings-two_factor_auth_hours$NWE\n"; + + $two_factor_container_stmt="SELECT container_id from vicidial_settings_containers where container_type='2FA_SETTINGS' order by container_id asc"; + $two_factor_container_rslt=mysql_to_mysqli($two_factor_container_stmt, $link); + $two_factor_container_list="\n"; + while ($pcr_row=mysqli_fetch_row($two_factor_container_rslt)) + { + $two_factor_container_list.="\n"; + } + echo "\"Two-Factor-Authentication\" "; + if ( (strlen($two_factor_container) > 0) and ($two_factor_container != '---DISABLED---') ) + {echo ""._QXZ("Two-Factor Auth Config Container")."";} + else + {echo _QXZ("Two-Factor Auth Config Container");} + echo ": $NWB#settings-two_factor_container$NWE\n"; + echo ""._QXZ("User Login Link Emails Allowed").": $NWB#settings-user_account_emails$NWE\n"; $phone_container_stmt="select container_id from vicidial_settings_containers where container_type='PHONE_DEFAULTS' order by container_id asc"; @@ -40590,18 +40679,20 @@ if ($ADD==311111111111111) { $phone_defaults_container_list.="\n"; } - echo ""; + echo ""; if ( (strlen($phone_defaults_container) > 0) and ($phone_defaults_container != '---DISABLED---') ) {echo ""._QXZ("Default Phone Settings Container")."";} else {echo _QXZ("Default Phone Settings Container");} echo ": $NWB#settings-phone_defaults_container$NWE\n"; - echo ""._QXZ("Default Phone Registration Password").": $NWB#settings-default_phone_registration_password$NWE     "._QXZ("Strength").":   "._QXZ("Length").": 0\n"; + echo ""._QXZ("Default Phone Registration Password").": $NWB#settings-default_phone_registration_password$NWE     "._QXZ("Strength").":   "._QXZ("Length").": 0\n"; - echo ""._QXZ("Default Phone Login Password").": $NWB#settings-default_phone_login_password$NWE     "._QXZ("Strength").":   "._QXZ("Length").": 0\n"; + echo ""._QXZ("Default Phone Login Password").": $NWB#settings-default_phone_login_password$NWE     "._QXZ("Strength").":   "._QXZ("Length").": 0\n"; - echo ""._QXZ("Default Server Password").": $NWB#settings-default_server_password$NWE     "._QXZ("Strength").":   "._QXZ("Length").": 0\n"; + echo ""._QXZ("Default Server Password").": $NWB#settings-default_server_password$NWE     "._QXZ("Strength").":   "._QXZ("Length").": 0\n"; + + echo ""._QXZ("Enable Automated Reports").": $NWB#settings-enable_auto_reports$NWE\n"; echo ""._QXZ("Report Default Format").": $NWB#settings-report_default_format$NWE\n"; @@ -45733,6 +45824,500 @@ if ($ADD==999997) ##### END user force change password page ##### +###################### +# ADD=99999701 - User 2FA(Two-Factor-Authentication) Page +###################### +if ($ADD==99999701) + { + $subhead_font = "style=\"font-family:HELVETICA;font-size:14;color:BLACK;font-weight:bold;\""; + + echo "\"Two-Factor-Authentication\" "._QXZ("Two-Factor-Authentication"),"
\n"; + + if ( ($SStwo_factor_auth_hours < 1) or ($SStwo_factor_container == '') or ($SStwo_factor_container == '---DISABLED---') ) + { + echo _QXZ("Two-Factor-Authentication is disabled on your system. Please contact your system administrator")." $SStwo_factor_auth_hours|$SStwo_factor_container\n"; + exit; + } + + $OBSCUREemail = $LOGemail; + $OBSCUREmobile_number = $LOGmobile_number; + + # first character and last 6 characters + $temp_emailARY = explode('@',$OBSCUREemail); + $field_temp_val = $temp_emailARY[0]; + $OBSCUREemail = substr($field_temp_val,0,2) . str_repeat(".", (strlen($field_temp_val) - 2)) . '@' . $temp_emailARY[1]; + # first 3 digits and last 2 digits + $field_temp_val = $OBSCUREmobile_number; + $OBSCUREmobile_number = substr($field_temp_val,0,3) . str_repeat("x", (strlen($field_temp_val) - 5)) . substr($field_temp_val,-2,2); + + ### BEGIN Gather 2FA settings container details ### + $valid_2FA_config=0; + $active_2FA_methods=0; + $auth_code_expire_minutes='30'; + $auth_code_attempts='10'; + $auth_code_length='6'; + $email_auth=''; + $email_from=''; + $email_subject=''; + $email_message=''; + $phone_auth=''; + $phone_prefix=''; + $phone_server_ip=''; + $phone_cid_number=''; + $phone_message_override=''; + $sms_auth=''; + $sms_cid_number=''; + $sms_url=''; + $stmt = "SELECT container_entry FROM vicidial_settings_containers where container_id='$SStwo_factor_container';"; + $rslt=mysql_to_mysqli($stmt, $link); + $SCinfo_ct = mysqli_num_rows($rslt); + if ($DB) {echo "$SCinfo_ct|$stmt\n";} + if ($SCinfo_ct > 0) + { + $row=mysqli_fetch_row($rslt); + $TFAcontainer_entry = $row[0]; + $TFAcontainer_entry = preg_replace("/\r|\t|\'|\"/",'',$TFAcontainer_entry); + $TFAcontainer_entry = preg_replace("/ => | =>|=> /",'=>',$TFAcontainer_entry); + $two_factor_settings = explode("\n",$TFAcontainer_entry); + $two_factor_settings_ct = count($two_factor_settings); + $tfal=0; + while ($two_factor_settings_ct >= $tfal) + { + if (preg_match("/^auth_code_expire_minutes=>/",$two_factor_settings[$tfal])) + { + $two_factor_settings[$tfal] = preg_replace("/auth_code_expire_minutes=>/",'',$two_factor_settings[$tfal]); + $auth_code_expire_minutes = $two_factor_settings[$tfal]; + } + if (preg_match("/^auth_code_attempts=>/",$two_factor_settings[$tfal])) + { + $two_factor_settings[$tfal] = preg_replace("/auth_code_attempts=>/",'',$two_factor_settings[$tfal]); + $auth_code_attempts = $two_factor_settings[$tfal]; + } + if (preg_match("/^auth_code_length=>/",$two_factor_settings[$tfal])) + { + $two_factor_settings[$tfal] = preg_replace("/auth_code_length=>/",'',$two_factor_settings[$tfal]); + $auth_code_length = $two_factor_settings[$tfal]; + } + if (preg_match("/^email_auth=>/",$two_factor_settings[$tfal])) + { + $two_factor_settings[$tfal] = preg_replace("/email_auth=>/",'',$two_factor_settings[$tfal]); + $email_auth = $two_factor_settings[$tfal]; + $active_2FA_methods++; + } + if (preg_match("/^email_from=>/",$two_factor_settings[$tfal])) + { + $two_factor_settings[$tfal] = preg_replace("/email_from=>/",'',$two_factor_settings[$tfal]); + $email_from = $two_factor_settings[$tfal]; + $valid_2FA_config++; + } + if (preg_match("/^email_subject=>/",$two_factor_settings[$tfal])) + { + $two_factor_settings[$tfal] = preg_replace("/email_subject=>/",'',$two_factor_settings[$tfal]); + $email_subject = $two_factor_settings[$tfal]; + } + if (preg_match("/^email_message=>/",$two_factor_settings[$tfal])) + { + $two_factor_settings[$tfal] = preg_replace("/email_message=>/",'',$two_factor_settings[$tfal]); + $email_message = $two_factor_settings[$tfal]; + } + if (preg_match("/^phone_auth=>/",$two_factor_settings[$tfal])) + { + $two_factor_settings[$tfal] = preg_replace("/phone_auth=>/",'',$two_factor_settings[$tfal]); + $phone_auth = $two_factor_settings[$tfal]; + $active_2FA_methods++; + } + if (preg_match("/^phone_prefix=>/",$two_factor_settings[$tfal])) + { + $two_factor_settings[$tfal] = preg_replace("/phone_prefix=>/",'',$two_factor_settings[$tfal]); + $phone_prefix = $two_factor_settings[$tfal]; + } + if (preg_match("/^phone_server_ip=>/",$two_factor_settings[$tfal])) + { + $two_factor_settings[$tfal] = preg_replace("/phone_server_ip=>/",'',$two_factor_settings[$tfal]); + $phone_server_ip = $two_factor_settings[$tfal]; + $valid_2FA_config++; + } + if (preg_match("/^phone_cid_number=>/",$two_factor_settings[$tfal])) + { + $two_factor_settings[$tfal] = preg_replace("/phone_cid_number=>/",'',$two_factor_settings[$tfal]); + $phone_cid_number = $two_factor_settings[$tfal]; + } + if (preg_match("/^phone_message_override=>/",$two_factor_settings[$tfal])) + { + $two_factor_settings[$tfal] = preg_replace("/phone_message_override=>/",'',$two_factor_settings[$tfal]); + $phone_message_override = $two_factor_settings[$tfal]; + } + if (preg_match("/^sms_auth=>/",$two_factor_settings[$tfal])) + { + $two_factor_settings[$tfal] = preg_replace("/sms_auth=>/",'',$two_factor_settings[$tfal]); + $sms_auth = $two_factor_settings[$tfal]; + $active_2FA_methods++; + } + if (preg_match("/^sms_cid_number=>/",$two_factor_settings[$tfal])) + { + $two_factor_settings[$tfal] = preg_replace("/sms_cid_number=>/",'',$two_factor_settings[$tfal]); + $sms_cid_number = $two_factor_settings[$tfal]; + } + if (preg_match("/^sms_url=>/",$two_factor_settings[$tfal])) + { + $two_factor_settings[$tfal] = preg_replace("/sms_url=>/",'',$two_factor_settings[$tfal]); + $sms_url = $two_factor_settings[$tfal]; + $valid_2FA_config++; + } + + $tfal++; + } + } + ### END Gather 2FA settings container details ### + if ( ($valid_2FA_config < 1) or ($active_2FA_methods < 1) ) + { + echo "
"._QXZ("Two-Factor-Authentication is not properly configured on your system. Please contact your system administrator")."

$valid_2FA_config|$SStwo_factor_auth_hours|$SStwo_factor_container

\n"; + exit; + } + if ( (strlen($LOGemail) < 4) and (strlen($LOGmobile_number) < 2) ) + { + echo _QXZ("Your User account is not configured for Two-Factor-Authentication. Please contact your system administrator").".\n"; + exit; + } + + $show_form=1; + if ( ($stage=='SUBMIT') or ($stage==_QXZ("SUBMIT")) ) + { + $auth_fail=0; + echo "
"; + if (strlen($rank) < 2) + { + echo _QXZ("Please go back and enter a valid authorization code")." |1|" . strlen($rank) . "|"; $auth_fail++; + } + else + { + $stmt="SELECT count(*) from vicidial_two_factor_auth where user='$user' and auth_code='$rank' and auth_stage='0' and auth_code_exp_date > NOW() and (auth_attempts < $auth_code_attempts);"; + $rslt=mysql_to_mysqli($stmt, $link); + if ($DB) {echo "$stmt\n";} + $auth_check_to_print = mysqli_num_rows($rslt); + if ($auth_check_to_print < 1) + {echo _QXZ("Please go back and enter a valid authorization code")." |2|$auth_check_to_print"; $auth_fail++;} + else + { + $row=mysqli_fetch_row($rslt); + if ($row[0] < 1) + {echo _QXZ("Please go back and enter a valid authorization code")." |3|$row[0]"; $auth_fail++;} + else + { + $stmt="UPDATE vicidial_two_factor_auth SET auth_stage='1', auth_attempts=(auth_attempts + 1) where user='$user' and auth_stage='0' and auth_code='$rank';"; + $rslt=mysql_to_mysqli($stmt, $link); + + $stmt = "INSERT INTO vicidial_agent_function_log set agent_log_id='0',user='$user',function='2FA_good',event_time=NOW(),campaign_id='-ADMIN-',user_group='$LOGuser_group',lead_id='0',uniqueid='SUCCESS',caller_code='$ip',stage='',comments='';"; + if ($DB) {echo "|$stmt|\n";} + $rslt=mysql_to_mysqli($stmt, $link); + + echo _QXZ("Authorization code accepted, your login is complete, you may now continue")."\n"; + } + } + } + if ($auth_fail > 0) + { + $stmt="UPDATE vicidial_two_factor_auth SET auth_attempts=(auth_attempts + 1) where user='$user' and auth_stage='0';"; + $rslt=mysql_to_mysqli($stmt, $link); + + $auth_failed_attempts=1; + $stmt="SELECT auth_attempts from vicidial_two_factor_auth where user='$user' and auth_stage='0' order by auth_code_exp_date desc limit 1;"; + $rslt=mysql_to_mysqli($stmt, $link); + if ($DB) {echo "$stmt\n";} + $auth_attempt_to_print = mysqli_num_rows($rslt); + if ($auth_attempt_to_print > 0) + { + $row=mysqli_fetch_row($rslt); + $auth_failed_attempts = $row[0]; + } + if ($auth_failed_attempts >= $auth_code_attempts) + { + $stmt="UPDATE vicidial_users set failed_login_count='$auth_failed_attempts',last_ip='$ip' where user='$user';"; + $rslt=mysql_to_mysqli($stmt, $link); + } + } + echo "
\n"; + exit; + } + + ##### BEGIN send out AUTH CODE and show auth-code entry page ##### + if ($auth_entry > 0) + { + $ACbegin = '1'; + $ACend = '9'; + $i=1; + while($i < $auth_code_length) + { + $ACbegin .= '0'; + $ACend .= '9'; + $i++; + } + $NEWauth_code = rand($ACbegin, $ACend); + $auth_exp_date = date("Y-m-d H:i:s", mktime(date("H")+$SStwo_factor_auth_hours,date("i"),date("s"),date("m"),date("d"),date("Y"))); + $auth_code_exp_date = date("Y-m-d H:i:s", mktime(date("H"),date("i")+$auth_code_expire_minutes,date("s"),date("m"),date("d"),date("Y"))); + + ### insert auth_code into vicidial_two_factor_auth table + $stmt="INSERT INTO vicidial_two_factor_auth SET auth_date=NOW(),auth_exp_date='$auth_exp_date',user='$user',auth_stage='0',auth_code='$NEWauth_code',auth_code_exp_date='$auth_code_exp_date',auth_method='$stage',auth_attempts='0';"; + $rslt=mysql_to_mysqli($stmt, $link); + $affected_rows = mysqli_affected_rows($link); + if ($DB) {echo "$affected_rows|$stmt\n";} + + # invalidate all older auth_code entries + if ($affected_rows > 0) + { + $stmt="UPDATE vicidial_two_factor_auth SET auth_stage='6' where user='$user' and auth_stage!='6' and auth_code!='$NEWauth_code';"; + $rslt=mysql_to_mysqli($stmt, $link); + $affected_rows = mysqli_affected_rows($link); + if ($DB) {echo "$affected_rows|$stmt\n";} + } + + ### Send auth code by EMAIL + if ($stage == 'EMAIL') + { + $email_message = preg_replace('/--A--auth_code--B--/i',"$NEWauth_code",$email_message); + + // To send HTML mail, the Content-type header must be set + $headers = 'MIME-Version: 1.0' . "\r\n"; + $headers .= 'Content-type: text/html; charset=iso-8859-1' . "\r\n"; + + // Create email headers + $headers .= 'From: ' . $email_from . "\r\n" . 'Reply-To: ' . $email_from . "\r\n" . 'X-Mailer: PHP/' . phpversion(); + + $body = "" . $email_message . ""; + + $success = mail($LOGemail, $email_subject, $body, $headers ); + if ($success) + { + $stmt = "INSERT INTO vicidial_agent_function_log set agent_log_id='0',user='$user',function='2FA_send',event_time=NOW(),campaign_id='-ADMIN-',user_group='$LOGuser_group',lead_id='0',uniqueid='SUCCESS',caller_code='$ip',stage='$stage',comments='EMAIL: $LOGemail';"; + + echo "
"._QXZ("Your authorization code has been sent by %1s to",0,'',$stage).": $OBSCUREemail
\n"; + } + else + { + $stmt = "INSERT INTO vicidial_agent_function_log set agent_log_id='0',user='$user',function='2FA_send',event_time=NOW(),campaign_id='-ADMIN-',user_group='$LOGuser_group',lead_id='0',uniqueid='ERROR',caller_code='$ip',stage='$stage',comments='EMAIL: $LOGemail';"; + + $error_msg = error_get_last()['message']; + echo "error_msg"; + } + + ### LOG INSERTION Admin Log Table ### + if ($DB) {echo "|$stmt|\n";} + $rslt=mysql_to_mysqli($stmt, $link); + } + + ### Send auth code by PHONE + if ($stage == 'PHONE') + { + $context_2FA = '2FA_say_auth_code'; + if (strlen($phone_message_override) > 0) {$context_2FA = $phone_message_override;} + if (strlen($ext_context) < 1) {$ext_context='default';} + $local_DEF = 'Local/'; + $local_AMP = '@'; + $Local_dial_timeout = '60000'; + $Ndialstring = "$phone_prefix$LOGmobile_number"; + $VMvariable = "Variable: access_code=$NEWauth_code"; + ### insert a NEW record to the vicidial_manager table to be processed + $stmtB = "INSERT INTO vicidial_manager(uniqueid,entry_date,status,response,server_ip,channel,action,callerid,cmd_line_b,cmd_line_c,cmd_line_d,cmd_line_e,cmd_line_f,cmd_line_g,cmd_line_h,cmd_line_i,cmd_line_j,cmd_line_k) values('',NOW(),'NEW','N','$phone_server_ip','','Originate','$VqueryCID','Exten: s','Context: $context_2FA','Channel: $local_DEF$Ndialstring$local_AMP$ext_context','Priority: 1','Callerid: $phone_cid_number','Timeout: $Local_dial_timeout','$VMvariable','','','')"; + $rslt=mysql_to_mysqli($stmtB, $link); + + $stmt = "INSERT INTO vicidial_agent_function_log set agent_log_id='0',user='$user',function='2FA_send',event_time=NOW(),campaign_id='-ADMIN-',user_group='$LOGuser_group',lead_id='0',uniqueid='SUCCESS',caller_code='$ip',stage='$stage',comments='PHONE: $LOGmobile_number';"; + if ($DB) {echo "|$stmt|\n";} + $rslt=mysql_to_mysqli($stmt, $link); + + echo "
"._QXZ("Your authorization code has been sent by %1s to",0,'',$stage).": $OBSCUREmobile_number
\n"; + } + + ### Send auth code by SMS + if ($stage == 'SMS') + { + $sms_url = preg_replace('/--A--auth_code--B--/i',"$NEWauth_code",$sms_url); + $sms_url = preg_replace('/--A--mobile_number--B--/i',"$LOGmobile_number",$sms_url); + + ### insert a new url log entry + $SQL_log = "$sms_url"; + $SQL_log = preg_replace('/;/','',$SQL_log); + $SQL_log = addslashes($SQL_log); + $stmt = "INSERT INTO vicidial_url_log SET uniqueid='2FA',url_date=NOW(),url_type='2FA_SMS',url='$SQL_log',url_response='';"; + # if ($DB) {echo "$stmt\n";} + $rslt=mysql_to_mysqli($stmt, $link); + $affected_rows = mysqli_affected_rows($link); + $url_id = mysqli_insert_id($link); + + $URLstart_sec = date("U"); + + ### grab the call_start_url ### + # if ($DB > 0) {echo "$sms_url
\n";} + $SCUfile = file("$sms_url"); + if ( !($SCUfile) ) + { + $error_array = error_get_last(); + $error_type = $error_array["type"]; + $error_message = $error_array["message"]; + $error_line = $error_array["line"]; + $error_file = $error_array["file"]; + } + + if ($DB > 0) {echo "$SCUfile[0]
\n";} + + ### update url log entry + $URLend_sec = date("U"); + $URLdiff_sec = ($URLend_sec - $URLstart_sec); + if ($SCUfile) + { + $SCUfile_contents = implode("", $SCUfile); + $SCUfile_contents = preg_replace('/;/','',$SCUfile_contents); + $SCUfile_contents = addslashes($SCUfile_contents); + } + else + { + $SCUfile_contents = "PHP ERROR: Type=$error_type - Message=$error_message - Line=$error_line - File=$error_file"; + } + $stmt = "UPDATE vicidial_url_log SET response_sec='$URLdiff_sec',url_response='$SCUfile_contents' where url_log_id='$url_id';"; + if ($DB) {echo "$stmt\n";} + $rslt=mysql_to_mysqli($stmt, $link); + $affected_rows = mysqli_affected_rows($link); + + $stmt = "INSERT INTO vicidial_agent_function_log set agent_log_id='0',user='$user',function='2FA_send',event_time=NOW(),campaign_id='-ADMIN-',user_group='$LOGuser_group',lead_id='0',uniqueid='SUCCESS',caller_code='$ip',stage='$stage',comments='SMS: $LOGmobile_number';"; + if ($DB) {echo "|$stmt|\n";} + $rslt=mysql_to_mysqli($stmt, $link); + + echo "
"._QXZ("Your authorization code has been sent by %1s to",0,'',$stage).": $OBSCUREmobile_number
\n"; + } + + echo "\n"; + + echo "
\n"; + echo ""; + + echo "
\n"; + echo "\n"; + echo "\n"; + echo "\n"; + echo "\n"; + echo "\n"; + echo "\n"; + echo "
\n"; + + echo "\n"; + + echo "\n"; + + + echo "\n"; + echo "
"._QXZ("Please enter the Auth Code that you have received by %1s into the field below, and click the SUBMIT button",0,'',$stage).". "._QXZ("To resend your auth code, click here to go back").".
 
"._QXZ("Authorization Code").":
\n"; + } + ##### END send out AUTH CODE and show auth-code entry page ##### + + ##### BEGIN choose how to send out AUTH CODE page ##### + else + { + if ($show_form > 0) + { + echo "\n"; + + echo "\n"; echo "\n"; @@ -1656,6 +1679,7 @@ if ( ($action == "MODIFY_CUSTOM_FIELDS") and ($list_id > 99) ) echo "\n"; echo "\n"; echo "\n"; + echo "\n"; echo "\n"; echo " $NWB#lists_fields-field_type$NWE \n"; echo "\n"; @@ -2020,7 +2044,7 @@ function add_field_function($DB,$link,$linkCUSTOM,$ip,$user,$table_exists,$field $SQLexecuted=0; - if ( ($field_type=='DISPLAY') or ($field_type=='SCRIPT') or ($field_type=='SWITCH') or (preg_match("/\|$field_label\|/i",$vicidial_list_fields)) or ($field_duplicate=='Y') ) + if ( ($field_type=='DISPLAY') or ($field_type=='SCRIPT') or ($field_type=='SWITCH') or ($field_type=='BUTTON') or (preg_match("/\|$field_label\|/i",$vicidial_list_fields)) or ($field_duplicate=='Y') ) { if ($DB) {echo "Non-DB $field_type field type, $field_label\n";} @@ -2127,7 +2151,7 @@ function add_field_function($DB,$link,$linkCUSTOM,$ip,$user,$table_exists,$field function modify_field_function($DB,$link,$linkCUSTOM,$ip,$user,$table_exists,$field_id,$list_id,$field_label,$field_name,$field_description,$field_rank,$field_help,$field_type,$field_options,$field_size,$field_max,$field_default,$field_required,$field_cost,$multi_position,$name_position,$field_order,$field_encrypt,$field_show_hide,$field_duplicate,$vicidial_list_fields,$field_rerank) { $field_db_exists=0; - if ( ($field_type=='DISPLAY') or ($field_type=='SCRIPT') or ($field_type=='SWITCH') or (preg_match("/\|$field_label\|/i",$vicidial_list_fields)) or ($field_duplicate=='Y') ) + if ( ($field_type=='DISPLAY') or ($field_type=='SCRIPT') or ($field_type=='SWITCH') or ($field_type=='BUTTON') or (preg_match("/\|$field_label\|/i",$vicidial_list_fields)) or ($field_duplicate=='Y') ) {$field_db_exists=1;} else { @@ -2258,7 +2282,7 @@ function modify_field_function($DB,$link,$linkCUSTOM,$ip,$user,$table_exists,$fi $SQLexecuted=0; - if ( ($field_type=='DISPLAY') or ($field_type=='SCRIPT') or ($field_type=='SWITCH') or (preg_match("/\|$field_label\|/i",$vicidial_list_fields)) or ($field_duplicate=='Y') ) + if ( ($field_type=='DISPLAY') or ($field_type=='SCRIPT') or ($field_type=='SWITCH') or ($field_type=='BUTTON') or (preg_match("/\|$field_label\|/i",$vicidial_list_fields)) or ($field_duplicate=='Y') ) { if ($DB) {echo _QXZ("Non-DB")." $field_type "._QXZ("field type").", $field_label\n";} $SQLexecuted++; @@ -2358,7 +2382,7 @@ function delete_field_function($DB,$link,$linkCUSTOM,$ip,$user,$table_exists,$fi { $SQLexecuted=0; - if ( ($field_type=='DISPLAY') or ($field_type=='SCRIPT') or ($field_type=='SWITCH') or (preg_match("/\|$field_label\|/i",$vicidial_list_fields)) or ($field_duplicate=='Y') ) + if ( ($field_type=='DISPLAY') or ($field_type=='SCRIPT') or ($field_type=='SWITCH') or ($field_type=='BUTTON') or (preg_match("/\|$field_label\|/i",$vicidial_list_fields)) or ($field_duplicate=='Y') ) { if ($DB) {echo "Non-DB $field_type field type, $field_label\n";} $SQLexecuted++; diff --git a/agc_2-X/trunk/www/vicidial/admin_mobile.php b/agc_2-X/trunk/www/vicidial/admin_mobile.php index 9f658667..ba84a332 100644 --- a/agc_2-X/trunk/www/vicidial/admin_mobile.php +++ b/agc_2-X/trunk/www/vicidial/admin_mobile.php @@ -361,8 +361,16 @@ $auth=0; $reports_auth=0; $qc_auth=0; $auth_message = user_authorization($PHP_AUTH_USER,$PHP_AUTH_PW,'QC',1,0); -if ($auth_message == 'GOOD') - {$user_auth=1;} +if ( ($auth_message == 'GOOD') or ($auth_message == '2FA') ) + { + $user_auth=1; + if ($auth_message == '2FA') + { + header ("Content-type: text/html; charset=utf-8"); + echo _QXZ("Your session is expired").". "._QXZ("Click here to log in").".\n"; + exit; + } + } if ($user_auth > 0) { diff --git a/agc_2-X/trunk/www/vicidial/admin_modify_lead.php b/agc_2-X/trunk/www/vicidial/admin_modify_lead.php index e8467df3..bf637e7f 100644 --- a/agc_2-X/trunk/www/vicidial/admin_modify_lead.php +++ b/agc_2-X/trunk/www/vicidial/admin_modify_lead.php @@ -410,8 +410,16 @@ if (strlen($phone_number)<6) {$phone_number=$old_phone;} $auth=0; $auth_message = user_authorization($PHP_AUTH_USER,$PHP_AUTH_PW,'',1,0); -if ($auth_message == 'GOOD') - {$auth=1;} +if ( ($auth_message == 'GOOD') or ($auth_message == '2FA') ) + { + $auth=1; + if ($auth_message == '2FA') + { + header ("Content-type: text/html; charset=utf-8"); + echo _QXZ("Your session is expired").". "._QXZ("Click here to log in").".\n"; + exit; + } + } if ($auth < 1) { diff --git a/agc_2-X/trunk/www/vicidial/admin_phones_bulk_insert.php b/agc_2-X/trunk/www/vicidial/admin_phones_bulk_insert.php index 98a87f51..e7b7d8e0 100644 --- a/agc_2-X/trunk/www/vicidial/admin_phones_bulk_insert.php +++ b/agc_2-X/trunk/www/vicidial/admin_phones_bulk_insert.php @@ -142,8 +142,16 @@ if ($sl_ct > 0) $auth=0; $auth_message = user_authorization($PHP_AUTH_USER,$PHP_AUTH_PW,'',1,0); -if ($auth_message == 'GOOD') - {$auth=1;} +if ( ($auth_message == 'GOOD') or ($auth_message == '2FA') ) + { + $auth=1; + if ($auth_message == '2FA') + { + header ("Content-type: text/html; charset=utf-8"); + echo _QXZ("Your session is expired").". "._QXZ("Click here to log in").".\n"; + exit; + } + } if ($auth < 1) { diff --git a/agc_2-X/trunk/www/vicidial/admin_search_lead.php b/agc_2-X/trunk/www/vicidial/admin_search_lead.php index 8a9b49ff..652b28f8 100644 --- a/agc_2-X/trunk/www/vicidial/admin_search_lead.php +++ b/agc_2-X/trunk/www/vicidial/admin_search_lead.php @@ -163,8 +163,16 @@ if ($sl_ct > 0) $auth=0; $auth_message = user_authorization($PHP_AUTH_USER,$PHP_AUTH_PW,'',1,0); -if ($auth_message == 'GOOD') - {$auth=1;} +if ( ($auth_message == 'GOOD') or ($auth_message == '2FA') ) + { + $auth=1; + if ($auth_message == '2FA') + { + header ("Content-type: text/html; charset=utf-8"); + echo _QXZ("Your session is expired").". "._QXZ("Click here to log in").".\n"; + exit; + } + } if ($auth < 1) { diff --git a/agc_2-X/trunk/www/vicidial/admin_soundboard.php b/agc_2-X/trunk/www/vicidial/admin_soundboard.php index 8a7b1a8f..b41aad6f 100644 --- a/agc_2-X/trunk/www/vicidial/admin_soundboard.php +++ b/agc_2-X/trunk/www/vicidial/admin_soundboard.php @@ -176,8 +176,16 @@ if (file_exists('options.php')) $auth=0; $auth_message = user_authorization($PHP_AUTH_USER,$PHP_AUTH_PW,'',1,0); -if ($auth_message == 'GOOD') - {$auth=1;} +if ( ($auth_message == 'GOOD') or ($auth_message == '2FA') ) + { + $auth=1; + if ($auth_message == '2FA') + { + header ("Content-type: text/html; charset=utf-8"); + echo _QXZ("Your session is expired").". "._QXZ("Click here to log in").".\n"; + exit; + } + } if ($auth < 1) { diff --git a/agc_2-X/trunk/www/vicidial/admin_url_multi.php b/agc_2-X/trunk/www/vicidial/admin_url_multi.php index 9d2d125a..16af5dd7 100644 --- a/agc_2-X/trunk/www/vicidial/admin_url_multi.php +++ b/agc_2-X/trunk/www/vicidial/admin_url_multi.php @@ -123,8 +123,16 @@ if ($sl_ct > 0) $auth=0; $auth_message = user_authorization($PHP_AUTH_USER,$PHP_AUTH_PW,'',1,0); -if ($auth_message == 'GOOD') - {$auth=1;} +if ( ($auth_message == 'GOOD') or ($auth_message == '2FA') ) + { + $auth=1; + if ($auth_message == '2FA') + { + header ("Content-type: text/html; charset=utf-8"); + echo _QXZ("Your session is expired").". "._QXZ("Click here to log in").".\n"; + exit; + } + } if ($auth < 1) { diff --git a/agc_2-X/trunk/www/vicidial/admin_user_list_new.php b/agc_2-X/trunk/www/vicidial/admin_user_list_new.php index 84d84681..827cb9c7 100644 --- a/agc_2-X/trunk/www/vicidial/admin_user_list_new.php +++ b/agc_2-X/trunk/www/vicidial/admin_user_list_new.php @@ -103,8 +103,16 @@ if ($sl_ct > 0) $auth=0; $auth_message = user_authorization($PHP_AUTH_USER,$PHP_AUTH_PW,'',1,0); -if ($auth_message == 'GOOD') - {$auth=1;} +if ( ($auth_message == 'GOOD') or ($auth_message == '2FA') ) + { + $auth=1; + if ($auth_message == '2FA') + { + header ("Content-type: text/html; charset=utf-8"); + echo _QXZ("Your session is expired").". "._QXZ("Click here to log in").".\n"; + exit; + } + } if ($auth < 1) { diff --git a/agc_2-X/trunk/www/vicidial/agent_sales_report_mobile.php b/agc_2-X/trunk/www/vicidial/agent_sales_report_mobile.php index 78052564..966b8404 100644 --- a/agc_2-X/trunk/www/vicidial/agent_sales_report_mobile.php +++ b/agc_2-X/trunk/www/vicidial/agent_sales_report_mobile.php @@ -100,8 +100,16 @@ $auth=0; $reports_auth=0; $admin_auth=0; $auth_message = user_authorization($PHP_AUTH_USER,$PHP_AUTH_PW,'REPORTS',1,0); -if ($auth_message == 'GOOD') - {$auth=1;} +if ( ($auth_message == 'GOOD') or ($auth_message == '2FA') ) + { + $auth=1; + if ($auth_message == '2FA') + { + header ("Content-type: text/html; charset=utf-8"); + echo _QXZ("Your session is expired").". "._QXZ("Click here to log in").".\n"; + exit; + } + } if ($auth > 0) { diff --git a/agc_2-X/trunk/www/vicidial/asterisk_debug.php b/agc_2-X/trunk/www/vicidial/asterisk_debug.php index 0e85be16..bea98fdc 100644 --- a/agc_2-X/trunk/www/vicidial/asterisk_debug.php +++ b/agc_2-X/trunk/www/vicidial/asterisk_debug.php @@ -72,8 +72,16 @@ $auth=0; $reports_auth=0; $admin_auth=0; $auth_message = user_authorization($PHP_AUTH_USER,$PHP_AUTH_PW,'',1,0); -if ($auth_message == 'GOOD') - {$auth=1;} +if ( ($auth_message == 'GOOD') or ($auth_message == '2FA') ) + { + $auth=1; + if ($auth_message == '2FA') + { + header ("Content-type: text/html; charset=utf-8"); + echo _QXZ("Your session is expired").". "._QXZ("Click here to log in").".\n"; + exit; + } + } if ($auth > 0) { diff --git a/agc_2-X/trunk/www/vicidial/audio_store.php b/agc_2-X/trunk/www/vicidial/audio_store.php index 13758f6a..939447c0 100644 --- a/agc_2-X/trunk/www/vicidial/audio_store.php +++ b/agc_2-X/trunk/www/vicidial/audio_store.php @@ -197,8 +197,10 @@ if ( (!preg_match("/\|$ip\|/", $server_ips)) and ($formIPvalid < 1) ) $reports_auth=0; $admin_auth=0; $auth_message = user_authorization($PHP_AUTH_USER,$PHP_AUTH_PW,'REPORTS',1,0); - if ($auth_message == 'GOOD') - {$auth=1;} + if ( ($auth_message == 'GOOD') or ($auth_message == '2FA') ) + { + $auth=1; + } if ($auth > 0) { diff --git a/agc_2-X/trunk/www/vicidial/email_agent_login_link.php b/agc_2-X/trunk/www/vicidial/email_agent_login_link.php index 01918869..9f0ccc73 100644 --- a/agc_2-X/trunk/www/vicidial/email_agent_login_link.php +++ b/agc_2-X/trunk/www/vicidial/email_agent_login_link.php @@ -92,8 +92,16 @@ if ($sl_ct > 0) $auth=0; $auth_message = user_authorization($PHP_AUTH_USER,$PHP_AUTH_PW,'',1,0); -if ($auth_message == 'GOOD') - {$auth=1;} +if ( ($auth_message == 'GOOD') or ($auth_message == '2FA') ) + { + $auth=1; + if ($auth_message == '2FA') + { + header ("Content-type: text/html; charset=utf-8"); + echo _QXZ("Your session is expired").". "._QXZ("Click here to log in").".\n"; + exit; + } + } if ($auth > 0) { diff --git a/agc_2-X/trunk/www/vicidial/functions.php b/agc_2-X/trunk/www/vicidial/functions.php index 366470f2..aa035cca 100644 --- a/agc_2-X/trunk/www/vicidial/functions.php +++ b/agc_2-X/trunk/www/vicidial/functions.php @@ -4,7 +4,7 @@ # # functions for administrative scripts and reports # -# Copyright (C) 2020 Matt Florell LICENSE: AGPLv2 +# Copyright (C) 2021 Matt Florell LICENSE: AGPLv2 # # # CHANGES: @@ -35,17 +35,18 @@ # 180508-2215 - Added new help display # 191013-0901 - Fixes for PHP7 # 200401-1920 - Added TimeToText function to convert integers to strings +# 210311-2316 - Added 2FA check in user_authorization function # ##### BEGIN validate user login credentials, check for failed lock out ##### function user_authorization($user,$pass,$user_option,$user_update,$api_call) { - global $link; + global $link,$php_script; # require("dbconnect_mysqli.php"); ############################################# ##### START SYSTEM_SETTINGS LOOKUP ##### - $stmt = "SELECT use_non_latin,webroot_writable,pass_hash_enabled,pass_key,pass_cost,allow_ip_lists,system_ip_blacklist FROM system_settings;"; + $stmt = "SELECT use_non_latin,webroot_writable,pass_hash_enabled,pass_key,pass_cost,allow_ip_lists,system_ip_blacklist,two_factor_auth_hours FROM system_settings;"; $rslt=mysql_to_mysqli($stmt, $link); if ($DB) {echo "$stmt\n";} $qm_conf_ct = mysqli_num_rows($rslt); @@ -59,6 +60,7 @@ function user_authorization($user,$pass,$user_option,$user_update,$api_call) $SSpass_cost = $row[4]; $SSallow_ip_lists = $row[5]; $SSsystem_ip_blacklist = $row[6]; + $SStwo_factor_auth_hours = $row[7]; } ##### END SETTINGS LOOKUP ##### ########################################### @@ -215,6 +217,40 @@ function user_authorization($user,$pass,$user_option,$user_update,$api_call) $rslt=mysql_to_mysqli($stmt, $link); } $auth_key='GOOD'; + + if ( ($SStwo_factor_auth_hours > 0) and ($php_script != 'admin.php') ) + { + $VUtwo_factor_override=''; + $stmt="SELECT two_factor_override from vicidial_users where user='$user';"; + if ($non_latin > 0) {$rslt=mysql_to_mysqli("SET NAMES 'UTF8'", $link);} + $rslt=mysql_to_mysqli($stmt, $link); + $two_factor_user_ct = mysqli_num_rows($rslt); + if ($two_factor_user_ct > 0) + { + $row=mysqli_fetch_row($rslt); + $VUtwo_factor_override = $row[0]; + } + if ($VUtwo_factor_override != 'DISABLED') + { + $VALID_2FA=1; + # check for 2FA being active, and if so, see if there is a non-expired 2FA auth + $stmt="SELECT count(*) from vicidial_two_factor_auth where user='$user' and auth_stage='1' and auth_exp_date > NOW();"; + $rslt=mysql_to_mysqli($stmt, $link); + if ($DB) {echo "$stmt\n";} + $auth_check_to_print = mysqli_num_rows($rslt); + if ($auth_check_to_print < 1) + {$VALID_2FA=0;} + else + { + $row=mysqli_fetch_row($rslt); + $VALID_2FA = $row[0]; + } + if ($VALID_2FA < 1) + { + $auth_key='2FA'; + } + } + } } } return $auth_key; diff --git a/agc_2-X/trunk/www/vicidial/help_documentation.txt b/agc_2-X/trunk/www/vicidial/help_documentation.txt index 05b608c9..3afc3501 100644 --- a/agc_2-X/trunk/www/vicidial/help_documentation.txt +++ b/agc_2-X/trunk/www/vicidial/help_documentation.txt @@ -1,4 +1,4 @@ -# version: 20210309220801 +# version: 20210311104801 users-user User ID This field is where you put the users ID number, can be up to 8 digits in length, Must be at least 2 characters in length. users-pass Password This field is where you put the users password. Must be at least 2 characters in length. A medium strength user password will be at least 10 characters in length, and a strong user password will be at least 20 characters in length and have letters as well as at least one number. It is recommended that you use a longer password if possible, stringing together several unrelated words with no spaces, and a number somewhere in the string. The maximum size of a password is 100 characters. users-force_change_password Force Change Password If this option is set to Y then the user will be prompted to change their password the next time they log in to the administration webpage or the agent screen. Default is N. @@ -10,7 +10,9 @@ users-phone_login Phone Login Here is where you can set a default phone log users-phone_pass Phone Pass Here is where you can set a default phone pass value for when the user logs into the agent screen. This value will populate the phone_pass automatically when the user logs in with their user-pass-campaign in the agent login screen. users-active Active This field defines whether the user is active in the system and can log in as an agent or manager. Default is Y. users-voicemail_id Voicemail ID This is the voicemail box that calls will be directed to in an AGENTDIRECT in-group at the drop time if the in-group has the drop method set to VOICEMAIL and the Voicemail field set to AGENTVMAIL. -users-optional Email, User Code and Territory These are optional fields. +users-optional User Code and Territory These are optional fields. +users-email Email This field can be used by some scripts and functions, like dispo_send_email.php and two-factor-authentication, referenced by the --A--agent_email--B-- variable. +users-mobile_number Mobile Number This field can be used by two-factor-authentication, if your system is configured for it. users-user_nickname User Nickname Optional alternative name used for agent when chatting with customers in the customer website chat feature. Only used if populated. users-user_new_lead_limit User New Lead Limit This Overall Limit setting will limit the number of new leads this user can dial across all lists per day. This feature will only work properly if the campaign is set to either the MANUAL or INBOUND_MAN Dial Method and No Hopper dialing is enabled. Default is -1 for disabled. users-hotkeys_active Hot Keys Active This option if set to 1 allows the user to use the Hot Keys quick-dispositioning function in the agent screen. @@ -446,12 +448,12 @@ lists_fields-field_rank Field Rank The order in which these fields is displ lists_fields-field_order Field Order If more than one field has the same rank, they will be placed on the same line and they will be placed in order by this value from lowest to highest, left to right. lists_fields-field_rerank Re-Rank Fields Below If set to YES, this option will move existing other fields of an equal or lower rank down on the form by one place. Default is NO. lists_fields-field_help Field Help Optional field, if you fill it in, the agent will be able to see this text when they click on a help link next to the field in their agent interface. -lists_fields-field_type Field Type This option defines the type of field that will be displayed. TEXT is a standard single-line entry form, AREA is a multi-line text box, SELECT is a single-selection pull-down menu, MULTI is a multiple-select box, RADIO is a list of radio buttons where only one option can be selected, CHECKBOX is a list of checkboxes where multiple options can be selected, DATE is a year month day calendar popup where the agent can select the date and TIME is a time selection box. The default is TEXT. For the SELECT, MULTI, RADIO and CHECKBOX options you must define the option values below in the Field Options box. DISPLAY will display only and not allow for modification by the agent. SCRIPT will also display only, but you are able to use script variables just like in the Scripts feature. SCRIPT fields will also only display the content in the Options, and not the field name like the DISPLAY type does. HIDDEN will not show the agent the field, but will allow the field to have data imported into it and exported from it, as well as have it available to the script tab and web form address. READONLY will display the value of the data in the field, but will not allow the agent to alter the data. HIDEBLOB is similar to HIDDEN except the data storage type on the database is a BLOB type, suitable for binary data or data that needs to be secured. The SWITCH field type allows the agent to switch the lead custom fields to another list, as well as reloading the FORM tab with the new set of list custom fields for the new list. To configure SWITCH type fields, you must define the button values below in the Field Options box. SOURCESELECT is a single-selection pull-down menu where there are multiple sets of options available depending on the value of another field for the lead, see the Field Options help for more details. -lists_fields-field_options Field Options For the SELECT, MULTI, RADIO and CHECKBOX field types, you must define the option values in this box. You must put a list of comma separated option label and option text here with each option one its own line. The first value should have no spaces in it, and neither values should have any punctuation. For example - electric_meter, Electric Meter. For the SCRIPT field types, this field is where you put your script contents. You can use single quote and amphersand characters as well so that you can create links and iframe elements. If you want to put urlencoded fields in this area, make sure you use the --U-- and --V-- flags for your variables instead of using A and B, for example --U--test_field--V--. You can also use the --M-- and --N-- flags to enclose basic Math equations to have them calculated when the script is loaded initially, for example multiplying test_field by 12 would be entered with --M--(--A--test_field--B-- * 12)--N--. For the SWITCH field type, you should define the list ID for the custom fields as well as the text that you want to appear in the button to activate the new form in a comma separated line, with one line for each button you want to appear. For the SWITCH field type, it is a requirement that one of the entries be the current list ID. For SOURCESELECT, if this field is set to use the -province- field to determine what values to use, then the first line in the Field Options box should be -source=>province-, without the dashes. The next options line will be the first province value to look for, for example -value=>Ontario-, and if the value for that field for the lead matches, the next lines will be the options to show with the value and display text separated by a pipe. After that, you can add more values each with options after them, like this example below shows:
source=>province
value=>Ontario
option=>|select month here
option=>September|September
option=>October|October
value=>Nova Scotia
option=>|select month here
option=>June|June
option=>July|July
option=>August|August
value=>British Columbia
option=>|select month here
option=>January|January
option=>February|February
option=>March|March
value=>
option=>|no match
+lists_fields-field_type Field Type This option defines the type of field that will be displayed. TEXT is a standard single-line entry form, AREA is a multi-line text box, SELECT is a single-selection pull-down menu, MULTI is a multiple-select box, RADIO is a list of radio buttons where only one option can be selected, CHECKBOX is a list of checkboxes where multiple options can be selected, DATE is a year month day calendar popup where the agent can select the date and TIME is a time selection box. The default is TEXT. For the SELECT, MULTI, RADIO and CHECKBOX options you must define the option values below in the Field Options box. DISPLAY will display only and not allow for modification by the agent. SCRIPT will also display only, but you are able to use script variables just like in the Scripts feature. SCRIPT fields will also only display the content in the Options, and not the field name like the DISPLAY type does. HIDDEN will not show the agent the field, but will allow the field to have data imported into it and exported from it, as well as have it available to the script tab and web form address. READONLY will display the value of the data in the field, but will not allow the agent to alter the data. HIDEBLOB is similar to HIDDEN except the data storage type on the database is a BLOB type, suitable for binary data or data that needs to be secured. The SWITCH field type allows the agent to switch the lead custom fields to another list, as well as reloading the FORM tab with the new set of list custom fields for the new list. To configure SWITCH type fields, you must define the button values below in the Field Options box. SOURCESELECT is a single-selection pull-down menu where there are multiple sets of options available depending on the value of another field for the lead, see the Field Options help for more details. BUTTON will allow you to commit changes made to the form and reload it, the Field Name will be the text next to the button, the Field Default will be the text on the button, and the Field Options will need to be SubmitRefresh with the Field Size set to 1 for it to function. +lists_fields-field_options Field Options For the SELECT, MULTI, RADIO and CHECKBOX field types, you must define the option values in this box. You must put a list of comma separated option label and option text here with each option one its own line. The first value should have no spaces in it, and neither values should have any punctuation. For example - electric_meter, Electric Meter. For the SCRIPT field types, this field is where you put your script contents. You can use single quote and amphersand characters as well so that you can create links and iframe elements. If you want to put urlencoded fields in this area, make sure you use the --U-- and --V-- flags for your variables instead of using A and B, for example --U--test_field--V--. You can also use the --M-- and --N-- flags to enclose basic Math equations to have them calculated when the script is loaded initially, for example multiplying test_field by 12 would be entered with --M--(--A--test_field--B-- * 12)--N--. For the SWITCH field type, you should define the list ID for the custom fields as well as the text that you want to appear in the button to activate the new form in a comma separated line, with one line for each button you want to appear. For the SWITCH field type, it is a requirement that one of the entries be the current list ID. For BUTTON, the only current option is to put SubmitRefresh as the Field Options, which will commit any changes you have made in the form and reload the form panel. For SOURCESELECT, if this field is set to use the -province- field to determine what values to use, then the first line in the Field Options box should be -source=>province-, without the dashes. The next options line will be the first province value to look for, for example -value=>Ontario-, and if the value for that field for the lead matches, the next lines will be the options to show with the value and display text separated by a pipe. After that, you can add more values each with options after them, like this example below shows:
source=>province
value=>Ontario
option=>|select month here
option=>September|September
option=>October|October
value=>Nova Scotia
option=>|select month here
option=>June|June
option=>July|July
option=>August|August
value=>British Columbia
option=>|select month here
option=>January|January
option=>February|February
option=>March|March
value=>
option=>|no match
lists_fields-multi_position Option Position For CHECKBOX and RADIO field types only, if set to HORIZONTAL the options will appear on the same line possibly wrapping to the line below if there are many options. If set to VERTICAL there will be only one option per line. Default is HORIZONTAL. -lists_fields-field_size Field Size This setting will mean different things depending on what the field type is. For TEXT fields, the size is the number of characters that will show in the field. For AREA fields, the size is the width of the text box in characters. For MULTI fields, this setting defines the number of options to be shown in the multi select list. For SELECT, RADIO, CHECKBOX, DATE and TIME this setting is ignored. +lists_fields-field_size Field Size This setting will mean different things depending on what the field type is. For TEXT fields, the size is the number of characters that will show in the field. For AREA fields, the size is the width of the text box in characters. For MULTI fields, this setting defines the number of options to be shown in the multi select list. For SELECT, RADIO, CHECKBOX, DATE and TIME this setting is ignored. For BUTTON fields this must be set to 1. lists_fields-field_max Field Max This setting will mean different things depending on what the field type is. For TEXT, HIDDEN and READONLY fields, the size is the maximum number of characters that are allowed in the field. For AREA fields, this field defines the number of rows of text visible in the text box. For MULTI, SELECT, RADIO, CHECKBOX, DATE and TIME this setting is ignored. -lists_fields-field_default Field Default This optional field lets you define what value to assign to a field if nothing is loaded into that field. Default is NULL which disables the default function. For DATE field types, the default is always set to today unless a number is put in in which case the date will be that many days plus or minus today. For TIME field types, the default is always set to the current server time unless a number is put in in which case the time will be that many minutes plus or minus current time. For RADIO and SELECT field types, the default must be one of the options defined for the field or NULL. +lists_fields-field_default Field Default This optional field lets you define what value to assign to a field if nothing is loaded into that field. Default is NULL which disables the default function. For DATE field types, the default is always set to today unless a number is put in in which case the date will be that many days plus or minus today. For TIME field types, the default is always set to the current server time unless a number is put in in which case the time will be that many minutes plus or minus current time. For RADIO and SELECT field types, the default must be one of the options defined for the field or NULL. For BUTTON fields, this is the text that appears on the button. lists_fields-field_cost Field Cost This read only field tells you what the cost of this field is in the custom field table for this list. There is no hard limit for the number of custom fields you can have in a list, but the total of the cost of all fields for the list must be below 65000. This typically allows for hundreds of fields, but if you specify several TEXT fields that are hundreds or thousands of characters in length then you may hit this limit quickly. If you need that much text in a field you should choose an AREA type, which are stored differently and do not use as much table space. lists_fields-field_encrypt Field Encrypt On the ViciHost.com platform a built-in, high-level NIST-approved encryption option is available for custom fields. Default is N. lists_fields-field_show_hide Field Show Hide On the ViciHost.com platform, this option allows you to display only set characters from a READONLY or TEXT field. If a TEXT field, the value and a blank field with be displayed, if the blank field is populated by the agent, then the previous value will be overwritten when the agent completes their call. Default is N. @@ -1118,6 +1120,8 @@ settings-mute_recordings Allow Mute Recordings This option if enabled allow settings-enable_auto_reports Enable Automated Reports This option if enabled allows you access to the Automated Reports section where you can set up reports to run at scheduled times and be delivered by email or FTP. Default is 0 for disabled. settings-first_login_trigger First Login Trigger This setting allows for the initial configuration of the server screen to be shown to the administrator when they first log into the system. settings-require_password_length User Password Minimum Length If set above 0, this setting will require that user passwords, phone and server passwords, and system settings default passwords be at least this minimum length of characters when those records settings are modified on the Modify pages. The most important factor in password security is the length of the password, and user passwords in this system can be up to 100 characters in length. Default is 0 for disabled. +settings-two_factor_auth_hours Two-Factor Auth Hours Two-Factor-Authentication, 2FA for short, adds a required second step to the login process through a method other than a password, such as an Email, Phone Call or Text-Message -SMS-. This 2FA Auth Hours field is where you define the number of hours each auth will last, or until the user logs out. Currently, 2FA is not available for agent screen logins. Default is 0 for 2FA disabled. +settings-two_factor_container Two-Factor Auth Config Container Must be a valid 2FA_SETTINGS Container Type for 2FA to work. For more information on the settings that can be used in that container, please see the -2FA_TWO_FACTOR_AUTHENTICATION.txt- document. settings-user_account_emails User Login Link Emails Allowed The feature will allow you to click on a link from the User Modify page to send an email to an agent with a shortcut URL web address that will allow them to more easily log in to the agent screen. You can select options to send these emails with or without the user password included. Default is DISABLED. settings-phone_defaults_container Default Phones Settings Container This feature allows you to use a settings container of the type PHONE_DEFAULTS to pre-load numerous settings into the phone creation form and create new phones with these values pre-set. Refer to the PHONE_DEFAULTS settings container for an example of a container with all available settings that can be pre-set. Default is ---DISABLED---. settings-default_phone_registration_password Default Phone Registration Password This is the default registration password used when new phones are added to the system. Default is test. @@ -1232,6 +1236,7 @@ ip_lists-ip_address IP Addresses This is the list of IP Addresses within th users-pause_code_approval Manager Pause Code Approval If a campaign pause code is set to require manager approval, the manager that approves the agent pause code selection must have this setting set to 1. Default is 0. users-modify_ip_lists Modify IP Lists If IP Lists are enabled on your system, this setting will allow this administrative user the ability to modify the IP Lists. Default is 0. users-ignore_ip_lists Ignore IP Lists If IP Lists are enabled on your system, this setting will allow this user to ignore the IP Lists settings when accessing the system. Default is 0. +users-two_factor_override Two Factor Auth Override If Two-Factor-Authorization is enabled on your system, this setting can override it. Default is NOT_ACTIVE which will not override the System Settings for 2FA. status_categories System Status Categories Through the use of system status categories, you can group together statuses to allow for statistical analysis on a group of statuses. The Category ID must be 2-20 characters in length with no spaces, the name must be 2-50 characters in length, the description is optional and TimeonVDAD Display defines whether that status will be one of the upto 4 statuses that can be calculated and displayed on the Time On VDAD Real-Time report. The Sale Category and Dead Lead Category are both used by the List Suggestion system when analyzing list statistics. admin_phones_bulk_insert-registration_password Registration Password This is the registration password that will be used for all of the phones that are created. For SIP and IAX2 protocol you should use a complex password for secutiry reasons. email_accounts Email Accounts The Email Accounts management section allows you to create, copy, and delete email account settings that will allow you to have email messages come into your system and be treated as if they were phone calls to agents. EMAIL ACCOUNTS MUST BE SET UP BY YOU AND AN EMAIL SERVICE PROVIDER - THAT IS NOT COVERED BY THIS MODULE. diff --git a/agc_2-X/trunk/www/vicidial/list_download.php b/agc_2-X/trunk/www/vicidial/list_download.php index 8e99442d..3fc36621 100644 --- a/agc_2-X/trunk/www/vicidial/list_download.php +++ b/agc_2-X/trunk/www/vicidial/list_download.php @@ -114,8 +114,16 @@ if ($sl_ct > 0) $auth=0; $auth_message = user_authorization($PHP_AUTH_USER,$PHP_AUTH_PW,'',1,0); -if ($auth_message == 'GOOD') - {$auth=1;} +if ( ($auth_message == 'GOOD') or ($auth_message == '2FA') ) + { + $auth=1; + if ($auth_message == '2FA') + { + header ("Content-type: text/html; charset=utf-8"); + echo _QXZ("Your session is expired").". "._QXZ("Click here to log in").".\n"; + exit; + } + } if ($auth < 1) { diff --git a/agc_2-X/trunk/www/vicidial/qc_modify_lead.php b/agc_2-X/trunk/www/vicidial/qc_modify_lead.php index e971b106..f5edc8d5 100644 --- a/agc_2-X/trunk/www/vicidial/qc_modify_lead.php +++ b/agc_2-X/trunk/www/vicidial/qc_modify_lead.php @@ -238,8 +238,16 @@ $Mhead_color = $SSstd_row5_background; $auth=0; $auth_message = user_authorization($PHP_AUTH_USER,$PHP_AUTH_PW,'QC',1,0); -if ($auth_message == 'GOOD') - {$auth=1;} +if ( ($auth_message == 'GOOD') or ($auth_message == '2FA') ) + { + $auth=1; + if ($auth_message == '2FA') + { + header ("Content-type: text/html; charset=utf-8"); + echo _QXZ("Your session is expired").". "._QXZ("Click here to log in").".\n"; + exit; + } + } if ($auth < 1) { diff --git a/agc_2-X/trunk/www/vicidial/realtime_report.php b/agc_2-X/trunk/www/vicidial/realtime_report.php index 9824feca..16073414 100644 --- a/agc_2-X/trunk/www/vicidial/realtime_report.php +++ b/agc_2-X/trunk/www/vicidial/realtime_report.php @@ -385,8 +385,16 @@ $auth=0; $reports_auth=0; $admin_auth=0; $auth_message = user_authorization($PHP_AUTH_USER,$PHP_AUTH_PW,'REPORTS',1,0); -if ($auth_message == 'GOOD') - {$auth=1;} +if ( ($auth_message == 'GOOD') or ($auth_message == '2FA') ) + { + $auth=1; + if ($auth_message == '2FA') + { + header ("Content-type: text/html; charset=utf-8"); + echo _QXZ("Your session is expired").". "._QXZ("Click here to log in").".\n"; + exit; + } + } if ($auth > 0) { diff --git a/agc_2-X/trunk/www/vicidial/realtime_report_mobile.php b/agc_2-X/trunk/www/vicidial/realtime_report_mobile.php index 5eb1e9a0..53a40875 100644 --- a/agc_2-X/trunk/www/vicidial/realtime_report_mobile.php +++ b/agc_2-X/trunk/www/vicidial/realtime_report_mobile.php @@ -306,8 +306,16 @@ $auth=0; $reports_auth=0; $admin_auth=0; $auth_message = user_authorization($PHP_AUTH_USER,$PHP_AUTH_PW,'REPORTS',1,0); -if ($auth_message == 'GOOD') - {$auth=1;} +if ( ($auth_message == 'GOOD') or ($auth_message == '2FA') ) + { + $auth=1; + if ($auth_message == '2FA') + { + header ("Content-type: text/html; charset=utf-8"); + echo _QXZ("Your session is expired").". "._QXZ("Click here to log in").".\n"; + exit; + } + } if ($auth > 0) { diff --git a/agc_2-X/trunk/www/vicidial/timeclock_edit.php b/agc_2-X/trunk/www/vicidial/timeclock_edit.php index 62c51329..86b80f2a 100644 --- a/agc_2-X/trunk/www/vicidial/timeclock_edit.php +++ b/agc_2-X/trunk/www/vicidial/timeclock_edit.php @@ -135,8 +135,16 @@ if ($sl_ct > 0) $auth=0; $reports_auth=0; $auth_message = user_authorization($PHP_AUTH_USER,$PHP_AUTH_PW,'',1,0); -if ($auth_message == 'GOOD') - {$auth=1;} +if ( ($auth_message == 'GOOD') or ($auth_message == '2FA') ) + { + $auth=1; + if ($auth_message == '2FA') + { + header ("Content-type: text/html; charset=utf-8"); + echo _QXZ("Your session is expired").". "._QXZ("Click here to log in").".\n"; + exit; + } + } if ($auth > 0) { diff --git a/agc_2-X/trunk/www/vicidial/user_stats.php b/agc_2-X/trunk/www/vicidial/user_stats.php index ef0d3182..de6fc541 100644 --- a/agc_2-X/trunk/www/vicidial/user_stats.php +++ b/agc_2-X/trunk/www/vicidial/user_stats.php @@ -233,8 +233,16 @@ $auth=0; $reports_auth=0; $admin_auth=0; $auth_message = user_authorization($PHP_AUTH_USER,$PHP_AUTH_PW,'REPORTS',1,0); -if ($auth_message == 'GOOD') - {$auth=1;} +if ( ($auth_message == 'GOOD') or ($auth_message == '2FA') ) + { + $auth=1; + if ($auth_message == '2FA') + { + header ("Content-type: text/html; charset=utf-8"); + echo _QXZ("Your session is expired").". "._QXZ("Click here to log in").".\n"; + exit; + } + } if ($auth > 0) { diff --git a/agc_2-X/trunk/www/vicidial/vicidial_custom_reports_admin.php b/agc_2-X/trunk/www/vicidial/vicidial_custom_reports_admin.php index a76dcb45..55c8bb81 100644 --- a/agc_2-X/trunk/www/vicidial/vicidial_custom_reports_admin.php +++ b/agc_2-X/trunk/www/vicidial/vicidial_custom_reports_admin.php @@ -106,8 +106,16 @@ $auth=0; $reports_auth=0; $admin_auth=0; $auth_message = user_authorization($PHP_AUTH_USER,$PHP_AUTH_PW,'REPORTS',1,0); -if ($auth_message == 'GOOD') - {$auth=1;} +if ( ($auth_message == 'GOOD') or ($auth_message == '2FA') ) + { + $auth=1; + if ($auth_message == '2FA') + { + header ("Content-type: text/html; charset=utf-8"); + echo _QXZ("Your session is expired").". "._QXZ("Click here to log in").".\n"; + exit; + } + } if ($auth > 0) {
\n"; + echo ""; + + echo "
\n"; + echo "\n"; + echo "\n"; + echo "\n"; + echo "\n"; + echo "\n"; + echo "
\n"; + + echo "\n"; + + echo "\n"; + + #echo "\n"; + echo "
"._QXZ("Your account has Two-Factor-Authorization enabled on it. In order to log in, you will need to verify your identity by submitting a temporary authorization code. Click on the icon below for the delivery method you would like to use to receive your authorization code").":

\n"; + + echo "\n"; + $displayed_2FA=0; + if ( (preg_match("/YES/i",$email_auth)) and (strlen($LOGemail) > 3) ) + { + echo " 0) {echo " onclick=\"send_2FA('EMAIL');\"";} echo ">\n"; + echo "\n"; + echo "\n"; + echo "\n"; + $displayed_2FA++; + } + if ( (preg_match("/YES/i",$phone_auth)) and (strlen($LOGmobile_number) > 1) ) + { + echo " 0) {echo " onclick=\"send_2FA('PHONE');\"";} echo ">\n"; + echo "\n"; + echo "\n"; + echo "\n"; + $displayed_2FA++; + } + if ( (preg_match("/YES/i",$sms_auth)) and (strlen($LOGmobile_number) > 1) ) + { + echo " 0) {echo " onclick=\"send_2FA('SMS');\"";} echo ">\n"; + echo "\n"; + echo "\n"; + echo "\n"; + $displayed_2FA++; + } + if ($displayed_2FA < 1) + { + echo _QXZ("Your User account is not configured for Two-Factor-Authentication. Please contact your system administrator").".\n"; + exit; + } + echo "
"._QXZ("Email you an auth code")."
"._QXZ("Send an email to").":
$OBSCUREemail
"._QXZ("Call you and play an auth code")."
"._QXZ("Place a phone call to").":
$OBSCUREmobile_number
"._QXZ("Text-Message you an auth code")."
"._QXZ("Send a message to").":
$OBSCUREmobile_number

 \n"; + + echo "
\n"; + } + } + ##### END choose how to send out AUTH CODE page ##### + } +##### END User 2FA(Two-Factor-Authentication) Page ##### + + + + + + + + + + + ###################### # ADD=999996 - initial install welcome page ###################### diff --git a/agc_2-X/trunk/www/vicidial/admin_NANPA_updater.php b/agc_2-X/trunk/www/vicidial/admin_NANPA_updater.php index 7dcfc6b2..8b7ff87e 100644 --- a/agc_2-X/trunk/www/vicidial/admin_NANPA_updater.php +++ b/agc_2-X/trunk/www/vicidial/admin_NANPA_updater.php @@ -105,8 +105,16 @@ $auth=0; $reports_auth=0; $qc_auth=0; $auth_message = user_authorization($PHP_AUTH_USER,$PHP_AUTH_PW,'QC',1,0); -if ($auth_message == 'GOOD') - {$user_auth=1;} +if ( ($auth_message == 'GOOD') or ($auth_message == '2FA') ) + { + $auth=1; + if ($auth_message == '2FA') + { + header ("Content-type: text/html; charset=utf-8"); + echo _QXZ("Your session is expired").". "._QXZ("Click here to log in").".\n"; + exit; + } + } if ($user_auth > 0) { diff --git a/agc_2-X/trunk/www/vicidial/admin_amm_multi.php b/agc_2-X/trunk/www/vicidial/admin_amm_multi.php index cc152204..9e9aac1d 100644 --- a/agc_2-X/trunk/www/vicidial/admin_amm_multi.php +++ b/agc_2-X/trunk/www/vicidial/admin_amm_multi.php @@ -120,8 +120,16 @@ if ($sl_ct > 0) $auth=0; $auth_message = user_authorization($PHP_AUTH_USER,$PHP_AUTH_PW,'',1,0); -if ($auth_message == 'GOOD') - {$auth=1;} +if ( ($auth_message == 'GOOD') or ($auth_message == '2FA') ) + { + $auth=1; + if ($auth_message == '2FA') + { + header ("Content-type: text/html; charset=utf-8"); + echo _QXZ("Your session is expired").". "._QXZ("Click here to log in").".\n"; + exit; + } + } if ($auth < 1) { diff --git a/agc_2-X/trunk/www/vicidial/admin_bulk_tools.php b/agc_2-X/trunk/www/vicidial/admin_bulk_tools.php index 4901b915..a940367c 100644 --- a/agc_2-X/trunk/www/vicidial/admin_bulk_tools.php +++ b/agc_2-X/trunk/www/vicidial/admin_bulk_tools.php @@ -174,8 +174,16 @@ if ($sl_ct > 0) # Valid user $auth=0; $auth_message = user_authorization($PHP_AUTH_USER,$PHP_AUTH_PW,'',1,0); -if ($auth_message == 'GOOD') - {$auth=1;} +if ( ($auth_message == 'GOOD') or ($auth_message == '2FA') ) + { + $auth=1; + if ($auth_message == '2FA') + { + header ("Content-type: text/html; charset=utf-8"); + echo _QXZ("Your session is expired").". "._QXZ("Click here to log in").".\n"; + exit; + } + } if ($auth < 1) { diff --git a/agc_2-X/trunk/www/vicidial/admin_campaign_multi_alt.php b/agc_2-X/trunk/www/vicidial/admin_campaign_multi_alt.php index b663ffb3..14edf77b 100644 --- a/agc_2-X/trunk/www/vicidial/admin_campaign_multi_alt.php +++ b/agc_2-X/trunk/www/vicidial/admin_campaign_multi_alt.php @@ -101,8 +101,16 @@ if ($sl_ct > 0) $auth=0; $auth_message = user_authorization($PHP_AUTH_USER,$PHP_AUTH_PW,'',1,0); -if ($auth_message == 'GOOD') - {$auth=1;} +if ( ($auth_message == 'GOOD') or ($auth_message == '2FA') ) + { + $auth=1; + if ($auth_message == '2FA') + { + header ("Content-type: text/html; charset=utf-8"); + echo _QXZ("Your session is expired").". "._QXZ("Click here to log in").".\n"; + exit; + } + } if ($auth < 1) { diff --git a/agc_2-X/trunk/www/vicidial/admin_email_accounts.php b/agc_2-X/trunk/www/vicidial/admin_email_accounts.php index 9c712b0c..cf1ebb94 100644 --- a/agc_2-X/trunk/www/vicidial/admin_email_accounts.php +++ b/agc_2-X/trunk/www/vicidial/admin_email_accounts.php @@ -187,8 +187,16 @@ if ($sl_ct > 0) $auth=0; $auth_message = user_authorization($PHP_AUTH_USER,$PHP_AUTH_PW,'',1,0); -if ($auth_message == 'GOOD') - {$auth=1;} +if ( ($auth_message == 'GOOD') or ($auth_message == '2FA') ) + { + $auth=1; + if ($auth_message == '2FA') + { + header ("Content-type: text/html; charset=utf-8"); + echo _QXZ("Your session is expired").". "._QXZ("Click here to log in").".\n"; + exit; + } + } if ($auth < 1) { diff --git a/agc_2-X/trunk/www/vicidial/admin_languages.php b/agc_2-X/trunk/www/vicidial/admin_languages.php index db452469..bfa9f15e 100644 --- a/agc_2-X/trunk/www/vicidial/admin_languages.php +++ b/agc_2-X/trunk/www/vicidial/admin_languages.php @@ -188,8 +188,16 @@ if ($sl_ct > 0) $auth=0; $auth_message = user_authorization($PHP_AUTH_USER,$PHP_AUTH_PW,'',1,0); -if ($auth_message == 'GOOD') - {$auth=1;} +if ( ($auth_message == 'GOOD') or ($auth_message == '2FA') ) + { + $auth=1; + if ($auth_message == '2FA') + { + header ("Content-type: text/html; charset=utf-8"); + echo _QXZ("Your session is expired").". "._QXZ("Click here to log in").".\n"; + exit; + } + } if ($auth < 1) { diff --git a/agc_2-X/trunk/www/vicidial/admin_launch_trigger.php b/agc_2-X/trunk/www/vicidial/admin_launch_trigger.php index 07722ad0..765fbeda 100644 --- a/agc_2-X/trunk/www/vicidial/admin_launch_trigger.php +++ b/agc_2-X/trunk/www/vicidial/admin_launch_trigger.php @@ -81,8 +81,16 @@ $auth=0; $reports_auth=0; $qc_auth=0; $auth_message = user_authorization($PHP_AUTH_USER,$PHP_AUTH_PW,'QC',1,0); -if ($auth_message == 'GOOD') - {$user_auth=1;} +if ( ($auth_message == 'GOOD') or ($auth_message == '2FA') ) + { + $user_auth=1; + if ($auth_message == '2FA') + { + header ("Content-type: text/html; charset=utf-8"); + echo _QXZ("Your session is expired").". "._QXZ("Click here to log in").".\n"; + exit; + } + } if ($user_auth > 0) { diff --git a/agc_2-X/trunk/www/vicidial/admin_listloader_fourth_gen.php b/agc_2-X/trunk/www/vicidial/admin_listloader_fourth_gen.php index 9bfd20e9..b9280a00 100644 --- a/agc_2-X/trunk/www/vicidial/admin_listloader_fourth_gen.php +++ b/agc_2-X/trunk/www/vicidial/admin_listloader_fourth_gen.php @@ -272,8 +272,16 @@ if ($sl_ct > 0) $auth=0; $auth_message = user_authorization($PHP_AUTH_USER,$PHP_AUTH_PW,'',1,0); -if ($auth_message == 'GOOD') - {$auth=1;} +if ( ($auth_message == 'GOOD') or ($auth_message == '2FA') ) + { + $auth=1; + if ($auth_message == '2FA') + { + header ("Content-type: text/html; charset=utf-8"); + echo _QXZ("Your session is expired").". "._QXZ("Click here to log in").".\n"; + exit; + } + } if ($auth < 1) { diff --git a/agc_2-X/trunk/www/vicidial/admin_lists_custom.php b/agc_2-X/trunk/www/vicidial/admin_lists_custom.php index de726f80..c7681a37 100644 --- a/agc_2-X/trunk/www/vicidial/admin_lists_custom.php +++ b/agc_2-X/trunk/www/vicidial/admin_lists_custom.php @@ -55,10 +55,11 @@ # 191013-1014 - Fixes for PHP7 # 210211-0032 - Added SOURCESELECT field type # 210304-2039 - Added option to "re-rank" field ranks when adding/updating a field in the middle of the form +# 210311-2338 - Added BUTTON field type and 2FA # -$admin_version = '2.14-46'; -$build = '210304-2039'; +$admin_version = '2.14-47'; +$build = '210311-2338'; require("dbconnect_mysqli.php"); require("functions.php"); @@ -228,8 +229,16 @@ if ($sl_ct > 0) $auth=0; $auth_message = user_authorization($PHP_AUTH_USER,$PHP_AUTH_PW,'',1,0); -if ($auth_message == 'GOOD') - {$auth=1;} +if ( ($auth_message == 'GOOD') or ($auth_message == '2FA') ) + { + $auth=1; + if ($auth_message == '2FA') + { + header ("Content-type: text/html; charset=utf-8"); + echo _QXZ("Your session is expired").". "._QXZ("Click here to log in").".\n"; + exit; + } + } if ($auth < 1) { @@ -1349,6 +1358,19 @@ if ( ($action == "MODIFY_CUSTOM_FIELDS") and ($list_id > 99) ) if ($A_field_default[$o]=='NULL') {$A_field_default[$o]='';} $field_HTML .= "\n"; } + if ($A_field_type[$o]=='BUTTON') + { + $field_options_array = explode("\n",$A_field_options[$o]); + if (preg_match("/^SubmitRefresh/i",$field_options_array[0])) + { + if ($A_multi_position[$o]=='VERTICAL') + {$field_HTML .= "   ";} + if (strlen($A_field_default[$o]) < 1) {$A_field_default[$o] = _QXZ("Commit Changes and Refresh Form");} + $field_HTML .= " \n"; + if ($A_multi_position[$o]=='VERTICAL') + {$field_HTML .= "
\n";} + } + } if ($A_field_type[$o]=='READONLY') { if ($A_field_default[$o]=='NULL') {$A_field_default[$o]='';} @@ -1548,6 +1570,7 @@ if ( ($action == "MODIFY_CUSTOM_FIELDS") and ($list_id > 99) ) echo "\n"; echo "\n"; echo "\n"; + echo "\n"; echo "\n"; echo " $NWB#lists_fields-field_type$NWE
"._QXZ("Field Options")." $A_field_rank[$o]: $NWB#lists_fields-field_options$NWE
"._QXZ("Field Options").": $NWB#lists_fields-field_options$NWE