Bump version to 1.1: implement strict license block, update keygen salt, fix localStorage tab storage default, list all modules on Info tab

This commit is contained in:
nertyog 2026-07-12 03:18:56 +03:00
parent 08fb912b9b
commit 3d598b6a4c
9 changed files with 138 additions and 29 deletions

View File

@ -1,6 +1,6 @@
============================================================================= =============================================================================
Poll Widget [NAT] Poll Widget [NAT]
Version: 1.0.0 Version: 1.1.0
Compatibility: OpenCart 2.0.x - 2.2.x / ocStore 2.1.x - 2.2.x Compatibility: OpenCart 2.0.x - 2.2.x / ocStore 2.1.x - 2.2.x
Author: NAT Author: NAT
Contact: info@nat.od.ua Contact: info@nat.od.ua
@ -18,7 +18,7 @@ Poll Widget [NAT] — это функциональный модуль для с
УСТАНОВКА: УСТАНОВКА:
1. Перейдите в панель управления OpenCart: "Модули / Расширения" -> "Установка расширений". 1. Перейдите в панель управления OpenCart: "Модули / Расширения" -> "Установка расширений".
2. Загрузите архив poll_widget_nat_OC_20_22_1_0.ocmod.zip. 2. Загрузите архив poll_widget_nat_OC_20_22_1_1.ocmod.zip.
3. Перейдите в "Модули / Расширения" -> "Модификаторы" и нажмите синюю кнопку "Обновить" (Очистить кэш). 3. Перейдите в "Модули / Расширения" -> "Модификаторы" и нажмите синюю кнопку "Обновить" (Очистить кэш).
4. Перейдите в "Система" -> "Пользователи" -> "Группы пользователей", выберите вашу группу (Administrator), нажмите "Выделить все" в правах просмотра и изменения, затем сохраните. 4. Перейдите в "Система" -> "Пользователи" -> "Группы пользователей", выберите вашу группу (Administrator), нажмите "Выделить все" в правах просмотра и изменения, затем сохраните.
5. Перейдите в "Модули / Расширения" -> "Расширения" -> тип "Модули", найдите "Poll Widget [NAT]" и нажмите "Установить", а затем "Редактировать". 5. Перейдите в "Модули / Расширения" -> "Расширения" -> тип "Модули", найдите "Poll Widget [NAT]" и нажмите "Установить", а затем "Редактировать".
@ -52,7 +52,7 @@ Poll Widget [NAT] — це функціональний модуль для ст
ВСТАНОВЛЕННЯ: ВСТАНОВЛЕННЯ:
1. Перейдіть до панелі керування OpenCart: "Модулі / Розширення" -> "Встановлення розширень". 1. Перейдіть до панелі керування OpenCart: "Модулі / Розширення" -> "Встановлення розширень".
2. Завантажте архів poll_widget_nat_OC_20_22_1_0.ocmod.zip. 2. Завантажте архів poll_widget_nat_OC_20_22_1_1.ocmod.zip.
3. Перейдіть до "Модулі / Розширення" -> "Модифікатори" і натисніть синю кнопку "Оновити". 3. Перейдіть до "Модулі / Розширення" -> "Модифікатори" і натисніть синю кнопку "Оновити".
4. Перейдіть до "Система" -> "Користувачі" -> "Групи користувачів", виберіть вашу групу (Administrator), натисніть "Виділити все" у правах перегляду та зміни, збережіть. 4. Перейдіть до "Система" -> "Користувачі" -> "Групи користувачів", виберіть вашу групу (Administrator), натисніть "Виділити все" у правах перегляду та зміни, збережіть.
5. Перейдіть до "Модулі / Розширення" -> "Розширення" -> тип "Модулі", знайдіть "Poll Widget [NAT]", натисніть "Встановити", а потім "Редагувати". 5. Перейдіть до "Модулі / Розширення" -> "Розширення" -> тип "Модулі", знайдіть "Poll Widget [NAT]", натисніть "Встановити", а потім "Редагувати".
@ -86,7 +86,7 @@ Poll Widget [NAT] is a powerful tool for creating responsive voting widgets and
INSTALLATION: INSTALLATION:
1. Go to OpenCart admin panel: "Extensions" -> "Installer". 1. Go to OpenCart admin panel: "Extensions" -> "Installer".
2. Upload the poll_widget_nat_OC_20_22_1_0.ocmod.zip archive. 2. Upload the poll_widget_nat_OC_20_22_1_1.ocmod.zip archive.
3. Go to "Extensions" -> "Modifications" and click the blue "Refresh" button. 3. Go to "Extensions" -> "Modifications" and click the blue "Refresh" button.
4. Go to "System" -> "Users" -> "User Groups", edit your group (Top Administrator), click "Select All" for Access and Modify permissions, then Save. 4. Go to "System" -> "Users" -> "User Groups", edit your group (Top Administrator), click "Select All" for Access and Modify permissions, then Save.
5. Go to "Extensions" -> "Extensions" -> choose "Modules", find "Poll Widget [NAT]", click "Install" and then "Edit". 5. Go to "Extensions" -> "Extensions" -> choose "Modules", find "Poll Widget [NAT]", click "Install" and then "Edit".

View File

@ -3,7 +3,7 @@
<name>Poll Widget [NAT]</name> <name>Poll Widget [NAT]</name>
<id>poll_widget_nat</id> <id>poll_widget_nat</id>
<code>poll_widget_nat_od_ua</code> <code>poll_widget_nat_od_ua</code>
<version>1.0.0</version> <version>1.1.0</version>
<author>NAT</author> <author>NAT</author>
<link>mailto:info@nat.od.ua</link> <link>mailto:info@nat.od.ua</link>

Binary file not shown.

View File

@ -24,7 +24,7 @@ Poll Widget [NAT] is a powerful tool for creating responsive voting widgets and
INSTALLATION: INSTALLATION:
1. Go to OpenCart admin panel: "Extensions" -> "Installer". 1. Go to OpenCart admin panel: "Extensions" -> "Installer".
2. Upload the `poll_widget_nat_OC_20_22_1_0.ocmod.zip` archive. 2. Upload the `poll_widget_nat_OC_20_22_1_1.ocmod.zip` archive.
3. Go to "Extensions" -> "Modifications" and click the blue "Refresh" button. 3. Go to "Extensions" -> "Modifications" and click the blue "Refresh" button.
4. Go to "System" -> "Users" -> "User Groups", edit your group (Top Administrator), click "Select All" for Access and Modify permissions, then Save. 4. Go to "System" -> "Users" -> "User Groups", edit your group (Top Administrator), click "Select All" for Access and Modify permissions, then Save.
5. Go to "Extensions" -> "Extensions" -> choose "Modules", find "Poll Widget [NAT]", click "Install" and then "Edit". 5. Go to "Extensions" -> "Extensions" -> choose "Modules", find "Poll Widget [NAT]", click "Install" and then "Edit".

View File

@ -61,7 +61,9 @@ class ControllerModulePollWidgetNat extends Controller {
$v_mid = 'tot'; $v_mid = 'tot';
$v_sfx = 'ka'; $v_sfx = 'ka';
$salt = ($v_k . $v_to . $v_bit) . ($v_end . $v_mid) . ($v_core . $v_sfx); $v_poll = 'poll_widget';
$salt = ($v_k . $v_to . $v_bit) . ($v_end . $v_poll . '_' . $v_mid) . ($v_core . $v_sfx);
while(count($parts) >= 2) { while(count($parts) >= 2) {
$domain = implode('.', $parts); $domain = implode('.', $parts);
if ($key === strtoupper(implode('-', str_split(substr(md5($domain . $salt), 0, 16), 4)))) return true; if ($key === strtoupper(implode('-', str_split(substr(md5($domain . $salt), 0, 16), 4)))) return true;
@ -165,6 +167,9 @@ class ControllerModulePollWidgetNat extends Controller {
public function add() { public function add() {
$this->load->language('module/poll_widget_nat'); $this->load->language('module/poll_widget_nat');
if (!$this->checkLicense($this->config->get('module_poll_widget_nat_license'))) {
$this->response->redirect($this->url->link('module/poll_widget_nat', 'token=' . $this->session->data['token'], true));
}
$this->document->setTitle($this->language->get('heading_title_raw')); $this->document->setTitle($this->language->get('heading_title_raw'));
$this->load->model('module/poll_widget_nat'); $this->load->model('module/poll_widget_nat');
@ -179,6 +184,9 @@ class ControllerModulePollWidgetNat extends Controller {
public function edit() { public function edit() {
$this->load->language('module/poll_widget_nat'); $this->load->language('module/poll_widget_nat');
if (!$this->checkLicense($this->config->get('module_poll_widget_nat_license'))) {
$this->response->redirect($this->url->link('module/poll_widget_nat', 'token=' . $this->session->data['token'], true));
}
$this->document->setTitle($this->language->get('heading_title_raw')); $this->document->setTitle($this->language->get('heading_title_raw'));
$this->load->model('module/poll_widget_nat'); $this->load->model('module/poll_widget_nat');
@ -193,6 +201,9 @@ class ControllerModulePollWidgetNat extends Controller {
public function delete() { public function delete() {
$this->load->language('module/poll_widget_nat'); $this->load->language('module/poll_widget_nat');
if (!$this->checkLicense($this->config->get('module_poll_widget_nat_license'))) {
$this->response->redirect($this->url->link('module/poll_widget_nat', 'token=' . $this->session->data['token'], true));
}
$this->load->model('module/poll_widget_nat'); $this->load->model('module/poll_widget_nat');
if (isset($this->request->get['poll_id']) && $this->validate()) { if (isset($this->request->get['poll_id']) && $this->validate()) {

View File

@ -342,6 +342,8 @@ $(document).ready(function() {
if ($target.length) { if ($target.length) {
$target.tab('show'); $target.tab('show');
} }
} else {
$mainTabs.find('a[href="#tab-general"]').tab('show');
} }
$mainTabs.on('shown.bs.tab', 'a[data-toggle="tab"]', function(e) { $mainTabs.on('shown.bs.tab', 'a[data-toggle="tab"]', function(e) {

View File

@ -3,10 +3,10 @@
<div class="page-header"> <div class="page-header">
<div class="container-fluid"> <div class="container-fluid">
<div class="pull-right"> <div class="pull-right">
<?php if ($is_licensed) { ?>
<button type="submit" form="form-module" data-toggle="tooltip" class="btn btn-primary" title="<?php echo $button_save; ?>"> <button type="submit" form="form-module" data-toggle="tooltip" class="btn btn-primary" title="<?php echo $button_save; ?>">
<i class="fa fa-save"></i> <i class="fa fa-save"></i>
</button> </button>
<?php if ($is_licensed) { ?>
<a href="<?php echo $add; ?>" data-toggle="tooltip" title="<?php echo $text_add; ?>" class="btn btn-success"><i class="fa fa-plus"></i></a> <a href="<?php echo $add; ?>" data-toggle="tooltip" title="<?php echo $text_add; ?>" class="btn btn-success"><i class="fa fa-plus"></i></a>
<?php } ?> <?php } ?>
<a href="<?php echo $cancel; ?>" data-toggle="tooltip" title="<?php echo $button_cancel; ?>" class="btn btn-default"><i class="fa fa-reply"></i></a> <a href="<?php echo $cancel; ?>" data-toggle="tooltip" title="<?php echo $button_cancel; ?>" class="btn btn-default"><i class="fa fa-reply"></i></a>
@ -36,13 +36,16 @@
</div> </div>
<div class="panel-body"> <div class="panel-body">
<?php if ($is_licensed) { ?>
<ul class="nav nav-tabs"> <ul class="nav nav-tabs">
<li class="active"><a href="#tab-general" data-toggle="tab"><?php echo $tab_polls; ?></a></li> <li class="active"><a href="#tab-general" data-toggle="tab"><?php echo $tab_polls; ?></a></li>
<li><a href="#tab-info" data-toggle="tab"><?php echo $tab_info; ?></a></li> <li><a href="#tab-info" data-toggle="tab"><?php echo $tab_info; ?></a></li>
</ul> </ul>
<?php } ?>
<div class="tab-content"> <div class="tab-content">
<div class="tab-pane active" id="tab-general"> <div class="tab-pane active" id="tab-general">
<?php if ($is_licensed) { ?>
<form action="<?php echo $action; ?>" method="post" enctype="multipart/form-data" id="form-module"> <form action="<?php echo $action; ?>" method="post" enctype="multipart/form-data" id="form-module">
<div class="row"> <div class="row">
<div class="col-md-4"> <div class="col-md-4">
@ -84,30 +87,16 @@
<button type="submit" class="btn btn-info"><i class="fa fa-refresh"></i></button> <button type="submit" class="btn btn-info"><i class="fa fa-refresh"></i></button>
</span> </span>
<span class="input-group-addon"> <span class="input-group-addon">
<?php if ($is_licensed) { ?>
<i class="fa fa-check text-success"></i> <i class="fa fa-check text-success"></i>
<?php } else { ?>
<i class="fa fa-times text-danger"></i>
<?php } ?>
</span> </span>
</div> </div>
</div> </div>
</div> </div>
</div> </div>
<?php if (!$is_licensed) { ?>
<div class="row">
<div class="col-md-12">
<div class="alert alert-warning">
<i class="fa fa-exclamation-triangle"></i> <?php echo $text_license_warning; ?>
</div>
</div>
</div>
<?php } ?>
</form> </form>
<hr> <hr>
<?php if ($is_licensed) { ?>
<div class="table-responsive"> <div class="table-responsive">
<table class="table table-bordered table-hover"> <table class="table table-bordered table-hover">
<thead> <thead>
@ -143,9 +132,39 @@
</tbody> </tbody>
</table> </table>
</div> </div>
<?php } else { ?>
<div class="row">
<div class="col-md-6 col-md-offset-3 col-sm-8 col-sm-offset-2">
<div class="well text-center" style="background: #fff; border: 1px solid #ffbc34; padding: 25px; border-radius: 8px; box-shadow: 0 4px 12px rgba(0,0,0,0.05); margin-top: 20px;">
<h3 style="color: #d9534f; margin-top: 0; font-weight: bold;"><i class="fa fa-exclamation-triangle"></i> Требуется активация модуля</h3>
<p style="font-size: 14px; margin-bottom: 25px; color: #666;"><?php echo $text_license_warning; ?></p>
<form action="<?php echo $action; ?>" method="post" enctype="multipart/form-data" id="form-module">
<div class="form-group" style="max-width: 400px; margin: 0 auto 20px;">
<label style="font-weight: bold; color: #333; margin-bottom: 8px;"><?php echo $entry_license; ?></label>
<div class="input-group">
<input type="text" name="module_poll_widget_nat_license" value="<?php echo $module_poll_widget_nat_license; ?>" class="form-control text-center" placeholder="Введите лицензионный ключ..." style="font-family: monospace; font-size: 16px; font-weight: bold; letter-spacing: 1px;" />
<span class="input-group-btn">
<button type="submit" class="btn btn-primary" style="font-weight: bold;"><i class="fa fa-key"></i> Активировать</button>
</span>
</div>
</div>
</form>
<div style="border-top: 1px solid #eee; padding-top: 20px; font-size: 13px; color: #666; text-align: left; max-width: 450px; margin: 0 auto;">
<strong style="color: #333;">Как получить лицензионный ключ:</strong>
<ul style="padding-left: 20px; margin-top: 8px; line-height: 1.6;">
<li>Напишите на почту <a href="mailto:info@nat.od.ua" style="font-weight: bold; color: #2980b9;">info@nat.od.ua</a> с указанием вашего домена и номера заказа.</li>
<li>Или свяжитесь с автором на форуме <a href="https://opencartforum.com/ru/files/developer/725443-nertyod/" target="_blank" style="font-weight: bold; color: #2980b9;">OpenCartForum (nertyod)</a>.</li>
</ul>
</div>
</div>
</div>
</div>
<?php } ?> <?php } ?>
</div> </div>
<?php if ($is_licensed) { ?>
<div class="tab-pane" id="tab-info"> <div class="tab-pane" id="tab-info">
<div class="alert alert-info" style="font-size: 15px;"> <div class="alert alert-info" style="font-size: 15px;">
<i class="fa fa-info-circle"></i> <?php echo $text_footer_ecosystem; ?> <i class="fa fa-info-circle"></i> <?php echo $text_footer_ecosystem; ?>
@ -160,8 +179,8 @@
</div> </div>
<div class="col-sm-6"> <div class="col-sm-6">
<div class="well" style="min-height: 140px; background: #fff;"> <div class="well" style="min-height: 140px; background: #fff;">
<h4 style="margin-top:0; color: #2c3e50;"><b><i class="fa fa-database text-primary"></i> <?php echo $text_database_opt_title; ?></b></h4> <h4 style="margin-top:0; color: #2c3e50;"><b><i class="fa fa-calendar-plus-o text-primary"></i> <?php echo $text_new_arrivals_title; ?></b></h4>
<p style="font-size: 13px;"><?php echo $text_database_opt_desc; ?></p> <p style="font-size: 13px;"><?php echo $text_new_arrivals_desc; ?></p>
</div> </div>
</div> </div>
</div> </div>
@ -180,10 +199,24 @@
</div> </div>
</div> </div>
<div class="row"> <div class="row">
<div class="col-sm-6">
<div class="well" style="min-height: 140px; background: #fff; border: 1px dashed #2980b9;">
<h4 style="margin-top:0; color: #2c3e50;"><b><i class="fa fa-question-circle text-primary"></i> <?php echo $text_poll_widget_title; ?></b> <span class="label label-success" style="font-size: 10px; vertical-align: middle;"><?php echo isset($text_current_module) ? $text_current_module : 'Текущий модуль'; ?></span></h4>
<p style="font-size: 13px;"><?php echo $text_poll_widget_desc; ?></p>
</div>
</div>
<div class="col-sm-6"> <div class="col-sm-6">
<div class="well" style="min-height: 140px; background: #fff;"> <div class="well" style="min-height: 140px; background: #fff;">
<h4 style="margin-top:0; color: #2c3e50;"><b><i class="fa fa-calendar-plus-o text-primary"></i> <?php echo $text_new_arrivals_title; ?></b></h4> <h4 style="margin-top:0; color: #2c3e50;"><b><i class="fa fa-database text-primary"></i> <?php echo $text_database_opt_title; ?></b></h4>
<p style="font-size: 13px;"><?php echo $text_new_arrivals_desc; ?></p> <p style="font-size: 13px;"><?php echo $text_database_opt_desc; ?></p>
</div>
</div>
</div>
<div class="row">
<div class="col-sm-6">
<div class="well" style="min-height: 140px; background: #fff;">
<h4 style="margin-top:0; color: #2c3e50;"><b><i class="fa fa-exchange text-primary"></i> <?php echo $text_easy_import_title; ?></b></h4>
<p style="font-size: 13px;"><?php echo $text_easy_import_desc; ?></p>
</div> </div>
</div> </div>
<div class="col-sm-6"> <div class="col-sm-6">
@ -196,8 +229,14 @@
<div class="row"> <div class="row">
<div class="col-sm-6"> <div class="col-sm-6">
<div class="well" style="min-height: 140px; background: #fff;"> <div class="well" style="min-height: 140px; background: #fff;">
<h4 style="margin-top:0; color: #2c3e50;"><b><i class="fa fa-exchange text-primary"></i> <?php echo $text_easy_import_title; ?></b></h4> <h4 style="margin-top:0; color: #2c3e50;"><b><i class="fa fa-line-chart text-primary"></i> <?php echo $text_utm_tracker_title; ?></b></h4>
<p style="font-size: 13px;"><?php echo $text_easy_import_desc; ?></p> <p style="font-size: 13px;"><?php echo $text_utm_tracker_desc; ?></p>
</div>
</div>
<div class="col-sm-6">
<div class="well" style="min-height: 140px; background: #fff;">
<h4 style="margin-top:0; color: #2c3e50;"><b><i class="fa fa-bullhorn text-primary"></i> <?php echo $text_info_title_promo_top_bar; ?></b></h4>
<p style="font-size: 13px;"><?php echo $text_info_desc_promo_top_bar; ?></p>
</div> </div>
</div> </div>
</div> </div>
@ -211,6 +250,7 @@
</a> </a>
</div> </div>
</div> </div>
<?php } ?>
</div> </div>
@ -221,4 +261,28 @@
</div> </div>
</div> </div>
</div> </div>
<?php if ($is_licensed) { ?>
<script type="text/javascript">
$(document).ready(function() {
// Сохранение/восстановление активной вкладки
var tabStorageKey = 'nat_active_tab_poll_widget_nat_list';
var $mainTabs = $('.panel-body > ul.nav-tabs');
var savedTab = localStorage.getItem(tabStorageKey);
if (savedTab) {
var $target = $mainTabs.find('a[href="' + savedTab + '"]');
if ($target.length) {
$target.tab('show');
}
} else {
$mainTabs.find('a[href="#tab-general"]').tab('show');
}
$mainTabs.on('shown.bs.tab', 'a[data-toggle="tab"]', function(e) {
localStorage.setItem(tabStorageKey, $(e.target).attr('href'));
});
});
</script>
<?php } ?>
<?php echo $footer; ?> <?php echo $footer; ?>

View File

@ -2,11 +2,37 @@
if (!defined('VERSION')) exit; if (!defined('VERSION')) exit;
class ControllerModulePollWidgetNat extends Controller { class ControllerModulePollWidgetNat extends Controller {
private function checkLicense($key) {
if (empty($key)) return false;
$host = explode(':', str_replace(array('http://', 'https://', 'www.'), '', strtolower($this->request->server['HTTP_HOST'])))[0];
$parts = explode('.', $host);
$v_core = '_redis';
$v_end = 'aet_';
$v_bit = '_lom';
$v_to = 'to';
$v_k = 'k';
$v_mid = 'tot';
$v_sfx = 'ka';
$v_poll = 'poll_widget';
$salt = ($v_k . $v_to . $v_bit) . ($v_end . $v_poll . '_' . $v_mid) . ($v_core . $v_sfx);
while(count($parts) >= 2) {
$domain = implode('.', $parts);
if ($key === strtoupper(implode('-', str_split(substr(md5($domain . $salt), 0, 16), 4)))) return true;
array_shift($parts);
}
return false;
}
public function index($setting) { public function index($setting) {
if (!isset($setting['poll_id'])) { if (!isset($setting['poll_id'])) {
return false; return false;
} }
if (!$this->checkLicense($this->config->get('module_poll_widget_nat_license'))) {
return false;
}
$poll_id = (int)$setting['poll_id']; $poll_id = (int)$setting['poll_id'];
$this->load->model('module/poll_widget_nat'); $this->load->model('module/poll_widget_nat');
@ -98,6 +124,12 @@ class ControllerModulePollWidgetNat extends Controller {
$this->load->model('module/poll_widget_nat'); $this->load->model('module/poll_widget_nat');
$this->load->language('module/poll_widget_nat'); $this->load->language('module/poll_widget_nat');
if (!$this->checkLicense($this->config->get('module_poll_widget_nat_license'))) {
$this->response->addHeader('Content-Type: application/json');
$this->response->setOutput(json_encode(array('error' => 'License verification failed.')));
return;
}
$poll_id = isset($this->request->post['poll_id']) ? (int)$this->request->post['poll_id'] : 0; $poll_id = isset($this->request->post['poll_id']) ? (int)$this->request->post['poll_id'] : 0;
$answer_index = isset($this->request->post['answer_index']) ? (int)$this->request->post['answer_index'] : -1; $answer_index = isset($this->request->post['answer_index']) ? (int)$this->request->post['answer_index'] : -1;