From 53777b47e73d2d6ba3ac688a3e008028e79cdc36 Mon Sep 17 00:00:00 2001 From: HB9HIL Date: Fri, 20 Feb 2026 01:24:27 +0100 Subject: [PATCH 1/9] use cache and it's already built in timebased invalidation for the callbook session keys --- application/libraries/Callbook.php | 90 +++++++++++++++++++++--------- 1 file changed, 65 insertions(+), 25 deletions(-) diff --git a/application/libraries/Callbook.php b/application/libraries/Callbook.php index d3bbe6ab1..a9eadcc9d 100644 --- a/application/libraries/Callbook.php +++ b/application/libraries/Callbook.php @@ -10,8 +10,48 @@ class Callbook { private $ci; + // Duration of session keys + + // QRZ.com + // They write that session keys have no guaranteed lifetime. We should cache it to reuse it, but also be prepared + // to get a new one if the session key is invalid. + // Older documents showed that the duration was between 12-24 hours. So we set it to 4 hours to be on the safe side. + // Ref.: https://www.qrz.com/docs/xml/current_spec.html + const QRZ_SESSION_DURATION = 14400; // 4 hours + private $qrz_session_cachekey = null; + + // QRZCQ.com + // I could not find any information about session key duration on their website. Let's cache it for at least 55 minutes. + // In code we are prepared for an invalid session key, so if the session key is invalid we will get a new one and retry the search. + // Ref.: https://www.qrzcq.com/docs/api/xml/ + const QRZCQ_SESSION_DURATION = 3300; // 55 minutes + private $qrzcq_session_cachekey = null; + + // HamQTH.com + // Session Key is valid for 1 hour according to their documentation. We set it just a few moments below that to 55 Minutes. + // Ref.: https://www.hamqth.com/developers.php + const HAMQTH_SESSION_DURATION = 3300; // 55 minutes + private $hamqth_session_cachekey = null; + + // QRZRU.com + // Session Key is valid for 1 hour according to their documentation. We set it just a few moments below that to 55 Minutes. + // Ref.: https://www.qrz.ru/help/api/xml + const QRZRU_SESSION_DURATION = 3300; // 55 minutes + private $qrzru_session_cachekey = null; + public function __construct() { $this->ci = & get_instance(); + + $this->ci->load->is_loaded('cache') ?: $this->ci->load->driver('cache', [ + 'adapter' => $this->ci->config->item('cache_adapter') ?? 'file', + 'backup' => $this->ci->config->item('cache_backup') ?? 'file', + 'key_prefix' => $this->ci->config->item('cache_key_prefix') ?? '' + ]); + + $this->qrz_session_cachekey = 'qrz_session_key_'.$this->ci->config->item('qrz_username'); + $this->qrzcq_session_cachekey = 'qrzcq_session_key_'.$this->ci->config->item('qrzcq_username'); + $this->hamqth_session_cachekey = 'hamqth_session_key_'.$this->ci->config->item('hamqth_username'); + $this->qrzru_session_cachekey = 'qrzru_session_key_'.$this->ci->config->item('qrzru_username'); } // TODO: @@ -95,24 +135,24 @@ class Callbook { } else { $username = $this->ci->config->item('qrz_username'); $password = $this->ci->config->item('qrz_password'); - - if (!$this->ci->session->userdata('qrz_session_key')) { + + if (!$this->ci->cache->get($this->qrz_session_cachekey)) { $qrz_session_key = $this->ci->qrz->session($username, $password); - $this->ci->session->set_userdata('qrz_session_key', $qrz_session_key); + $this->ci->cache->save($this->qrz_session_cachekey, $qrz_session_key, self::QRZ_SESSION_DURATION); } - $callbook = $this->ci->qrz->search($callsign, $this->ci->session->userdata('qrz_session_key'), $fullname); + $callbook = $this->ci->qrz->search($callsign, $this->ci->cache->get($this->qrz_session_cachekey), $fullname); if ($callbook['error'] ?? '' == 'Invalid session key') { $qrz_session_key = $this->ci->qrz->session($username, $password); - $this->ci->session->set_userdata('qrz_session_key', $qrz_session_key); - $callbook = $this->ci->qrz->search($callsign, $this->ci->session->userdata('qrz_session_key'), $fullname); + $this->ci->cache->save($this->qrz_session_cachekey, $qrz_session_key, self::QRZ_SESSION_DURATION); + $callbook = $this->ci->qrz->search($callsign, $this->ci->cache->get($this->qrz_session_cachekey), $fullname); } if (strpos($callbook['error'] ?? '', 'Not found') !== false && strpos($callsign, "/") !== false) { $plaincall = $this->get_plaincall($callsign); // Now try again but give back reduced data, as we can't validate location and stuff (true at the end) - $callbook = $this->ci->qrz->search($plaincall, $this->ci->session->userdata('qrz_session_key'), $fullname, true); + $callbook = $this->ci->qrz->search($plaincall, $this->ci->cache->get($this->qrz_session_cachekey), $fullname, true); } } $callbook['source'] = $this->ci->qrz->sourcename(); @@ -131,10 +171,10 @@ class Callbook { $username = $this->ci->config->item('qrzcq_username'); $password = $this->ci->config->item('qrzcq_password'); - if (!$this->ci->session->userdata('qrzcq_session_key')) { + if (!$this->ci->cache->get($this->qrzcq_session_cachekey)) { $result = $this->ci->qrzcq->session($username, $password); if ($result[0] == 0) { - $this->ci->session->set_userdata('qrzcq_session_key', $result[1]); + $this->ci->cache->save($this->qrzcq_session_cachekey, $result[1], self::QRZCQ_SESSION_DURATION); } else { $data['error'] = __("QRZCQ Error").": ".$result[1]; $data['source'] = $this->ci->qrzcq->sourcename(); @@ -142,18 +182,18 @@ class Callbook { } } - $callbook = $this->ci->qrzcq->search($callsign, $this->ci->session->userdata('qrzcq_session_key')); + $callbook = $this->ci->qrzcq->search($callsign, $this->ci->cache->get($this->qrzcq_session_cachekey)); if ($callbook['error'] ?? '' == 'Invalid session key') { $qrzcq_session_key = $this->ci->qrzcq->session($username, $password); - $this->ci->session->set_userdata('qrzcq_session_key', $qrzcq_session_key); - $callbook = $this->ci->qrzcq->search($callsign, $this->ci->session->userdata('qrzcq_session_key')); + $this->ci->cache->save($this->qrzcq_session_cachekey, $qrzcq_session_key, self::QRZCQ_SESSION_DURATION); + $callbook = $this->ci->qrzcq->search($callsign, $this->ci->cache->get($this->qrzcq_session_cachekey)); } if (strpos($callbook['error'] ?? '', 'Not found') !== false && strpos($callsign, "/") !== false) { $plaincall = $this->get_plaincall($callsign); // Now try again but give back reduced data, as we can't validate location and stuff (true at the end) - $callbook = $this->ci->qrzcq->search($plaincall, $this->ci->session->userdata('qrzcq_session_key'), true); + $callbook = $this->ci->qrzcq->search($plaincall, $this->ci->cache->get($this->qrzcq_session_cachekey), true); } } $callbook['source'] = $this->ci->qrzcq->sourcename(); @@ -173,30 +213,30 @@ class Callbook { $username = $this->ci->config->item('hamqth_username'); $password = $this->ci->config->item('hamqth_password'); - if (!$this->ci->session->userdata('hamqth_session_key')) { + if (!$this->ci->cache->get($this->hamqth_session_cachekey)) { $hamqth_session_key = $this->ci->hamqth->session($username, $password); if ($hamqth_session_key == false) { $callbook['error'] = __("Error obtaining a session key for HamQTH query"); $callbook['source'] = $this->ci->hamqth->sourcename(); return $callbook; } else { - $this->ci->session->set_userdata('hamqth_session_key', $hamqth_session_key); + $this->ci->cache->save($this->hamqth_session_cachekey, $hamqth_session_key, self::HAMQTH_SESSION_DURATION); } } - $callbook = $this->ci->hamqth->search($callsign, $this->ci->session->userdata('hamqth_session_key')); + $callbook = $this->ci->hamqth->search($callsign, $this->ci->cache->get($this->hamqth_session_cachekey)); // If HamQTH session has expired, start a new session and retry the search. if ($callbook['error'] == "Session does not exist or expired") { $hamqth_session_key = $this->ci->hamqth->session($username, $password); - $this->ci->session->set_userdata('hamqth_session_key', $hamqth_session_key); - $callbook = $this->ci->hamqth->search($callsign, $this->ci->session->userdata('hamqth_session_key')); + $this->ci->cache->save($this->hamqth_session_cachekey, $hamqth_session_key, self::HAMQTH_SESSION_DURATION); + $callbook = $this->ci->hamqth->search($callsign, $this->ci->cache->get($this->hamqth_session_cachekey)); } if (strpos($callbook['error'] ?? '', 'Not found') !== false && strpos($callsign, "/") !== false) { $plaincall = $this->get_plaincall($callsign); // Now try again but give back reduced data, as we can't validate location and stuff (true at the end) - $callbook = $this->ci->hamqth->search($plaincall, $this->ci->session->userdata('hamqth_session_key'), true); + $callbook = $this->ci->hamqth->search($plaincall, $this->ci->cache->get($this->hamqth_session_cachekey), true); } } $callbook['source'] = $this->ci->hamqth->sourcename(); @@ -215,23 +255,23 @@ class Callbook { $username = $this->ci->config->item('qrzru_username'); $password = $this->ci->config->item('qrzru_password'); - if (!$this->ci->session->userdata('qrzru_session_key')) { + if (!$this->ci->cache->get($this->qrzru_session_cachekey)) { $result = $this->ci->qrzru->session($username, $password); - $this->ci->session->set_userdata('qrzru_session_key', $result); + $this->ci->cache->save($this->qrzru_session_cachekey, $result, self::QRZRU_SESSION_DURATION); } - $callbook = $this->ci->qrzru->search($callsign, $this->ci->session->userdata('qrzru_session_key')); + $callbook = $this->ci->qrzru->search($callsign, $this->ci->cache->get($this->qrzru_session_cachekey)); if ($callbook['error'] ?? '' == 'Session does not exist or expired') { $qrzru_session_key = $this->ci->qrzru->session($username, $password); - $this->ci->session->set_userdata('qrzru_session_key', $qrzru_session_key); - $callbook = $this->ci->qrzru->search($callsign, $this->ci->session->userdata('qrzru_session_key')); + $this->ci->cache->save($this->qrzru_session_cachekey, $qrzru_session_key, self::QRZRU_SESSION_DURATION); + $callbook = $this->ci->qrzru->search($callsign, $this->ci->cache->get($this->qrzru_session_cachekey)); } if (strpos($callbook['error'] ?? '', 'Callsign not found') !== false && strpos($callsign, "/") !== false) { $plaincall = $this->get_plaincall($callsign); // Now try again but give back reduced data, as we can't validate location and stuff (true at the end) - $callbook = $this->ci->qrzru->search($plaincall, $this->ci->session->userdata('qrzru_session_key'), true); + $callbook = $this->ci->qrzru->search($plaincall, $this->ci->cache->get($this->qrzru_session_cachekey), true); } } $callbook['source'] = $this->ci->qrzru->sourcename(); From fc0ae9f6720949e7e1b6aff87bb188a56b0ab3ea Mon Sep 17 00:00:00 2001 From: HB9HIL Date: Fri, 20 Feb 2026 07:56:15 +0100 Subject: [PATCH 2/9] fix: cache only the qrzcq sessionkey instead the whole array --- application/libraries/Callbook.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/application/libraries/Callbook.php b/application/libraries/Callbook.php index a9eadcc9d..d9c496464 100644 --- a/application/libraries/Callbook.php +++ b/application/libraries/Callbook.php @@ -186,7 +186,7 @@ class Callbook { if ($callbook['error'] ?? '' == 'Invalid session key') { $qrzcq_session_key = $this->ci->qrzcq->session($username, $password); - $this->ci->cache->save($this->qrzcq_session_cachekey, $qrzcq_session_key, self::QRZCQ_SESSION_DURATION); + $this->ci->cache->save($this->qrzcq_session_cachekey, $qrzcq_session_key[1], self::QRZCQ_SESSION_DURATION); $callbook = $this->ci->qrzcq->search($callsign, $this->ci->cache->get($this->qrzcq_session_cachekey)); } From a3c8aa5464abe8010a8806df2b450c15fa02ecab Mon Sep 17 00:00:00 2001 From: HB9HIL Date: Fri, 20 Feb 2026 08:31:06 +0100 Subject: [PATCH 3/9] remove redundant sourcename calls --- application/libraries/Callbook.php | 43 +++++++++++++----------------- 1 file changed, 18 insertions(+), 25 deletions(-) diff --git a/application/libraries/Callbook.php b/application/libraries/Callbook.php index d9c496464..e541d18cd 100644 --- a/application/libraries/Callbook.php +++ b/application/libraries/Callbook.php @@ -126,12 +126,12 @@ class Callbook { } function qrz($callsign, $fullname) { - if (!$this->ci->load->is_loaded('qrz')) { - $this->ci->load->library('qrz'); - } + $this->ci->load->is_loaded('qrz') ?: $this->ci->load->library('qrz'); + + $callbook['source'] = $this->ci->qrz->sourcename(); + if ($this->ci->config->item('qrz_username') == null || $this->ci->config->item('qrz_password') == null) { $callbook['error'] = 'Lookup not configured. Please review configuration.'; - $callbook['source'] = $this->ci->qrz->sourcename(); } else { $username = $this->ci->config->item('qrz_username'); $password = $this->ci->config->item('qrz_password'); @@ -155,18 +155,17 @@ class Callbook { $callbook = $this->ci->qrz->search($plaincall, $this->ci->cache->get($this->qrz_session_cachekey), $fullname, true); } } - $callbook['source'] = $this->ci->qrz->sourcename(); return $callbook; } function qrzcq($callsign) { - if (!$this->ci->load->is_loaded('qrzcq')) { - $this->ci->load->library('qrzcq'); - } + $this->ci->load->is_loaded('qrzcq') ?: $this->ci->load->library('qrzcq'); + + $callbook['source'] = $this->ci->qrzcq->sourcename(); + if ($this->ci->config->item('qrzcq_username') == null || $this->ci->config->item('qrzcq_password') == null) { $callbook['error'] = 'Lookup not configured. Please review configuration.'; - $callbook['source'] = $this->ci->qrzcq->sourcename(); } else { $username = $this->ci->config->item('qrzcq_username'); $password = $this->ci->config->item('qrzcq_password'); @@ -176,9 +175,8 @@ class Callbook { if ($result[0] == 0) { $this->ci->cache->save($this->qrzcq_session_cachekey, $result[1], self::QRZCQ_SESSION_DURATION); } else { - $data['error'] = __("QRZCQ Error").": ".$result[1]; - $data['source'] = $this->ci->qrzcq->sourcename(); - return $data; + $callbook['error'] = __("QRZCQ Error").": ".$result[1]; + return $callbook; } } @@ -196,19 +194,17 @@ class Callbook { $callbook = $this->ci->qrzcq->search($plaincall, $this->ci->cache->get($this->qrzcq_session_cachekey), true); } } - $callbook['source'] = $this->ci->qrzcq->sourcename(); return $callbook; } function hamqth($callsign) { - // Load the HamQTH library - if (!$this->ci->load->is_loaded('hamqth')) { - $this->ci->load->library('hamqth'); - } + $this->ci->load->is_loaded('hamqth') ?: $this->ci->load->library('hamqth'); + + $callbook['source'] = $this->ci->hamqth->sourcename(); + if ($this->ci->config->item('hamqth_username') == null || $this->ci->config->item('hamqth_password') == null) { $callbook['error'] = 'Lookup not configured. Please review configuration.'; - $callbook['source'] = $this->ci->hamqth->sourcename(); } else { $username = $this->ci->config->item('hamqth_username'); $password = $this->ci->config->item('hamqth_password'); @@ -217,7 +213,6 @@ class Callbook { $hamqth_session_key = $this->ci->hamqth->session($username, $password); if ($hamqth_session_key == false) { $callbook['error'] = __("Error obtaining a session key for HamQTH query"); - $callbook['source'] = $this->ci->hamqth->sourcename(); return $callbook; } else { $this->ci->cache->save($this->hamqth_session_cachekey, $hamqth_session_key, self::HAMQTH_SESSION_DURATION); @@ -239,18 +234,17 @@ class Callbook { $callbook = $this->ci->hamqth->search($plaincall, $this->ci->cache->get($this->hamqth_session_cachekey), true); } } - $callbook['source'] = $this->ci->hamqth->sourcename(); return $callbook; } function qrzru($callsign) { - if (!$this->ci->load->is_loaded('qrzru')) { - $this->ci->load->library('qrzru'); - } + $this->ci->load->is_loaded('qrzru') ?: $this->ci->load->library('qrzru'); + + $callbook['source'] = $this->ci->qrzru->sourcename(); + if ($this->ci->config->item('qrzru_username') == null || $this->ci->config->item('qrzru_password') == null) { $callbook['error'] = 'Lookup not configured. Please review configuration.'; - $callbook['source'] = $this->ci->qrzru->sourcename(); } else { $username = $this->ci->config->item('qrzru_username'); $password = $this->ci->config->item('qrzru_password'); @@ -274,7 +268,6 @@ class Callbook { $callbook = $this->ci->qrzru->search($plaincall, $this->ci->cache->get($this->qrzru_session_cachekey), true); } } - $callbook['source'] = $this->ci->qrzru->sourcename(); return $callbook; } From 4cc348e56e2ce3a4e48cd9f56c42de1dedcdd7d2 Mon Sep 17 00:00:00 2001 From: HB9HIL Date: Fri, 20 Feb 2026 08:34:34 +0100 Subject: [PATCH 4/9] single callbook functions don't need to be public, changed to private functions since we always need to call the main getCallbookData function --- application/libraries/Callbook.php | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/application/libraries/Callbook.php b/application/libraries/Callbook.php index e541d18cd..95c6db67d 100644 --- a/application/libraries/Callbook.php +++ b/application/libraries/Callbook.php @@ -106,16 +106,16 @@ class Callbook { function queryCallbook($callsign, $source) { switch ($source) { case 'qrz': - $callbook = $this->qrz($callsign, $this->ci->config->item('use_fullname')); + $callbook = $this->_qrz($callsign, $this->ci->config->item('use_fullname')); break; case 'qrzcq': - $callbook = $this->qrzcq($callsign); + $callbook = $this->_qrzcq($callsign); break; case 'hamqth': - $callbook = $this->hamqth($callsign); + $callbook = $this->_hamqth($callsign); break; case 'qrzru': - $callbook = $this->qrzru($callsign); + $callbook = $this->_qrzru($callsign); break; default: $callbook['error'] = 'No callbook defined. Please review configuration.'; @@ -125,7 +125,7 @@ class Callbook { return $callbook; } - function qrz($callsign, $fullname) { + private function _qrz($callsign, $fullname) { $this->ci->load->is_loaded('qrz') ?: $this->ci->load->library('qrz'); $callbook['source'] = $this->ci->qrz->sourcename(); @@ -159,7 +159,7 @@ class Callbook { return $callbook; } - function qrzcq($callsign) { + private function _qrzcq($callsign) { $this->ci->load->is_loaded('qrzcq') ?: $this->ci->load->library('qrzcq'); $callbook['source'] = $this->ci->qrzcq->sourcename(); @@ -198,7 +198,7 @@ class Callbook { return $callbook; } - function hamqth($callsign) { + private function _hamqth($callsign) { $this->ci->load->is_loaded('hamqth') ?: $this->ci->load->library('hamqth'); $callbook['source'] = $this->ci->hamqth->sourcename(); @@ -238,7 +238,7 @@ class Callbook { return $callbook; } - function qrzru($callsign) { + private function _qrzru($callsign) { $this->ci->load->is_loaded('qrzru') ?: $this->ci->load->library('qrzru'); $callbook['source'] = $this->ci->qrzru->sourcename(); From 959254f1863559fe153a76fa783b897e543a5ede Mon Sep 17 00:00:00 2001 From: HB9HIL Date: Fri, 20 Feb 2026 08:40:54 +0100 Subject: [PATCH 5/9] check config more explicit --- application/libraries/Callbook.php | 26 ++++++++++++++------------ 1 file changed, 14 insertions(+), 12 deletions(-) diff --git a/application/libraries/Callbook.php b/application/libraries/Callbook.php index 95c6db67d..6699f0fa5 100644 --- a/application/libraries/Callbook.php +++ b/application/libraries/Callbook.php @@ -129,12 +129,12 @@ class Callbook { $this->ci->load->is_loaded('qrz') ?: $this->ci->load->library('qrz'); $callbook['source'] = $this->ci->qrz->sourcename(); + $username = trim($this->ci->config->item('qrz_username') ?? ''); + $password = trim($this->ci->config->item('qrz_password') ?? ''); - if ($this->ci->config->item('qrz_username') == null || $this->ci->config->item('qrz_password') == null) { + if ($username == '' || $password == '') { $callbook['error'] = 'Lookup not configured. Please review configuration.'; } else { - $username = $this->ci->config->item('qrz_username'); - $password = $this->ci->config->item('qrz_password'); if (!$this->ci->cache->get($this->qrz_session_cachekey)) { $qrz_session_key = $this->ci->qrz->session($username, $password); @@ -163,12 +163,12 @@ class Callbook { $this->ci->load->is_loaded('qrzcq') ?: $this->ci->load->library('qrzcq'); $callbook['source'] = $this->ci->qrzcq->sourcename(); + $username = trim($this->ci->config->item('qrzcq_username') ?? ''); + $password = trim($this->ci->config->item('qrzcq_password') ?? ''); - if ($this->ci->config->item('qrzcq_username') == null || $this->ci->config->item('qrzcq_password') == null) { + if ($username == '' || $password == '') { $callbook['error'] = 'Lookup not configured. Please review configuration.'; } else { - $username = $this->ci->config->item('qrzcq_username'); - $password = $this->ci->config->item('qrzcq_password'); if (!$this->ci->cache->get($this->qrzcq_session_cachekey)) { $result = $this->ci->qrzcq->session($username, $password); @@ -203,11 +203,12 @@ class Callbook { $callbook['source'] = $this->ci->hamqth->sourcename(); - if ($this->ci->config->item('hamqth_username') == null || $this->ci->config->item('hamqth_password') == null) { + $username = trim($this->ci->config->item('hamqth_username') ?? ''); + $password = trim($this->ci->config->item('hamqth_password') ?? ''); + + if ($username == '' || $password == '') { $callbook['error'] = 'Lookup not configured. Please review configuration.'; } else { - $username = $this->ci->config->item('hamqth_username'); - $password = $this->ci->config->item('hamqth_password'); if (!$this->ci->cache->get($this->hamqth_session_cachekey)) { $hamqth_session_key = $this->ci->hamqth->session($username, $password); @@ -243,11 +244,12 @@ class Callbook { $callbook['source'] = $this->ci->qrzru->sourcename(); - if ($this->ci->config->item('qrzru_username') == null || $this->ci->config->item('qrzru_password') == null) { + $username = trim($this->ci->config->item('qrzru_username') ?? ''); + $password = trim($this->ci->config->item('qrzru_password') ?? ''); + + if ($username == '' || $password == '') { $callbook['error'] = 'Lookup not configured. Please review configuration.'; } else { - $username = $this->ci->config->item('qrzru_username'); - $password = $this->ci->config->item('qrzru_password'); if (!$this->ci->cache->get($this->qrzru_session_cachekey)) { $result = $this->ci->qrzru->session($username, $password); From b8a8e43a3252c8f5f34638fac2a29c307ddb2f2e Mon Sep 17 00:00:00 2001 From: HB9HIL Date: Fri, 20 Feb 2026 08:50:00 +0100 Subject: [PATCH 6/9] translated return message if no lookup is configured and used a variable for it as it is used multiple times --- application/libraries/Callbook.php | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/application/libraries/Callbook.php b/application/libraries/Callbook.php index 6699f0fa5..cc4a2cb1e 100644 --- a/application/libraries/Callbook.php +++ b/application/libraries/Callbook.php @@ -39,6 +39,9 @@ class Callbook { const QRZRU_SESSION_DURATION = 3300; // 55 minutes private $qrzru_session_cachekey = null; + // Some generic stuff + private $logbook_not_configured; + public function __construct() { $this->ci = & get_instance(); @@ -52,6 +55,8 @@ class Callbook { $this->qrzcq_session_cachekey = 'qrzcq_session_key_'.$this->ci->config->item('qrzcq_username'); $this->hamqth_session_cachekey = 'hamqth_session_key_'.$this->ci->config->item('hamqth_username'); $this->qrzru_session_cachekey = 'qrzru_session_key_'.$this->ci->config->item('qrzru_username'); + + $this->logbook_not_configured = __("Lookup not configured. Please review configuration."); } // TODO: @@ -118,7 +123,7 @@ class Callbook { $callbook = $this->_qrzru($callsign); break; default: - $callbook['error'] = 'No callbook defined. Please review configuration.'; + $callbook['error'] = $this->logbook_not_configured; } log_message('debug', 'Callbook lookup for '.$callsign.' using '.$source.': '.((($callbook['error'] ?? '' ) != '') ? $callbook['error'] : 'Success')); @@ -133,7 +138,7 @@ class Callbook { $password = trim($this->ci->config->item('qrz_password') ?? ''); if ($username == '' || $password == '') { - $callbook['error'] = 'Lookup not configured. Please review configuration.'; + $callbook['error'] = $this->logbook_not_configured; } else { if (!$this->ci->cache->get($this->qrz_session_cachekey)) { @@ -167,7 +172,7 @@ class Callbook { $password = trim($this->ci->config->item('qrzcq_password') ?? ''); if ($username == '' || $password == '') { - $callbook['error'] = 'Lookup not configured. Please review configuration.'; + $callbook['error'] = $this->logbook_not_configured; } else { if (!$this->ci->cache->get($this->qrzcq_session_cachekey)) { @@ -207,7 +212,7 @@ class Callbook { $password = trim($this->ci->config->item('hamqth_password') ?? ''); if ($username == '' || $password == '') { - $callbook['error'] = 'Lookup not configured. Please review configuration.'; + $callbook['error'] = $this->logbook_not_configured; } else { if (!$this->ci->cache->get($this->hamqth_session_cachekey)) { @@ -248,7 +253,7 @@ class Callbook { $password = trim($this->ci->config->item('qrzru_password') ?? ''); if ($username == '' || $password == '') { - $callbook['error'] = 'Lookup not configured. Please review configuration.'; + $callbook['error'] = $this->logbook_not_configured; } else { if (!$this->ci->cache->get($this->qrzru_session_cachekey)) { From 7904e306257930bcb0a7a9f103379d719aa1a99e Mon Sep 17 00:00:00 2001 From: HB9HIL Date: Fri, 20 Feb 2026 09:23:42 +0100 Subject: [PATCH 7/9] add a simple validate sessionkey helper function --- application/libraries/Callbook.php | 53 +++++++++++++++++++++++++++--- 1 file changed, 49 insertions(+), 4 deletions(-) diff --git a/application/libraries/Callbook.php b/application/libraries/Callbook.php index cc4a2cb1e..e481702a5 100644 --- a/application/libraries/Callbook.php +++ b/application/libraries/Callbook.php @@ -41,6 +41,7 @@ class Callbook { // Some generic stuff private $logbook_not_configured; + private $error_obtaining_sessionkey; public function __construct() { $this->ci = & get_instance(); @@ -57,6 +58,7 @@ class Callbook { $this->qrzru_session_cachekey = 'qrzru_session_key_'.$this->ci->config->item('qrzru_username'); $this->logbook_not_configured = __("Lookup not configured. Please review configuration."); + $this->error_obtaining_sessionkey = __("Error obtaining a session key for callbook. Error: %s"); } // TODO: @@ -143,6 +145,10 @@ class Callbook { if (!$this->ci->cache->get($this->qrz_session_cachekey)) { $qrz_session_key = $this->ci->qrz->session($username, $password); + if (!$this->_validate_sessionkey($qrz_session_key)) { + $callbook['error'] = sprintf($this->error_obtaining_sessionkey, $qrz_session_key); + return $callbook; + } $this->ci->cache->save($this->qrz_session_cachekey, $qrz_session_key, self::QRZ_SESSION_DURATION); } @@ -150,6 +156,10 @@ class Callbook { if ($callbook['error'] ?? '' == 'Invalid session key') { $qrz_session_key = $this->ci->qrz->session($username, $password); + if (!$this->_validate_sessionkey($qrz_session_key)) { + $callbook['error'] = sprintf($this->error_obtaining_sessionkey, $qrz_session_key); + return $callbook; + } $this->ci->cache->save($this->qrz_session_cachekey, $qrz_session_key, self::QRZ_SESSION_DURATION); $callbook = $this->ci->qrz->search($callsign, $this->ci->cache->get($this->qrz_session_cachekey), $fullname); } @@ -177,6 +187,10 @@ class Callbook { if (!$this->ci->cache->get($this->qrzcq_session_cachekey)) { $result = $this->ci->qrzcq->session($username, $password); + if (!$this->_validate_sessionkey($result[1])) { + $callbook['error'] = sprintf($this->error_obtaining_sessionkey, $result[1]); + return $callbook; + } if ($result[0] == 0) { $this->ci->cache->save($this->qrzcq_session_cachekey, $result[1], self::QRZCQ_SESSION_DURATION); } else { @@ -189,6 +203,10 @@ class Callbook { if ($callbook['error'] ?? '' == 'Invalid session key') { $qrzcq_session_key = $this->ci->qrzcq->session($username, $password); + if (!$this->_validate_sessionkey($qrzcq_session_key[1])) { + $callbook['error'] = sprintf($this->error_obtaining_sessionkey, $qrzcq_session_key[1]); + return $callbook; + } $this->ci->cache->save($this->qrzcq_session_cachekey, $qrzcq_session_key[1], self::QRZCQ_SESSION_DURATION); $callbook = $this->ci->qrzcq->search($callsign, $this->ci->cache->get($this->qrzcq_session_cachekey)); } @@ -207,7 +225,6 @@ class Callbook { $this->ci->load->is_loaded('hamqth') ?: $this->ci->load->library('hamqth'); $callbook['source'] = $this->ci->hamqth->sourcename(); - $username = trim($this->ci->config->item('hamqth_username') ?? ''); $password = trim($this->ci->config->item('hamqth_password') ?? ''); @@ -217,8 +234,8 @@ class Callbook { if (!$this->ci->cache->get($this->hamqth_session_cachekey)) { $hamqth_session_key = $this->ci->hamqth->session($username, $password); - if ($hamqth_session_key == false) { - $callbook['error'] = __("Error obtaining a session key for HamQTH query"); + if (!$this->_validate_sessionkey($hamqth_session_key)) { + $callbook['error'] = sprintf($this->error_obtaining_sessionkey, $hamqth_session_key); return $callbook; } else { $this->ci->cache->save($this->hamqth_session_cachekey, $hamqth_session_key, self::HAMQTH_SESSION_DURATION); @@ -230,6 +247,10 @@ class Callbook { // If HamQTH session has expired, start a new session and retry the search. if ($callbook['error'] == "Session does not exist or expired") { $hamqth_session_key = $this->ci->hamqth->session($username, $password); + if (!$this->_validate_sessionkey($hamqth_session_key)) { + $callbook['error'] = sprintf($this->error_obtaining_sessionkey, $hamqth_session_key); + return $callbook; + } $this->ci->cache->save($this->hamqth_session_cachekey, $hamqth_session_key, self::HAMQTH_SESSION_DURATION); $callbook = $this->ci->hamqth->search($callsign, $this->ci->cache->get($this->hamqth_session_cachekey)); } @@ -248,7 +269,6 @@ class Callbook { $this->ci->load->is_loaded('qrzru') ?: $this->ci->load->library('qrzru'); $callbook['source'] = $this->ci->qrzru->sourcename(); - $username = trim($this->ci->config->item('qrzru_username') ?? ''); $password = trim($this->ci->config->item('qrzru_password') ?? ''); @@ -258,6 +278,10 @@ class Callbook { if (!$this->ci->cache->get($this->qrzru_session_cachekey)) { $result = $this->ci->qrzru->session($username, $password); + if (!$this->_validate_sessionkey($result)) { + $callbook['error'] = sprintf($this->error_obtaining_sessionkey, $result); + return $callbook; + } $this->ci->cache->save($this->qrzru_session_cachekey, $result, self::QRZRU_SESSION_DURATION); } @@ -265,6 +289,10 @@ class Callbook { if ($callbook['error'] ?? '' == 'Session does not exist or expired') { $qrzru_session_key = $this->ci->qrzru->session($username, $password); + if (!$this->_validate_sessionkey($qrzru_session_key)) { + $callbook['error'] = sprintf($this->error_obtaining_sessionkey, $qrzru_session_key); + return $callbook; + } $this->ci->cache->save($this->qrzru_session_cachekey, $qrzru_session_key, self::QRZRU_SESSION_DURATION); $callbook = $this->ci->qrzru->search($callsign, $this->ci->cache->get($this->qrzru_session_cachekey)); } @@ -279,6 +307,23 @@ class Callbook { return $callbook; } + private function _validate_sessionkey($key) { + // Session key must be a non-empty string + if ($key == false || $key == '' || !is_string($key)) { + return false; + } + + // All session keys should be at least 10 characters. Regarding to their documentation all keys have aprox. the same format + // "2331uf894c4bd29f3923f3bacf02c532d7bd9" + // Since it can differ and we want to don't overcomplicate things we simply check if the key is at least 10 characters long. + // If not, we consider it as invalid. + if (strlen($key) < 10) { + return false; + } + + return true; + } + function get_plaincall($callsign) { $split_callsign = explode('/', $callsign); if (count($split_callsign) == 1) { // case of plain callsign --> return callsign From 46b2427914b1dcf3b8f97c60c015ef29d9c0b92a Mon Sep 17 00:00:00 2001 From: HB9HIL Date: Fri, 20 Feb 2026 09:27:48 +0100 Subject: [PATCH 8/9] just to make sure we invalidate a possible session key in cache --- application/libraries/Callbook.php | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/application/libraries/Callbook.php b/application/libraries/Callbook.php index e481702a5..f58df3b2c 100644 --- a/application/libraries/Callbook.php +++ b/application/libraries/Callbook.php @@ -147,6 +147,7 @@ class Callbook { $qrz_session_key = $this->ci->qrz->session($username, $password); if (!$this->_validate_sessionkey($qrz_session_key)) { $callbook['error'] = sprintf($this->error_obtaining_sessionkey, $qrz_session_key); + $this->ci->cache->delete($this->qrz_session_cachekey); return $callbook; } $this->ci->cache->save($this->qrz_session_cachekey, $qrz_session_key, self::QRZ_SESSION_DURATION); @@ -158,6 +159,7 @@ class Callbook { $qrz_session_key = $this->ci->qrz->session($username, $password); if (!$this->_validate_sessionkey($qrz_session_key)) { $callbook['error'] = sprintf($this->error_obtaining_sessionkey, $qrz_session_key); + $this->ci->cache->delete($this->qrz_session_cachekey); return $callbook; } $this->ci->cache->save($this->qrz_session_cachekey, $qrz_session_key, self::QRZ_SESSION_DURATION); @@ -189,6 +191,7 @@ class Callbook { $result = $this->ci->qrzcq->session($username, $password); if (!$this->_validate_sessionkey($result[1])) { $callbook['error'] = sprintf($this->error_obtaining_sessionkey, $result[1]); + $this->ci->cache->delete($this->qrzcq_session_cachekey); return $callbook; } if ($result[0] == 0) { @@ -205,6 +208,7 @@ class Callbook { $qrzcq_session_key = $this->ci->qrzcq->session($username, $password); if (!$this->_validate_sessionkey($qrzcq_session_key[1])) { $callbook['error'] = sprintf($this->error_obtaining_sessionkey, $qrzcq_session_key[1]); + $this->ci->cache->delete($this->qrzcq_session_cachekey); return $callbook; } $this->ci->cache->save($this->qrzcq_session_cachekey, $qrzcq_session_key[1], self::QRZCQ_SESSION_DURATION); @@ -236,6 +240,7 @@ class Callbook { $hamqth_session_key = $this->ci->hamqth->session($username, $password); if (!$this->_validate_sessionkey($hamqth_session_key)) { $callbook['error'] = sprintf($this->error_obtaining_sessionkey, $hamqth_session_key); + $this->ci->cache->delete($this->hamqth_session_cachekey); return $callbook; } else { $this->ci->cache->save($this->hamqth_session_cachekey, $hamqth_session_key, self::HAMQTH_SESSION_DURATION); @@ -249,6 +254,7 @@ class Callbook { $hamqth_session_key = $this->ci->hamqth->session($username, $password); if (!$this->_validate_sessionkey($hamqth_session_key)) { $callbook['error'] = sprintf($this->error_obtaining_sessionkey, $hamqth_session_key); + $this->ci->cache->delete($this->hamqth_session_cachekey); return $callbook; } $this->ci->cache->save($this->hamqth_session_cachekey, $hamqth_session_key, self::HAMQTH_SESSION_DURATION); @@ -280,6 +286,7 @@ class Callbook { $result = $this->ci->qrzru->session($username, $password); if (!$this->_validate_sessionkey($result)) { $callbook['error'] = sprintf($this->error_obtaining_sessionkey, $result); + $this->ci->cache->delete($this->qrzru_session_cachekey); return $callbook; } $this->ci->cache->save($this->qrzru_session_cachekey, $result, self::QRZRU_SESSION_DURATION); @@ -291,6 +298,7 @@ class Callbook { $qrzru_session_key = $this->ci->qrzru->session($username, $password); if (!$this->_validate_sessionkey($qrzru_session_key)) { $callbook['error'] = sprintf($this->error_obtaining_sessionkey, $qrzru_session_key); + $this->ci->cache->delete($this->qrzru_session_cachekey); return $callbook; } $this->ci->cache->save($this->qrzru_session_cachekey, $qrzru_session_key, self::QRZRU_SESSION_DURATION); From 23701867f06ef7cc755b24087b75b526d46860e7 Mon Sep 17 00:00:00 2001 From: HB9HIL Date: Fri, 20 Feb 2026 09:48:00 +0100 Subject: [PATCH 9/9] always return source with lookup data --- application/libraries/Hamqth.php | 1 + application/libraries/Qrz.php | 1 + application/libraries/Qrzcq.php | 1 + application/libraries/Qrzru.php | 1 + 4 files changed, 4 insertions(+) diff --git a/application/libraries/Hamqth.php b/application/libraries/Hamqth.php index 5c3bbc403..bddaca7b7 100644 --- a/application/libraries/Hamqth.php +++ b/application/libraries/Hamqth.php @@ -127,6 +127,7 @@ class Hamqth { } } finally { + $data['source'] = $this->sourcename(); return $data; } } diff --git a/application/libraries/Qrz.php b/application/libraries/Qrz.php index 161f2e00a..48d51d07c 100644 --- a/application/libraries/Qrz.php +++ b/application/libraries/Qrz.php @@ -182,6 +182,7 @@ class Qrz { $data['cqzone'] = ''; } } finally { + $data['source'] = $this->sourcename(); return $data; } } diff --git a/application/libraries/Qrzcq.php b/application/libraries/Qrzcq.php index 4518e072b..d8f99f241 100644 --- a/application/libraries/Qrzcq.php +++ b/application/libraries/Qrzcq.php @@ -143,6 +143,7 @@ class Qrzcq { } } finally { + $data['source'] = $this->sourcename(); return $data; } } diff --git a/application/libraries/Qrzru.php b/application/libraries/Qrzru.php index 63e423aef..fe659e13b 100644 --- a/application/libraries/Qrzru.php +++ b/application/libraries/Qrzru.php @@ -114,6 +114,7 @@ class Qrzru { $data['cqz'] = ''; } } finally { + $data['source'] = $this->sourcename(); return $data; } }