2019-10-20 22:10:24 +02:00
|
|
|
// @license magnet:?xt=urn:btih:0b31508aeb0634b347b8270c7bee4d411b5d4109&dn=agpl-3.0.txt AGPL-3.0
|
2021-10-21 11:44:03 +02:00
|
|
|
'use strict';
|
2020-02-13 18:22:35 +01:00
|
|
|
/* globals context, openNotification, openPopupWithSource, xmlHttpRequestJson */
|
2019-02-13 15:06:28 +01:00
|
|
|
|
2020-02-13 18:22:35 +01:00
|
|
|
function fix_popup_preview_selector() {
|
|
|
|
const link = document.getElementById('popup-preview-selector');
|
|
|
|
|
|
|
|
if (!link) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
link.addEventListener('click', function (ev) {
|
|
|
|
const selector_entries = document.getElementById('path_entries').value;
|
|
|
|
const href = link.href.replace('selector-token', encodeURIComponent(selector_entries));
|
|
|
|
|
|
|
|
openPopupWithSource(href);
|
|
|
|
|
|
|
|
ev.preventDefault();
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2021-10-21 11:44:03 +02:00
|
|
|
// <crypto form (Web login)>
|
|
|
|
function poormanSalt() { // If crypto.getRandomValues is not available
|
2019-02-13 15:06:28 +01:00
|
|
|
const base = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ.0123456789/abcdefghijklmnopqrstuvwxyz';
|
|
|
|
let text = '$2a$04$';
|
|
|
|
for (let i = 22; i > 0; i--) {
|
|
|
|
text += base.charAt(Math.floor(Math.random() * 64));
|
|
|
|
}
|
|
|
|
return text;
|
|
|
|
}
|
|
|
|
|
2020-11-02 12:03:16 +01:00
|
|
|
function forgetOpenCategories() {
|
|
|
|
localStorage.removeItem('FreshRSS_open_categories');
|
|
|
|
}
|
|
|
|
|
2019-02-13 15:06:28 +01:00
|
|
|
function init_crypto_form() {
|
|
|
|
/* globals dcodeIO */
|
|
|
|
const crypto_form = document.getElementById('crypto-form');
|
|
|
|
if (!crypto_form) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!(window.dcodeIO)) {
|
|
|
|
if (window.console) {
|
|
|
|
console.log('FreshRSS waiting for bcrypt.js…');
|
|
|
|
}
|
|
|
|
setTimeout(init_crypto_form, 100);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2020-11-02 12:03:16 +01:00
|
|
|
forgetOpenCategories();
|
|
|
|
|
2020-12-31 00:13:29 +01:00
|
|
|
const submit_button = document.getElementById('loginButton');
|
2020-12-22 17:36:50 +01:00
|
|
|
submit_button.disabled = false;
|
|
|
|
|
2019-02-13 15:06:28 +01:00
|
|
|
crypto_form.onsubmit = function (e) {
|
|
|
|
submit_button.disabled = true;
|
|
|
|
let success = false;
|
|
|
|
|
|
|
|
const req = new XMLHttpRequest();
|
|
|
|
req.open('GET', './?c=javascript&a=nonce&user=' + document.getElementById('username').value, false);
|
|
|
|
req.onerror = function () {
|
2021-10-21 11:44:03 +02:00
|
|
|
openNotification('Communication error!', 'bad');
|
|
|
|
};
|
2019-02-13 15:06:28 +01:00
|
|
|
req.send();
|
|
|
|
if (req.status == 200) {
|
|
|
|
const json = xmlHttpRequestJson(req);
|
|
|
|
if (!json.salt1 || !json.nonce) {
|
|
|
|
openNotification('Invalid user!', 'bad');
|
|
|
|
} else {
|
|
|
|
try {
|
2021-10-21 11:44:03 +02:00
|
|
|
const strong = window.Uint32Array && window.crypto && (typeof window.crypto.getRandomValues === 'function');
|
|
|
|
const s = dcodeIO.bcrypt.hashSync(document.getElementById('passwordPlain').value, json.salt1);
|
|
|
|
const c = dcodeIO.bcrypt.hashSync(json.nonce + s, strong ? dcodeIO.bcrypt.genSaltSync(4) : poormanSalt());
|
2019-02-13 15:06:28 +01:00
|
|
|
document.getElementById('challenge').value = c;
|
|
|
|
if (!s || !c) {
|
|
|
|
openNotification('Crypto error!', 'bad');
|
|
|
|
} else {
|
|
|
|
success = true;
|
|
|
|
}
|
|
|
|
} catch (ex) {
|
|
|
|
openNotification('Crypto exception! ' + ex, 'bad');
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
req.onerror();
|
|
|
|
}
|
|
|
|
|
|
|
|
submit_button.disabled = false;
|
|
|
|
return success;
|
|
|
|
};
|
|
|
|
}
|
2021-10-21 11:44:03 +02:00
|
|
|
// </crypto form (Web login)>
|
2019-02-13 15:06:28 +01:00
|
|
|
|
|
|
|
function init_password_observers() {
|
|
|
|
document.querySelectorAll('.toggle-password').forEach(function (a) {
|
2021-10-21 11:44:03 +02:00
|
|
|
a.onmousedown = function (ev) {
|
|
|
|
const passwordField = document.getElementById(this.getAttribute('data-toggle'));
|
|
|
|
passwordField.setAttribute('type', 'text');
|
|
|
|
this.classList.add('active');
|
|
|
|
return false;
|
|
|
|
};
|
|
|
|
a.onmouseup = function (ev) {
|
|
|
|
const passwordField = document.getElementById(this.getAttribute('data-toggle'));
|
|
|
|
passwordField.setAttribute('type', 'password');
|
|
|
|
this.classList.remove('active');
|
|
|
|
return false;
|
|
|
|
};
|
|
|
|
});
|
2019-02-13 15:06:28 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
function init_select_observers() {
|
|
|
|
document.querySelectorAll('.select-change').forEach(function (s) {
|
2021-10-21 11:44:03 +02:00
|
|
|
s.onchange = function (ev) {
|
|
|
|
const opt = s.options[s.selectedIndex];
|
|
|
|
const url = opt.getAttribute('data-url');
|
|
|
|
if (url) {
|
|
|
|
s.disabled = true;
|
|
|
|
s.value = '';
|
|
|
|
if (s.form) {
|
|
|
|
s.form.querySelectorAll('[type=submit]').forEach(function (b) {
|
|
|
|
b.disabled = true;
|
|
|
|
});
|
|
|
|
}
|
|
|
|
location.href = url;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
});
|
2019-02-13 15:06:28 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
function init_slider_observers() {
|
2021-10-21 11:44:03 +02:00
|
|
|
const slider = document.getElementById('slider');
|
|
|
|
const closer = document.getElementById('close-slider');
|
2019-02-13 15:06:28 +01:00
|
|
|
if (!slider) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
document.querySelector('.post').onclick = function (ev) {
|
2021-10-21 11:44:03 +02:00
|
|
|
const a = ev.target.closest('.open-slider');
|
|
|
|
if (a) {
|
|
|
|
if (!context.ajax_loading) {
|
|
|
|
context.ajax_loading = true;
|
|
|
|
|
|
|
|
const req = new XMLHttpRequest();
|
|
|
|
req.open('GET', a.href + '&ajax=1', true);
|
|
|
|
req.responseType = 'document';
|
|
|
|
req.onload = function (e) {
|
|
|
|
slider.innerHTML = this.response.body.innerHTML;
|
|
|
|
slider.classList.add('active');
|
|
|
|
closer.classList.add('active');
|
|
|
|
context.ajax_loading = false;
|
|
|
|
fix_popup_preview_selector();
|
|
|
|
};
|
|
|
|
req.send();
|
|
|
|
return false;
|
2019-02-13 15:06:28 +01:00
|
|
|
}
|
2021-10-21 11:44:03 +02:00
|
|
|
}
|
|
|
|
};
|
2019-02-13 15:06:28 +01:00
|
|
|
|
|
|
|
closer.onclick = function (ev) {
|
2021-10-21 11:44:03 +02:00
|
|
|
if (data_leave_validation() || confirm(context.i18n.confirmation_default)) {
|
|
|
|
slider.querySelectorAll('form').forEach(function (f) { f.reset(); });
|
|
|
|
closer.classList.remove('active');
|
|
|
|
slider.classList.remove('active');
|
|
|
|
return true;
|
|
|
|
} else {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
};
|
2019-02-13 15:06:28 +01:00
|
|
|
}
|
|
|
|
|
Feature/new archiving (#2335)
* Change archiving config page layout
I've changed some wording and moved actions into a
maintenance section.
* Update purge action
Now we have more control on the purge action. The configuration allows
us to choose what to keep and what to discard in a more precise way.
At the moment, the configuration applies for all feeds.
* Add purge configuration on feed level
Now the extend purge configuration is available on feed level.
It is stored as attributes and will be used in the purge action.
* Update purge action
Now the purge action uses the feed configuration if it exists and
defaults on user configuration if not.
* Add empty option in period list
* Fix configuration warnings
* Add archiving configuration on categories
See #2369
* Add user info back
* Add explanations in UI
* Fixes for SQLite + error + misc.
* Fix invalid feed reference
* Short array syntax
Only for new code, so far
* Fix prefix error
* Query performance, default values
Work in progress
* Fix default values and confirm before leaving
Form cancel and confirm changes before leaving were broken.
And start taking advantage of the short echo syntax `<?= ?>` as we have
moved to PHP 5.4+
* More work
* Tuning SQL
* Fix MariaDB + performance issue
* SQL performance
* Fix SQLite bug
* Fix some attributes JSON encoding bugs
Especially for SQLite export/import
* More uniform, fix bugs
More uniform between global, category, feed settings
* Drop special cases for old articles during refresh
Instead will use lastSeen date with the new archiving logic.
This was generating problems anyway
https://github.com/FreshRSS/FreshRSS/issues/2154
* Draft drop index keep_history
Not needed anymore
* MySQL typo
Now properly tested with MySQL, PostgreSQL, SQLite
* More work for legacy values
Important to avoid overriding user's preference and risking deleting
data erroneously
* Fix PHP 7.3 / 7.4 warnings
@aledeg "Trying to use values of type null, bool, int, float or resource
as an array (such as $null["key"]) will now generate a notice. "
https://php.net/migration74.incompatible
* Reintroduce min articles and take care of legacy parameters
* A few changes forgotten
* Draft of migration + DROP of feed.keep_history
* Fix several errors
And give up using const for SQL to allow multiple database types (and we
cannot redefine a const)
* Add keep_min to categories + factorise archiving logic
* Legacy fix
* Fix bug yield from
* Minor: Use JSON_UNESCAPED_SLASHE for attributes
And make more uniform
* Fix sign and missing variable
* Fine tune the logic
2019-10-23 00:52:15 +02:00
|
|
|
function data_leave_validation() {
|
|
|
|
const ds = document.querySelectorAll('[data-leave-validation]');
|
|
|
|
for (let i = ds.length - 1; i >= 0; i--) {
|
|
|
|
const input = ds[i];
|
|
|
|
if (input.type === 'checkbox' || input.type === 'radio') {
|
|
|
|
if (input.checked != input.getAttribute('data-leave-validation')) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
} else if (input.value != input.getAttribute('data-leave-validation')) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2019-02-13 15:06:28 +01:00
|
|
|
function init_configuration_alert() {
|
|
|
|
window.onsubmit = function (e) {
|
2021-10-21 11:44:03 +02:00
|
|
|
window.hasSubmit = true;
|
|
|
|
};
|
2019-02-13 15:06:28 +01:00
|
|
|
window.onbeforeunload = function (e) {
|
2021-10-21 11:44:03 +02:00
|
|
|
if (window.hasSubmit) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if (!data_leave_validation()) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
};
|
2019-02-13 15:06:28 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
function init_extra() {
|
|
|
|
if (!window.context) {
|
|
|
|
if (window.console) {
|
|
|
|
console.log('FreshRSS extra waiting for JS…');
|
|
|
|
}
|
2021-10-21 11:44:03 +02:00
|
|
|
window.setTimeout(init_extra, 50); // Wait for all js to be loaded
|
2019-02-13 15:06:28 +01:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
init_crypto_form();
|
|
|
|
init_password_observers();
|
|
|
|
init_select_observers();
|
|
|
|
init_slider_observers();
|
|
|
|
init_configuration_alert();
|
2020-02-13 18:22:35 +01:00
|
|
|
fix_popup_preview_selector();
|
2019-02-13 15:06:28 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
if (document.readyState && document.readyState !== 'loading') {
|
|
|
|
init_extra();
|
|
|
|
} else {
|
|
|
|
document.addEventListener('DOMContentLoaded', function () {
|
2021-10-21 11:44:03 +02:00
|
|
|
if (window.console) {
|
|
|
|
console.log('FreshRSS extra waiting for DOMContentLoaded…');
|
|
|
|
}
|
|
|
|
init_extra();
|
|
|
|
}, false);
|
2019-02-13 15:06:28 +01:00
|
|
|
}
|
2019-10-20 22:10:24 +02:00
|
|
|
// @license-end
|