Merge pull request #594 from magicbug/lotw-sync

Lotw sync
这个提交包含在:
Peter Goodhall 2020-09-02 11:26:03 +01:00 提交者 GitHub
当前提交 33055f5ab0
找不到此签名对应的密钥
GPG 密钥 ID: 4AEE18F83AFDEB23
共有 20 个文件被更改,包括 980 次插入24 次删除

查看文件

@ -80,7 +80,7 @@ $autoload['helper'] = array('url', 'security');
|
*/
$autoload['config'] = array('cloudlog', 'bands');
$autoload['config'] = array('cloudlog', 'bands', 'lotw');
/*

19
application/config/lotw.php 普通文件
查看文件

@ -0,0 +1,19 @@
<?php
defined('BASEPATH') OR exit('No direct script access allowed');
/*
*
* Configuration file for all things relating to LOTW
*
*/
/*
|--------------------------------------------------------------------------
| Folder location for storing P12 certficiate files on the system
|--------------------------------------------------------------------------
|
| This folder must be outside of your www root for security reasons
|
*/
$config['lotw_keys_folder'] = "";

查看文件

@ -21,7 +21,8 @@ $config['migration_enabled'] = TRUE;
| be upgraded / downgraded to.
|
*/
$config['migration_version'] = 42;
$config['migration_version'] = 48;
/*
|--------------------------------------------------------------------------

查看文件

@ -117,7 +117,7 @@ return array(
'json' => array('application/json', 'text/json'),
'pem' => array('application/x-x509-user-cert', 'application/x-pem-file', 'application/octet-stream'),
'p10' => array('application/x-pkcs10', 'application/pkcs10'),
'p12' => 'application/x-pkcs12',
'p12' => 'application/octet-stream',
'p7a' => 'application/x-pkcs7-signature',
'p7c' => array('application/pkcs7-mime', 'application/x-pkcs7-mime'),
'p7m' => array('application/pkcs7-mime', 'application/x-pkcs7-mime'),

查看文件

@ -1,6 +1,22 @@
<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
class Lotw extends CI_Controller {
/*
|--------------------------------------------------------------------------
| Controller: Lotw
|--------------------------------------------------------------------------
|
| This Controller handles all things LOTW, upload and download.
|
|
| Note:
| If you plan on using any of the code within this class please credit
| Cloudlog or Peter, 2M0SQL, a lot of hard work went into building the
| signing of files.
|
| Big Thanks to Rodrigo PY2RAF for all the help and information about OpenSSL
|
*/
/* Controls who can access the controller and its functions */
function __construct()
@ -9,6 +25,359 @@ class Lotw extends CI_Controller {
$this->load->helper(array('form', 'url'));
}
/*
|--------------------------------------------------------------------------
| Function: index
|--------------------------------------------------------------------------
|
| Default function for the controller which loads when doing /lotw
| this shows all the uploaded lotw p12 certificates the user has uploaded
|
*/
public function index() {
// Load required models for page generation
$this->load->model('LotwCert');
// Get Array of the logged in users LOTW certs.
$data['lotw_cert_results'] = $this->LotwCert->lotw_certs($this->session->userdata('user_id'));
// Set Page Title
$data['page_title'] = "Logbook of the World";
// Load Views
$this->load->view('interface_assets/header', $data);
$this->load->view('lotw_views/index');
$this->load->view('interface_assets/footer');
}
/*
|--------------------------------------------------------------------------
| Function: cert_upload
|--------------------------------------------------------------------------
|
| Nothing fancy just shows the cert_upload form for uploading p12 files
|
*/
public function cert_upload() {
// Set Page Title
$data['page_title'] = "Logbook of the World";
// Load Views
$this->load->view('interface_assets/header', $data);
$this->load->view('lotw_views/upload_cert', array('error' => ' ' ));
$this->load->view('interface_assets/footer');
}
/*
|--------------------------------------------------------------------------
| Function: do_cert_upload
|--------------------------------------------------------------------------
|
| do_cert_upload is called from cert_upload form submit and handles uploading
| and processing of p12 files and storing the data into mysql
|
*/
public function do_cert_upload()
{
$config['upload_path'] = './uploads/lotw/certs';
$config['allowed_types'] = 'p12';
$this->load->library('upload', $config);
if ( ! $this->upload->do_upload('userfile'))
{
// Upload of P12 Failed
$error = array('error' => $this->upload->display_errors());
// Set Page Title
$data['page_title'] = "Logbook of the World";
// Load Views
$this->load->view('interface_assets/header', $data);
$this->load->view('lotw_views/upload_cert', $error);
$this->load->view('interface_assets/footer');
}
else
{
// Load database queries
$this->load->model('LotwCert');
//Upload of P12 successful
$data = array('upload_data' => $this->upload->data());
$info = $this->decrypt_key($data['upload_data']['full_path']);
// Check to see if certificate is already in the system
$new_certficiate = $this->LotwCert->find_cert($info['issued_callsign'], $this->session->userdata('user_id'));
// Check DXCC & Store Country Name
$this->load->model('Logbook_model');
$dxcc_check = $this->Logbook_model->check_dxcc_table($info['issued_callsign'], $info['validFrom']);
$dxcc = $dxcc_check[1];
if($new_certficiate == 0) {
// New Certificate Store in Database
// Store Certificate Data into MySQL
$this->LotwCert->store_certficiate($this->session->userdata('user_id'), $info['issued_callsign'], $dxcc, $info['validFrom'], $info['validTo_Date'], $info['pem_key'], $info['general_cert']);
// Cert success flash message
$this->session->set_flashdata('Success', $info['issued_callsign'].' Certficiate Imported.');
} else {
// Certficiate is in the system time to update
$this->LotwCert->update_certficiate($this->session->userdata('user_id'), $info['issued_callsign'], $dxcc, $info['validFrom'], $info['validTo_Date'], $info['pem_key'], $info['general_cert']);
// Cert success flash message
$this->session->set_flashdata('Success', $info['issued_callsign'].' Certficiate Updated.');
}
// p12 certificate processed time to delete the file
unlink($data['upload_data']['full_path']);
// Get Array of the logged in users LOTW certs.
$data['lotw_cert_results'] = $this->LotwCert->lotw_certs($this->session->userdata('user_id'));
// Set Page Title
$data['page_title'] = "Logbook of the World";
// Load Views
$this->load->view('interface_assets/header', $data);
$this->load->view('lotw_views/index');
$this->load->view('interface_assets/footer');
}
}
/*
|--------------------------------------------------------------------------
| Function: lotw_upload
|--------------------------------------------------------------------------
|
| This function Uploads to LOTW
|
*/
public function lotw_upload() {
// Get Station Profile Data
$this->load->model('Stations');
$station_profiles = $this->Stations->all();
// Array of QSO IDs being Uploaded
$qso_id_array = array();
if ($station_profiles->num_rows() >= 1) {
foreach ($station_profiles->result() as $station_profile)
{
// Get Certificate Data
$this->load->model('LotwCert');
$data['station_profile'] = $station_profile;
$data['lotw_cert_info'] = $this->LotwCert->lotw_cert_details($station_profile->station_callsign);
$this->load->model('Dxcc');
$data['station_profile_dxcc'] = $this->Dxcc->lookup_country($data['lotw_cert_info']->cert_dxcc);
// Get QSOs
$this->load->model('Logbook_model');
$data['qsos'] = $this->Logbook_model->get_lotw_qsos_to_upload($data['station_profile']->station_id, $data['lotw_cert_info']->date_created, $data['lotw_cert_info']->date_expires);
foreach ($data['qsos']->result() as $temp_qso) {
array_push($qso_id_array, $temp_qso->COL_PRIMARY_KEY);
}
//$this->load->view('lotw_views/adif_views/adif_export', $data);
// Build File to save
$adif_to_save = $this->load->view('lotw_views/adif_views/adif_export', $data, TRUE);
// Build Filename
$filename_for_saving = $data['lotw_cert_info']->callsign."-".date("Y-m-d-H-i-s")."-cloudlog.tq8";
$gzdata = gzencode($adif_to_save, 9);
$fp = fopen($filename_for_saving, "w");
fwrite($fp, $gzdata);
fclose($fp);
//The URL that accepts the file upload.
$url = 'https://lotw.arrl.org/lotw/upload';
//The name of the field for the uploaded file.
$uploadFieldName = 'upfile';
//The full path to the file that you want to upload
$filePath = realpath($filename_for_saving);
//Initiate cURL
$ch = curl_init();
//Set the URL
curl_setopt($ch, CURLOPT_URL, $url);
//Set the HTTP request to POST
curl_setopt($ch, CURLOPT_POST, true);
//Tell cURL to return the output as a string.
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
//If the function curl_file_create exists
if(function_exists('curl_file_create')){
//Use the recommended way, creating a CURLFile object.
$filePath = curl_file_create($filePath);
} else{
//Otherwise, do it the old way.
//Get the canonicalized pathname of our file and prepend
//the @ character.
$filePath = '@' . realpath($filePath);
//Turn off SAFE UPLOAD so that it accepts files
//starting with an @
curl_setopt($ch, CURLOPT_SAFE_UPLOAD, false);
}
//Setup our POST fields
$postFields = array(
$uploadFieldName => $filePath
);
curl_setopt($ch, CURLOPT_POSTFIELDS, $postFields);
//Execute the request
$result = curl_exec($ch);
//If an error occured, throw an exception
//with the error message.
if(curl_errno($ch)){
throw new Exception(curl_error($ch));
}
$pos = strpos($result, "<!-- .UPL. accepted -->");
if ($pos === false) {
// Upload of TQ8 Failed for unknown reason
echo "Upload Failed";
} else {
// Upload of TQ8 was successfull
echo "Upload Successful - ".$filename_for_saving;
$this->LotwCert->last_upload($data['lotw_cert_info']->lotw_cert_id);
// Mark QSOs as Sent
foreach ($qso_id_array as $qso_number) {
$this->Logbook_model->mark_lotw_sent($qso_number);
}
}
// Delete TQ8 File - This is done regardless of whether upload was succcessful
unlink(realpath($filename_for_saving));
}
} else {
echo "No Station Profiles";
}
}
/*
|--------------------------------------------------------------------------
| Function: delete_cert
|--------------------------------------------------------------------------
|
| Deletes LOTW certificate from the MySQL table
|
*/
public function delete_cert($cert_id) {
$this->load->model('LotwCert');
$this->LotwCert->delete_certficiate($this->session->userdata('user_id'), $cert_id);
$this->session->set_flashdata('Success', 'Certficiate Deleted.');
redirect('/lotw/');
}
/*
|--------------------------------------------------------------------------
| Function: peter
|--------------------------------------------------------------------------
|
| Temp function to test development bits
|
*/
public function peter() {
$this->load->model('LotwCert');
$this->load->model('Logbook_model');
$dxcc = $this->Logbook_model->check_dxcc_table("2M0SQL", "2020-05-07 17:20:27");
print_r($dxcc);
// Get Array of the logged in users LOTW certs.
echo $this->LotwCert->find_cert($this->session->userdata('user_id'), "2M0SQL");
}
/*
|--------------------------------------------------------------------------
| Function: decrypt_key
|--------------------------------------------------------------------------
|
| Accepts p12 file and optional password and encrypts the file returning
| the required fields for LOTW and the PEM Key
|
*/
public function decrypt_key($file, $password = "") {
$results = array();
$password = $password; // Only needed if 12 has a password set
$filename = file_get_contents('file://'.$file);
$worked = openssl_pkcs12_read($filename, $results, $password);
$data['general_cert'] = $results['cert'];
if($worked) {
// Reading p12 successful
$new_password = "cloudlog"; // set default password
$result = null;
$worked = openssl_pkey_export($results['pkey'], $result, $new_password);
if($worked) {
// Store PEM Key in Array
$data['pem_key'] = $result;
} else {
// Error Log Error Message
log_message('error', openssl_error_string());
// Set warning message redirect to LOTW main page
$this->session->set_flashdata('Warning', openssl_error_string());
redirect('/lotw/');
}
} else {
// Reading p12 failed log error message
log_message('error', openssl_error_string());
// Set warning message redirect to LOTW main page
$this->session->set_flashdata('Warning', openssl_error_string());
redirect('/lotw/');
}
// Read Cert Data
$certdata= openssl_x509_parse($results['cert'],0);
// Store Variables
$data['issued_callsign'] = $certdata['subject']['undefined'];
$data['issued_name'] = $certdata['subject']['commonName'];
$data['validFrom'] = $certdata['extensions']['1.3.6.1.4.1.12348.1.2'];
$data['validTo_Date'] = $certdata['extensions']['1.3.6.1.4.1.12348.1.3'];
return $data;
}
private function loadFromFile($filepath)
{
$this->load->model('user_model');
@ -206,7 +575,7 @@ class Lotw extends CI_Controller {
$this->load->model('user_model');
if(!$this->user_model->authorize(2)) { $this->session->set_flashdata('notice', 'You\'re not allowed to do that!'); redirect('dashboard'); }
$data['page_title'] = "LoTW .TQ8 Upload";
$data['page_title'] = "LoTW .TQ8 Upload";
$config['upload_path'] = './uploads/';
$config['allowed_types'] = 'tq8|TQ8';
@ -367,4 +736,24 @@ class Lotw extends CI_Controller {
}
function signlog($sign_key, $string) {
$qso_string = $string;
$key = $sign_key;
$pkeyid = openssl_pkey_get_private($key, 'cloudlog');
//openssl_sign($plaintext, $signature, $pkeyid, OPENSSL_ALGO_SHA1 );
//openssl_free_key($pkeyid);
if(openssl_sign($qso_string, $signature, $pkeyid, OPENSSL_ALGO_SHA1)) {
openssl_free_key($pkeyid);
$signature_b64 = base64_encode($signature);
return $signature_b64;
}
}
} // end class

查看文件

@ -0,0 +1,46 @@
<?php
defined('BASEPATH') OR exit('No direct script access allowed');
class Migration_add_lotw_certs_table extends CI_Migration {
public function up()
{
$this->dbforge->add_field(array(
'lotw_cert_id' => array(
'type' => 'INT',
'constraint' => 1,
'unsigned' => TRUE,
'auto_increment' => TRUE
),
'callsign' => array(
'type' => 'VARCHAR',
'constraint' => '100',
),
'cert_dxcc' => array(
'type' => 'VARCHAR',
'constraint' => '255',
),
'date_created' => array(
'type' => 'DATETIME',
'null' => TRUE,
),
'date_expires' => array(
'type' => 'DATETIME',
'null' => TRUE,
),
));
$this->dbforge->add_key('lotw_cert_id', TRUE);
$this->dbforge->create_table('lotw_certs');
}
public function down()
{
$this->dbforge->drop_table('lotw_certs');
}
}

查看文件

@ -0,0 +1,21 @@
<?php
defined('BASEPATH') OR exit('No direct script access allowed');
class Migration_add_key_to_lotw_certs extends CI_Migration {
public function up()
{
$fields = array(
'cert_key TEXT',
);
$this->dbforge->add_column('lotw_certs', $fields);
}
public function down()
{
$this->dbforge->drop_column('lotw_certs', 'key');
}
}

查看文件

@ -0,0 +1,21 @@
<?php
defined('BASEPATH') OR exit('No direct script access allowed');
class Migration_add_userid_to_lotw_certs extends CI_Migration {
public function up()
{
$fields = array(
'user_id int(11) DEFAULT NULL',
);
$this->dbforge->add_column('lotw_certs', $fields);
}
public function down()
{
$this->dbforge->drop_column('lotw_certs', 'user_id');
}
}

查看文件

@ -0,0 +1,21 @@
<?php
defined('BASEPATH') OR exit('No direct script access allowed');
class Migration_add_last_upload_to_lotw_certs extends CI_Migration {
public function up()
{
$fields = array(
'last_upload DATETIME DEFAULT NULL',
);
$this->dbforge->add_column('lotw_certs', $fields);
}
public function down()
{
$this->dbforge->drop_column('lotw_certs', 'last_upload');
}
}

查看文件

@ -0,0 +1,21 @@
<?php
defined('BASEPATH') OR exit('No direct script access allowed');
class Migration_add_cert_to_lotw_certs extends CI_Migration {
public function up()
{
$fields = array(
'cert TEXT',
);
$this->dbforge->add_column('lotw_certs', $fields);
}
public function down()
{
$this->dbforge->drop_column('lotw_certs', 'cert');
}
}

查看文件

@ -0,0 +1,20 @@
<?php
defined('BASEPATH') OR exit('No direct script access allowed');
class Migration_add_county_to_stationprofile extends CI_Migration {
public function up()
{
$fields = array(
'county varchar(255) DEFAULT NULL',
);
$this->dbforge->add_column('station_profile', $fields);
}
public function down()
{
$this->dbforge->drop_column('station_profile', 'county');
}
}

查看文件

@ -463,7 +463,7 @@ class DXCC extends CI_Model {
}
return $sql;
}
/*
* Function gets worked and confirmed summary on each band on the active stationprofile
*/
@ -520,5 +520,18 @@ class DXCC extends CI_Model {
return $query->result();
}
function lookup_country($country)
{
$query = $this->db->query('
SELECT *
FROM dxcc_entities
WHERE name = "'.$country.'"
ORDER BY LENGTH( prefix ) DESC
LIMIT 1
');
return $query->row();
}
}
?>

查看文件

@ -2209,7 +2209,37 @@ class Logbook_model extends CI_Model {
return null;
}
}
function get_lotw_qsos_to_upload($station_id, $start_date, $end_date) {
$this->db->select('COL_PRIMARY_KEY,COL_CALL, COL_BAND, COL_BAND_RX, COL_TIME_ON, COL_RST_RCVD, COL_RST_SENT, COL_MODE, COL_FREQ, COL_FREQ_RX, COL_GRIDSQUARE, COL_SAT_NAME, COL_PROP_MODE, COL_LOTW_QSL_SENT, station_id');
$this->db->where("station_id", $station_id);
$this->db->where('COL_LOTW_QSL_SENT !=', "Y");
$this->db->where('COL_PROP_MODE !=', "INTERNET");
$this->db->where('COL_TIME_ON >=', $start_date);
$this->db->where('COL_TIME_ON <=', $end_date);
$this->db->order_by("COL_TIME_ON", "desc");
$query = $this->db->get($this->config->item('table_name'));
return $query;
}
function mark_lotw_sent($qso_id) {
$data = array(
'COL_LOTW_QSLSDATE' => date("Y-m-d H:i:s"),
'COL_LOTW_QSL_SENT' => 'Y',
);
$this->db->where('COL_PRIMARY_KEY', $qso_id);
$this->db->update($this->config->item('table_name'), $data);
return "Updated";
}
}
function validateADIFDate($date, $format = 'Ymd')

查看文件

@ -1,16 +0,0 @@
<?php
class LOTW extends CI_Model {
function __construct()
{
// Call the Model constructor
parent::__construct();
}
function empty_table($table) {
$this->db->empty_table($table);
}
}
?>

查看文件

@ -0,0 +1,95 @@
<?php
class LotwCert extends CI_Model {
function __construct()
{
// Call the Model constructor
parent::__construct();
}
/*
|--------------------------------------------------------------------------
| Function: lotw_certs
|--------------------------------------------------------------------------
|
| Returns all lotw_certs for a selected user via the $user_id parameter
|
*/
function lotw_certs($user_id) {
$this->db->where('user_id', $user_id);
$this->db->group_by("callsign");
$this->db->order_by('cert_dxcc', 'ASC');
$query = $this->db->get('lotw_certs');
return $query;
}
function lotw_cert_details($callsign) {
$this->db->where('callsign', $callsign);
$query = $this->db->get('lotw_certs');
return $query->row();
}
function find_cert($callsign, $user_id) {
$this->db->where('user_id', $user_id);
$this->db->where('callsign', $callsign);
$query = $this->db->get('lotw_certs');
return $query->num_rows();
}
function store_certficiate($user_id, $callsign, $dxcc, $date_created, $date_expires, $cert_key, $general_cert) {
$data = array(
'user_id' => $user_id,
'callsign' => $callsign,
'cert_dxcc' => $dxcc,
'date_created' => $date_created,
'date_expires' => $date_expires,
'cert_key' => $cert_key,
'cert' => $general_cert,
);
$this->db->insert('lotw_certs', $data);
}
function update_certficiate($user_id, $callsign, $dxcc, $date_created, $date_expires, $cert_key, $general_cert) {
$data = array(
'cert_dxcc' => $dxcc,
'date_created' => $date_created,
'date_expires' => $date_expires,
'cert_key' => $cert_key,
'cert' => $general_cert
);
$this->db->where('user_id', $user_id);
$this->db->where('callsign', $callsign);
$this->db->update('lotw_certs', $data);
}
function delete_certficiate($user_id, $lotw_cert_id) {
$this->db->where('lotw_cert_id', $lotw_cert_id);
$this->db->where('user_id', $user_id);
$this->db->delete('lotw_certs');
}
function last_upload($certID) {
$data = array(
'last_upload' => date("Y-m-d H:i:s"),
);
$this->db->where('lotw_cert_id', $certID);
$this->db->update('lotw_certs', $data);
return "Updated";
}
function empty_table($table) {
$this->db->empty_table($table);
}
}
?>

查看文件

@ -110,7 +110,7 @@
<div class="dropdown-divider"></div>
<a class="dropdown-item" href="<?php echo site_url('lotw/import');?>" title="LoTW Import"><i class="fas fa-sync"></i> LoTW Import</a>
<a class="dropdown-item" href="<?php echo site_url('lotw');?>" title="LoTW Import"><i class="fas fa-sync"></i> LoTW</a>
<div class="dropdown-divider"></div>

查看文件

@ -0,0 +1,137 @@
<?php
$clean_cert = trim($lotw_cert_info->cert);
$cert1 = str_replace("-----BEGIN CERTIFICATE-----", "", $clean_cert);
$cert2 = str_replace("-----END CERTIFICATE-----", "", $cert1);
?>
<TQSL_IDENT:54>TQSL V2.5.4 Lib: V2.5 Config: V11.12 AllowDupes: false
<Rec_Type:5>tCERT
<CERT_UID:1>1
<CERTIFICATE:<?php echo strlen(trim($cert2)) + 1; ?>><?php echo trim($cert2); ?>
<eor>
<Rec_Type:8>tSTATION
<STATION_UID:1>1
<CERT_UID:1>1
<CALL:<?php echo strlen($lotw_cert_info->callsign); ?>><?php echo $lotw_cert_info->callsign; ?>
<DXCC:<?php echo strlen($station_profile_dxcc->adif); ?>><?php echo $station_profile_dxcc->adif; ?>
<?php if(isset($station_profile->station_gridsquare)) { ?><GRIDSQUARE:<?php echo strlen($station_profile->station_gridsquare); ?>><?php echo $station_profile->station_gridsquare; ?><?php } ?>
<?php if(isset($station_profile->station_itu)) { ?><ITUZ:<?php echo strlen($station_profile->station_itu); ?>><?php echo $station_profile->station_itu; ?><?php } ?>
<?php if(isset($station_profile->station_cq)) { ?><CQZ:<?php echo strlen($station_profile->station_cq); ?>><?php echo $station_profile->station_cq; ?><?php } ?>
<?php if(isset($station_profile->station_iota)) { ?><IOTA:<?php echo strlen($station_profile->station_iota); ?>><?php echo $station_profile->station_iota; ?><?php } ?>
<?php if(isset($station_profile->state) && $station_profile->station_country = "UNITED STATES OF AMERICA") { ?><US_STATE:<?php echo strlen($station_profile->state); ?>><?php echo $station_profile->state; ?><?php } ?>
<?php if(isset($station_profile->station_cnty) && $station_profile->station_country = "UNITED STATES OF AMERICA") { ?><US_COUNTY:<?php echo strlen($station_profile->station_cnty); ?>><?php echo $station_profile->station_cnty; ?><?php } ?>
<eor>
<?php foreach ($qsos->result() as $qso) { ?>
<Rec_Type:8>tCONTACT
<STATION_UID:1>1
<CALL:<?php echo strlen($qso->COL_CALL); ?>><?php echo $qso->COL_CALL; ?>
<BAND:<?php echo strlen($qso->COL_BAND); ?>><?php echo strtoupper($qso->COL_BAND); ?>
<MODE:<?php echo strlen($qso->COL_MODE); ?>><?php echo strtoupper($qso->COL_MODE); ?>
<?php if($qso->COL_FREQ != "" || $qso->COL_FREQ != "0") { ?><?php $freq_in_mhz = $qso->COL_FREQ / 1000000; ?><FREQ:<?php echo strlen($freq_in_mhz); ?>><?php echo $freq_in_mhz; ?><?php } ?>
<?php if($qso->COL_FREQ_RX != "" || $qso->COL_FREQ_RX != "0") { ?><?php $freq_in_mhz_rx = $qso->COL_FREQ_RX / 1000000; ?><FREQ_RX:<?php echo strlen($freq_in_mhz_rx); ?>><?php echo $freq_in_mhz_rx; ?><?php } ?>
<?php if($qso->COL_PROP_MODE) { ?><PROP_MODE:<?php echo strlen($qso->COL_PROP_MODE); ?>><?php echo strtoupper($qso->COL_PROP_MODE); ?><?php } ?>
<?php if($qso->COL_SAT_NAME) { ?><SAT_NAME:<?php echo strlen($qso->COL_SAT_NAME); ?>><?php echo strtoupper($qso->COL_SAT_NAME); ?><?php } ?>
<?php if($qso->COL_BAND_RX) { ?><BAND_RX:<?php echo strlen($qso->COL_BAND_RX); ?>><?php echo strtoupper($qso->COL_BAND_RX); ?><?php } ?>
<?php $date_on = strtotime($qso->COL_TIME_ON); $new_date = date('Y-m-d', $date_on); ?>
<QSO_DATE:<?php echo strlen($new_date); ?>><?php echo $new_date; ?>
<?php $time_on = strtotime($qso->COL_TIME_ON); $new_on = date('H:i:s', $time_on); ?>
<QSO_TIME:<?php echo strlen($new_on."Z"); ?>><?php echo $new_on."Z"; ?>
<?php
$sign_string = "";
// Add CQ Zone
if($station_profile->station_cq) {
$sign_string .= $station_profile->station_cq;
}
// Add Gridsquare
if($station_profile->station_gridsquare) {
$sign_string .= strtoupper($station_profile->station_gridsquare);
}
if($station_profile->station_iota) {
$sign_string .= strtoupper($station_profile->station_iota);
}
if($station_profile->station_itu) {
$sign_string .= $station_profile->station_itu;
}
if(isset($station_profile->state) && $station_profile->station_country = "UNITED STATES OF AMERICA") {
$sign_string .= strtoupper($station_profile->state);
}
if($qso->COL_BAND) {
$sign_string .= strtoupper($qso->COL_BAND);
}
if($qso->COL_BAND_RX) {
$sign_string .= strtoupper($qso->COL_BAND_RX);
}
if($qso->COL_CALL) {
$sign_string .= strtoupper($qso->COL_CALL);
}
if($freq_in_mhz) {
$sign_string .= strtoupper($freq_in_mhz);
}
if($qso->COL_FREQ_RX != "" || $qso->COL_FREQ_RX != "0") {
$sign_string .= strtoupper($freq_in_mhz_rx);
}
if($qso->COL_MODE) {
$sign_string .= strtoupper($qso->COL_MODE);
}
if($qso->COL_PROP_MODE) {
$sign_string .= strtoupper($qso->COL_PROP_MODE);
}
$sign_string .= $new_date;
$sign_string .= $new_on."Z";
if($qso->COL_SAT_NAME) {
$sign_string .= strtoupper($qso->COL_SAT_NAME);
}
?>
<?php
$CI =& get_instance();
$signed_item = $CI->signlog($lotw_cert_info->cert_key, $sign_string);
?>
<SIGN_LOTW_V2.0:<?php echo strlen($signed_item)+1; ?>:6><?php echo $signed_item; ?>
<SIGNDATA:<?php echo strlen($sign_string); ?>><?php echo $sign_string; ?>
<eor>
<?php } ?>

查看文件

@ -0,0 +1,95 @@
<div class="container lotw">
<br>
<a class="btn btn-success btn-sm float-right" href="<?php echo site_url('/lotw/import'); ?>" role="button"><i class="fas fa-cloud-upload-alt"></i> LoTW Import</a><h1><?php echo $page_title; ?></h1>
<div class="alert alert-danger" role="alert">
<i class="fas fa-exclamation-triangle"></i> Please be aware that LoTw Sync is BETA, you might get errors, this isn't fully production ready.
</div>
<!-- Card Starts -->
<div class="card">
<div class="card-header">
<a class="btn btn-success btn-sm float-right" href="<?php echo site_url('/lotw/cert_upload'); ?>" role="button"><i class="fas fa-cloud-upload-alt"></i> Upload Certificate</a><i class="fab fa-expeditedssl"></i> Available Certificates
</div>
<div class="card-body">
<?php if(isset($error)) { ?>
<div class="alert alert-danger" role="alert">
<?php echo $error; ?>
</div>
<?php } ?>
<?php if(isset($_SESSION['Success'])) { ?>
<div class="alert alert-success" role="alert">
<?php echo $_SESSION['Success']; ?>
</div>
<?php } ?>
<?php if ($lotw_cert_results->num_rows() > 0) { ?>
<div class="table-responsive">
<table class="table table-hover">
<thead class="thead-light">
<tr>
<th scope="col">Callsign</th>
<th scope="col">DXCC</th>
<th scope="col">Date Created</th>
<th scope="col">Date Expires</th>
<th scope="col">Status</th>
<th scope="col">Options</th>
</tr>
</thead>
<tbody>
<?php foreach ($lotw_cert_results->result() as $row) { ?>
<tr>
<td><?php echo $row->callsign; ?></td>
<td><?php echo ucfirst($row->cert_dxcc); ?></td>
<td><?php
$valid_form = strtotime( $row->date_created );
$new_valid_from = date($this->config->item('qso_date_format'), $valid_form );
echo $new_valid_from; ?>
</td>
<td>
<?php
$valid_to = strtotime( $row->date_expires );
$new_valid_to = date($this->config->item('qso_date_format'), $valid_to );
echo $new_valid_to; ?>
</td>
<td>
<?php $current_date = date('Y-m-d H:i:s'); ?>
<?php if ($current_date <= $row->date_expires) { ?>
<span class="badge badge-success">Valid</span>
<?php } else { ?>
<span class="badge badge-dark">Expired</span>
<?php } ?>
<?php if ($row->last_upload) { ?>
<span class="badge badge-success"><?php echo $row->last_upload; ?></span>
<?php } else { ?>
<span class="badge badge-warning">Not Synced</span>
<?php } ?>
</td>
<td>
<a class="btn btn-primary btn-sm" href="<?php echo site_url('lotw/delete_cert/'.$row->lotw_cert_id); ?>" role="button"><i class="far fa-trash-alt"></i> Delete</a>
</td>
</tr>
<?php } ?>
</tbody>
</table>
</div>
<?php } else { ?>
<div class="alert alert-info" role="alert">
You need to upload some LoTW p12 certificates to use this area.
</div>
<?php } ?>
</div>
</div>
<!-- Card Ends -->
</div>

查看文件

@ -0,0 +1,43 @@
<div class="container lotw">
<h1><?php echo $page_title; ?></h1>
<!-- Card Starts -->
<div class="card">
<div class="card-header">
Upload Logbook of the World .p12 Certificate
</div>
<div class="card-body">
<?php if($error != " ") { ?>
<div class="alert alert-danger" role="alert">
<?php echo $error; ?>
</div>
<?php } ?>
<div class="alert alert-info" role="alert">
<h5>Export .p12 File Instructions</h5>
<ul>
<li>Open TQSL & go to the Callsign Certificates Tab</li>
<li>Right Flick on desired Callsign</li>
<li>Click "Save Callsign Certificate File" and do not add a password</li>
<li>Upload File below.</li>
</ul>
</div>
<?php echo form_open_multipart('lotw/do_cert_upload');?>
<div class="form-group">
<label for="exampleFormControlFile1">Upload LoTW P12 File</label>
<input type="file" name="userfile" class="form-control-file" id="exampleFormControlFile1">
</div>
<button type="submit" value="upload" class="btn btn-primary">Upload File</button>
</form>
</div>
</div>
<!-- Card Ends -->
</div>

查看文件

@ -53,7 +53,7 @@
<small id="stationDXCCInputHelp" class="form-text text-muted">Station DXCC</small>
</div>
<div class="form-group">
<div class="form-group">
<label for="stationCityInput">Station City</label>
<input type="text" class="form-control" name="city" id="stationCityInput" aria-describedby="stationCityInputHelp" required>
<small id="stationCityInputHelp" class="form-text text-muted">Station City for example Inverness</small>