Skip to content

Commit 339ba31

Browse files
authored
2.8.4
2 parents d8cc21f + 30ee758 commit 339ba31

9 files changed

Lines changed: 172 additions & 12 deletions

File tree

application/config/migration.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@
2222
|
2323
*/
2424

25-
$config['migration_version'] = 239;
25+
$config['migration_version'] = 240;
2626

2727
/*
2828
|--------------------------------------------------------------------------

application/controllers/Logbook.php

Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -614,6 +614,12 @@ function view($id)
614614

615615
$this->load->model('logbook_model');
616616
$data['query'] = $this->logbook_model->get_qso($id);
617+
// Guard against inaccessible or missing QSO to avoid calling result() on null
618+
if (!$data['query'] || $data['query']->num_rows() === 0) {
619+
$this->session->set_flashdata('notice', "You're not allowed to do that!");
620+
redirect('dashboard');
621+
return;
622+
}
617623
$data['dxccFlag'] = $this->dxccflag->get($data['query']->result()[0]->COL_DXCC);
618624

619625
if ($this->session->userdata('user_measurement_base') == NULL) {
@@ -851,7 +857,9 @@ function partial($id)
851857
if (isset($callsign['callsign']['dxcc'])) {
852858
$this->load->model('logbook_model');
853859
$entity = $this->logbook_model->get_entity($callsign['callsign']['dxcc']);
854-
$callsign['callsign']['dxcc_name'] = $entity['name'];
860+
if (is_array($entity) && isset($entity['name'])) {
861+
$callsign['callsign']['dxcc_name'] = $entity['name'];
862+
}
855863
}
856864
} elseif ($this->session->userdata('callbook_type') == "HamQTH") {
857865
// Load the HamQTH library
@@ -884,7 +892,9 @@ function partial($id)
884892
if (isset($callsign['callsign']['dxcc'])) {
885893
$this->load->model('logbook_model');
886894
$entity = $this->logbook_model->get_entity($callsign['callsign']['dxcc']);
887-
$callsign['callsign']['dxcc_name'] = $entity['name'];
895+
if (is_array($entity) && isset($entity['name'])) {
896+
$callsign['callsign']['dxcc_name'] = $entity['name'];
897+
}
888898
}
889899
if (isset($callsign['callsign']['error'])) {
890900
$callsign['error'] = $callsign['callsign']['error'];
@@ -968,7 +978,9 @@ function search_result($id = "", $id2 = "")
968978
if (isset($data['callsign']['dxcc'])) {
969979
$this->load->model('logbook_model');
970980
$entity = $this->logbook_model->get_entity($data['callsign']['dxcc']);
971-
$data['callsign']['dxcc_name'] = $entity['name'];
981+
if (is_array($entity) && isset($entity['name'])) {
982+
$data['callsign']['dxcc_name'] = $entity['name'];
983+
}
972984
}
973985
if (isset($data['callsign']['gridsquare'])) {
974986
$this->load->model('logbook_model');
@@ -1005,7 +1017,9 @@ function search_result($id = "", $id2 = "")
10051017
if (isset($data['callsign']['dxcc'])) {
10061018
$this->load->model('logbook_model');
10071019
$entity = $this->logbook_model->get_entity($data['callsign']['dxcc']);
1008-
$data['callsign']['dxcc_name'] = $entity['name'];
1020+
if (is_array($entity) && isset($entity['name'])) {
1021+
$data['callsign']['dxcc_name'] = $entity['name'];
1022+
}
10091023
}
10101024
if (isset($data['callsign']['error'])) {
10111025
$data['error'] = $data['callsign']['error'];

application/controllers/Logbooks.php

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -132,7 +132,7 @@ public function delete_relationship($logbook_id, $station_id) {
132132
}
133133

134134
// Get station location details
135-
$station = $this->stations->profile($station_id);
135+
$station = $this->stations->profile_clean($station_id);
136136

137137
if ($station) {
138138
$is_owner = $this->logbooks_model->is_logbook_owner($logbook_id);
@@ -144,6 +144,8 @@ public function delete_relationship($logbook_id, $station_id) {
144144
} else {
145145
$this->session->set_flashdata('notice', 'You can only unlink your own station locations');
146146
}
147+
} else {
148+
$this->session->set_flashdata('notice', 'Station location not found');
147149
}
148150

149151
redirect('logbooks/edit/'.$logbook_id);

application/controllers/Qrz.php

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -536,10 +536,15 @@ private function loadFromFile($filepath) {
536536
}
537537

538538
$call = str_replace("_","/",$record['call']);
539-
$station_callsign = str_replace("_","/",$record['station_callsign']);
539+
$station_callsign = str_replace("_","/",$record['station_callsign'] ?? '');
540540
$band = $record['band'] ?? ''; // Ensure band exists
541541
$mode = $record['mode'] ?? ''; // Ensure mode exists
542542

543+
// Log if station_callsign is missing
544+
if (!isset($record['station_callsign']) || $record['station_callsign'] === '') {
545+
log_message('error', 'QRZ import: Missing station_callsign for QSO with callsign: ' . $call . ' on ' . $time_on);
546+
}
547+
543548
// Add record data to batch
544549
$batch_data[] = [
545550
'time_on' => $time_on,
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
<?php
2+
3+
defined('BASEPATH') OR exit('No direct script access allowed');
4+
5+
/*
6+
* Tag Cloudlog as 2.8.4 Migration
7+
*/
8+
9+
class Migration_tag_2_8_4 extends CI_Migration {
10+
11+
public function up()
12+
{
13+
14+
// Tag Cloudlog 2.8.4
15+
$this->db->where('option_name', 'version');
16+
$this->db->update('options', array('option_value' => '2.8.4'));
17+
18+
// Trigger Version Info Dialog
19+
$this->db->where('option_type', 'version_dialog');
20+
$this->db->where('option_name', 'confirmed');
21+
$this->db->update('user_options', array('option_value' => 'false'));
22+
23+
}
24+
25+
public function down()
26+
{
27+
$this->db->where('option_name', 'version');
28+
$this->db->update('options', array('option_value' => '2.8.3'));
29+
}
30+
}

application/models/Logbook_model.php

Lines changed: 27 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5026,15 +5026,39 @@ function wab_qso_details($wab)
50265026

50275027
public function check_qso_is_accessible($id)
50285028
{
5029-
// check if qso belongs to user
5029+
// Allow access if QSO belongs to current user OR
5030+
// if QSO's station is part of the user's active logbook (including shared permissions)
5031+
5032+
// First: owner check (current behavior)
50305033
$this->db->select($this->config->item('table_name') . '.COL_PRIMARY_KEY');
50315034
$this->db->join('station_profile', $this->config->item('table_name') . '.station_id = station_profile.station_id');
50325035
$this->db->where('station_profile.user_id', $this->session->userdata('user_id'));
50335036
$this->db->where($this->config->item('table_name') . '.COL_PRIMARY_KEY', $id);
5034-
$query = $this->db->get($this->config->item('table_name'));
5035-
if ($query->num_rows() == 1) {
5037+
$ownerQuery = $this->db->get($this->config->item('table_name'));
5038+
if ($ownerQuery->num_rows() == 1) {
50365039
return true;
50375040
}
5041+
5042+
// Second: shared-logbook check via active logbook relationships
5043+
$CI = &get_instance();
5044+
$CI->load->model('logbooks_model');
5045+
$activeLogbookId = $this->session->userdata('active_station_logbook');
5046+
5047+
// Ensure user has at least read access to the active logbook
5048+
if ($activeLogbookId && $CI->logbooks_model->check_logbook_is_accessible($activeLogbookId, 'read')) {
5049+
$logbooks_locations_array = $CI->logbooks_model->list_logbook_relationships($activeLogbookId);
5050+
5051+
if (!empty($logbooks_locations_array)) {
5052+
$this->db->select($this->config->item('table_name') . '.COL_PRIMARY_KEY');
5053+
$this->db->where_in($this->config->item('table_name') . '.station_id', $logbooks_locations_array);
5054+
$this->db->where($this->config->item('table_name') . '.COL_PRIMARY_KEY', $id);
5055+
$sharedQuery = $this->db->get($this->config->item('table_name'));
5056+
if ($sharedQuery->num_rows() == 1) {
5057+
return true;
5058+
}
5059+
}
5060+
}
5061+
50385062
return false;
50395063
}
50405064

application/models/Setup_model.php

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,12 @@ function getCountryCount() {
1111

1212
function getLogbookCount() {
1313
$userid = xss_clean($this->session->userdata('user_id'));
14-
$sql = 'select count(*) as count from station_logbooks where user_id =' . $userid;
14+
// Count logbooks the user owns OR has been granted permissions to
15+
$sql = "SELECT COUNT(DISTINCT sl.logbook_id) AS count
16+
FROM station_logbooks sl
17+
LEFT JOIN station_logbooks_permissions slp
18+
ON slp.logbook_id = sl.logbook_id AND slp.user_id = {$userid}
19+
WHERE sl.user_id = {$userid} OR slp.user_id = {$userid}";
1520
$query = $this->db->query($sql);
1621

1722
return $query->row()->count;
@@ -31,7 +36,10 @@ function getAllSetupCounts() {
3136

3237
$sql = "SELECT
3338
(SELECT COUNT(*) FROM dxcc_entities) as country_count,
34-
(SELECT COUNT(*) FROM station_logbooks WHERE user_id = {$userid}) as logbook_count,
39+
(SELECT COUNT(DISTINCT sl.logbook_id) FROM station_logbooks sl
40+
LEFT JOIN station_logbooks_permissions slp
41+
ON slp.logbook_id = sl.logbook_id AND slp.user_id = {$userid}
42+
WHERE sl.user_id = {$userid} OR slp.user_id = {$userid}) as logbook_count,
3543
(SELECT COUNT(*) FROM station_profile WHERE user_id = {$userid}) as location_count";
3644

3745
$query = $this->db->query($sql);

application/views/logbooks/index.php

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -122,6 +122,15 @@ class="btn btn-primary btn-sm"
122122
title="<?php echo lang('station_logbooks_edit_logbook') . ': ' . $row->logbook_name;?>">
123123
<i class="fas fa-edit"></i>
124124
</a>
125+
<?php if($row->public_slug != '') { ?>
126+
<button class="btn btn-success btn-sm"
127+
title="Get Embed Code"
128+
data-bs-toggle="modal"
129+
data-bs-target="#embedModal"
130+
onclick="setEmbedCode('<?php echo $row->public_slug; ?>', '<?php echo addslashes($row->logbook_name); ?>')">
131+
<i class="fas fa-code"></i>
132+
</button>
133+
<?php } ?>
125134
<?php if($row->user_id == $this->session->userdata('user_id') || (isset($row->access_level) && $row->access_level == 'admin')) { ?>
126135
<a href="<?php echo site_url('logbooks/manage_sharing')."/".$row->logbook_id; ?>"
127136
class="btn btn-info btn-sm"
@@ -167,3 +176,68 @@ class="btn btn-danger btn-sm"
167176
<?php } ?>
168177

169178
</div>
179+
180+
<!-- Embed Code Modal -->
181+
<div class="modal fade" id="embedModal" tabindex="-1" aria-labelledby="embedModalLabel" aria-hidden="true">
182+
<div class="modal-dialog modal-lg">
183+
<div class="modal-content">
184+
<div class="modal-header">
185+
<h5 class="modal-title" id="embedModalLabel">
186+
<i class="fas fa-code me-2"></i>Embed Widget - <span id="embedLogbookName"></span>
187+
</h5>
188+
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
189+
</div>
190+
<div class="modal-body">
191+
<p class="text-muted mb-3">Copy the code below and paste it into your website to embed your logbook widget:</p>
192+
<div class="mb-3">
193+
<label for="embedCodeInput" class="form-label">Embed Code</label>
194+
<div class="input-group">
195+
<textarea class="form-control" id="embedCodeInput" rows="4" readonly></textarea>
196+
<button class="btn btn-primary" type="button" id="copyEmbedBtn" title="Copy to clipboard">
197+
<i class="fas fa-copy me-1"></i>Copy
198+
</button>
199+
</div>
200+
</div>
201+
<div class="alert alert-info" role="alert">
202+
<strong>Note:</strong> Make sure your logbook has a public slug configured before embedding.
203+
</div>
204+
</div>
205+
<div class="modal-footer">
206+
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Close</button>
207+
</div>
208+
</div>
209+
</div>
210+
</div>
211+
212+
<script>
213+
function setEmbedCode(publicSlug, logbookName) {
214+
const baseUrl = '<?php echo site_url('widgets/qsos'); ?>';
215+
const iframeCode = `<iframe src="${baseUrl}/${publicSlug}" width="100%" height="600" frameborder="0" allowfullscreen></iframe>`;
216+
217+
document.getElementById('embedCodeInput').value = iframeCode;
218+
document.getElementById('embedLogbookName').textContent = logbookName;
219+
}
220+
221+
document.addEventListener('DOMContentLoaded', function() {
222+
const copyBtn = document.getElementById('copyEmbedBtn');
223+
if (copyBtn) {
224+
copyBtn.addEventListener('click', function() {
225+
const textarea = document.getElementById('embedCodeInput');
226+
textarea.select();
227+
document.execCommand('copy');
228+
229+
// Visual feedback
230+
const originalText = copyBtn.innerHTML;
231+
copyBtn.innerHTML = '<i class="fas fa-check me-1"></i>Copied!';
232+
copyBtn.classList.add('btn-success');
233+
copyBtn.classList.remove('btn-primary');
234+
235+
setTimeout(() => {
236+
copyBtn.innerHTML = originalText;
237+
copyBtn.classList.remove('btn-success');
238+
copyBtn.classList.add('btn-primary');
239+
}, 2000);
240+
});
241+
}
242+
});
243+
</script>

application/views/widgets/qsos.php

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,9 @@
5151
</tr>
5252
<?php $i++; } ?>
5353
</table>
54+
<div style="text-align: right; margin-top: 10px; font-size: 0.85em; color: #999;">
55+
Powered by <a href="https://github.com/magicbug/Cloudlog" target="_blank" style="color: #0066cc; text-decoration: none;">Cloudlog</a>
56+
</div>
5457
</body>
5558

5659
</html>

0 commit comments

Comments
 (0)