You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
246 lines
6.9 KiB
246 lines
6.9 KiB
8 years ago
|
/*
|
||
8 years ago
|
* GreeterUtils.js
|
||
8 years ago
|
*
|
||
8 years ago
|
* Copyright © 2017 Antergos Developers <dev@antergos.com>
|
||
8 years ago
|
*
|
||
|
* This file is part of lightdm-webkit2-greeter.
|
||
|
*
|
||
|
* lightdm-webkit2-greeter is free software; you can redistribute it and/or modify
|
||
|
* it under the terms of the GNU General Public License as published by
|
||
|
* the Free Software Foundation; either version 3 of the License, or
|
||
|
* (at your option) any later version.
|
||
|
*
|
||
|
* lightdm-webkit2-greeter is distributed in the hope that it will be useful,
|
||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||
|
* GNU General Public License for more details.
|
||
|
*
|
||
|
* The following additional terms are in effect as per Section 7 of the license:
|
||
|
*
|
||
|
* The preservation of all legal notices and author attributions in
|
||
|
* the material or in the Appropriate Legal Notices displayed
|
||
|
* by works containing it is required.
|
||
|
*
|
||
|
* You should have received a copy of the GNU General Public License
|
||
|
* along with lightdm-webkit2-greeter; If not, see <http://www.gnu.org/licenses/>.
|
||
|
*/
|
||
|
|
||
8 years ago
|
if ( 'undefined' === typeof window.navigator.languages ) {
|
||
|
window.navigator.languages = [ window.navigator.language ];
|
||
|
}
|
||
|
|
||
|
moment.locale( window.navigator.languages );
|
||
8 years ago
|
|
||
|
let localized_invalid_date = moment('today', '!@#'),
|
||
|
time_language = null,
|
||
8 years ago
|
time_format = null,
|
||
|
allowed_dirs = null;
|
||
8 years ago
|
|
||
|
|
||
8 years ago
|
|
||
8 years ago
|
/**
|
||
8 years ago
|
* Provides various utility methods for use in greeter themes. The greeter will automatically
|
||
8 years ago
|
* create an instance of this class when it starts. The instance can be accessed
|
||
8 years ago
|
* with the global variable: [`theme_utils`](#dl-window-theme_utils).
|
||
8 years ago
|
*
|
||
|
* @memberOf LightDM
|
||
8 years ago
|
*/
|
||
8 years ago
|
class ThemeUtils {
|
||
8 years ago
|
/**
|
||
8 years ago
|
* Binds `this` to class, `context`, for all of the class's methods.
|
||
8 years ago
|
*
|
||
8 years ago
|
* @arg {object} context An ES6 class instance with at least one method.
|
||
8 years ago
|
*
|
||
8 years ago
|
* @return {object} `context` with `this` bound to it for all of its methods.
|
||
8 years ago
|
*/
|
||
8 years ago
|
bind_this( context ) {
|
||
8 years ago
|
let excluded_methods = ['constructor'];
|
||
8 years ago
|
|
||
8 years ago
|
function not_excluded( _method, _context ) {
|
||
|
let is_excluded = excluded_methods.findIndex( excluded_method => _method === excluded_method ) > -1,
|
||
|
is_method = 'function' === typeof _context[_method];
|
||
8 years ago
|
|
||
8 years ago
|
return is_method && !is_excluded;
|
||
8 years ago
|
}
|
||
|
|
||
8 years ago
|
for ( let obj = context; obj; obj = Object.getPrototypeOf( obj ) ) {
|
||
|
// Stop once we have traveled all the way up the inheritance chain
|
||
8 years ago
|
if ( 'Object' === obj.constructor.name ) {
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
for ( let method of Object.getOwnPropertyNames( obj ) ) {
|
||
8 years ago
|
if ( not_excluded( method, context ) ) {
|
||
|
context[method] = context[method].bind( context );
|
||
8 years ago
|
}
|
||
|
}
|
||
|
}
|
||
8 years ago
|
}
|
||
8 years ago
|
|
||
|
|
||
|
/**
|
||
|
* Returns the contents of directory found at `path` provided that the (normalized) `path`
|
||
|
* meets at least one of the following conditions:
|
||
|
* * Is located within the greeter themes' root directory.
|
||
|
* * Has been explicitly allowed in the greeter's config file.
|
||
8 years ago
|
* * Is located within the greeter's shared data directory (`/var/lib/lightdm-data`).
|
||
|
* * Is located in `/tmp`.
|
||
8 years ago
|
*
|
||
8 years ago
|
* @param {string} path The abs path to desired directory.
|
||
8 years ago
|
*
|
||
8 years ago
|
* @returns {string[]} List of abs paths for the files and directories found in `path`.
|
||
8 years ago
|
*/
|
||
8 years ago
|
dirlist( path ) {
|
||
|
let allowed = true;
|
||
|
|
||
|
if ( '' === path || ! path instanceof String ) {
|
||
|
console.log('[ERROR] theme_utils.dirlist(): path must be a non-empty string!');
|
||
|
allowed = false;
|
||
|
|
||
|
} else if ( null !== path.match(/^[^/].+/) ) {
|
||
|
console.log('[ERROR] theme_utils.dirlist(): path must not include be absolute!');
|
||
|
allowed = false;
|
||
|
}
|
||
|
|
||
|
if ( null !== path.match(/\/\.+(?=\/)/) ) {
|
||
|
// No special directory names allowed (eg ../../)
|
||
|
path = path.replace(/\/\.+(?=\/)/g, '' );
|
||
|
}
|
||
|
|
||
|
if ( null === allowed_dirs ) {
|
||
8 years ago
|
let user = lightdm.users.pop(),
|
||
|
user_data_dir = greeter_config.get_str( user.username, 'lightdm_data_dir' ),
|
||
|
lightdm_data_dir = user_data_dir.substr( 0, user_data_dir.lastIndexOf('/') );
|
||
8 years ago
|
|
||
|
allowed_dirs = {
|
||
8 years ago
|
themes_dir: greeter_config.get_str( 'greeter', 'themes_dir' ),
|
||
|
backgrounds_dir: greeter_config.get_str( 'branding', 'background_images' ),
|
||
|
lightdm_data_dir: lightdm_data_dir,
|
||
|
tmpdir: '/tmp',
|
||
8 years ago
|
};
|
||
|
}
|
||
|
|
||
|
if ( ! Object.keys( allowed_dirs ).some( dir => path.startsWith( allowed_dirs[dir] ) ) ) {
|
||
|
console.log(`[ERROR] theme_utils.dirlist(): path is not allowed: ${path}`);
|
||
|
allowed = false;
|
||
|
}
|
||
|
|
||
|
if ( ! allowed ) {
|
||
|
return [];
|
||
|
}
|
||
|
|
||
|
try {
|
||
|
return __ThemeUtils.dirlist( path );
|
||
|
|
||
|
} catch( err ) {
|
||
|
console.log( `[ERROR] theme_utils.dirlist(): ${err}` );
|
||
|
return [];
|
||
|
}
|
||
|
}
|
||
8 years ago
|
|
||
|
/**
|
||
|
* Escape HTML entities in a string.
|
||
|
*
|
||
8 years ago
|
* @param {string} text The text to be escaped.
|
||
8 years ago
|
*
|
||
8 years ago
|
* @returns {string}
|
||
8 years ago
|
*/
|
||
8 years ago
|
esc_html( text ) {
|
||
|
return this.txt2html( text );
|
||
|
}
|
||
8 years ago
|
|
||
|
|
||
|
/**
|
||
8 years ago
|
* Get the current time in a localized format. Time format and language are auto-detected
|
||
|
* by default, but can be set manually in the greeter config file.
|
||
|
* * `language` defaults to the system's language, but can be set manually in the config file.
|
||
|
* * When `time_format` config file option has a valid value, time will be formatted
|
||
8 years ago
|
* according to that value.
|
||
|
* * When `time_format` does not have a valid value, the time format will be `LT`
|
||
|
* which is `1:00 PM` or `13:00` depending on the system's locale.
|
||
8 years ago
|
*
|
||
8 years ago
|
* @return {string} The current localized time.
|
||
8 years ago
|
*/
|
||
|
get_current_localized_time() {
|
||
8 years ago
|
if ( null === time_language ) {
|
||
|
let config = greeter_config.greeter,
|
||
|
manual_language = ( '' !== config.time_language && 'auto' !== config.time_language ),
|
||
|
manual_time_format = ( '' !== config.time_format && 'auto' !== config.time_format );
|
||
|
|
||
|
time_language = manual_language ? config.time_language : window.navigator.language;
|
||
|
time_format = manual_time_format ? config.time_format : 'LT';
|
||
|
|
||
|
if ( manual_language ) {
|
||
|
moment.locale( time_language );
|
||
|
}
|
||
|
}
|
||
|
|
||
8 years ago
|
let local_time = moment().format( time_format );
|
||
8 years ago
|
|
||
|
if ( local_time === localized_invalid_date ) {
|
||
|
local_time = moment().format( 'LT' );
|
||
|
}
|
||
|
|
||
|
return local_time;
|
||
8 years ago
|
}
|
||
8 years ago
|
|
||
|
|
||
|
/**
|
||
8 years ago
|
* Use {@link window.theme_utils.esc_html()} instead.
|
||
|
*
|
||
|
* @deprecated
|
||
8 years ago
|
*/
|
||
8 years ago
|
txt2html( text ) {
|
||
|
try {
|
||
|
return __ThemeUtils.txt2html( text );
|
||
|
|
||
|
} catch( err ) {
|
||
|
console.log( `[ERROR] theme_utils.dirlist(): ${err}` );
|
||
|
return text;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
8 years ago
|
|
||
8 years ago
|
|
||
8 years ago
|
const __theme_utils = new Promise( (resolve, reject) => {
|
||
|
let waiting = 0;
|
||
|
|
||
|
const check_window_prop = () => {
|
||
|
if ( waiting > 15000 ) {
|
||
|
return reject( 'Timeout Reached!');
|
||
|
}
|
||
|
|
||
|
setTimeout( () => {
|
||
|
waiting += 1;
|
||
|
|
||
|
if ( '__ThemeUtils' in window ) {
|
||
|
return resolve( (() => new ThemeUtils())() );
|
||
|
}
|
||
|
|
||
|
check_window_prop();
|
||
8 years ago
|
}, 0 );
|
||
8 years ago
|
};
|
||
|
|
||
|
check_window_prop();
|
||
|
});
|
||
|
|
||
|
|
||
8 years ago
|
/**
|
||
8 years ago
|
* Theme Utils - various utility methods for use in greeter themes.
|
||
8 years ago
|
* @name theme_utils
|
||
8 years ago
|
* @type {LightDM.ThemeUtils}
|
||
8 years ago
|
* @memberOf window
|
||
8 years ago
|
*/
|
||
8 years ago
|
__theme_utils.then( result => {
|
||
|
window.theme_utils = result;
|
||
8 years ago
|
|
||
8 years ago
|
/**
|
||
8 years ago
|
* ***Deprecated!*** Use {@link window.theme_utils} instead.
|
||
8 years ago
|
* @name greeterutil
|
||
8 years ago
|
* @type {LightDM.ThemeUtils}
|
||
8 years ago
|
* @memberOf window
|
||
8 years ago
|
* @deprecated
|
||
8 years ago
|
*/
|
||
|
window.greeterutil = window.theme_utils;
|
||
|
} );
|