diff --git a/agc_2-X/trunk/UPGRADE b/agc_2-X/trunk/UPGRADE index b100e0c1..0c804212 100644 --- a/agc_2-X/trunk/UPGRADE +++ b/agc_2-X/trunk/UPGRADE @@ -602,6 +602,9 @@ OTHER CHANGES: throttling if set to an audible sound at a 20 second interval. Tested with the 'click_quiet' sound file at a volume of '25'. +169. Added WAV audio file validation for Audio Store, and display of badly + formatted WAV files in the audio chooser in admin.php + diff --git a/agc_2-X/trunk/docs/NON-AGENT_API.txt b/agc_2-X/trunk/docs/NON-AGENT_API.txt index 22252b0d..22d90a51 100644 --- a/agc_2-X/trunk/docs/NON-AGENT_API.txt +++ b/agc_2-X/trunk/docs/NON-AGENT_API.txt @@ -1,4 +1,4 @@ -NON-AGENT API DOCUMENT Started: 2008-07-24 Updated: 2021-03-20 +NON-AGENT API DOCUMENT Started: 2008-07-24 Updated: 2021-03-22 This document describes the functions of an API(Application Programming Interface) for all functions NOT directly relating to the VICIDIAL Agent screen. @@ -180,6 +180,7 @@ Changes: 210316-2207 - Added lead_all_info function 210319-1720 - Added special 'xDAYS' value option for callback_datetime 210320-2127 - Added 'custom_fields_add' option for update_list function +210322-1218 - Added display of bad wav file formats on sounds_list function API Functions use the 'function' variable 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 ab99fd1f..8f11128e 100644 --- a/agc_2-X/trunk/extras/MySQL_AST_CREATE_tables.sql +++ b/agc_2-X/trunk/extras/MySQL_AST_CREATE_tables.sql @@ -3440,6 +3440,8 @@ audio_format VARCHAR(10) default 'unknown', audio_filesize BIGINT(20) UNSIGNED default '0', audio_epoch BIGINT(20) UNSIGNED default '0', audio_length INT(10) UNSIGNED default '0', +wav_format_details VARCHAR(255) default '', +wav_asterisk_valid ENUM('','GOOD','BAD','NA') default '', unique index (audio_filename) ) ENGINE=MyISAM; @@ -4869,4 +4871,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='1624',db_schema_update_date=NOW(),reload_timestamp=NOW(); +UPDATE system_settings SET db_schema_version='1625',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 af037f4d..b24adc15 100644 --- a/agc_2-X/trunk/extras/upgrade_2.14.sql +++ b/agc_2-X/trunk/extras/upgrade_2.14.sql @@ -1594,3 +1594,8 @@ ALTER TABLE quality_control_checkpoint_log ADD checkpoint_text_presets TEXT AFTE ALTER TABLE quality_control_checkpoints ADD checkpoint_text_presets TEXT AFTER checkpoint_text; UPDATE system_settings SET db_schema_version='1624',db_schema_update_date=NOW() where db_schema_version < 1624; + +ALTER TABLE audio_store_details ADD wav_format_details VARCHAR(255) default ''; +ALTER TABLE audio_store_details ADD wav_asterisk_valid ENUM('','GOOD','BAD','NA') default ''; + +UPDATE system_settings SET db_schema_version='1625',db_schema_update_date=NOW() where db_schema_version < 1625; diff --git a/agc_2-X/trunk/www/vicidial/audio_store.php b/agc_2-X/trunk/www/vicidial/audio_store.php index 9c7805f5..cf070b53 100644 --- a/agc_2-X/trunk/www/vicidial/audio_store.php +++ b/agc_2-X/trunk/www/vicidial/audio_store.php @@ -32,15 +32,17 @@ # 180618-2300 - Modified calls to audio file chooser function # 201002-1536 - Allowed for secure sounds_web_server setting # 210321-0131 - Added classAudioFile PHP library for WAV file format validation +# 210322-1220 - Added checking of .wav files for asterisk-compatible format # -$version = '2.14-24'; -$build = '210321-0131'; +$version = '2.14-25'; +$build = '210322-1220'; $MT[0]=''; require("dbconnect_mysqli.php"); require("functions.php"); +require ('classAudioFile.php'); $server_name = getenv("SERVER_NAME"); $PHP_SELF=$_SERVER['PHP_SELF']; @@ -320,6 +322,112 @@ if ($action == "LIST") } +##### BEGIN go through all Audio Store WAV files and validate for asterisk compatibility ##### +$stmt = "SELECT count(*) FROM audio_store_details where audio_format='wav' and wav_asterisk_valid='';"; +$rslt=mysql_to_mysqli($stmt, $link); +if ($DB) {echo "$stmt\n";} +$wuv_ct = mysqli_num_rows($rslt); +if ( ($wuv_ct > 0) or ($action == "ALL_WAV_VALIDATION") ) + { + $i=0; + $filename_sort=$MT; + $dirpath = "$WeBServeRRooT/$sounds_web_directory"; + $dh = opendir($dirpath); + while (false !== ($file = readdir($dh))) + { + # Do not list subdirectories + if ( (!is_dir("$dirpath/$file")) and (preg_match('/\.wav$|\.gsm$/', $file)) ) + { + if (file_exists("$dirpath/$file")) + { + $file_names[$i] = $file; + $file_epoch[$i] = filemtime("$dirpath/$file"); + $file_dates[$i] = date ("Y-m-d H:i:s.", filemtime("$dirpath/$file")); + $file_sizes[$i] = filesize("$dirpath/$file"); + $filename_sort[$i] = $file . "----------" . $i . "----------" . $file_sizes[$i]; + $i++; + } + } + } + closedir($dh); + + sort($filename_sort); + + sleep(1); + + $wav_valid=0; + $wav_invalid=0; + $not_wav=0; + $k=0; + while($k < $i) + { + $filename_split = explode('----------',$filename_sort[$k]); + $m = $filename_split[1]; + $size = $filename_split[2]; + $audio_filesize = filesize("$dirpath/$file_names[$m]"); + if ($size == $audio_filesize) + { + $audio_filename = $file_names[$m]; + $audio_epoch = date("U"); + $wav_format_details=''; + $wav_asterisk_valid='NA'; + + if (preg_match("/\.wav$/", $audio_filename)) + { + $audio_format='wav'; + $audio_length = ($audio_filesize / 16000); + + $AF = new AudioFile; + $AF->loadFile("$dirpath/$file_names[$m]"); + + $wav_type = $AF->wave_type; + $wav_compression = $AF->getCompression ($AF->wave_compression); + $wav_channels = $AF->wave_channels; + $wav_framerate = $AF->wave_framerate; + $wav_bits=$AF->wave_bits; + $audio_length=number_format ($AF->wave_length,"0"); + $invalid_wav=0; + + if (!preg_match('/^wav/i',$wav_type)) {$invalid_wav++;} + if (!preg_match('/^pcm/i',$wav_compression)) {$invalid_wav++;} + if ($wav_channels > 1) {$invalid_wav++;} + if ( ($wav_framerate > 8000) or ($wav_framerate < 8000) ) {$invalid_wav++;} + if ( ($wav_bits > 16) or ($wav_bits < 16) ) {$invalid_wav++;} + + $wav_format_details = "$wav_type channels: $wav_channels framerate: $wav_framerate bits: $wav_bits length: $audio_length compression: $wav_compression"; + + if ($invalid_wav > 0) + { + $wav_asterisk_valid='BAD'; + $wav_invalid++; + } + else + { + $wav_asterisk_valid='GOOD'; + $wav_valid++; + } + + $stmt="INSERT IGNORE INTO audio_store_details SET audio_filename='$audio_filename',audio_format='$audio_format',audio_filesize='$audio_filesize',audio_epoch='$audio_epoch',audio_length='$audio_length',wav_format_details='$wav_format_details',wav_asterisk_valid='$wav_asterisk_valid' ON DUPLICATE KEY UPDATE audio_filesize='$audio_filesize',audio_epoch='$audio_epoch',audio_length='$audio_length',wav_format_details='$wav_format_details',wav_asterisk_valid='$wav_asterisk_valid';"; + if ($DB) {echo "|$stmt|\n";} + $rslt=mysql_to_mysqli($stmt, $link); + $affected_rowsX = mysqli_affected_rows($link); + } + else + { + $not_wav++; + } + + if ($DB) {echo "$k\t$file_names[$m]\t$wav_asterisk_valid\n";} + } + $k++; + } + + if ($DB) {echo "SUMMARY: WAV VALID: $wav_valid WAV INVALID: $wav_invalid NOT WAV: $not_wav\n";} + } +##### END go through all Audio Store WAV files and validate for asterisk compatibility ##### + + + ### upload audio file from server to webserver # curl 'http://10.0.0.4/vicidial/audio_store.php?action=AUTOUPLOAD' -F "audiofile=@/var/lib/asterisk/sounds/beep.gsm" if ($action == "AUTOUPLOAD") @@ -546,14 +654,22 @@ if ($action == "MANUALUPLOAD") $audiofile_name = preg_replace("/\^/",'',$audiofile_name); if (preg_match("/\.wav$|\.gsm$/", $audiofile_name)) { + $audio_epoch = date("U"); + $audio_format='gsm'; + $audio_filesize = filesize("$WeBServeRRooT/$sounds_web_directory/$audiofile_name"); + $audio_length = ($audio_filesize / 1650); + $wav_format_details=''; + $wav_asterisk_valid='NA'; + copy($AF_path, "$WeBServeRRooT/$sounds_web_directory/$audiofile_name"); chmod("$WeBServeRRooT/$sounds_web_directory/$audiofile_name", 0766); - echo "
"._QXZ("SUCCESS").": $audiofile_name "._QXZ("uploaded")." "._QXZ("size").":" . filesize("$WeBServeRRooT/$sounds_web_directory/$audiofile_name") . "

\n"; + echo "
"._QXZ("SUCCESS").": $audiofile_name "._QXZ("uploaded")." "._QXZ("size").": $audio_filesize

\n"; if (preg_match("/\.wav$/", $audiofile_name)) { - require ('classAudioFile.php'); + $audio_format='wav'; + $audio_length = ($audio_filesize / 16000); $AF = new AudioFile; $AF->loadFile("$WeBServeRRooT/$sounds_web_directory/$audiofile_name"); @@ -563,6 +679,7 @@ if ($action == "MANUALUPLOAD") $wav_channels = $AF->wave_channels; $wav_framerate = $AF->wave_framerate; $wav_bits=$AF->wave_bits; + $audio_length=number_format ($AF->wave_length,"0"); $invalid_wav=0; if (!preg_match('/^wav/i',$wav_type)) {$invalid_wav++;} @@ -571,25 +688,35 @@ if ($action == "MANUALUPLOAD") if ( ($wav_framerate > 8000) or ($wav_framerate < 8000) ) {$invalid_wav++;} if ( ($wav_bits > 16) or ($wav_bits < 16) ) {$invalid_wav++;} + $wav_format_details = "$wav_type channels: $wav_channels framerate: $wav_framerate bits: $wav_bits length: $audio_length compression: $wav_compression"; + if ($invalid_wav > 0) { + $wav_asterisk_valid='BAD'; echo "  

"._QXZ("INVALID WAV FILE FORMAT").": ($audiofile_name)
  $wav_type   "._QXZ("channels").": $wav_channels   "._QXZ("framerate").": $wav_framerate   "._QXZ("bits").": $wav_bits   "._QXZ("compression").": $wav_compression


\n"; } else { + $wav_asterisk_valid='GOOD'; echo "  
"._QXZ("WAV FILE FORMAT VALIDATED").": $wav_type   "._QXZ("channels").": $wav_channels   "._QXZ("framerate").": $wav_framerate   "._QXZ("bits").": $wav_bits   "._QXZ("compression").": $wav_compression

\n"; } echo "
"; } + $stmt="INSERT IGNORE INTO audio_store_details SET audio_filename='$audiofile_name',audio_format='$audio_format',audio_filesize='$audio_filesize',audio_epoch='$audio_epoch',audio_length='$audio_length',wav_format_details='$wav_format_details',wav_asterisk_valid='$wav_asterisk_valid' ON DUPLICATE KEY UPDATE audio_filesize='$audio_filesize',audio_epoch='$audio_epoch',audio_length='$audio_length',wav_format_details='$wav_format_details',wav_asterisk_valid='$wav_asterisk_valid';"; + if ($DB) {echo "|$stmt|\n";} + $rslt=mysql_to_mysqli($stmt, $link); + $affected_rowsX = mysqli_affected_rows($link); + $stmt="UPDATE servers SET sounds_update='Y';"; $rslt=mysql_to_mysqli($stmt, $link); + $affected_rowsY = mysqli_affected_rows($link); ### LOG INSERTION Admin Log Table ### $SQL_log = "$stmt|"; $SQL_log = preg_replace('/;/', '', $SQL_log); $SQL_log = addslashes($SQL_log); - $stmt="INSERT INTO vicidial_admin_log set event_date=NOW(), user='$PHP_AUTH_USER', ip_address='$ip', event_section='AUDIOSTORE', event_type='LOAD', record_id='manualupload', event_code='$audiofile_name " . filesize("$WeBServeRRooT/$sounds_web_directory/$audiofile_name") . "', event_sql=\"$SQL_log\", event_notes='$audiofile_name $AF_path $AF_orig Invalid: $invalid_wav $wav_type   "._QXZ("channels").": $wav_channels   "._QXZ("framerate").": $wav_framerate   "._QXZ("bits").": $wav_bits   "._QXZ("compression").": $wav_compression';"; + $stmt="INSERT INTO vicidial_admin_log set event_date=NOW(), user='$PHP_AUTH_USER', ip_address='$ip', event_section='AUDIOSTORE', event_type='LOAD', record_id='manualupload', event_code='$audiofile_name $audio_filesize', event_sql=\"$SQL_log\", event_notes='$audiofile_name $AF_path $AF_orig Invalid: $invalid_wav $wav_type   "._QXZ("channels").": $wav_channels   "._QXZ("framerate").": $wav_framerate   "._QXZ("bits").": $wav_bits   "._QXZ("compression").": $wav_compression "._QXZ("length").": $audio_length $affected_rowsX|$affected_rowsY';"; if ($DB) {echo "|$stmt|\n";} $rslt=mysql_to_mysqli($stmt, $link); } diff --git a/agc_2-X/trunk/www/vicidial/non_agent_api.php b/agc_2-X/trunk/www/vicidial/non_agent_api.php index ffb92035..ba659b75 100644 --- a/agc_2-X/trunk/www/vicidial/non_agent_api.php +++ b/agc_2-X/trunk/www/vicidial/non_agent_api.php @@ -168,10 +168,11 @@ # 210316-2207 - Added lead_all_info function # 210319-1720 - Added special 'xDAYS' value option for callback_datetime # 210320-2127 - Added 'custom_fields_add' option for update_list function +# 210322-1218 - Added display of bad wav file formats on sounds_list function # -$version = '2.14-145'; -$build = '210320-2127'; +$version = '2.14-146'; +$build = '210322-1218'; $api_url_log = 0; $startMS = microtime(); @@ -1202,6 +1203,18 @@ if ($function == 'sounds_list') exit; } + $bad_wavs='|'; + $stmt="SELECT audio_filename from audio_store_details where wav_asterisk_valid='BAD';"; + $rslt=mysql_to_mysqli($stmt, $link); + $bw_ct = mysqli_num_rows($rslt); + $bw=0; + while ($bw_ct > $bw) + { + $row=mysqli_fetch_row($rslt); + $bad_wavs .= "$row[0]|"; + $bw++; + } + $dh = opendir($dirpath); if ($DB>0) {echo "DEBUG: sounds_list variables - $dirpath|$stage|$format\n";} @@ -1297,8 +1310,18 @@ if ($function == 'sounds_list') echo "\n"; } $sf++; + $BWB=''; $BWE=''; + if ( (preg_match('/\.wav$/', $file_names[$m])) and (strlen($bad_wavs) > 2) ) + { + $temp_filename = $file_names[$m]; + if (preg_match("/\|$temp_filename\|/",$bad_wavs)) + { + $BWB=''; + $BWE="     "._QXZ("BAD WAV FORMAT").""; + } + } echo "$sf\n"; - echo "$file_names[$m]\n"; + echo "$BWB$file_names[$m]$BWE\n"; echo "$file_dates[$m]\n"; echo "$file_sizes[$m]\n"; echo ""._QXZ("PLAY")."\n";