diff --git a/application/controllers/Cabrillo.php b/application/controllers/Cabrillo.php index 972fd0f5e..1f745372f 100644 --- a/application/controllers/Cabrillo.php +++ b/application/controllers/Cabrillo.php @@ -188,19 +188,25 @@ class Cabrillo extends CI_Controller { //get flag about the presence of the serial number $serial_number_present = ($this->input->post('serial_number_present', true) == 1); + //get flag about the presence of the trx number + $trx_number_present = ($this->input->post('trx_number_present', true) == 1); + //parse the uploaded file - $parsed_cbr = $this->cbr_parser->parse_from_file('./uploads/'.$data['upload_data']['file_name'], $serial_number_present); + $parsed_cbr = $this->cbr_parser->parse_from_file('./uploads/'.$data['upload_data']['file_name'], $serial_number_present, $trx_number_present); - //return with error, reset upload filesize - if(count($parsed_cbr["QSOS"]) < 1) + //if parsing fails, return with error, reset upload filesize + if(isset($parsed_cbr['error'])) { - $data['error'] = __("Broken CBR file - no QSO data or incomplete header found."); + //get error message from parser + $data['error'] = $parsed_cbr['error']; + //reset upload filesize $data['max_upload'] = ini_get('upload_max_filesize'); //delete uploaded file unlink('./uploads/' . $data['upload_data']['file_name']); + //return view $this->load->view('interface_assets/header', $data); $this->load->view('adif/import', $data); $this->load->view('interface_assets/footer'); @@ -263,23 +269,25 @@ class Cabrillo extends CI_Controller { $stxstring = null; $srxstring = null; - //process all sent exchanges + //process all sent exchanges, handle those that are shorter than maximum gracefully for ($i=1; $i <= $sent_exchange_count; $i++) { - if($stxstring == null) - { - $stxstring = $qso["SENT_EXCH_" . $i]; - }else{ - $stxstring = $stxstring . ' ' . $qso["SENT_EXCH_" . $i]; + if(isset($qso["SENT_EXCH_" . $i])){ + if($stxstring == null){ + $stxstring = $qso["SENT_EXCH_" . $i]; + }else{ + $stxstring = $stxstring . ' ' . $qso["SENT_EXCH_" . $i]; + } } } - //process all sent exchanges + //process all sent exchanges, handle those that are shorter than maximum gracefully for ($i=1; $i <= $rcvd_exchange_count; $i++) { - if($srxstring == null) - { - $srxstring = $qso["RCVD_EXCH_" . $i]; - }else{ - $srxstring = $srxstring . ' ' . $qso["RCVD_EXCH_" . $i]; + if(isset($qso["RCVD_EXCH_" . $i])){ + if($srxstring == null){ + $srxstring = $qso["RCVD_EXCH_" . $i]; + }else{ + $srxstring = $srxstring . ' ' . $qso["RCVD_EXCH_" . $i]; + } } } diff --git a/application/libraries/Cbr_parser.php b/application/libraries/Cbr_parser.php index 73c35a0db..5c39d4458 100644 --- a/application/libraries/Cbr_parser.php +++ b/application/libraries/Cbr_parser.php @@ -1,13 +1,13 @@ parse(mb_convert_encoding(file_get_contents($filename), "UTF-8"), $serial_number_present); + return $this->parse(mb_convert_encoding(file_get_contents($filename), "UTF-8"), $serial_number_present, $trx_number_present); } - public function parse(string $input, $serial_number_present = false) : array + public function parse(string $input, $serial_number_present = false, $trx_number_present = false) : array { //split the input into lines $lines = explode("\n", trim($input)); @@ -35,6 +35,11 @@ class CBR_Parser $qso_mode = false; } + //if we encounter a QTC, skip that line + if(strpos($line, 'QTC:') === 0){ + continue; + } + //if we encounter "END-OF-LOG", stop processing lines if (strpos($line, 'END-OF-LOG') === 0) { break; @@ -59,13 +64,38 @@ class CBR_Parser //split the line into the elements $qso_elements = preg_split('/\s+/', trim($line)); + //check occurances of signal rapport values + $counts = array_count_values($qso_elements); + $count59s = ($counts["59"] ?? 0) + ($counts["599"] ?? 0); + + //for those few contests who do not have signal exchange, synthesize one based on best efforts + if($count59s < 2 and isset($header['CALLSIGN'])){ + + //get own callsign from header + $own_callsign = $header['CALLSIGN']; + + //get position of own callsign + $index = array_search($own_callsign, $qso_elements); + + //add synthesized sent signal rapport after own callsign + if ($index !== false) { + array_splice($qso_elements, $index + 1, 0, "59"); + } + + //search for the next amateur radio callsign after my own and add another 59. Abort after first find + for ($i = $index + 1; $i < count($qso_elements); $i++) { + $value = $qso_elements[$i]; + if(preg_match('/(?=[A-Z0-9]*[A-Z])[A-Z0-9]{1,3}[0-9][A-Z0-9]{0,7}/', $value) === 1){ + array_splice($qso_elements, $i + 1, 0, "59"); + break; + } + } + } + //determine maximum qso field size - $max_qso_fields = max($max_qso_fields, count($qso_elements)); + $max_qso_fields = max($max_qso_fields ?? 0, count($qso_elements)); - //add qso elements to qso line array - array_push($qso_lines_raw, $qso_elements); - - //find all occurrences of "59" + //find all occurrences of "59" or "599" $indices_of_59 = []; foreach ($qso_elements as $index => $value) { if ($value === "59" or $value === "599") { @@ -73,6 +103,15 @@ class CBR_Parser } } + //abort further processing if we find a line without a valid signal report (59 or 599) + if(count($indices_of_59) < 1) { + + //return error result + $result = []; + $result['error'] = __("Broken CBR file - no valid exchange or callsigns found"); + return $result; + } + //find common indices position if ($common_59_indices === null) { //initialize common indices on the first iteration @@ -82,6 +121,9 @@ class CBR_Parser $common_59_indices = array_intersect($common_59_indices, $indices_of_59); } + //add qso elements to qso line array + array_push($qso_lines_raw, $qso_elements); + //skip to next line continue; } @@ -89,30 +131,20 @@ class CBR_Parser //abort further processing if no qso lines were found, return header only if(count($qso_lines_raw) < 1) { - $result = []; - $result["HEADER"] = $header; - $result["QSOS"] = []; - $result["SENT_59_POS"] = 0; - $result["RCVD_59_POS"] = 0; - $result["SENT_EXCHANGE_COUNT"] = 0; - $result["RCVD_EXCHANGE_COUNT"] = 0; - //return result + //return error result + $result = []; + $result['error'] = __("Broken CBR file - no QSO data found."); return $result; } //abort if basic things (Callsign and Contest ID) are not included in the header $header_fields = array_keys($header); if(!in_array('CALLSIGN', $header_fields) or !in_array('CONTEST', $header_fields)){ + + //return error result $result = []; - $result["HEADER"] = $header; - $result["QSOS"] = []; - $result["SENT_59_POS"] = 0; - $result["RCVD_59_POS"] = 0; - $result["SENT_EXCHANGE_COUNT"] = 0; - $result["RCVD_EXCHANGE_COUNT"] = 0; - - //return blank result + $result['error'] = __("Broken CBR file - incomplete header found."); return $result; } @@ -120,6 +152,15 @@ class CBR_Parser $sent_59_pos = min($common_59_indices); $rcvd_59_pos = max($common_59_indices); + //abort if position of sent and received signal exchange is identical + if($sent_59_pos == $rcvd_59_pos){ + + //return error result + $result = []; + $result['error'] = __("Broken CBR file - no valid exchange or callsigns found"); + return $result; + } + //get codeigniter instance $CI = &get_instance(); @@ -171,7 +212,7 @@ class CBR_Parser //get all remaining received exchanges $exchange_nr = 1; $startindex = ($rcvd_59_pos + ($serial_number_present ? 2 : 1)); - $endindex = (count($line)); + $endindex = count($line) - ($trx_number_present ? 1 : 0); for ($i = $startindex; $i < $endindex; $i++) { $qso_line["RCVD_EXCH_" . $exchange_nr] = $line[$i]; $exchange_nr++; @@ -200,12 +241,15 @@ class CBR_Parser case '144': $band = '2m'; break; + case '220': case '222': $band = '1.25m'; break; + case '430': case '432': $band = '70cm'; break; + case '900': case '902': $band = '33cm'; break; @@ -292,7 +336,7 @@ class CBR_Parser $result["SENT_59_POS"] = $sent_59_pos; $result["RCVD_59_POS"] = $rcvd_59_pos; $result["SENT_EXCHANGE_COUNT"] = $rcvd_59_pos - $sent_59_pos - ($serial_number_present ? 3 : 2); - $result["RCVD_EXCHANGE_COUNT"] = $max_qso_fields - 1 - $rcvd_59_pos - ($serial_number_present ? 1 : 0); + $result["RCVD_EXCHANGE_COUNT"] = $max_qso_fields - 1 - $rcvd_59_pos - ($serial_number_present ? 1 : 0) - ($trx_number_present ? 1 : 0); //return result return $result; diff --git a/application/views/adif/import.php b/application/views/adif/import.php index 93b778f1e..7f87c9a51 100644 --- a/application/views/adif/import.php +++ b/application/views/adif/import.php @@ -410,6 +410,10 @@ echo ''; } ?> +