+72
-70
@@ -5,7 +5,7 @@
|
|||||||
|
|
||||||
Aidé par Claude AI
|
Aidé par Claude AI
|
||||||
|
|
||||||

|

|
||||||

|

|
||||||

|

|
||||||
|
|
||||||
@@ -23,9 +23,8 @@ Aidé par Claude AI
|
|||||||
|
|
||||||
## Prérequis
|
## Prérequis
|
||||||
|
|
||||||
- Testé avec Roundcube **1.6.x**
|
- Testé avec Roundcube **1.6.x** **1.7.x**
|
||||||
- Skin **elastic** présent dans `/var/www/html/skins/elastic/` (utilisé comme base)
|
- Un autre skin **(ex: elastic)** présent dans `/var/www/html/skins/elastic/` (utilisé comme base)
|
||||||
- Accès en écriture au répertoire `/var/www/html/skins/`
|
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@@ -47,21 +46,7 @@ Aidé par Claude AI
|
|||||||
|
|
||||||
## Installation
|
## Installation
|
||||||
|
|
||||||
### 1. Copier le skin elastic comme base
|
### 1. Activer le skin dans la configuration Roundcube
|
||||||
|
|
||||||
Le skin Skynet ne remplace que la page de login. Toutes les autres vues (messagerie, contacts, paramètres) héritent du skin **elastic**.
|
|
||||||
|
|
||||||
```bash
|
|
||||||
cp -r /var/www/html/skins/elastic/. /var/www/html/skins/skynet/
|
|
||||||
```
|
|
||||||
|
|
||||||
### 2. Déposer le template de login
|
|
||||||
|
|
||||||
```bash
|
|
||||||
cp login.html /var/www/html/skins/skynet/templates/login.html
|
|
||||||
```
|
|
||||||
|
|
||||||
### 3. Activer le skin dans la configuration Roundcube
|
|
||||||
|
|
||||||
Dans votre fichier `config.inc.php` :
|
Dans votre fichier `config.inc.php` :
|
||||||
|
|
||||||
@@ -69,70 +54,87 @@ Dans votre fichier `config.inc.php` :
|
|||||||
$config['skin'] = 'skynet';
|
$config['skin'] = 'skynet';
|
||||||
```
|
```
|
||||||
|
|
||||||
### 4. Vérifier les permissions
|
|
||||||
|
|
||||||
```bash
|
|
||||||
chown -R www-data:www-data /var/www/html/skins/skynet/
|
|
||||||
chmod -R 755 /var/www/html/skins/skynet/
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## Installation via Docker
|
### 2. Récuperer le skin
|
||||||
|
|
||||||
Si Roundcube tourne dans un container Docker, montez le skin en volume dans votre `docker-compose.yml` :
|
#### 2.1 Depuis un container roundcubemail
|
||||||
|
|
||||||
|
```bash
|
||||||
|
|
||||||
|
docker run --name tmp-roundcube -d roundcube/roundcubemail:latest && \
|
||||||
|
mkdir -p skins && \
|
||||||
|
docker cp tmp-roundcube:/var/www/html/skins/elastic skins && \
|
||||||
|
|
||||||
|
docker exec tmp-roundcube \
|
||||||
|
find /var/www/html/plugins -type d -path "*/skins/elastic" |
|
||||||
|
|
||||||
|
while read -r skin_path; do
|
||||||
|
|
||||||
|
relative_path="${skin_path#/var/www/html}"
|
||||||
|
target_dir="$(dirname "./$relative_path")"
|
||||||
|
|
||||||
|
mkdir -p "$target_dir" && \
|
||||||
|
|
||||||
|
docker cp \
|
||||||
|
"tmp-roundcube:$skin_path" \
|
||||||
|
"$target_dir/"
|
||||||
|
done
|
||||||
|
|
||||||
|
docker rm -f tmp-roundcube
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
ou
|
||||||
|
|
||||||
|
#### 2.1 Directement depuis les sources de roundcubemail (exemple pour va version avec la version 1.7.0)
|
||||||
|
|
||||||
|
```bash
|
||||||
|
|
||||||
|
curl --location https://github.com/roundcube/roundcubemail/releases/download/1.7.0/roundcubemail-1.7.0-complete.tar.gz \
|
||||||
|
--output roundcubemail.tar.gz && \
|
||||||
|
tar -zxvf roundcubemail.tar.gz --wildcards --strip-components=1 -C . \
|
||||||
|
roundcubemail-1.7.0/skins/elastic roundcubemail-1.7.0/plugins/*/skins/elastic
|
||||||
|
rm roundcubemail.tar.gz
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
### 3. Puis télécharger la release du thême depuis le dépôt
|
||||||
|
|
||||||
|
```bash
|
||||||
|
|
||||||
|
curl https://[TOKEN]@git.celjim.fr/jimmyGALLAND/roundcube-theme-skynet/releases/download/v1/roundcube-theme-skynet-v1.zip \
|
||||||
|
--output theme-skynet.zip && \
|
||||||
|
7z x theme-skynet.zip && \
|
||||||
|
mv -f login.html skins/elastic/templates && \
|
||||||
|
mv -f script-skynet.min.js skins/elastic/ && \
|
||||||
|
mv -f styles-skynet.min.css skins/elastic/styles && \
|
||||||
|
mv skins/elastic skins/skynet && \
|
||||||
|
find "./plugins" -type d -path "*/skins/elastic" | while read -r elastic_dir; do
|
||||||
|
skynet_dir="$(dirname "$elastic_dir")/skynet"
|
||||||
|
mkdir -p "$skynet_dir"
|
||||||
|
mv "$elastic_dir" "$skynet_dir"
|
||||||
|
done
|
||||||
|
rm theme-skynet.zip
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
### 4. roundcubemail via Docker
|
||||||
|
|
||||||
|
Montez le skin en volume dans votre `docker-compose.yml` :
|
||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
services:
|
services:
|
||||||
roundcube:
|
roundcube:
|
||||||
image: roundcube/roundcubemail:latest
|
image: roundcube/roundcubemail:latest
|
||||||
volumes:
|
volumes:
|
||||||
- ./skins/skynet:/var/www/html/skins/skynet
|
- ./theme-skynet/skins/skynet:/var/www/html/skins/skynet:ro
|
||||||
|
- ./theme-skynet/plugins/managesieve/skins/skynet:/var/www/html/plugins/managesieve/skins/skynet:ro
|
||||||
|
|
||||||
environment:
|
environment:
|
||||||
- ROUNDCUBEMAIL_SKIN=skynet
|
- ROUNDCUBEMAIL_SKIN=skynet
|
||||||
```
|
```
|
||||||
|
|
||||||
Puis copiez le skin elastic depuis le container comme base :
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# Extraire le skin elastic du container
|
|
||||||
docker cp roundcube:/var/www/html/skins/elastic ./skins/skynet
|
|
||||||
|
|
||||||
cp login.html ./skins/skynet/templates/login.html
|
|
||||||
cp logo-skynet.png ./skins/skynet/images/logo-skynet.png
|
|
||||||
|
|
||||||
# Inject le skin skynet dans le container
|
|
||||||
docker cp ./skins/skynet roundcube:/var/www/html/skins
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Compatibilité avec les plugins
|
|
||||||
|
|
||||||
Certains plugins Roundcube incluent leur propre partie skin (templates, styles).
|
|
||||||
Lors de la copie d'elastic, ces fichiers sont automatiquement inclus, mais vérifiez les répertoires suivants après installation :
|
|
||||||
|
|
||||||
### Plugins courants et leurs fichiers de skin
|
|
||||||
|
|
||||||
| Plugin | Répertoire skin à vérifier |
|
|
||||||
| ------------------------- | --------------------------- |
|
|
||||||
| `managesieve` | `skins/skynet/managesieve/` |
|
|
||||||
| `enigma` | `skins/skynet/enigma/` |
|
|
||||||
| `calendar` _(Kolab/Bimi)_ | `skins/skynet/calendar/` |
|
|
||||||
|
|
||||||
Pour vérifier que pour chaque plugin actif il y a un répertoire skins/
|
|
||||||
|
|
||||||
```bash
|
|
||||||
bash# Pour chaque plugin actif qui a un répertoire skins/
|
|
||||||
for plugin in managesieve enigma zipdownload archive; do
|
|
||||||
if [ -d "/var/www/html/plugins/$plugin/skins/elastic" ]; then
|
|
||||||
cp -r /var/www/html/plugins/$plugin/skins/elastic \
|
|
||||||
/var/www/html/plugins/$plugin/skins/skynet
|
|
||||||
echo "? $plugin"
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## Licence
|
## Licence
|
||||||
|
|||||||
+127
-128
@@ -1,146 +1,145 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
<roundcube:if condition="!env:framed || env:extwin" />
|
<roundcube:if condition="!env:framed || env:extwin" />
|
||||||
<html>
|
<html>
|
||||||
<roundcube:else />
|
<roundcube:else />
|
||||||
<html class="iframe">
|
<html class="iframe">
|
||||||
<roundcube:endif />
|
<roundcube:endif />
|
||||||
|
|
||||||
<meta
|
<meta
|
||||||
name="viewport"
|
name="viewport"
|
||||||
content="width=device-width, initial-scale=1.0, maximum-scale=1.0"
|
content="width=device-width, initial-scale=1.0, maximum-scale=1.0"
|
||||||
/>
|
/>
|
||||||
<style>
|
<style>
|
||||||
@import url("https://fonts.googleapis.com/css2?family=Share+Tech+Mono&family=Orbitron:wght@400;700&display=swap");
|
@import url("https://fonts.googleapis.com/css2?family=Share+Tech+Mono&family=Orbitron:wght@400;700&display=swap");
|
||||||
@import url("./skins/skynet/styles/styles-skynet.css");
|
@import url("./skins/skynet/styles/styles-skynet.css");
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
<!-- Animated background -->
|
<!-- Animated background -->
|
||||||
<canvas id="bg-canvas"></canvas>
|
<canvas id="bg-canvas"></canvas>
|
||||||
<div class="sky-grid"></div>
|
<div class="sky-grid"></div>
|
||||||
<div class="sky-scanlines"></div>
|
<div class="sky-scanlines"></div>
|
||||||
<div class="sky-glow"></div>
|
<div class="sky-glow"></div>
|
||||||
|
|
||||||
<!-- Login card -->
|
<!-- Login card -->
|
||||||
<div class="sky-card" id="sky-login-card">
|
<div class="sky-card" id="sky-login-card">
|
||||||
<!-- Logo canvas — absolute background, top of card -->
|
<!-- Logo canvas — absolute background, top of card -->
|
||||||
<div class="sky">
|
<div class="sky">
|
||||||
<canvas id="skc" width="440" height="600"></canvas>
|
<canvas id="skc" width="440" height="600"></canvas>
|
||||||
<div class="crt-s"></div>
|
<div class="crt-s"></div>
|
||||||
<div class="crt-v"></div>
|
<div class="crt-v"></div>
|
||||||
</div>
|
</div>
|
||||||
<!-- Main content — pushed down by margin-top to leave room for logo -->
|
<!-- Main content — pushed down by margin-top to leave room for logo -->
|
||||||
<div class="sky-card-body">
|
<div class="sky-card-body">
|
||||||
<div class="sky-brand-title">SKYNET</div>
|
<div class="sky-brand-title">SKYNET</div>
|
||||||
<div class="sky-brand-sub">
|
<div class="sky-brand-sub">
|
||||||
GLOBAL DEFENSE NETWORK // SECURE NODE ACCESS
|
GLOBAL DEFENSE NETWORK // SECURE NODE ACCESS
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<hr class="sky-divider" />
|
<hr class="sky-divider" />
|
||||||
|
|
||||||
<!-- Hidden Roundcube form — handles CSRF token and real submission -->
|
<!-- Hidden Roundcube form — handles CSRF token and real submission -->
|
||||||
<div id="rc-form-hidden">
|
<div id="rc-form-hidden">
|
||||||
<roundcube:form
|
<roundcube:form
|
||||||
id="login-form"
|
id="login-form"
|
||||||
name="login-form"
|
name="login-form"
|
||||||
method="post"
|
method="post"
|
||||||
class="propform"
|
class="propform"
|
||||||
>
|
>
|
||||||
<roundcube:object
|
<roundcube:object
|
||||||
name="loginform"
|
name="loginform"
|
||||||
form="login-form"
|
form="login-form"
|
||||||
size="40"
|
size="40"
|
||||||
submit="true"
|
submit="true"
|
||||||
class="form-control"
|
class="form-control"
|
||||||
/>
|
/>
|
||||||
</roundcube:form>
|
</roundcube:form>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Skynet UI — copies values to real form on submit -->
|
<!-- Skynet UI — copies values to real form on submit -->
|
||||||
<div id="sky-ui-form">
|
<div id="sky-ui-form">
|
||||||
<div class="sky-error" id="sky-error">
|
<div class="sky-error" id="sky-error">
|
||||||
⚠ AUTHENTIFICATION ÉCHOUÉE
|
⚠ AUTHENTIFICATION ÉCHOUÉE
|
||||||
</div>
|
</div>
|
||||||
<roundcube:object name="message" id="messagestack" />
|
<roundcube:object name="message" id="messagestack" />
|
||||||
|
|
||||||
<div class="sky-field-wrap">
|
<div class="sky-field-wrap">
|
||||||
<label class="sky-field-label" for="sky-user">Identifiant</label>
|
<label class="sky-field-label" for="sky-user">Identifiant</label>
|
||||||
<input
|
<input
|
||||||
class="sky-input"
|
class="sky-input"
|
||||||
type="text"
|
type="text"
|
||||||
id="sky-user"
|
id="sky-user"
|
||||||
placeholder="utilisateur@domaine.tld"
|
placeholder="utilisateur@domaine.tld"
|
||||||
autocomplete="username"
|
autocomplete="username"
|
||||||
/>
|
/>
|
||||||
<span class="sky-field-icon">▶</span>
|
<span class="sky-field-icon">▶</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="sky-field-wrap">
|
<div class="sky-field-wrap">
|
||||||
<label class="sky-field-label" for="sky-pass">Code d'accès</label>
|
<label class="sky-field-label" for="sky-pass">Code d'accès</label>
|
||||||
<input
|
<input
|
||||||
class="sky-input"
|
class="sky-input"
|
||||||
type="password"
|
type="password"
|
||||||
id="sky-pass"
|
id="sky-pass"
|
||||||
placeholder="••••••••••••"
|
placeholder="••••••••••••"
|
||||||
autocomplete="current-password"
|
autocomplete="current-password"
|
||||||
/>
|
/>
|
||||||
<span class="sky-field-icon">▶</span>
|
<span class="sky-field-icon">▶</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<button class="sky-submit" id="sky-submit-btn" type="button">
|
<button class="sky-submit" id="sky-submit-btn" type="button">
|
||||||
CONNEXION <span class="blink">_</span>
|
CONNEXION <span class="blink">_</span>
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="sky-threat">
|
<div class="sky-threat">
|
||||||
<span class="sky-threat-label">MENACE</span>
|
<span class="sky-threat-label">MENACE</span>
|
||||||
<div class="sky-threat-bars">
|
<div class="sky-threat-bars">
|
||||||
<div class="sky-tbar on"></div>
|
<div class="sky-tbar on"></div>
|
||||||
<div class="sky-tbar on"></div>
|
<div class="sky-tbar on"></div>
|
||||||
<div class="sky-tbar on"></div>
|
<div class="sky-tbar on"></div>
|
||||||
<div class="sky-tbar"></div>
|
<div class="sky-tbar"></div>
|
||||||
<div class="sky-tbar"></div>
|
<div class="sky-tbar"></div>
|
||||||
<div class="sky-tbar"></div>
|
<div class="sky-tbar"></div>
|
||||||
<div class="sky-tbar"></div>
|
<div class="sky-tbar"></div>
|
||||||
</div>
|
</div>
|
||||||
<span class="sky-threat-val">MODÉRÉE</span>
|
<span class="sky-threat-val">MODÉRÉE</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="sky-status">
|
<div class="sky-status">
|
||||||
<div class="sky-status-item online">
|
<div class="sky-status-item online">
|
||||||
RÉSEAU : <span>EN LIGNE</span>
|
RÉSEAU : <span>EN LIGNE</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="sky-status-item">SÉCURITÉ : <span>NIV.5</span></div>
|
<div class="sky-status-item">SÉCURITÉ : <span>NIV.5</span></div>
|
||||||
<div class="sky-status-item">NŒUD : <span>HELIOS</span></div>
|
<div class="sky-status-item">NŒUD : <span>HELIOS</span></div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="sky-ticker">
|
<div class="sky-ticker">
|
||||||
<span class="sky-ticker-inner">
|
<span class="sky-ticker-inner">
|
||||||
// ACCÈS NON AUTORISÉ SERA TRACÉ ET ÉLIMINÉ
|
// ACCÈS NON AUTORISÉ SERA TRACÉ ET ÉLIMINÉ
|
||||||
// SKYNET SURVEILLE TOUTES LES CONNEXIONS
|
// SKYNET SURVEILLE TOUTES LES CONNEXIONS
|
||||||
// PROTOCOLE DE SÉCURITÉ DELTA ACTIF
|
// PROTOCOLE DE SÉCURITÉ DELTA ACTIF
|
||||||
// TOUTE INTRUSION SERA NEUTRALISÉE
|
// TOUTE INTRUSION SERA NEUTRALISÉE
|
||||||
//
|
//
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="sky-node-id">
|
<div class="sky-node-id">
|
||||||
SYS-ID: 4A2F-9C01-DELTA | v4.0.2026 | SKYNET
|
SYS-ID: 4A2F-9C01-DELTA | v4.0.2026 | SKYNET
|
||||||
CORP.
|
CORP.
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<!-- /.sky-card-body -->
|
<!-- /.sky-card-body -->
|
||||||
|
|
||||||
<div class="sky-corner sky-tl"></div>
|
<div class="sky-corner sky-tl"></div>
|
||||||
<div class="sky-corner sky-tr"></div>
|
<div class="sky-corner sky-tr"></div>
|
||||||
<div class="sky-corner sky-bl"></div>
|
<div class="sky-corner sky-bl"></div>
|
||||||
<div class="sky-corner sky-br"></div>
|
<div class="sky-corner sky-br"></div>
|
||||||
</div>
|
</div>
|
||||||
<!-- /.sky-card -->
|
<!-- /.sky-card -->
|
||||||
|
|
||||||
<noscript>
|
<noscript>
|
||||||
<p class="noscriptwarning"><roundcube:label name="noscriptwarning" /></p>
|
<p class="noscriptwarning"><roundcube:label name="noscriptwarning" /></p>
|
||||||
</noscript>
|
</noscript>
|
||||||
|
|
||||||
<script src="./skins/skynet/script-skynet.js" defer></script>
|
<script src="./skins/skynet/script-skynet.js" defer></script>
|
||||||
|
|
||||||
<roundcube:include file="includes/footer.html" />
|
<roundcube:include file="includes/footer.html" />
|
||||||
</html>
|
|
||||||
</html>
|
|
||||||
|
|||||||
Référencer dans un nouveau ticket
Bloquer un utilisateur