Compare commits

...

14 Commits

Author SHA1 Message Date
Book Pauk
437244b7cf Merge tag '1.2.8' into develop
1.2.8
2025-06-04 09:28:40 +07:00
Book Pauk
8c9fd7678d Merge branch 'release/1.2.8' 2025-06-04 09:28:35 +07:00
Book Pauk
01313d66b2 Версия 1.2.8 2025-06-04 09:28:15 +07:00
Book Pauk
eaeacbfb1b Улучшено форматирование текста при копировании из окна 2025-06-04 09:23:13 +07:00
Book Pauk
5328998c21 Merge tag '1.2.7' into develop
1.2.7
2025-02-22 14:44:22 +07:00
Book Pauk
ee066c7c4b Merge branch 'release/1.2.7' 2025-02-22 14:44:18 +07:00
Book Pauk
130aebb514 Версия 1.2.7 2025-02-22 14:43:18 +07:00
Book Pauk
dbec1e630e Отключена форма для сбора донатов 2025-02-22 14:39:29 +07:00
Book Pauk
583b966616 Мелкая оптимизация, чтобы не отдавал большой конфиг каждый раз при обновлении страницы 2025-02-22 14:31:19 +07:00
Book Pauk
9e509ac845 Обновление caniuse-lite 2025-02-22 13:49:57 +07:00
Book Pauk
4ea2d8918e Merge tag '1.2.6' into develop
1.2.6
2024-10-03 15:43:48 +07:00
Book Pauk
6667688193 Merge branch 'release/1.2.6' 2024-10-03 15:43:44 +07:00
Book Pauk
30a1629f23 Исправления из-за нарушения авторских прав 2024-10-03 15:38:16 +07:00
Book Pauk
ba50faeebb Merge tag '1.2.5' into develop
1.2.5
2024-10-03 11:51:40 +07:00
14 changed files with 96 additions and 53 deletions

View File

@@ -1,12 +1,15 @@
import wsc from './webSocketConnection'; import wsc from './webSocketConnection';
class Misc { class Misc {
async loadConfig() { async loadConfig(_configHash) {
const query = {params: [ const query = {
'name', 'version', 'mode', 'maxUploadFileSize', 'useExternalBookConverter', params: [
'acceptFileExt', 'bucEnabled', 'branch', 'networkLibraryLink', 'restricted' 'name', 'version', 'mode', 'maxUploadFileSize', 'useExternalBookConverter',
]}; 'acceptFileExt', 'bucEnabled', 'branch', 'networkLibraryLink', 'restricted'
],
_configHash,
};
const config = await wsc.message(await wsc.send(Object.assign({action: 'get-config'}, query))); const config = await wsc.message(await wsc.send(Object.assign({action: 'get-config'}, query)));
if (config.error) if (config.error)

View File

@@ -154,8 +154,11 @@ class App {
(async() => { (async() => {
//загрузим конфиг сервера //загрузим конфиг сервера
try { try {
const config = await miscApi.loadConfig(); const config = await miscApi.loadConfig(this.config._configHash);
this.commit('config/setConfig', config);
if (!config._useCached)
this.commit('config/setConfig', config);
this.showPage = true; this.showPage = true;
} catch(e) { } catch(e) {
//проверим, не получен ли конфиг ранее //проверим, не получен ли конфиг ранее

View File

@@ -52,18 +52,21 @@ class CopyTextPage {
from = (from < 0 ? 0 : from); from = (from < 0 ? 0 : from);
to = paraIndex + 100; to = paraIndex + 100;
to = (to > parsed.para.length ? parsed.para.length : to); to = (to > parsed.para.length ? parsed.para.length : to);
cut = '<p>..... Текст вырезан. Если хотите скопировать больше, поставьте в настройках галочку "Загружать весь текст"'; cut = '<dd>..... Текст вырезан. Если хотите скопировать больше, поставьте в настройках галочку "Загружать весь текст"';
} }
if (from > 0) if (from > 0)
text += cut; text += cut;
for (let i = from; i < to; i++) { for (let i = from; i < to; i++) {
const p = parsed.para[i]; const p = parsed.para[i];
if (p.addIndex > 0)
continue;
const parts = parsed.splitToStyle(p.text); const parts = parsed.splitToStyle(p.text);
if (this.stopInit) if (this.stopInit)
return; return;
text += `<p id="p${i}" class="copyPara">`; text += `<dd id="p${i}" class="copyPara">&nbsp;&nbsp;`;
for (const part of parts) for (const part of parts)
text += part.text; text += part.text;

View File

@@ -51,7 +51,7 @@ const tabs = [
['MouseHelpPage', 'Мышь/тачскрин'], ['MouseHelpPage', 'Мышь/тачскрин'],
['HotkeysHelpPage', 'Клавиатура'], ['HotkeysHelpPage', 'Клавиатура'],
['VersionHistoryPage', 'История версий'], ['VersionHistoryPage', 'История версий'],
['DonateHelpPage', 'Помочь проекту'], //['DonateHelpPage', 'Помочь проекту'],
]; ];
const componentOptions = { const componentOptions = {

View File

@@ -416,7 +416,7 @@ class Reader {
await wallpaperStorage.init(); await wallpaperStorage.init();
await coversStorage.init(); await coversStorage.init();
await bookManager.init(this.settings, this.restricted); await bookManager.init(this.settings);
bookManager.addEventListener(this.bookManagerEvent); bookManager.addEventListener(this.bookManagerEvent);
if (this.$root.getRootRoute() == '/reader') { if (this.$root.getRootRoute() == '/reader') {
@@ -1267,6 +1267,19 @@ class Reader {
return result; return result;
} }
isUrlAllowed(url) {
const restrictedSites = this.restricted?.sites;
if (restrictedSites) {
url = url.toLowerCase();
for (const site of restrictedSites) {
if (url.indexOf(site) === 0)
return false;
}
}
return true;
}
async _loadBook(opts) { async _loadBook(opts) {
if (!opts || !opts.url) { if (!opts || !opts.url) {
this.mostRecentBook(); this.mostRecentBook();
@@ -1277,6 +1290,11 @@ class Reader {
let url = encodeURI(decodeURI(opts.url)); let url = encodeURI(decodeURI(opts.url));
if (!this.isUrlAllowed(url)) {
this.$root.stdDialog.alert('Книга не загружена, причина: нарушение авторских прав.<br>Приносим извинения за неудобство.', '', {color: 'negative'});
return;
}
if ((url.indexOf('http://') != 0) && (url.indexOf('https://') != 0) && if ((url.indexOf('http://') != 0) && (url.indexOf('https://') != 0) &&
(url.indexOf('disk://') != 0)) (url.indexOf('disk://') != 0))
url = 'http://' + url; url = 'http://' + url;

View File

@@ -131,7 +131,7 @@ class ReaderDialogs {
async init() { async init() {
await this.showWhatsNew(); await this.showWhatsNew();
await this.showDonation(); //await this.showDonation();
} }
loadSettings() { loadSettings() {

View File

@@ -53,7 +53,7 @@
</q-checkbox> </q-checkbox>
</div> </div>
<div class="sets-item row"> <!--div class="sets-item row">
<div class="sets-label label"> <div class="sets-label label">
Уведомление Уведомление
</div> </div>
@@ -63,7 +63,7 @@
Показывать диалог для сбора пожертвований Показывать диалог для сбора пожертвований
</q-tooltip> </q-tooltip>
</q-checkbox> </q-checkbox>
</div> </div-->
<!----------------------------------------------> <!---------------------------------------------->
<div class="sets-part-header"> <div class="sets-part-header">

View File

@@ -1,8 +0,0 @@
export default {
restrictedData: `<?xml version="1.0" encoding="utf-8"?>
<FictionBook xmlns="http://www.gribuser.ru/xml/fictionbook/2.0" xmlns:l="http://www.w3.org/1999/xlink">
<description><title-info><book-title>Нарушение авторских прав</book-title></title-info></description>
<body><section><p>Книга не загружена по причине нарушения авторских прав.</p></section></body>
</FictionBook>`,
};

View File

@@ -3,7 +3,6 @@ import path from 'path-browserify';
import _ from 'lodash'; import _ from 'lodash';
import BookParser from './BookParser'; import BookParser from './BookParser';
import bmHelper from './bmHelper';
import readerApi from '../../../api/reader'; import readerApi from '../../../api/reader';
import coversStorage from './coversStorage'; import coversStorage from './coversStorage';
import * as utils from '../../../share/utils'; import * as utils from '../../../share/utils';
@@ -27,10 +26,9 @@ const bmRecentStoreNew = localForage.createInstance({
}); });
class BookManager { class BookManager {
async init(settings, restricted) { async init(settings) {
this.loaded = false; this.loaded = false;
this.settings = settings; this.settings = settings;
this.restricted = restricted;
this.eventListeners = []; this.eventListeners = [];
this.books = {}; this.books = {};
@@ -234,18 +232,6 @@ class BookManager {
return inflator.result; return inflator.result;
} }
isUrlAllowed(url) {
const restrictedSites = this.restricted?.sites;
if (restrictedSites) {
for (const site of restrictedSites) {
if (url.indexOf(site) === 0)
return false;
}
}
return true;
}
async addBook(newBook, callback) { async addBook(newBook, callback) {
let meta = {url: newBook.url, path: newBook.path}; let meta = {url: newBook.url, path: newBook.path};
@@ -362,10 +348,6 @@ class BookManager {
} }
async parseBook(meta, data, callback) { async parseBook(meta, data, callback) {
if (!this.isUrlAllowed(meta.url)) {
data = bmHelper.restrictedData;
}
const parsed = new BookParser(this.settings); const parsed = new BookParser(this.settings);
const parsedMeta = await parsed.parse(data, callback); const parsedMeta = await parsed.parse(data, callback);

View File

@@ -1,6 +1,33 @@
export const versionHistory = [ export const versionHistory = [
{ {
version: '1.2.5', version: '1.2.8',
releaseDate: '2025-06-04',
showUntil: '2025-06-03',
content:
`
<ul>
<li>исправление багов</li>
</ul>
`
},
{
version: '1.2.7',
releaseDate: '2025-02-22',
showUntil: '2025-02-21',
content:
`
<ul>
<li>отключена форма для сбора донатов</li>
<li>мелкие оптимизации</li>
</ul>
`
},
{
version: '1.2.6',
releaseDate: '2024-10-03', releaseDate: '2024-10-03',
showUntil: '2024-10-02', showUntil: '2024-10-02',
content: content:

View File

@@ -1,4 +1,3 @@
import miscApi from '../../api/misc';
// initial state // initial state
const state = { const state = {
name: null, name: null,

16
package-lock.json generated
View File

@@ -1,12 +1,12 @@
{ {
"name": "liberama", "name": "liberama",
"version": "1.2.5", "version": "1.2.6",
"lockfileVersion": 2, "lockfileVersion": 2,
"requires": true, "requires": true,
"packages": { "packages": {
"": { "": {
"name": "liberama", "name": "liberama",
"version": "1.2.5", "version": "1.2.6",
"hasInstallScript": true, "hasInstallScript": true,
"license": "CC0-1.0", "license": "CC0-1.0",
"dependencies": { "dependencies": {
@@ -3364,9 +3364,9 @@
} }
}, },
"node_modules/caniuse-lite": { "node_modules/caniuse-lite": {
"version": "1.0.30001643", "version": "1.0.30001700",
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001643.tgz", "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001700.tgz",
"integrity": "sha512-ERgWGNleEilSrHM6iUz/zJNSQTP8Mr21wDWpdgvRwcTXGAq6jMtOUPP4dqFPTdKqZ2wKTdtB+uucZ3MRpAUSmg==", "integrity": "sha512-2S6XIXwaE7K7erT8dY+kLQcpa5ms63XlRkMkReXjle+kf6c5g38vyMl+Z5y8dSxOFDhcFe+nxnn261PLxBSQsQ==",
"dev": true, "dev": true,
"funding": [ "funding": [
{ {
@@ -13709,9 +13709,9 @@
} }
}, },
"caniuse-lite": { "caniuse-lite": {
"version": "1.0.30001643", "version": "1.0.30001700",
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001643.tgz", "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001700.tgz",
"integrity": "sha512-ERgWGNleEilSrHM6iUz/zJNSQTP8Mr21wDWpdgvRwcTXGAq6jMtOUPP4dqFPTdKqZ2wKTdtB+uucZ3MRpAUSmg==", "integrity": "sha512-2S6XIXwaE7K7erT8dY+kLQcpa5ms63XlRkMkReXjle+kf6c5g38vyMl+Z5y8dSxOFDhcFe+nxnn261PLxBSQsQ==",
"dev": true "dev": true
}, },
"chalk": { "chalk": {

View File

@@ -1,6 +1,6 @@
{ {
"name": "liberama", "name": "liberama",
"version": "1.2.5", "version": "1.2.8",
"author": "Book Pauk <bookpauk@gmail.com>", "author": "Book Pauk <bookpauk@gmail.com>",
"license": "CC0-1.0", "license": "CC0-1.0",
"repository": "bookpauk/liberama", "repository": "bookpauk/liberama",

View File

@@ -20,6 +20,8 @@ class WebSocketController {
this.readerWorker = new ReaderWorker(config); this.readerWorker = new ReaderWorker(config);
this.workerState = new WorkerState(); this.workerState = new WorkerState();
this.configHash = '';
if (config.bucEnabled) { if (config.bucEnabled) {
this.bucClient = new BUCClient(config); this.bucClient = new BUCClient(config);
} }
@@ -119,8 +121,22 @@ class WebSocketController {
async getConfig(req, ws) { async getConfig(req, ws) {
if (Array.isArray(req.params)) { if (Array.isArray(req.params)) {
const paramsSet = new Set(req.params); const paramsSet = new Set(req.params);
const _configHash = req._configHash;
this.send(_.pick(this.config, this.config.webConfigParams.filter(x => paramsSet.has(x))), req, ws); let response = {_useCached: true};
//оптимизация, чтобы не отдавал большой конфиг каждый раз при обновлении страницы
if (!_configHash || _configHash !== this.configHash) {
if (!this.configHash) {
const webConfig = _.pick(this.config, this.config.webConfigParams);
this.configHash = await utils.getBufHash(Buffer.from(JSON.stringify(webConfig)), 'sha256', 'hex');
}
response = _.pick(this.config, this.config.webConfigParams.filter(x => paramsSet.has(x)));
response._configHash = this.configHash;
}
this.send(response, req, ws);
} else { } else {
throw new Error('params is not an array'); throw new Error('params is not an array');
} }