yannstatic/static/2019/12/25/utiliser-son-android-de-facon-plus-securisee.html

1988 lines
211 KiB
HTML
Raw Normal View History

2024-10-31 20:18:37 +01:00
<!DOCTYPE html><html lang="fr">
<head><meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=no"><title>utiliser-son-android-de-facon-plus-securisee - YannStatic</title>
<meta name="description" content="URL: https://linuxfr.org/news/utiliser-son-android-de-facon-plus-securiseeTitle: Utiliser son Android de façon plus sécuriséeAuthors: voxdemonix ...">
<link rel="canonical" href="https://static.rnmkcy.eu/2019/12/25/utiliser-son-android-de-facon-plus-securisee.html"><link rel="alternate" type="application/rss+xml" title="YannStatic" href="/feed.xml">
<!-- - include head/favicon.html - -->
<link rel="shortcut icon" type="image/png" href="/assets/favicon/favicon.png"><link rel="stylesheet" href="/assets/css/main.css"><link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.0.13/css/all.css" ><!-- start custom head snippets --><link rel="stylesheet" href="/assets/css/expand.css">
<!-- end custom head snippets --><script>(function() {
window.isArray = function(val) {
return Object.prototype.toString.call(val) === '[object Array]';
};
window.isString = function(val) {
return typeof val === 'string';
};
window.hasEvent = function(event) {
return 'on'.concat(event) in window.document;
};
window.isOverallScroller = function(node) {
return node === document.documentElement || node === document.body || node === window;
};
window.isFormElement = function(node) {
var tagName = node.tagName;
return tagName === 'INPUT' || tagName === 'SELECT' || tagName === 'TEXTAREA';
};
window.pageLoad = (function () {
var loaded = false, cbs = [];
window.addEventListener('load', function () {
var i;
loaded = true;
if (cbs.length > 0) {
for (i = 0; i < cbs.length; i++) {
cbs[i]();
}
}
});
return {
then: function(cb) {
cb && (loaded ? cb() : (cbs.push(cb)));
}
};
})();
})();
(function() {
window.throttle = function(func, wait) {
var args, result, thisArg, timeoutId, lastCalled = 0;
function trailingCall() {
lastCalled = new Date;
timeoutId = null;
result = func.apply(thisArg, args);
}
return function() {
var now = new Date,
remaining = wait - (now - lastCalled);
args = arguments;
thisArg = this;
if (remaining <= 0) {
clearTimeout(timeoutId);
timeoutId = null;
lastCalled = now;
result = func.apply(thisArg, args);
} else if (!timeoutId) {
timeoutId = setTimeout(trailingCall, remaining);
}
return result;
};
};
})();
(function() {
var Set = (function() {
var add = function(item) {
var i, data = this._data;
for (i = 0; i < data.length; i++) {
if (data[i] === item) {
return;
}
}
this.size ++;
data.push(item);
return data;
};
var Set = function(data) {
this.size = 0;
this._data = [];
var i;
if (data.length > 0) {
for (i = 0; i < data.length; i++) {
add.call(this, data[i]);
}
}
};
Set.prototype.add = add;
Set.prototype.get = function(index) { return this._data[index]; };
Set.prototype.has = function(item) {
var i, data = this._data;
for (i = 0; i < data.length; i++) {
if (this.get(i) === item) {
return true;
}
}
return false;
};
Set.prototype.is = function(map) {
if (map._data.length !== this._data.length) { return false; }
var i, j, flag, tData = this._data, mData = map._data;
for (i = 0; i < tData.length; i++) {
for (flag = false, j = 0; j < mData.length; j++) {
if (tData[i] === mData[j]) {
flag = true;
break;
}
}
if (!flag) { return false; }
}
return true;
};
Set.prototype.values = function() {
return this._data;
};
return Set;
})();
window.Lazyload = (function(doc) {
var queue = {js: [], css: []}, sources = {js: {}, css: {}}, context = this;
var createNode = function(name, attrs) {
var node = doc.createElement(name), attr;
for (attr in attrs) {
if (attrs.hasOwnProperty(attr)) {
node.setAttribute(attr, attrs[attr]);
}
}
return node;
};
var end = function(type, url) {
var s, q, qi, cbs, i, j, cur, val, flag;
if (type === 'js' || type ==='css') {
s = sources[type], q = queue[type];
s[url] = true;
for (i = 0; i < q.length; i++) {
cur = q[i];
if (cur.urls.has(url)) {
qi = cur, val = qi.urls.values();
qi && (cbs = qi.callbacks);
for (flag = true, j = 0; j < val.length; j++) {
cur = val[j];
if (!s[cur]) {
flag = false;
}
}
if (flag && cbs && cbs.length > 0) {
for (j = 0; j < cbs.length; j++) {
cbs[j].call(context);
}
qi.load = true;
}
}
}
}
};
var load = function(type, urls, callback) {
var s, q, qi, node, i, cur,
_urls = typeof urls === 'string' ? new Set([urls]) : new Set(urls), val, url;
if (type === 'js' || type ==='css') {
s = sources[type], q = queue[type];
for (i = 0; i < q.length; i++) {
cur = q[i];
if (_urls.is(cur.urls)) {
qi = cur;
break;
}
}
val = _urls.values();
if (qi) {
callback && (qi.load || qi.callbacks.push(callback));
callback && (qi.load && callback());
} else {
q.push({
urls: _urls,
callbacks: callback ? [callback] : [],
load: false
});
for (i = 0; i < val.length; i++) {
node = null, url = val[i];
if (s[url] === undefined) {
(type === 'js' ) && (node = createNode('script', { src: url }));
(type === 'css') && (node = createNode('link', { rel: 'stylesheet', href: url }));
if (node) {
node.onload = (function(type, url) {
return function() {
end(type, url);
};
})(type, url);
(doc.head || doc.body).appendChild(node);
s[url] = false;
}
}
}
}
}
};
return {
js: function(url, callback) {
load('js', url, callback);
},
css: function(url, callback) {
load('css', url, callback);
}
};
})(this.document);
})();
</script><script>
(function() {
var TEXT_VARIABLES = {
version: '2.2.6',
sources: {
font_awesome: 'https://use.fontawesome.com/releases/v5.0.13/css/all.css',
jquery: '/assets/js/jquery.min.js',
leancloud_js_sdk: '//cdn.jsdelivr.net/npm/leancloud-storage@3.13.2/dist/av-min.js',
chart: 'https://cdn.bootcss.com/Chart.js/2.7.2/Chart.bundle.min.js',
gitalk: {
js: 'https://cdn.bootcss.com/gitalk/1.2.2/gitalk.min.js',
css: 'https://cdn.bootcss.com/gitalk/1.2.2/gitalk.min.css'
},
valine: 'https://unpkg.com/valine/dist/Valine.min.js'
},
site: {
toc: {
selectors: 'h1,h2,h3'
}
},
paths: {
search_js: '/assets/search.js'
}
};
window.TEXT_VARIABLES = TEXT_VARIABLES;
})();
</script>
</head>
<body>
<div class="root" data-is-touch="false">
<div class="layout--page js-page-root"><!----><div class="page__main js-page-main page__viewport hide-footer has-aside has-aside cell cell--auto">
<div class="page__main-inner"><div class="page__header d-print-none"><header class="header"><div class="main">
<div class="header__title">
<div class="header__brand"><svg id="svg" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="400" height="478.9473684210526" viewBox="0, 0, 400,478.9473684210526"><g id="svgg"><path id="path0" d="M308.400 56.805 C 306.970 56.966,303.280 57.385,300.200 57.738 C 290.906 58.803,278.299 59.676,269.200 59.887 L 260.600 60.085 259.400 61.171 C 258.010 62.428,256.198 63.600,255.645 63.600 C 255.070 63.600,252.887 65.897,252.598 66.806 C 252.460 67.243,252.206 67.600,252.034 67.600 C 251.397 67.600,247.206 71.509,247.202 72.107 C 247.201 72.275,246.390 73.190,245.400 74.138 C 243.961 75.517,243.598 76.137,243.592 77.231 C 243.579 79.293,241.785 83.966,240.470 85.364 C 239.176 86.740,238.522 88.365,237.991 91.521 C 237.631 93.665,236.114 97.200,235.554 97.200 C 234.938 97.200,232.737 102.354,232.450 104.472 C 232.158 106.625,230.879 109.226,229.535 110.400 C 228.933 110.926,228.171 113.162,226.434 119.500 C 226.178 120.435,225.795 121.200,225.584 121.200 C 225.373 121.200,225.200 121.476,225.200 121.813 C 225.200 122.149,224.885 122.541,224.500 122.683 C 223.606 123.013,223.214 123.593,223.204 124.600 C 223.183 126.555,220.763 132.911,219.410 134.562 C 218.443 135.742,217.876 136.956,217.599 138.440 C 217.041 141.424,215.177 146.434,214.532 146.681 C 214.240 146.794,214.000 147.055,214.000 147.261 C 214.000 147.467,213.550 148.086,213.000 148.636 C 212.450 149.186,212.000 149.893,212.000 150.208 C 212.000 151.386,208.441 154.450,207.597 153.998 C 206.319 153.315,204.913 150.379,204.633 147.811 C 204.365 145.357,202.848 142.147,201.759 141.729 C 200.967 141.425,199.200 137.451,199.200 135.974 C 199.200 134.629,198.435 133.224,196.660 131.311 C 195.363 129.913,194.572 128.123,193.870 125.000 C 193.623 123.900,193.236 122.793,193.010 122.540 C 190.863 120.133,190.147 118.880,188.978 115.481 C 188.100 112.928,187.151 111.003,186.254 109.955 C 185.358 108.908,184.518 107.204,183.847 105.073 C 183.280 103.273,182.497 101.329,182.108 100.753 C 181.719 100.177,180.904 98.997,180.298 98.131 C 179.693 97.265,178.939 95.576,178.624 94.378 C 178.041 92.159,177.125 90.326,175.023 87.168 C 174.375 86.196,173.619 84.539,173.342 83.486 C 172.800 81.429,171.529 79.567,170.131 78.785 C 169.654 78.517,168.697 77.511,168.006 76.549 C 167.316 75.587,166.594 74.800,166.402 74.800 C 166.210 74.800,164.869 73.633,163.421 72.206 C 160.103 68.936,161.107 69.109,146.550 69.301 C 133.437 69.474,128.581 70.162,126.618 72.124 C 126.248 72.495,125.462 72.904,124.872 73.033 C 124.282 73.163,123.088 73.536,122.219 73.863 C 121.349 74.191,119.028 74.638,117.061 74.858 C 113.514 75.254,109.970 76.350,108.782 77.419 C 107.652 78.436,100.146 80.400,97.388 80.400 C 95.775 80.400,93.167 81.360,91.200 82.679 C 90.430 83.195,89.113 83.804,88.274 84.031 C 85.875 84.681,78.799 90.910,74.400 96.243 L 73.400 97.456 73.455 106.028 C 73.526 117.055,74.527 121.238,77.820 124.263 C 78.919 125.273,80.400 127.902,80.400 128.842 C 80.400 129.202,81.075 130.256,81.900 131.186 C 83.563 133.059,85.497 136.346,86.039 138.216 C 86.233 138.886,87.203 140.207,88.196 141.153 C 89.188 142.098,90.000 143.104,90.000 143.388 C 90.000 144.337,92.129 148.594,92.869 149.123 C 93.271 149.410,93.600 149.831,93.600 150.059 C 93.600 150.286,93.932 150.771,94.337 151.136 C 94.743 151.501,95.598 153.004,96.237 154.475 C 96.877 155.947,97.760 157.351,98.200 157.596 C 98.640 157.841,99.900 159.943,101.000 162.267 C 102.207 164.817,103.327 166.644,103.825 166.876 C 104.278 167.087,105.065 168.101,105.573 169.130 C 107.658 173.348,108.097 174.093,110.006 176.647 C 111.103 178.114,112.000 179.725,112.000 180.227 C 112.000 181.048,113.425 183.163,114.678 184.200 C 115.295 184.711,117.396 188.733,117.720 190.022 C 117.855 190.562,118.603 191.633,119.381 192.402 C 120.160 193.171,121.496 195.258,122.351 197.039 C 123.206 198.820,124.167 200.378,124.487 200.501 C 124.807 200.624,125.953 202.496,127.034 204.662 C 128.114 206.828,129.676 209.299,130.505 210.153 C 131.333 211.007,132.124 212.177,132.262 212.753 C 132.618 214.239,134.291 217.048,136.288 219.5
" href="/">YannStatic</a></div><!--<button class="button button--secondary button--circle search-button js-search-toggle"><i class="fas fa-search"></i></button>--><!-- <li><button class="button button--secondary button--circle search-button js-search-toggle"><i class="fas fa-search"></i></button></li> -->
<!-- Champ de recherche -->
<div id="searchbox" class="search search--dark" style="visibility: visible">
<div class="main">
<div class="search__header"></div>
<div class="search-bar">
<div class="search-box js-search-box">
<div class="search-box__icon-search"><i class="fas fa-search"></i></div>
<input id="search-input" type="text" />
<!-- <div class="search-box__icon-clear js-icon-clear">
<a><i class="fas fa-times"></i></a>
</div> -->
</div>
</div>
</div>
</div>
<!-- Script pointing to search-script.js -->
<script>/*!
* Simple-Jekyll-Search
* Copyright 2015-2020, Christian Fei
* Licensed under the MIT License.
*/
(function(){
'use strict'
var _$Templater_7 = {
compile: compile,
setOptions: setOptions
}
const options = {}
options.pattern = /\{(.*?)\}/g
options.template = ''
options.middleware = function () {}
function setOptions (_options) {
options.pattern = _options.pattern || options.pattern
options.template = _options.template || options.template
if (typeof _options.middleware === 'function') {
options.middleware = _options.middleware
}
}
function compile (data) {
return options.template.replace(options.pattern, function (match, prop) {
const value = options.middleware(prop, data[prop], options.template)
if (typeof value !== 'undefined') {
return value
}
return data[prop] || match
})
}
'use strict';
function fuzzysearch (needle, haystack) {
var tlen = haystack.length;
var qlen = needle.length;
if (qlen > tlen) {
return false;
}
if (qlen === tlen) {
return needle === haystack;
}
outer: for (var i = 0, j = 0; i < qlen; i++) {
var nch = needle.charCodeAt(i);
while (j < tlen) {
if (haystack.charCodeAt(j++) === nch) {
continue outer;
}
}
return false;
}
return true;
}
var _$fuzzysearch_1 = fuzzysearch;
'use strict'
/* removed: const _$fuzzysearch_1 = require('fuzzysearch') */;
var _$FuzzySearchStrategy_5 = new FuzzySearchStrategy()
function FuzzySearchStrategy () {
this.matches = function (string, crit) {
return _$fuzzysearch_1(crit.toLowerCase(), string.toLowerCase())
}
}
'use strict'
var _$LiteralSearchStrategy_6 = new LiteralSearchStrategy()
function LiteralSearchStrategy () {
this.matches = function (str, crit) {
if (!str) return false
str = str.trim().toLowerCase()
crit = crit.trim().toLowerCase()
return crit.split(' ').filter(function (word) {
return str.indexOf(word) >= 0
}).length === crit.split(' ').length
}
}
'use strict'
var _$Repository_4 = {
put: put,
clear: clear,
search: search,
setOptions: __setOptions_4
}
/* removed: const _$FuzzySearchStrategy_5 = require('./SearchStrategies/FuzzySearchStrategy') */;
/* removed: const _$LiteralSearchStrategy_6 = require('./SearchStrategies/LiteralSearchStrategy') */;
function NoSort () {
return 0
}
const data = []
let opt = {}
opt.fuzzy = false
opt.limit = 10
opt.searchStrategy = opt.fuzzy ? _$FuzzySearchStrategy_5 : _$LiteralSearchStrategy_6
opt.sort = NoSort
opt.exclude = []
function put (data) {
if (isObject(data)) {
return addObject(data)
}
if (isArray(data)) {
return addArray(data)
}
return undefined
}
function clear () {
data.length = 0
return data
}
function isObject (obj) {
return Boolean(obj) && Object.prototype.toString.call(obj) === '[object Object]'
}
function isArray (obj) {
return Boolean(obj) && Object.prototype.toString.call(obj) === '[object Array]'
}
function addObject (_data) {
data.push(_data)
return data
}
function addArray (_data) {
const added = []
clear()
for (let i = 0, len = _data.length; i < len; i++) {
if (isObject(_data[i])) {
added.push(addObject(_data[i]))
}
}
return added
}
function search (crit) {
if (!crit) {
return []
}
return findMatches(data, crit, opt.searchStrategy, opt).sort(opt.sort)
}
function __setOptions_4 (_opt) {
opt = _opt || {}
opt.fuzzy = _opt.fuzzy || false
opt.limit = _opt.limit || 10
opt.searchStrategy = _opt.fuzzy ? _$FuzzySearchStrategy_5 : _$LiteralSearchStrategy_6
opt.sort = _opt.sort || NoSort
opt.exclude = _opt.exclude || []
}
function findMatches (data, crit, strategy, opt) {
const matches = []
for (let i = 0; i < data.length && matches.length < opt.limit; i++) {
const match = findMatchesInObject(data[i], crit, strategy, opt)
if (match) {
matches.push(match)
}
}
return matches
}
function findMatchesInObject (obj, crit, strategy, opt) {
for (const key in obj) {
if (!isExcluded(obj[key], opt.exclude) && strategy.matches(obj[key], crit)) {
return obj
}
}
}
function isExcluded (term, excludedTerms) {
for (let i = 0, len = excludedTerms.length; i < len; i++) {
const excludedTerm = excludedTerms[i]
if (new RegExp(excludedTerm).test(term)) {
return true
}
}
return false
}
/* globals ActiveXObject:false */
'use strict'
var _$JSONLoader_2 = {
load: load
}
function load (location, callback) {
const xhr = getXHR()
xhr.open('GET', location, true)
xhr.onreadystatechange = createStateChangeListener(xhr, callback)
xhr.send()
}
function createStateChangeListener (xhr, callback) {
return function () {
if (xhr.readyState === 4 && xhr.status === 200) {
try {
callback(null, JSON.parse(xhr.responseText))
} catch (err) {
callback(err, null)
}
}
}
}
function getXHR () {
return window.XMLHttpRequest ? new window.XMLHttpRequest() : new ActiveXObject('Microsoft.XMLHTTP')
}
'use strict'
var _$OptionsValidator_3 = function OptionsValidator (params) {
if (!validateParams(params)) {
throw new Error('-- OptionsValidator: required options missing')
}
if (!(this instanceof OptionsValidator)) {
return new OptionsValidator(params)
}
const requiredOptions = params.required
this.getRequiredOptions = function () {
return requiredOptions
}
this.validate = function (parameters) {
const errors = []
requiredOptions.forEach(function (requiredOptionName) {
if (typeof parameters[requiredOptionName] === 'undefined') {
errors.push(requiredOptionName)
}
})
return errors
}
function validateParams (params) {
if (!params) {
return false
}
return typeof params.required !== 'undefined' && params.required instanceof Array
}
}
'use strict'
var _$utils_9 = {
merge: merge,
isJSON: isJSON
}
function merge (defaultParams, mergeParams) {
const mergedOptions = {}
for (const option in defaultParams) {
mergedOptions[option] = defaultParams[option]
if (typeof mergeParams[option] !== 'undefined') {
mergedOptions[option] = mergeParams[option]
}
}
return mergedOptions
}
function isJSON (json) {
try {
if (json instanceof Object && JSON.parse(JSON.stringify(json))) {
return true
}
return false
} catch (err) {
return false
}
}
var _$src_8 = {};
(function (window) {
'use strict'
let options = {
searchInput: null,
resultsContainer: null,
json: [],
success: Function.prototype,
searchResultTemplate: '<li><a href="{url}" title="{desc}">{title}</a></li>',
templateMiddleware: Function.prototype,
sortMiddleware: function () {
return 0
},
noResultsText: 'No results found',
limit: 10,
fuzzy: false,
debounceTime: null,
exclude: []
}
let debounceTimerHandle
const debounce = function (func, delayMillis) {
if (delayMillis) {
clearTimeout(debounceTimerHandle)
debounceTimerHandle = setTimeout(func, delayMillis)
} else {
func.call()
}
}
const requiredOptions = ['searchInput', 'resultsContainer', 'json']
/* removed: const _$Templater_7 = require('./Templater') */;
/* removed: const _$Repository_4 = require('./Repository') */;
/* removed: const _$JSONLoader_2 = require('./JSONLoader') */;
const optionsValidator = _$OptionsValidator_3({
required: requiredOptions
})
/* removed: const _$utils_9 = require('./utils') */;
window.SimpleJekyllSearch = function (_options) {
const errors = optionsValidator.validate(_options)
if (errors.length > 0) {
throwError('You must specify the following required options: ' + requiredOptions)
}
options = _$utils_9.merge(options, _options)
_$Templater_7.setOptions({
template: options.searchResultTemplate,
middleware: options.templateMiddleware
})
_$Repository_4.setOptions({
fuzzy: options.fuzzy,
limit: options.limit,
sort: options.sortMiddleware,
exclude: options.exclude
})
if (_$utils_9.isJSON(options.json)) {
initWithJSON(options.json)
} else {
initWithURL(options.json)
}
const rv = {
search: search
}
typeof options.success === 'function' && options.success.call(rv)
return rv
}
function initWithJSON (json) {
_$Repository_4.put(json)
registerInput()
}
function initWithURL (url) {
_$JSONLoader_2.load(url, function (err, json) {
if (err) {
throwError('failed to get JSON (' + url + ')')
}
initWithJSON(json)
})
}
function emptyResultsContainer () {
options.resultsContainer.innerHTML = ''
}
function appendToResultsContainer (text) {
options.resultsContainer.innerHTML += text
}
function registerInput () {
options.searchInput.addEventListener('input', function (e) {
if (isWhitelistedKey(e.which)) {
emptyResultsContainer()
debounce(function () { search(e.target.value) }, options.debounceTime)
}
})
}
function search (query) {
if (isValidQuery(query)) {
emptyResultsContainer()
render(_$Repository_4.search(query), query)
}
}
function render (results, query) {
const len = results.length
if (len === 0) {
return appendToResultsContainer(options.noResultsText)
}
for (let i = 0; i < len; i++) {
results[i].query = query
appendToResultsContainer(_$Templater_7.compile(results[i]))
}
}
function isValidQuery (query) {
return query && query.length > 0
}
function isWhitelistedKey (key) {
return [13, 16, 20, 37, 38, 39, 40, 91].indexOf(key) === -1
}
function throwError (message) {
throw new Error('SimpleJekyllSearch --- ' + message)
}
})(window)
}());
</script>
<!-- Configuration -->
<script>
SimpleJekyllSearch({
searchInput: document.getElementById('search-input'),
resultsContainer: document.getElementById('results-container'),
json: '/search.json',
//searchResultTemplate: '<li><a href="https://static.rnmkcy.eu{url}">{date}&nbsp;{title}</a></li>'
searchResultTemplate: '<li><a href="{url}">{date}&nbsp;{title}</a></li>'
})
</script>
<!-- Fin déclaration champ de recherche --></div><nav class="navigation">
<ul><li class="navigation__item"><a href="/archive.html">Etiquettes</a></li><li class="navigation__item"><a href="/htmldoc.html">Documents</a></li><li class="navigation__item"><a href="/liens_ttrss.html">Liens</a></li><li class="navigation__item"><a href="/aide-jekyll-text-theme.html">Aide</a></li></ul>
</nav></div>
</header>
</div><div class="page__content"><div class ="main"><div class="grid grid--reverse">
<div class="col-main cell cell--auto"><!-- start custom main top snippet --><div id="results-container" class="search-result js-search-result"></div><!-- end custom main top snippet -->
<article itemscope itemtype="http://schema.org/Article"><div class="article__header"><header><h1 style="color:Tomato;">utiliser-son-android-de-facon-plus-securisee</h1></header></div><meta itemprop="headline" content="utiliser-son-android-de-facon-plus-securisee"><div class="article__info clearfix"><ul class="left-col menu"><li>
2024-11-08 14:10:33 +01:00
<a class="button button--secondary button--pill button--sm" style="color:#00FFFF" href="/archive.html?tag=android">android</a>
2024-10-31 20:18:37 +01:00
</li></ul><ul class="right-col menu"><li>
<i class="far fa-calendar-alt"></i>&nbsp;<span title="Création" style="color:#FF00FF">25&nbsp;déc.&nbsp;&nbsp;2019</span>
<span title="Modification" style="color:#00FF7F">23&nbsp;nov.&nbsp;&nbsp;2018</span></li></ul></div><meta itemprop="datePublished" content="2018-11-23T00:00:00+01:00">
<meta itemprop="keywords" content="android"><div class="js-article-content">
<div class="layout--article"><!-- start custom article top snippet -->
<style>
#myBtn {
display: none;
position: fixed;
bottom: 10px;
right: 10px;
z-index: 99;
font-size: 12px;
font-weight: bold;
border: none;
outline: none;
background-color: white;
color: black;
cursor: pointer;
padding: 5px;
border-radius: 4px;
}
#myBtn:hover {
background-color: #555;
}
</style>
<button onclick="topFunction()" id="myBtn" title="Haut de page">&#8679;</button>
<script>
//Get the button
var mybutton = document.getElementById("myBtn");
// When the user scrolls down 20px from the top of the document, show the button
window.onscroll = function() {scrollFunction()};
function scrollFunction() {
if (document.body.scrollTop > 20 || document.documentElement.scrollTop > 20) {
mybutton.style.display = "block";
} else {
mybutton.style.display = "none";
}
}
// When the user clicks on the button, scroll to the top of the document
function topFunction() {
document.body.scrollTop = 0;
document.documentElement.scrollTop = 0;
}
</script>
<!-- end custom article top snippet -->
<div class="article__content" itemprop="articleBody"><details>
<summary><b>Afficher/cacher Sommaire</b></summary>
<!-- affichage sommaire -->
<div class="toc-aside js-toc-root"></div>
</details><p>URL: https://linuxfr.org/news/utiliser-son-android-de-facon-plus-securisee
Title: Utiliser son Android de façon plus sécurisée
Authors: voxdemonix
ZeroHeure, BAud, Davy Defaud, Yves Bourguignon, jcr83, Nils Ratusznik, palm123, xev et Pierre Jarillon
Date: 2018-06-03T19:16:13+02:00
License: CC by-sa
Tags: android, sécurité, cybersécurité et smartphone
Score: 21</p>
<p>Android, le système dexploitation largement majoritaire sur les mobiles, est, comme chacun le sait sur <em>LinuxFr.org</em>, construit sur un noyau Linux.</p>
<p>Linux étant sous licence GPL, tout peut vous sembler parfait, mais en réalité la couche applicative Android est beaucoup moins amicale que son noyau Linux.</p>
<p>Le but de cet article est de vous expliquer le fonctionnement dAndroid, de vous faire découvrir sa face cachée et de vous expliquer comment vivre avec dans les meilleures conditions possibles.</p>
<hr />
<p><a href="https://linuxfr.org/users/partagetonsavoir/journaux/utiliser-son-android-de-facon-plus-securise">Journal à lorigine de la dépêche</a></p>
<hr />
<p>Origine de larticle : <a href="https://www.0rion.netlib.re/forum4/viewtopic.php?f=79&amp;t=779">via Web</a> ou <a href="http://fr47f6ecynx4dgq6.onion/forum4/viewtopic.php?f=79&amp;t=779">via Tor</a>.
<img src="https://image.noelshack.com/fichiers/2018/22/7/1528024223-android.jpg" alt="Entête de larticle" /> 🍭 <em>Si tu fais des conneries avec ta vie privée et celle des autres, tu es une balance, peu importe tes excuses ou ton déni.</em> 🍭</p>
<h1 id="point-de-départ">Point de Départ</h1>
<p>Introduction
————
<a href="https://fr.wikipedia.org/wiki/Android">Android</a> est un système en partie libre, assez dur à dompter tout en étant celui offrant le plus de possibilités. Il est généralement livré avec des applications publicitaires, des <a href="https://fr.wikipedia.org/wiki/Logiciel_espion">espiongiciels (<em>spywares/tracker</em>)</a> à la pelle (surtout <a href="https://fr.wikipedia.org/wiki/Google_Analytics">Google Analytics</a>) et autres applications dérangeantes autant pour le confort personnel, la philosophie que laspect sécuritaire ou énergétique.
Par exemple, lors de linitialisation de votre appareil, Facebook (qui est préinstallé sur quasi tous les appareils Android) va récupérer votre liste de contacts et se lautoenvoyer, même si vous navez jamais utilisé FB de toute votre vie.</p>
<p>Les opérateurs et fabricants ont tendance à modifier le système — par exemple, HTC qui insère son propre lanceur (<em>launcher</em>) et ses propres <em>widgets</em> — lexistence de différences dun mobile Android à un autre est donc « normale ».</p>
<p>Petit rappel : votre machine vous sert souvent pour communiquer avec dautres humains. <em>Grosso modo</em>, elle sert dorgane comme votre bouche et vos oreilles. Si vous et vos interlocuteurs ne pouvez faire confiance à votre bouche et vos oreilles, comment communiquer avec vous?</p>
<p>Attention : méfiezvous des trop nombreux comparatifs dont le but nest point de vous aider à choisir le bon logiciel mais plutôt de rapporter de largent à son auteur.</p>
<h2 id="petit-résumé-du-fonctionnement-dandroid">Petit résumé du fonctionnement dAndroid</h2>
<p><a href="https://fr.wikipedia.org/wiki/Android">Android</a> est un moteur <a href="https://fr.wikipedia.org/wiki/Linux">Linux</a>, faisant tourner une <a href="https://fr.wikipedia.org/wiki/Machine_virtuelle">machine virtuelle</a> (émulateur) exécutant du <a href="https://fr.wikipedia.org/wiki/Java_%28langage%29">Java</a>.
Contrairement aux systèmes sur ordinateur où chaque application range ses données dans son coin et où cest parfois le bordel, sur Android, certaines informations sont centralisées dans une <a href="https://fr.m.wikipedia.org/wiki/Base_de_donn%C3%A9es">base de données</a> principale. Ainsi, chaque application y aura accès ou non selon votre gestion des permissions. De fait, les calendriers, les SMS/MMS, la position et les contacts peuvent être accessibles à toutes les applications sans passer par la case exportation. Le danger est justement cette facilité daccès pour les applications préinstallées par les <a href="https://fr.m.wikipedia.org/wiki/Op%C3%A9rateur_de_r%C3%A9seau_mobile">opérateurs</a>, auxquelles ces derniers auront sournoisement autorisé toutes les permissions.
Android ne permet pas encore une utilisation aussi poussée que sur ordinateur. On citera, entre autres, la difficulté abusive pour programmer ou scripter, limpossibilité dafficher plusieurs fenêtres en même temps, labsence du montage à distance, etc.</p>
<p>Un truc très important à savoir avec les appareils Android : le nombre dapplications installables ou à mettre à jour sur un appareil diminue avec le temps car les nouvelles versions ont besoin dun système plus récent.</p>
<p><strong>Explications détaillées pour les barbus :</strong> En effet, il ny a plus de mises à jours système après environ deux ans de vie du produit. La raison majeure étant que l<a href="https://fr.wikipedia.org/wiki/Architecture_ARM">architecture ARM</a> ellemême est très morcelée et la prise en charge varie fortement entre les différents concepteurs de briques de base (processeur, décodage vidéo, accélération 3D, WiFi, etc.), les assembleurs de <a href="https://fr.wikipedia.org/wiki/SoC">systèmes monopuces (SoC)</a> qui en plus apportent des spécificités, les assembleurs de téléphones qui en rajoutent une couche en termes de matériel et de logiciel, puis éventuellement lopérateur chez qui le téléphone a été acheté et qui ajoute sa surcouche logicielle.
Au final, nimporte quel maillon peut flancher et, en bout de chaîne, il est banal de se retrouver avec une image Android qui traîne de vieux pilotes, qui nest pas facile à maintenir et qui, avouonsle, arrange bien les fabricants de téléphones qui ont une nouvelle gamme à vendre et qui conçoivent leurs produits au plus juste de la garantie légale et avec des ambitions marketing (comme pouvoir afficher de grosses autonomies au détriment de la durabilité de la batterie).
Google (qui possède Android) essaye, via le <a href="https://www.lesnumeriques.com/telephone-portable/project-treble-reponse-google-a-fragmentation-android-n63061.html">projet Treble</a>, de limiter en partie ce problème.</p>
<h2 id="règles-de-base">Règles de base</h2>
<ul>
<li><strong>Méfiezvous de ce que vous installez ou de ce qui est préinstallé :</strong> ninstallez pas des applications inutiles, à la provenance douteuse (y compris sur le <em>Play Store</em>) ou demandant des permissions suspicieuses. Noubliez pas non plus que la plupart des <a href="https://fr.wikipedia.org/wiki/Cheval_de_Troie_(informatique)">chevaux de Troie</a> se cachent dans des applications dun premier abord normales. Votre vie privée ne peut être protégée si vous installez des applications qui pompent toutes vos données. Afin de les éviter au maximum, utilisez des <a href="https://fr.wikipedia.org/wiki/Logiciel_libre">applications libres</a> en lieu et place de celles installées par défaut (attention, certaines applications libres, provenant généralement des fabricants, embarquent <a href="https://fr.wikipedia.org/wiki/Google_Analytics">Google Analytics</a>).</li>
<li><strong>Verrouillage de lécran :</strong> toujours laisser le verrouillage automatique de lécran. La majorité des piratages sexplique par un proche qui pique le mobile ou va sur le PC non verrouillé quand on a le dos tourné.</li>
<li><strong>Un service ou une application conçue dans votre pays nest pas de meilleure qualité « parce que voilà ».</strong> Il faut que les gens derrière lapplication ou le service poursuivent des objectifs finals concordant avec vos attentes. La communauté aussi est très importante, elle ne doit pas être composée en majorité dimbéciles demandant des <a href="http://www.planet-libre.org/index.php?post_id=16592">antifonctionnalités</a> (voir, par exemple, les commentaires sous les applications foscam où des gens demandent lintroduction de ce quun averti appellerait une « <a href="https://fr.wikipedia.org/wiki/Backdoor">porte dérobée</a> »).
Évitez quand même les pays à mauvaise réputation (Chine, Russie, Moyen Orient, Turquie).</li>
<li><strong>Lantivirus ne vous protégera jamais de vos incompétences ou méconnaissances.</strong> Lantivirus ne peut vous protéger de vos propres erreurs. Si vous exécutez une application contenant un « pourriciel » (<em>malware</em>), que votre antivirus vous demande si cest normal et que vous répondez <em>Oui</em>, alors lantivirus ne va pas bloquer le vilain. Aucun antivirus ne vous protégera jamais de vos propres actions.</li>
<li><strong>Cest normal de ne pas tout savoir.</strong> Personne nest omniscient, vous ne savez pas tout sur tout et allez commettre des erreurs. Il faut laccepter et réfléchir à comment diminuer limpact de vos erreurs éventuelles.</li>
<li><strong>Ne laissez pas vos émetteursrécepteurs allumés inutilement.</strong> Noubliez surtout pas de couper le WiFi, le Bluetooth et le NFC lorsque vous nen avez pas besoin. Il faut savoir quil est très, très, très facile de vous suivre grâce aux identifiants (voir <a href="https://fr.wikipedia.org/wiki/Adresse_mac">adresse MAC</a>) et ce, sans que vous soyez connecté. En effet, votre machine va polluer régulièrement lair de requêtes permettant de savoir si un des réseaux (pour le WiFi) ou une des machines (pour le Bluetooth) avec « connexion automatique » (par défaut) est à portée de connexion.</li>
<li><strong>Ne vous connectez à des services quen HTTPS, jamais en HTTP. (sauf les <code class="language-plaintext highlighter-rouge">.onion</code>)</strong> Il vous arrive probablement de vous connecter à des réseaux WiFi non sécurisés, à des réseau privés virtuels (VPN) ou à Tor. Il ne faut <strong>jamais</strong> faire confiance aux machines intermédiaires entre vous et le destinataire. Pour éviter de vous faire piller vos mots de passe, utilisez toujours HTTPS.</li>
</ul>
<h1 id="premiers-pas">Premiers pas</h1>
<p><strong>Note :</strong> prenez votre temps, en cas derreur le risque cest de foutre en lair votre machine et les réparations ne sont pas gratuites. À vos risques et périls, <em>hacker</em> vaillant rien dimpossible!</p>
<h2 id="avant-lachat">Avant lachat</h2>
<p>Avant dacheter un nouvel appareil il faut vérifier sur Internet que ce nest pas juste une bouse de marketeux. Pour ce faire, renseignezvous afin de connaître les retours dexpérience dautres personnes (attention aux faux com), de savoir sil est facilement « rootable », si les mises à jour système ne se bloquent pas au bout de six mois, etc. Ne succombez surtout pas aux publicités sans vérifier derrière et ne soyez pas le premier de tout lInternet à tenter de « rooter » un nouvel appareil. ;)</p>
<h2 id="root-accès-superutilisateur">Root (accès superutilisateur)</h2>
<p><strong>Attention :</strong> risque de bloquer votre machine (<em>break</em>, <em>freeze</em>, <a href="https://fr.wikipedia.org/wiki/Bootloop"><em>bootloop</em></a>)</p>
<p><strong>Explications :</strong> Laccès <em><a href="https://fr.wikipedia.org/wiki/Utilisateur_root">root</a></em> vous permet dautoriser des applications à accomplir des actions en <a href="https://fr.wikipedia.org/wiki/Utilisateur_root">superutilisateur</a>. Pour avoir accès en superutilisateur, sur la plupart des machines Android, il vous faudra utiliser un <em>hack</em>. Cette bidouille est parfois prévue par les fabricants (par exemple, <a href="https://fr.wikipedia.org/wiki/HTC">HTC</a> et <a href="https://fr.wikipedia.org/wiki/Sony">Sony</a> qui vous fournissent un tuto si vous leur offrez vos informations personnelles [<em>tracking</em>]). La raison pour laquelle laccès <em>root</em> est aussi difficile à avoir est simple : vous interdire de supprimer les applications publicitaires, ainsi que les logiciels espions des fabricants, opérateurs, fournisseurs ou encore étatiques, et vous empêcher davoir le contrôle complet de votre machine.
Attention, déverrouiller le chargeur damorçage (pour pouvoir « rooter ») peut provoquer la fin de la garantie pour certains appareils.</p>
<p><strong>Chaque appareil aura donc une méthode spécifique pour avoir accès en superutilisateur, mais en général, vous devrez :</strong></p>
<ol>
<li>désactiver le chiffrement de la partition :
<ul>
<li>lancez votre appareil sans carte SIM,</li>
<li>si cest votre premier lancement, dites non à un maximum des questions quil va vous poser et faites la mise à jour système,</li>
<li>une fois lappareil lancé, allez dans <em>Paramètres</em><em>Verrouillage décran et sécurité</em><em>Chiffrer lappareil</em><em>Désactiver le chiffrement des données</em> (vous pourrez, au choix, le réactiver plus tard ou non, si votre ROM est compatible);</li>
</ul>
</li>
<li>déverrouiller le chargeur damorçage (<em><a href="https://www.androidpit.fr/c-est-quoi-bootloader-android">bootloader</a></em>);</li>
<li>« rooter » votre appareil en suivant la procédure spécifique à lappareil (cherchez sur un moteur de recherche « root <em>nom_COMPLET_de_votre_appareil</em> »).</li>
</ol>
<h2 id="premier-lancement-dandroid">Premier lancement dAndroid</h2>
<ol>
<li>/!\ ne placez surtout pas votre carte SIM;</li>
<li>répondez aux questions afin de lancer lappareil; veillez à décliner respectueusement toutes les offres de vous faire espionner et choisissez ignorer lorsque lappareil vous demandera le code du WiFi;</li>
<li>une fois lappareil lancé, rendezvous dans vos <em>Paramètres</em> puis <em>Applications</em> et <em>Forcez larrêt</em> puis <em>Désactivez</em> les applications chelou (Facebook et compagnie) en veillant à ne pas toucher aux applications risquant de rendre instable votre appareil — pour les applications de votre opérateur ou du fabricant il faudra se renseigner sur le Net, voire y aller à tâtons avec le risque de casser votre appareil, donc faites très attention; si après avoir désactivé une application vous commencez à avoir plein derreurs provenant du système Android, réactivez cette application <strong>avant</strong> tout redémarrage du système (sinon, risque de <em><a href="https://fr.wikipedia.org/wiki/Bootloop">bootloop</a></em>);</li>
<li>désactivez les publicités ciblées, voire tout ce qui utilise un compte Google, Microsoft, Apple, etc.;</li>
<li>désactivez la gestion du NFC (à moins que vous ne lutilisiez);</li>
<li>autorisez linstallation dapplication en dehors du Google Play Store;</li>
<li>installez <a href="https://f-droid.org/">F-Droid</a>, la bibliothèque dapplications libres puis <a href="https://f-droid.org/packages/com.github.yeriomin.yalpstore/">YalpStore</a> pour pouvoir installer les applications provenant du Google Play Store sans passer par ce dernier.</li>
</ol>
<h1 id="communiquer-avec-dautres-humains">Communiquer avec dautres humains</h1>
<p>Via Internet
————</p>
<h3 id="xmpp--tor">XMPP + Tor</h3>
<p><img src="https://image.noelshack.com/fichiers/2018/22/7/1528025433-tor-xmpp-movim.gif" alt="Animation expliquant Tor + XMPP" /></p>
<p>Applications : <a href="https://f-droid.org/en/packages/eu.siacs.conversations/">Conversation</a> et/ou <a href="https://f-droid.org/en/packages/com.movim.movim/">Movim</a> + <a href="https://guardianproject.info/apps/orbot/">Orbot</a>
<a href="https://fr.wikipedia.org/wiki/XMPP">XMPP</a> est le protocole qui se cache derrière <a href="https://movim.eu/">Movim</a> et <a href="https://conversations.im/">Conversation</a>, deux puissants clients de communication qui vous permettront doublier Facebook une bonne fois pour toutes.
Movim est une alternative complète à Facebook, alors que Conversation est une alternative à Messenger (lapplication de clavardage de Facebook).
Afin dempêcher le pistage via ladresse IP, que vous hébergiez votre propre serveur <a href="https://fr.wikipedia.org/wiki/XMPP">XMPP</a> ou que vous soyez inscrit sur un serveur de la confédération, il est conseillé dutiliser <a href="https://guardianproject.info/apps/orbot/">Orbot</a>. Ce dernier va, pour vos données circulant entre vous et le serveur <a href="https://fr.wikipedia.org/wiki/XMPP">XMPP</a>, les faire transiter par le réseau <a href="https://fr.wikipedia.org/wiki/Tor_%28r%C3%A9seau%29">Tor</a> et ainsi dissimuler votre adresse IP. Cest assez important si vous vous déplacez avec votre appareil afin dempêcher la géolocalisation, plus particulièrement si vous utilisez les points daccès WiFi gratuits (<em><a href="https://fr.wikipedia.org/wiki/Borne_Wi-Fi">hotspots</a></em>) et réseaux <a href="https://fr.wikipedia.org/wiki/FON">FON</a> (dont vos changements dadresse IP au fur et à mesure de vos connexions aux différents points daccès <a href="https://fr.wikipedia.org/wiki/FON">FON</a> vont permettre de récupérer vos déplacements plus facilement quen 4G) :</p>
<ol>
<li>ouvrez Fdroid, activez le dépôt <em>Gardian Project</em> et cherchez puis installez Orbot et, au choix, Conversation ou Movim (ou les deux);</li>
<li>lancez Orbot, activez le <em>mode RPV</em> puis allez dans <em>Applis pouvant utiliser Tor</em> et cochez Movim et Conversation;</li>
<li>lancez ensuite Movim ou Conversation au choix et soit rentrez les informations pour vous connecter, soit créez un nouveau compte, mais attention : si la création de compte est gratuite dans la fédération Movim, celle chez Conversation est payante (8€/an);</li>
<li>si vous utilisez Conversation, rendezvous dans les <em>Options</em> puis <em>Options avancées</em> et cochez <em>utiliser Tor</em>;</li>
<li><em>enjoy!</em></li>
</ol>
<p><strong>Conversation</strong>
<img src="https://image.noelshack.com/fichiers/2018/22/7/1528025497-screenshot-conversation.jpg" alt="Capture décran de lapplication Android Conversation" /></p>
<p><strong>Movim</strong>
<img src="https://image.noelshack.com/fichiers/2018/22/7/1528025564-android-movim-demo.gif" alt="Capture décran de lapplication Android Movim" /></p>
<h2 id="via-sms">Via SMS</h2>
<p><strong>Note :</strong> tout message envoyé non chiffré peut être lu par lopérateur et le <a href="https://fr.wikipedia.org/wiki/Processeur_de_bande_de_base">modem de lappareil</a>.</p>
<h3 id="silence-le-plus-sécurisé">Silence (le plus sécurisé)</h3>
<p><img src="https://image.noelshack.com/fichiers/2018/22/7/1528025607-silence.png" alt="Logo de Silence" />
<a href="https://fr.wikipedia.org/wiki/Silence_%28application%29">Silence</a> est une <a href="https://fr.wikipedia.org/wiki/Logiciel_libre">application libre</a> (licence <a href="https://github.com/SilenceIM/Silence/blob/master/LICENSE">GPLv3</a>) permettant denvoyer et de recevoir des <a href="https://fr.wikipedia.org/wiki/Sms">SMS</a>. Sa particularité est de <a href="https://fr.wikipedia.org/wiki/Chiffrement">chiffrer</a> les SMS, ils sont donc illisibles autant pour les autres applications que pour un éventuel voleur de mobile. En revanche, elle ne résiste pas longtemps aux <a href="https://fr.wikipedia.org/wiki/Attaque_par_force_brute">attaques par force brute</a> via serveur.
La sécurité quelle amène peut en revanche provoquer des problèmes dintégration avec dautres applications : lapplication <em>Contact</em> ne pourra plus afficher les derniers SMS envoyés et reçus dans les informations dudit contact, <a href="https://f-droid.org/en/packages/fr.unix_experience.owncloud_sms/">Nextcloud-SMS</a> ne pourra plus récupérer les SMS, les applications de sauvegarde non plus.
<a href="https://fr.wikipedia.org/wiki/Silence_%28application%29">Silence</a> peut envoyer des SMS chiffrés si lexpéditeur et le destinataire ont tous deux lapplication installée. Mais le <a href="https://fr.wikipedia.org/wiki/Chiffrement">chiffrement</a> a un coût : la taille maximum dun SMS passe de 140 caractères à une septantaine seulement.
Petit défaut : les émoticônes ne sont pas toujours automatiquement transformées en images.
<img src="https://image.noelshack.com/fichiers/2018/22/7/1528025658-silence-screenshot.png" alt="Capture décran de lapplication Android Silence" /></p>
<h3 id="qksms-le-plus-intégré">QKSMS (le plus intégré)</h3>
<p><img src="https://image.noelshack.com/fichiers/2018/22/7/1528025704-qksms-logo.png" alt="Logo QKSMS" /></p>
<p><a href="https://github.com/moezbhatti/qksms">QKSMS</a> est une <a href="https://fr.wikipedia.org/wiki/Logiciel_libre">application libre</a> (licence <a href="https://github.com/SilenceIM/Silence/blob/master/LICENSE">GPLv3</a>) permettant denvoyer et de recevoir des <a href="https://fr.wikipedia.org/wiki/Sms">SMS</a>. Elle est très bien intégrée au système Android et peut fonctionner avec <a href="https://f-droid.org/en/packages/fr.unix_experience.owncloud_sms/">Nextcloud-SMS</a>, etc. Les mises à jour sont régulières, les émoticônes automatiquement transformées en image (si vous avez coché loption dans les paramètres), les SMS ne sont pas <a href="https://fr.wikipedia.org/wiki/Chiffrement">chiffrés</a>.
Selon vos préférences, vous pouvez linstaller via <a href="https://f-droid.org/en/packages/com.moez.QKSMS/">F-Droid</a> ou via <a href="https://play.google.com/store/apps/details?id=com.moez.QKSMS">Google Play Store</a>.</p>
<p><img src="https://image.noelshack.com/fichiers/2018/22/7/1528025746-android-qksms-demo.gif" alt="Démo Android QKSMS" /></p>
<h1 id="gestion-de-la-mémoire">Gestion de la mémoire</h1>
<p>Le Cloud et la synchronisation des données
——————————————
Vos données font partie de votre mémoire et il faut en prendre soin. Ainsi, il est important de sauvegarder ses données afin de se prémunir des pannes <strong>matérielles</strong>. Avant, on utilisait des <a href="https://fr.wikipedia.org/wiki/Sauvegarde">sauvegardes</a> sur des disques durs externes qui prenaient la poussière. Et lorsque le disque dur externe tombait en panne, on perdait nos données. Aujourdhui, il y a le <em>Cloud</em> qui permet de soustraiter la mémoire chez un fournisseur de stockage en ligne. Bien entendu, rien ne vous empêche dêtre vousmême votre propre fournisseur <em>Cloud</em>.
Mais attention, le <em>Cloud</em> permet de se prémunir des pannes matérielles mais pas dun piratage ou dune extorsion de mot de passe.
Pour ce faire, privilégiez donc les services de fournisseurs envers qui vous avez relativement confiance. Ces fournisseurs doivent autant que faire se peut utiliser des <a href="https://fr.wikipedia.org/wiki/Logiciel_libre">technologies libres</a> qui ont pour énorme gain, entre autres, de pousser à toujours plus de sécurité.
Nhésitez pas à couper la synchronisation durant la nuit, sauf si vous avez des données à synchroniser. En effet, les logiciels de synchro consomment autant dénergie et de données de nuit que de jour.
<strong>Avec un serveur <a href="https://nextcloud.com/">Nextcloud</a> (<a href="https://www.0rion.netlib.re/forum4/viewtopic.php?f=107&amp;t=401">tuto dinstall</a>) et votre Android, vous pouvez :</strong></p>
<ul>
<li>synchroniser vos fichiers en toute sécurité;</li>
<li><a href="https://www.0rion.netlib.re/forum4/viewtopic.php?f=93&amp;t=748">exporter la géolocalisation avec GpsLogger</a>;</li>
<li><a href="https://linuxfr.org/wiki/tuto-howto-android-synchroniser-ses-notes-sur-nextcloud-ou-owncloud">synchroniser vos notes</a>;</li>
<li><a href="https://linuxfr.org/wiki/tuto-howto-android-synchroniser-calendrier-via-owncloud-nextcloud">synchroniser vos calendriers</a>;</li>
<li>exporter automatiquement vos photos et vidéos;</li>
<li>sauvegarder vos SMS.</li>
</ul>
<h2 id="le-chiffrement">Le chiffrement</h2>
<p>Vous pouvez chiffrer le contenu de la mémoire du mobile et ce sans installer dapplication supplémentaire, cest complètement géré par Android. Le <a href="https://fr.wikipedia.org/wiki/Chiffrement">chiffrement</a> permet de rendre illisible le contenu de la mémoire pour un voleur, tant que ce dernier ne dispose pas dune puissance de calcul suffisante pour lancer une <a href="https://fr.wikipedia.org/wiki/Attaque_par_force_brute">attaque par force brute</a>.
Sachez que le chiffrement a un impact sur les performances de la machine, qui peut varier en fonction du processeur et de la qualité de la mémoire.
Attention : le chiffrement de la mémoire nest pas toujours compatible ou stable avec les gestionnaires damorçage (<em>bootloaders</em>) déverrouillés, bien que les retours aient lair positif. En revanche, toutes les <a href="https://www.xda-developers.com/what-is-custom-rom-android/">ROM</a> ne gèrent pas forcément le chiffrement.</p>
<h1 id="gestion-des-applications">Gestion des applications</h1>
<p>Gestion des permissions
———————–
###Comment gérer les permissions des applications</p>
<ul>
<li><em>Paramètres</em><em>Applications</em><em>Paramètres</em><em>Autorisation des applications</em>;</li>
<li>autorisez le moins de permissions possible aux applications ;)
<img src="https://image.noelshack.com/fichiers/2018/22/7/1528025786-screenshot-2018-05-30-android-acceder-menu-permissions-applications.gif" alt="screenshot-2018_05_30-Android-Acceder_menu_permissions_applications" /></li>
</ul>
<p>###Lutilisation de données forgées (<em>fake data</em>) pour les applications demandant trop de permissions
<a href="https://forum.xda-developers.com/xposed/modules/xprivacylua6-0-android-privacy-manager-t3730663">XPrivacyLua</a> (pour Android6 ou plus) ou <a href="https://forum.xda-developers.com/xposed/modules/xprivacy-ultimate-android-privacy-app-t2320783">XPrivacy</a> (pour Android5 ou moins) permet de leurrer les applications. Si vous êtes obligé dinstaller une application demandant trop de permissions, cest fait pour vous. <strong>Laccès superutilisateur (<em>root</em>) est obligatoire.</strong>
<img src="https://image.noelshack.com/fichiers/2018/22/7/1528025833-xprivacy.png" alt="screenshot XPrivacy" /></p>
<p>###Supprimer ou restreindre les permissions dune application
<a href="https://fr.wikipedia.org/wiki/Lucky_Patcher">Lucky Patcher</a> peut être utilisé pour supprimer des permissions à une application. Cest au niveau de lapplication que la modification sera appliquée et donc peu importe les autorisations accordées par le système. Cela peut, bien entendu, provoquer des instabilités voire des dysfonctionnements des applications modifiées et des applications qui dépendent delles.</p>
<h2 id="gérer-le-démarrage-des-applications">Gérer le démarrage des applications.</h2>
<p>Lors de leur installation ou de leur paramétrage, les applications peuvent « demander » à Android de les lancer lorsquil y a certains évènements : démarrage (<em>boot</em>) de la machine, connexion à Internet en WiFi ou par le réseau opérateur, extinction de la machine, etc. Vous pouvez utiliser lapplication libre <a href="https://f-droid.org/wiki/index.php?title=com.elsdoerfer.android.autostart">Autostarts</a> (ou via <a href="https://play.google.com/store/apps/details?id=com.elsdoerfer.android.autostarts">PlayStore/Yalp</a>) pour gérer quelle application peut démarrer en fonction de quel type dévènement. Si vous avez installé <a href="https://f-droid.org/en/packages/de.robv.android.xposed.installer/">XPosed Framework</a>, à la place dautostart vous pouvez installer et utiliser son <a href="http://repo.xposed.info/module/de.defim.apk.bootmanager">module BootManager</a> selon vos préférences (<strong>laccès superutilisateur <em>root</em> est obligatoire</strong>).
<img src="https://image.noelshack.com/fichiers/2018/22/7/1528025872-android-autostarts-demo.gif" alt="Android-Autostarts-Demo" /></p>
<h2 id="forcer-la-suppression-dapplications">Forcer la suppression dapplications</h2>
<p>Certaines applications comme Facebook, AVG et compagnie sont installées par les opérateurs (contre rétribution) avec blocage pour empêcher lutilisateur final de les désinstaller. Pour contrer cela, vous pouvez utiliser <a href="https://fr.wikipedia.org/wiki/Lucky_Patcher">Lucky Patcher</a>, il permet de forcer la désinstallation dapplications, la suppression de publicité et autres bidouilles (<strong>laccès superutilisateur <em>root</em> est obligatoire</strong>).
Pour supprimer une application vous navez quà lancer Lucky Patcher, chercher ladite application, cliquer dessus puis choisir <em>Désinstaller lapplication</em>.
<strong>Attention :</strong> avant de supprimer une application vérifiez que votre système ou dautres applications nen dépendent pas. Pour ce faire, désactivezla, vérifiez si aucune erreur ne se produit avec les autres applications ou pire le système Android. Ensuite, redémarrez votre machine et si toujours aucune erreur ne se produit, alors vous pouvez la supprimer. Pensez à faire une sauvegarde de lapplication afin de pouvoir la restaurer en cas de problème. <strong>Ne supprimez pas les applications des fabricants et opérateurs ni les applications système, car vous risquez un <em><a href="https://fr.wikipedia.org/wiki/Bootloop">bootloop</a></em>!</strong></p>
<p><img src="https://image.noelshack.com/fichiers/2018/22/7/1528026352-screenshot-2018-06-01-luckypatcher-remove-application.gif" alt="Démo de suppression dapplication Android avec Lucky Patcher" /></p>
<p><img src="https://image.noelshack.com/fichiers/2018/22/7/1528026394-android-luckypatcher-demo.gif" alt="Démo de lapplication Android Lucky Patcher" /></p>
<h1 id="les-applications-de-rencontre">Les applications de rencontre</h1>
<p><img src="https://image.noelshack.com/fichiers/2018/22/7/1528026440-alice-wanted-dark-disney-disney-cruiseplan.gif" alt="Alice au pays des merveilles" /></p>
<p>Si vous avez moins de trente ans, cest <strong>la</strong> catégorie qui pompe vos données personnelles et qui pourtant reste incontournable. En revanche, dans cette catégorie, nespérez pas, il ny a pas encore dapplication de rencontre libre ni sans espionnage. Donc, voyons comment sauver vos miches sans vous empêcher de tchatcher.</p>
<h2 id="les-applications-de-rencontre-généralistes-badoo-facebook-meetic-tinder">Les applications de rencontre généralistes (Badoo, Facebook, Meetic, Tinder…)</h2>
<p><strong>Note :</strong> elles dépendent beaucoup de <a href="https://en.wikipedia.org/wiki/Google_Play_Services">Google Play Service</a>. Elles napprécient pas trop <a href="https://guardianproject.info/apps/orbot/">Orbot</a>.</p>
<p>Elles nont pas besoin de la Géolocalisation (sauf si vous utilisez une fonctionnalité basée dessus).
Sur les versions dAndroid permettant la gestion des permissions, vous pouvez leur verrouiller laccès à quasi tout sans quelles cessent de fonctionner. Pour les Android plus vieux, il faudra passer par <a href="https://forum.xda-developers.com/xposed/modules/xprivacy-ultimate-android-privacy-app-t2320783">XPrivacy</a>, comme expliqué plus haut. Sil faut vraiment autoriser des permissions contraignantes (par exemple, laccès à lidentifiant de lappareil), passez par <a href="https://forum.xda-developers.com/xposed/modules/xprivacylua6-0-android-privacy-manager-t3730663">XPrivacyLUA</a>.
Pensez autant que faire se peut à supprimer les métadonnées de vos photos via, par exemple, Scrambled Exif (<a href="https://f-droid.org/en/packages/com.jarsilio.android.scrambledeggsif/">sur F-Droid</a> ou sur <a href="https://play.google.com/store/apps/details?id=com.jarsilio.android.scrambledeggsif">Google PlayStore</a>). Noubliez pas que les autres utilisateurs peuvent facilement recopier vos photos et les utiliser pour faire de faux comptes. ;)</p>
<h2 id="les-applications-basées-sur-la-géolocalisation-happn-meetwo-theleague">Les applications basées sur la Géolocalisation (Happn, Meetwo, The League…)</h2>
<p><strong>Note :</strong> elles dépendent beaucoup de <a href="https://en.wikipedia.org/wiki/Google_Play_Services">Google Play Service</a>. Elles napprécient pas trop <a href="https://guardianproject.info/apps/orbot/">Orbot</a>.</p>
<p>Après utilisation, bien penser à <em>Forcer larrêt</em> de lapplication dans le menu <em>Application</em> dAndroid ou <em>a minima</em> de couper la géolocalisation. Pour répondre aux <em>Matches</em>, il faut que lapplication soit lancée et connectée à Internet, mais pas besoin de la géolocalisation pour cela.</p>
<h1 id="lutter-contre-les-vols">Lutter contre les vols</h1>
<p>Géolocalisation
—————
<strong>Note :</strong> peut avoir une incidence sur la batterie et la charge réseau selon la configuration.</p>
<p>Vous pouvez régler un logiciel comme <a href="https://gpslogger.app/">GPSLogger</a> pour exporter la <a href="https://fr.wikipedia.org/wiki/Geolocalisation">géolocalisation</a> de votre appareil en permanence ou uniquement lors du redémarrage de votre appareil.
Si vous disposez dun compte sur un serveur <a href="https://fr.wikipedia.org/wiki/Nextcloud">Nextcloud</a> ou <a href="https://fr.wikipedia.org/wiki/Owncloud">Owncloud</a>, vous pouvez suivre ce tutoriel: <a href="https://www.0rion.netlib.re/forum4/viewtopic.php?f=93&amp;t=748"><em>Exporter géolocalisation sur le cloud (Nextcloud/Owncloud) avec GpsLogger</em></a>.</p>
<h2 id="utiliser-des-mots-de-passe-dapplication-token-ou-encore-apikey">Utiliser des « mots de passe dapplication » (Token ou encore API Key)</h2>
<p>Certains services, comme Nextcloud, permettent de créer des mots de passe uniques permettant dêtre utilisés par une seule (ou plusieurs) applications. Ainsi, en cas de vol, on pourrait éventuellement récupérer votre mot de passe dapplication, mais pas le vrai mot de passe de votre compte (ni des éventuels autres services sur lesquels vous pourriez avoir réutilisé ce mot de passe). Utilisez autant que faire se peut ce mécanisme et, en cas de vol/piratage, allez révoquer directement les accès compromis et ce le plus vite possible.
<img src="https://image.noelshack.com/fichiers/2018/23/3/1528241705-exemple-nextcloud-connexion-via-jeton.gif" alt="Exemple Nextcloud de connexion via un jeton" /></p>
<h2 id="laccès-à-distance">Laccès à distance</h2>
<p><strong>Note :</strong> a une incidence sur la batterie et la charge réseau.</p>
<p>Certaines applications vous permettent de contrôler votre appareil Android à distance (depuis un ordinateur). La plus connue est <a href="https://www.airdroid.com/fr/index.html">AirDroid</a>, hélas non libre et pas des plus saines (lapplication permettant un contrôle depuis le site de lentreprise). Il nexiste actuellement aucune alternative libre.</p>
</div>
<div class="d-print-none"><footer class="article__footer"><meta itemprop="dateModified" content="2019-12-25T00:00:00+01:00"><!-- start custom article footer snippet -->
<!-- end custom article footer snippet -->
<!--
<div align="right"><a type="application/rss+xml" href="/feed.xml" title="S'abonner"><i class="fa fa-rss fa-2x"></i></a>
&emsp;</div>
-->
</footer>
<div class="article__section-navigator clearfix"><div class="previous"><span>PRÉCÉDENT</span><a href="/2019/12/25/un-vrai-coffre-fort-numerique_2017-06-12T21_56_39.html">un-vrai-coffre-fort-numerique_2017-06-12T21_56_39</a></div><div class="next"><span>SUIVANT</span><a href="/2019/12/25/virtualbox-AdditionsInvit%C3%A9Debian.html">virtualbox-AdditionsInvitéDebian</a></div></div></div>
</div>
<script>(function() {
var SOURCES = window.TEXT_VARIABLES.sources;
window.Lazyload.js(SOURCES.jquery, function() {
$(function() {
var $this ,$scroll;
var $articleContent = $('.js-article-content');
var hasSidebar = $('.js-page-root').hasClass('layout--page--sidebar');
var scroll = hasSidebar ? '.js-page-main' : 'html, body';
$scroll = $(scroll);
$articleContent.find('.highlight').each(function() {
$this = $(this);
$this.attr('data-lang', $this.find('code').attr('data-lang'));
});
$articleContent.find('h1[id], h2[id], h3[id], h4[id], h5[id], h6[id]').each(function() {
$this = $(this);
$this.append($('<a class="anchor d-print-none" aria-hidden="true"></a>').html('<i class="fas fa-anchor"></i>'));
});
$articleContent.on('click', '.anchor', function() {
$scroll.scrollToAnchor('#' + $(this).parent().attr('id'), 400);
});
});
});
})();
</script>
</div><section class="page__comments d-print-none"></section></article><!-- start custom main bottom snippet -->
<!-- end custom main bottom snippet -->
</div>
</div></div></div></div>
</div><script>(function() {
var SOURCES = window.TEXT_VARIABLES.sources;
window.Lazyload.js(SOURCES.jquery, function() {
var $body = $('body'), $window = $(window);
var $pageRoot = $('.js-page-root'), $pageMain = $('.js-page-main');
var activeCount = 0;
function modal(options) {
var $root = this, visible, onChange, hideWhenWindowScroll = false;
var scrollTop;
function setOptions(options) {
var _options = options || {};
visible = _options.initialVisible === undefined ? false : show;
onChange = _options.onChange;
hideWhenWindowScroll = _options.hideWhenWindowScroll;
}
function init() {
setState(visible);
}
function setState(isShow) {
if (isShow === visible) {
return;
}
visible = isShow;
if (visible) {
activeCount++;
scrollTop = $(window).scrollTop() || $pageMain.scrollTop();
$root.addClass('modal--show');
$pageMain.scrollTop(scrollTop);
activeCount === 1 && ($pageRoot.addClass('show-modal'), $body.addClass('of-hidden'));
hideWhenWindowScroll && window.hasEvent('touchstart') && $window.on('scroll', hide);
$window.on('keyup', handleKeyup);
} else {
activeCount > 0 && activeCount--;
$root.removeClass('modal--show');
$window.scrollTop(scrollTop);
activeCount === 0 && ($pageRoot.removeClass('show-modal'), $body.removeClass('of-hidden'));
hideWhenWindowScroll && window.hasEvent('touchstart') && $window.off('scroll', hide);
$window.off('keyup', handleKeyup);
}
onChange && onChange(visible);
}
function show() {
setState(true);
}
function hide() {
setState(false);
}
function handleKeyup(e) {
// Char Code: 27 ESC
if (e.which === 27) {
hide();
}
}
setOptions(options);
init();
return {
show: show,
hide: hide,
$el: $root
};
}
$.fn.modal = modal;
});
})();
</script><div class="modal modal--overflow page__search-modal d-print-none js-page-search-modal"><script>
(function () {
var SOURCES = window.TEXT_VARIABLES.sources;
window.Lazyload.js(SOURCES.jquery, function() {
// search panel
var search = (window.search || (window.search = {}));
var useDefaultSearchBox = window.useDefaultSearchBox === undefined ?
true : window.useDefaultSearchBox ;
var $searchModal = $('.js-page-search-modal');
var $searchToggle = $('.js-search-toggle');
var searchModal = $searchModal.modal({ onChange: handleModalChange, hideWhenWindowScroll: true });
var modalVisible = false;
search.searchModal = searchModal;
var $searchBox = null;
var $searchInput = null;
var $searchClear = null;
function getModalVisible() {
return modalVisible;
}
search.getModalVisible = getModalVisible;
function handleModalChange(visible) {
modalVisible = visible;
if (visible) {
search.onShow && search.onShow();
useDefaultSearchBox && $searchInput[0] && $searchInput[0].focus();
} else {
search.onShow && search.onHide();
useDefaultSearchBox && $searchInput[0] && $searchInput[0].blur();
setTimeout(function() {
useDefaultSearchBox && ($searchInput.val(''), $searchBox.removeClass('not-empty'));
search.clear && search.clear();
window.pageAsideAffix && window.pageAsideAffix.refresh();
}, 400);
}
}
$searchToggle.on('click', function() {
modalVisible ? searchModal.hide() : searchModal.show();
});
// Char Code: 83 S, 191 /
$(window).on('keyup', function(e) {
if (!modalVisible && !window.isFormElement(e.target || e.srcElement) && (e.which === 83 || e.which === 191)) {
modalVisible || searchModal.show();
}
});
if (useDefaultSearchBox) {
$searchBox = $('.js-search-box');
$searchInput = $searchBox.children('input');
$searchClear = $searchBox.children('.js-icon-clear');
search.getSearchInput = function() {
return $searchInput.get(0);
};
search.getVal = function() {
return $searchInput.val();
};
search.setVal = function(val) {
$searchInput.val(val);
};
$searchInput.on('focus', function() {
$(this).addClass('focus');
});
$searchInput.on('blur', function() {
$(this).removeClass('focus');
});
$searchInput.on('input', window.throttle(function() {
var val = $(this).val();
if (val === '' || typeof val !== 'string') {
search.clear && search.clear();
} else {
$searchBox.addClass('not-empty');
search.onInputNotEmpty && search.onInputNotEmpty(val);
}
}, 400));
$searchClear.on('click', function() {
$searchInput.val(''); $searchBox.removeClass('not-empty');
search.clear && search.clear();
});
}
});
})();
</script><div class="search search--dark">
<div class="main">
<div class="search__header">Recherche</div>
<div class="search-bar">
<div class="search-box js-search-box">
<div class="search-box__icon-search"><i class="fas fa-search"></i></div>
<input id="search-input" type="text" />
<div class="search-box__icon-clear js-icon-clear">
<a><i class="fas fa-times"></i></a>
</div>
</div>
<button class="button button--theme-dark button--pill search__cancel js-search-toggle">
Annuler</button>
</div>
<div id="results-container" class="search-result js-search-result"></div>
</div>
</div>
<!-- Script pointing to search-script.js -->
<script>/*!
* Simple-Jekyll-Search
* Copyright 2015-2020, Christian Fei
* Licensed under the MIT License.
*/
(function(){
'use strict'
var _$Templater_7 = {
compile: compile,
setOptions: setOptions
}
const options = {}
options.pattern = /\{(.*?)\}/g
options.template = ''
options.middleware = function () {}
function setOptions (_options) {
options.pattern = _options.pattern || options.pattern
options.template = _options.template || options.template
if (typeof _options.middleware === 'function') {
options.middleware = _options.middleware
}
}
function compile (data) {
return options.template.replace(options.pattern, function (match, prop) {
const value = options.middleware(prop, data[prop], options.template)
if (typeof value !== 'undefined') {
return value
}
return data[prop] || match
})
}
'use strict';
function fuzzysearch (needle, haystack) {
var tlen = haystack.length;
var qlen = needle.length;
if (qlen > tlen) {
return false;
}
if (qlen === tlen) {
return needle === haystack;
}
outer: for (var i = 0, j = 0; i < qlen; i++) {
var nch = needle.charCodeAt(i);
while (j < tlen) {
if (haystack.charCodeAt(j++) === nch) {
continue outer;
}
}
return false;
}
return true;
}
var _$fuzzysearch_1 = fuzzysearch;
'use strict'
/* removed: const _$fuzzysearch_1 = require('fuzzysearch') */;
var _$FuzzySearchStrategy_5 = new FuzzySearchStrategy()
function FuzzySearchStrategy () {
this.matches = function (string, crit) {
return _$fuzzysearch_1(crit.toLowerCase(), string.toLowerCase())
}
}
'use strict'
var _$LiteralSearchStrategy_6 = new LiteralSearchStrategy()
function LiteralSearchStrategy () {
this.matches = function (str, crit) {
if (!str) return false
str = str.trim().toLowerCase()
crit = crit.trim().toLowerCase()
return crit.split(' ').filter(function (word) {
return str.indexOf(word) >= 0
}).length === crit.split(' ').length
}
}
'use strict'
var _$Repository_4 = {
put: put,
clear: clear,
search: search,
setOptions: __setOptions_4
}
/* removed: const _$FuzzySearchStrategy_5 = require('./SearchStrategies/FuzzySearchStrategy') */;
/* removed: const _$LiteralSearchStrategy_6 = require('./SearchStrategies/LiteralSearchStrategy') */;
function NoSort () {
return 0
}
const data = []
let opt = {}
opt.fuzzy = false
opt.limit = 10
opt.searchStrategy = opt.fuzzy ? _$FuzzySearchStrategy_5 : _$LiteralSearchStrategy_6
opt.sort = NoSort
opt.exclude = []
function put (data) {
if (isObject(data)) {
return addObject(data)
}
if (isArray(data)) {
return addArray(data)
}
return undefined
}
function clear () {
data.length = 0
return data
}
function isObject (obj) {
return Boolean(obj) && Object.prototype.toString.call(obj) === '[object Object]'
}
function isArray (obj) {
return Boolean(obj) && Object.prototype.toString.call(obj) === '[object Array]'
}
function addObject (_data) {
data.push(_data)
return data
}
function addArray (_data) {
const added = []
clear()
for (let i = 0, len = _data.length; i < len; i++) {
if (isObject(_data[i])) {
added.push(addObject(_data[i]))
}
}
return added
}
function search (crit) {
if (!crit) {
return []
}
return findMatches(data, crit, opt.searchStrategy, opt).sort(opt.sort)
}
function __setOptions_4 (_opt) {
opt = _opt || {}
opt.fuzzy = _opt.fuzzy || false
opt.limit = _opt.limit || 10
opt.searchStrategy = _opt.fuzzy ? _$FuzzySearchStrategy_5 : _$LiteralSearchStrategy_6
opt.sort = _opt.sort || NoSort
opt.exclude = _opt.exclude || []
}
function findMatches (data, crit, strategy, opt) {
const matches = []
for (let i = 0; i < data.length && matches.length < opt.limit; i++) {
const match = findMatchesInObject(data[i], crit, strategy, opt)
if (match) {
matches.push(match)
}
}
return matches
}
function findMatchesInObject (obj, crit, strategy, opt) {
for (const key in obj) {
if (!isExcluded(obj[key], opt.exclude) && strategy.matches(obj[key], crit)) {
return obj
}
}
}
function isExcluded (term, excludedTerms) {
for (let i = 0, len = excludedTerms.length; i < len; i++) {
const excludedTerm = excludedTerms[i]
if (new RegExp(excludedTerm).test(term)) {
return true
}
}
return false
}
/* globals ActiveXObject:false */
'use strict'
var _$JSONLoader_2 = {
load: load
}
function load (location, callback) {
const xhr = getXHR()
xhr.open('GET', location, true)
xhr.onreadystatechange = createStateChangeListener(xhr, callback)
xhr.send()
}
function createStateChangeListener (xhr, callback) {
return function () {
if (xhr.readyState === 4 && xhr.status === 200) {
try {
callback(null, JSON.parse(xhr.responseText))
} catch (err) {
callback(err, null)
}
}
}
}
function getXHR () {
return window.XMLHttpRequest ? new window.XMLHttpRequest() : new ActiveXObject('Microsoft.XMLHTTP')
}
'use strict'
var _$OptionsValidator_3 = function OptionsValidator (params) {
if (!validateParams(params)) {
throw new Error('-- OptionsValidator: required options missing')
}
if (!(this instanceof OptionsValidator)) {
return new OptionsValidator(params)
}
const requiredOptions = params.required
this.getRequiredOptions = function () {
return requiredOptions
}
this.validate = function (parameters) {
const errors = []
requiredOptions.forEach(function (requiredOptionName) {
if (typeof parameters[requiredOptionName] === 'undefined') {
errors.push(requiredOptionName)
}
})
return errors
}
function validateParams (params) {
if (!params) {
return false
}
return typeof params.required !== 'undefined' && params.required instanceof Array
}
}
'use strict'
var _$utils_9 = {
merge: merge,
isJSON: isJSON
}
function merge (defaultParams, mergeParams) {
const mergedOptions = {}
for (const option in defaultParams) {
mergedOptions[option] = defaultParams[option]
if (typeof mergeParams[option] !== 'undefined') {
mergedOptions[option] = mergeParams[option]
}
}
return mergedOptions
}
function isJSON (json) {
try {
if (json instanceof Object && JSON.parse(JSON.stringify(json))) {
return true
}
return false
} catch (err) {
return false
}
}
var _$src_8 = {};
(function (window) {
'use strict'
let options = {
searchInput: null,
resultsContainer: null,
json: [],
success: Function.prototype,
searchResultTemplate: '<li><a href="{url}" title="{desc}">{title}</a></li>',
templateMiddleware: Function.prototype,
sortMiddleware: function () {
return 0
},
noResultsText: 'No results found',
limit: 10,
fuzzy: false,
debounceTime: null,
exclude: []
}
let debounceTimerHandle
const debounce = function (func, delayMillis) {
if (delayMillis) {
clearTimeout(debounceTimerHandle)
debounceTimerHandle = setTimeout(func, delayMillis)
} else {
func.call()
}
}
const requiredOptions = ['searchInput', 'resultsContainer', 'json']
/* removed: const _$Templater_7 = require('./Templater') */;
/* removed: const _$Repository_4 = require('./Repository') */;
/* removed: const _$JSONLoader_2 = require('./JSONLoader') */;
const optionsValidator = _$OptionsValidator_3({
required: requiredOptions
})
/* removed: const _$utils_9 = require('./utils') */;
window.SimpleJekyllSearch = function (_options) {
const errors = optionsValidator.validate(_options)
if (errors.length > 0) {
throwError('You must specify the following required options: ' + requiredOptions)
}
options = _$utils_9.merge(options, _options)
_$Templater_7.setOptions({
template: options.searchResultTemplate,
middleware: options.templateMiddleware
})
_$Repository_4.setOptions({
fuzzy: options.fuzzy,
limit: options.limit,
sort: options.sortMiddleware,
exclude: options.exclude
})
if (_$utils_9.isJSON(options.json)) {
initWithJSON(options.json)
} else {
initWithURL(options.json)
}
const rv = {
search: search
}
typeof options.success === 'function' && options.success.call(rv)
return rv
}
function initWithJSON (json) {
_$Repository_4.put(json)
registerInput()
}
function initWithURL (url) {
_$JSONLoader_2.load(url, function (err, json) {
if (err) {
throwError('failed to get JSON (' + url + ')')
}
initWithJSON(json)
})
}
function emptyResultsContainer () {
options.resultsContainer.innerHTML = ''
}
function appendToResultsContainer (text) {
options.resultsContainer.innerHTML += text
}
function registerInput () {
options.searchInput.addEventListener('input', function (e) {
if (isWhitelistedKey(e.which)) {
emptyResultsContainer()
debounce(function () { search(e.target.value) }, options.debounceTime)
}
})
}
function search (query) {
if (isValidQuery(query)) {
emptyResultsContainer()
render(_$Repository_4.search(query), query)
}
}
function render (results, query) {
const len = results.length
if (len === 0) {
return appendToResultsContainer(options.noResultsText)
}
for (let i = 0; i < len; i++) {
results[i].query = query
appendToResultsContainer(_$Templater_7.compile(results[i]))
}
}
function isValidQuery (query) {
return query && query.length > 0
}
function isWhitelistedKey (key) {
return [13, 16, 20, 37, 38, 39, 40, 91].indexOf(key) === -1
}
function throwError (message) {
throw new Error('SimpleJekyllSearch --- ' + message)
}
})(window)
}());
</script>
<!-- Configuration -->
<script>
SimpleJekyllSearch({
searchInput: document.getElementById('search-input'),
resultsContainer: document.getElementById('results-container'),
noResultsText: '<p>Aucun résultat!</p>',
json: '/search.json',
searchResultTemplate: '<li><a href="{url}">{date}&nbsp;{title}</a>&nbsp;(Création {create})</li>'
})
</script>
</div></div>
<script>(function() {
var SOURCES = window.TEXT_VARIABLES.sources;
window.Lazyload.js(SOURCES.jquery, function() {
function scrollToAnchor(anchor, duration, callback) {
var $root = this;
$root.animate({ scrollTop: $(anchor).position().top }, duration, function() {
window.history.replaceState(null, '', window.location.href.split('#')[0] + anchor);
callback && callback();
});
}
$.fn.scrollToAnchor = scrollToAnchor;
});
})();
(function() {
var SOURCES = window.TEXT_VARIABLES.sources;
window.Lazyload.js(SOURCES.jquery, function() {
function affix(options) {
var $root = this, $window = $(window), $scrollTarget, $scroll,
offsetBottom = 0, scrollTarget = window, scroll = window.document, disabled = false, isOverallScroller = true,
rootTop, rootLeft, rootHeight, scrollBottom, rootBottomTop,
hasInit = false, curState;
function setOptions(options) {
var _options = options || {};
_options.offsetBottom && (offsetBottom = _options.offsetBottom);
_options.scrollTarget && (scrollTarget = _options.scrollTarget);
_options.scroll && (scroll = _options.scroll);
_options.disabled !== undefined && (disabled = _options.disabled);
$scrollTarget = $(scrollTarget);
isOverallScroller = window.isOverallScroller($scrollTarget[0]);
$scroll = $(scroll);
}
function preCalc() {
top();
rootHeight = $root.outerHeight();
rootTop = $root.offset().top + (isOverallScroller ? 0 : $scrollTarget.scrollTop());
rootLeft = $root.offset().left;
}
function calc(needPreCalc) {
needPreCalc && preCalc();
scrollBottom = $scroll.outerHeight() - offsetBottom - rootHeight;
rootBottomTop = scrollBottom - rootTop;
}
function top() {
if (curState !== 'top') {
$root.removeClass('fixed').css({
left: 0,
top: 0
});
curState = 'top';
}
}
function fixed() {
if (curState !== 'fixed') {
$root.addClass('fixed').css({
left: rootLeft + 'px',
top: 0
});
curState = 'fixed';
}
}
function bottom() {
if (curState !== 'bottom') {
$root.removeClass('fixed').css({
left: 0,
top: rootBottomTop + 'px'
});
curState = 'bottom';
}
}
function setState() {
var scrollTop = $scrollTarget.scrollTop();
if (scrollTop >= rootTop && scrollTop <= scrollBottom) {
fixed();
} else if (scrollTop < rootTop) {
top();
} else {
bottom();
}
}
function init() {
if(!hasInit) {
var interval, timeout;
calc(true); setState();
// run calc every 100 millisecond
interval = setInterval(function() {
calc();
}, 100);
timeout = setTimeout(function() {
clearInterval(interval);
}, 45000);
window.pageLoad.then(function() {
setTimeout(function() {
clearInterval(interval);
clearTimeout(timeout);
}, 3000);
});
$scrollTarget.on('scroll', function() {
disabled || setState();
});
$window.on('resize', function() {
disabled || (calc(true), setState());
});
hasInit = true;
}
}
setOptions(options);
if (!disabled) {
init();
}
$window.on('resize', window.throttle(function() {
init();
}, 200));
return {
setOptions: setOptions,
refresh: function() {
calc(true, { animation: false }); setState();
}
};
}
$.fn.affix = affix;
});
})();
(function() {
var SOURCES = window.TEXT_VARIABLES.sources;
window.Lazyload.js(SOURCES.jquery, function() {
function toc(options) {
var $root = this, $window = $(window), $scrollTarget, $scroller, $tocUl = $('<ul class="toc toc--ellipsis"></ul>'), $tocLi, $headings, $activeLast, $activeCur,
selectors = 'h1,h2,h3', container = 'body', scrollTarget = window, scroller = 'html, body', disabled = false,
headingsPos, scrolling = false, hasRendered = false, hasInit = false;
function setOptions(options) {
var _options = options || {};
_options.selectors && (selectors = _options.selectors);
_options.container && (container = _options.container);
_options.scrollTarget && (scrollTarget = _options.scrollTarget);
_options.scroller && (scroller = _options.scroller);
_options.disabled !== undefined && (disabled = _options.disabled);
$headings = $(container).find(selectors).filter('[id]');
$scrollTarget = $(scrollTarget);
$scroller = $(scroller);
}
function calc() {
headingsPos = [];
$headings.each(function() {
headingsPos.push(Math.floor($(this).position().top));
});
}
function setState(element, disabled) {
var scrollTop = $scrollTarget.scrollTop(), i;
if (disabled || !headingsPos || headingsPos.length < 1) { return; }
if (element) {
$activeCur = element;
} else {
for (i = 0; i < headingsPos.length; i++) {
if (scrollTop >= headingsPos[i]) {
$activeCur = $tocLi.eq(i);
} else {
$activeCur || ($activeCur = $tocLi.eq(i));
break;
}
}
}
$activeLast && $activeLast.removeClass('active');
($activeLast = $activeCur).addClass('active');
}
function render() {
if(!hasRendered) {
$root.append($tocUl);
$headings.each(function() {
var $this = $(this);
$tocUl.append($('<li></li>').addClass('toc-' + $this.prop('tagName').toLowerCase())
.append($('<a></a>').text($this.text()).attr('href', '#' + $this.prop('id'))));
});
$tocLi = $tocUl.children('li');
$tocUl.on('click', 'a', function(e) {
e.preventDefault();
var $this = $(this);
scrolling = true;
setState($this.parent());
$scroller.scrollToAnchor($this.attr('href'), 400, function() {
scrolling = false;
});
});
}
hasRendered = true;
}
function init() {
var interval, timeout;
if(!hasInit) {
render(); calc(); setState(null, scrolling);
// run calc every 100 millisecond
interval = setInterval(function() {
calc();
}, 100);
timeout = setTimeout(function() {
clearInterval(interval);
}, 45000);
window.pageLoad.then(function() {
setTimeout(function() {
clearInterval(interval);
clearTimeout(timeout);
}, 3000);
});
$scrollTarget.on('scroll', function() {
disabled || setState(null, scrolling);
});
$window.on('resize', window.throttle(function() {
if (!disabled) {
render(); calc(); setState(null, scrolling);
}
}, 100));
}
hasInit = true;
}
setOptions(options);
if (!disabled) {
init();
}
$window.on('resize', window.throttle(function() {
init();
}, 200));
return {
setOptions: setOptions
};
}
$.fn.toc = toc;
});
})();
/*(function () {
})();*/
</script><script>
/* toc must before affix, since affix need to konw toc' height. */(function() {
var SOURCES = window.TEXT_VARIABLES.sources;
var TOC_SELECTOR = window.TEXT_VARIABLES.site.toc.selectors;
window.Lazyload.js(SOURCES.jquery, function() {
var $window = $(window);
var $articleContent = $('.js-article-content');
var $tocRoot = $('.js-toc-root'), $col2 = $('.js-col-aside');
var toc;
var tocDisabled = false;
var hasSidebar = $('.js-page-root').hasClass('layout--page--sidebar');
var hasToc = $articleContent.find(TOC_SELECTOR).length > 0;
function disabled() {
return $col2.css('display') === 'none' || !hasToc;
}
tocDisabled = disabled();
toc = $tocRoot.toc({
selectors: TOC_SELECTOR,
container: $articleContent,
scrollTarget: hasSidebar ? '.js-page-main' : null,
scroller: hasSidebar ? '.js-page-main' : null,
disabled: tocDisabled
});
$window.on('resize', window.throttle(function() {
tocDisabled = disabled();
toc && toc.setOptions({
disabled: tocDisabled
});
}, 100));
});
})();
(function() {
var SOURCES = window.TEXT_VARIABLES.sources;
window.Lazyload.js(SOURCES.jquery, function() {
var $window = $(window), $pageFooter = $('.js-page-footer');
var $pageAside = $('.js-page-aside');
var affix;
var tocDisabled = false;
var hasSidebar = $('.js-page-root').hasClass('layout--page--sidebar');
affix = $pageAside.affix({
offsetBottom: $pageFooter.outerHeight(),
scrollTarget: hasSidebar ? '.js-page-main' : null,
scroller: hasSidebar ? '.js-page-main' : null,
scroll: hasSidebar ? $('.js-page-main').children() : null,
disabled: tocDisabled
});
$window.on('resize', window.throttle(function() {
affix && affix.setOptions({
disabled: tocDisabled
});
}, 100));
window.pageAsideAffix = affix;
});
})();
</script><!---->
</div>
<script>(function () {
var $root = document.getElementsByClassName('root')[0];
if (window.hasEvent('touchstart')) {
$root.dataset.isTouch = true;
document.addEventListener('touchstart', function(){}, false);
}
})();
</script>
</body>
</html>