Initialisation depot

This commit is contained in:
Serge NOEL
2026-02-10 12:12:11 +01:00
commit c3176e8d79
818 changed files with 52573 additions and 0 deletions
+423
View File
@@ -0,0 +1,423 @@
# Configuration HTTPS pour naval.lan avec Traefik (Kubernetes)
Ce guide explique comment configurer HTTPS pour votre domaine local `naval.lan` en utilisant Traefik dans Kubernetes sans avertissements de certificat sur les clients Windows et Linux.
## Vue d'ensemble
Pour éviter les avertissements de certificat auto-signé, vous devez :
1. Créer votre propre Autorité de Certification (CA)
2. Générer des certificats SSL signés par votre CA
3. Configurer Traefik pour utiliser ces certificats
4. Installer le certificat CA sur toutes les machines clientes
## Partie 1 : Créer votre propre Autorité de Certification
### 1.1. Générer la clé privée et le certificat CA
Sur votre serveur ou poste de travail Linux :
```bash
# Créer un répertoire pour les certificats
mkdir -p ~/certs/naval-ca
cd ~/certs/naval-ca
# Générer la clé privée CA (RSA 4096 bits)
openssl genrsa -out ca-key.pem 4096
# Générer le certificat CA (valide 10 ans)
openssl req -new -x509 -days 3650 -key ca-key.pem -out ca-cert.pem \
-subj "/C=FR/ST=Region/L=Ville/O=Naval Local CA/OU=IT/CN=Naval Local Root CA"
```
**Important** : Gardez `ca-key.pem` en sécurité ! C'est votre clé privée CA racine.
## Partie 2 : Générer le certificat SSL pour naval.lan
### 2.1. Créer le fichier de configuration OpenSSL
Créez un fichier nommé `naval-lan.conf` :
```bash
cat > naval-lan.conf <<EOF
[req]
default_bits = 2048
prompt = no
default_md = sha256
req_extensions = req_ext
distinguished_name = dn
[dn]
C = FR
ST = Region
L = Ville
O = Naval Local
OU = Département IT
CN = *.naval.lan
[req_ext]
subjectAltName = @alt_names
[alt_names]
DNS.1 = naval.lan
DNS.2 = *.naval.lan
DNS.3 = localhost
IP.1 = 127.0.0.1
EOF
```
### 2.2. Générer la demande de signature de certificat (CSR)
```bash
# Générer la clé privée pour naval.lan
openssl genrsa -out naval-lan-key.pem 2048
# Générer le CSR
openssl req -new -key naval-lan-key.pem -out naval-lan.csr -config naval-lan.conf
```
### 2.3. Signer le certificat avec votre CA
```bash
# Signer le certificat (valide 2 ans)
openssl x509 -req -in naval-lan.csr -CA ca-cert.pem -CAkey ca-key.pem \
-CAcreateserial -out naval-lan-cert.pem -days 730 \
-extensions req_ext -extfile naval-lan.conf
# Vérifier le certificat
openssl x509 -in naval-lan-cert.pem -text -noout
```
## Partie 3 : Configurer Traefik dans Kubernetes
### 3.1. Créer un Secret Kubernetes avec les certificats
```bash
# Créer un namespace pour Traefik (s'il n'existe pas)
kubectl create namespace traefik --dry-run=client -o yaml | kubectl apply -f -
# Créer le secret avec vos certificats
kubectl create secret tls naval-lan-tls \
--cert=naval-lan-cert.pem \
--key=naval-lan-key.pem \
-n traefik
```
### 3.2. Mettre à jour la configuration Traefik
Créez ou mettez à jour votre fichier de valeurs Helm Traefik (`traefik-values.yaml`) :
```yaml
# traefik-values.yaml
additionalArguments:
- "--providers.kubernetescrd"
- "--entrypoints.websecure.http.tls=true"
- "--entrypoints.web.address=:80"
- "--entrypoints.websecure.address=:443"
ports:
web:
port: 80
exposedPort: 80
websecure:
port: 443
exposedPort: 443
tls:
enabled: true
# Monter le certificat TLS
volumes:
- name: naval-lan-tls
mountPath: "/certs"
type: secret
persistence:
enabled: true
```
### 3.3. Créer l'IngressRoute pour vos services
Exemple de configuration IngressRoute :
```yaml
apiVersion: traefik.containo.us/v1alpha1
kind: IngressRoute
metadata:
name: myapp-ingressroute
namespace: default
spec:
entryPoints:
- websecure
routes:
- match: Host(`myapp.naval.lan`)
kind: Rule
services:
- name: myapp-service
port: 80
tls:
secretName: naval-lan-tls
---
# Optionnel : redirection HTTP vers HTTPS
apiVersion: traefik.containo.us/v1alpha1
kind: IngressRoute
metadata:
name: myapp-http-redirect
namespace: default
spec:
entryPoints:
- web
routes:
- match: Host(`myapp.naval.lan`)
kind: Rule
services:
- name: myapp-service
port: 80
middlewares:
- name: redirect-to-https
---
apiVersion: traefik.containo.us/v1alpha1
kind: Middleware
metadata:
name: redirect-to-https
namespace: default
spec:
redirectScheme:
scheme: https
permanent: true
```
### 3.4. Appliquer la configuration Traefik
```bash
# Si vous utilisez Helm
helm upgrade --install traefik traefik/traefik \
-n traefik \
-f traefik-values.yaml
# Appliquer l'IngressRoute
kubectl apply -f ingressroute.yaml
```
## Partie 4 : Installer le certificat CA sur les machines clientes
### 4.1. Clients Linux
#### Ubuntu/Debian :
```bash
# Copier ca-cert.pem vers votre client Linux
sudo cp ca-cert.pem /usr/local/share/ca-certificates/naval-ca.crt
# Mettre à jour les certificats CA
sudo update-ca-certificates
# Vérifier
openssl s_client -connect myapp.naval.lan:443 -CAfile /usr/local/share/ca-certificates/naval-ca.crt
```
#### RHEL/CentOS/Fedora :
```bash
# Copier ca-cert.pem vers votre client Linux
sudo cp ca-cert.pem /etc/pki/ca-trust/source/anchors/naval-ca.crt
# Mettre à jour les certificats CA
sudo update-ca-trust
# Vérifier
openssl s_client -connect myapp.naval.lan:443
```
#### Pour Firefox (utilise son propre magasin de certificats) :
1. Ouvrir Firefox
2. Aller dans **Paramètres****Vie privée et sécurité**
3. Descendre jusqu'à **Certificats** → Cliquer sur **Afficher les certificats**
4. Aller dans l'onglet **Autorités**
5. Cliquer sur **Importer**
6. Sélectionner `ca-cert.pem`
7. Cocher "Confirmer cette AC pour identifier des sites web"
8. Cliquer sur OK
### 4.2. Clients Windows
#### Méthode 1 : Utilisation de MMC (Console de gestion Microsoft)
1. Copier `ca-cert.pem` sur votre machine Windows
2. Le renommer en `ca-cert.crt` (optionnel, pour une meilleure reconnaissance)
3. Faire un clic droit sur `ca-cert.crt`**Installer le certificat**
4. Choisir **Ordinateur local** (nécessite les droits administrateur)
5. Cliquer sur **Suivant**
6. Sélectionner **Placer tous les certificats dans le magasin suivant**
7. Cliquer sur **Parcourir** → Sélectionner **Autorités de certification racines de confiance**
8. Cliquer sur **Suivant****Terminer**
9. Cliquer sur **Oui** à l'avertissement de sécurité
#### Méthode 2 : Utilisation de la ligne de commande (PowerShell Administrateur)
```powershell
# Importer le certificat dans le magasin CA racine de confiance
Import-Certificate -FilePath "C:\chemin\vers\ca-cert.pem" -CertStoreLocation Cert:\LocalMachine\Root
# Vérifier
Get-ChildItem -Path Cert:\LocalMachine\Root | Where-Object {$_.Subject -like "*Naval*"}
```
#### Méthode 3 : Utilisation de certutil (Invite de commandes en Administrateur)
```cmd
certutil -addstore -f "ROOT" ca-cert.pem
```
#### Pour Firefox sur Windows :
Mêmes étapes que Firefox sur Linux ci-dessus.
### 4.3. Vérifier l'installation
#### Linux :
```bash
# Tester avec curl
curl -v https://myapp.naval.lan
# Tester avec openssl
openssl s_client -connect myapp.naval.lan:443 -showcerts
```
#### Windows :
```powershell
# Tester avec PowerShell
Invoke-WebRequest -Uri https://myapp.naval.lan
# Ou utiliser le navigateur
# Naviguer vers https://myapp.naval.lan
```
## Partie 5 : Configuration DNS
Assurez-vous que vos clients peuvent résoudre les domaines `naval.lan` :
### 5.1. Option 1 : Serveur DNS local (Recommandé)
Configurez un serveur DNS local (dnsmasq, Pi-hole, ou DNS Windows) avec :
```
*.naval.lan → [IP Traefik Ingress]
```
### 5.2. Option 2 : Fichier hosts
#### Linux : `/etc/hosts`
```bash
sudo nano /etc/hosts
```
#### Windows : `C:\Windows\System32\drivers\etc\hosts` (en tant qu'Administrateur)
```
notepad C:\Windows\System32\drivers\etc\hosts
```
Ajouter les entrées :
```
192.168.1.100 myapp.naval.lan
192.168.1.100 dashboard.naval.lan
```
Remplacez `192.168.1.100` par l'IP de votre ingress Traefik.
## Partie 6 : Renouvellement du certificat
Vos certificats expireront. Pour les renouveler :
```bash
cd ~/certs/naval-ca
# Générer un nouveau CSR (ou réutiliser la clé existante)
openssl req -new -key naval-lan-key.pem -out naval-lan-new.csr -config naval-lan.conf
# Signer avec la CA
openssl x509 -req -in naval-lan-new.csr -CA ca-cert.pem -CAkey ca-key.pem \
-CAcreateserial -out naval-lan-cert-new.pem -days 730 \
-extensions req_ext -extfile naval-lan.conf
# Mettre à jour le secret Kubernetes
kubectl create secret tls naval-lan-tls \
--cert=naval-lan-cert-new.pem \
--key=naval-lan-key.pem \
-n traefik \
--dry-run=client -o yaml | kubectl apply -f -
# Redémarrer les pods Traefik pour recharger le certificat
kubectl rollout restart deployment traefik -n traefik
```
## Dépannage
### Certificat non approuvé après l'installation
- **Vider le cache du navigateur** : Certains navigateurs mettent en cache la validation des certificats
- **Redémarrer le navigateur** : Nécessaire pour Chrome/Edge sur Windows
- **Vérifier la chaîne de certificats** : `openssl s_client -connect myapp.naval.lan:443 -showcerts`
### Erreur "NET::ERR_CERT_AUTHORITY_INVALID"
- Vérifier que le certificat CA est dans le bon magasin
- Sur Windows, assurez-vous qu'il est dans "Autorités de certification racines de confiance", pas "Intermédiaire"
- Vérifier que les noms alternatifs du sujet du certificat incluent votre domaine
### Firefox affiche toujours un avertissement
- Firefox utilise son propre magasin de certificats sur toutes les plateformes
- Vous devez importer le certificat CA directement dans Firefox
### Certificat expiré
- Vérifier la validité du certificat : `openssl x509 -in naval-lan-cert.pem -noout -dates`
- Suivre les étapes de renouvellement de la Partie 6
## Considérations de sécurité
1. **Protéger votre clé privée CA** (`ca-key.pem`) :
- Stockez-la en sécurité
- Envisagez de la chiffrer avec une phrase secrète
- Conservez des sauvegardes dans des emplacements sécurisés
2. **Période de validité du certificat** :
- Ne la rendez pas trop longue (2 ans maximum recommandé)
- Configurez des rappels de calendrier pour le renouvellement
3. **Contrôle d'accès** :
- N'installez le certificat CA que sur les machines que vous contrôlez
- Ne partagez pas votre clé privée CA
4. **Isolation réseau** :
- Gardez votre domaine `.lan` isolé d'Internet
- Utilisez des règles de pare-feu pour empêcher l'accès externe
## Commandes de référence rapide
```bash
# Vérifier les détails du certificat
openssl x509 -in naval-lan-cert.pem -text -noout
# Tester la connexion HTTPS
curl -v https://myapp.naval.lan
# Voir la CA installée sur Linux
awk -v cmd='openssl x509 -noout -subject' '/BEGIN/{close(cmd)};{print | cmd}' < /etc/ssl/certs/ca-certificates.crt | grep -i naval
# Voir la CA installée sur Windows (PowerShell)
Get-ChildItem -Path Cert:\LocalMachine\Root | Where-Object {$_.Subject -like "*Naval*"}
# Obtenir l'IP ingress Traefik
kubectl get svc -n traefik traefik -o jsonpath='{.status.loadBalancer.ingress[0].ip}'
```
## Ressources supplémentaires
- [Documentation Traefik](https://doc.traefik.io/traefik/)
- [Documentation OpenSSL](https://www.openssl.org/docs/)
- [Secrets TLS Kubernetes](https://kubernetes.io/docs/concepts/configuration/secret/#tls-secrets)
---
**Créé** : 9 janvier 2026
**Dernière mise à jour** : 9 janvier 2026
+423
View File
@@ -0,0 +1,423 @@
# Setting Up HTTPS for naval.lan with Traefik (Kubernetes)
This guide explains how to set up HTTPS for your local domain `naval.lan` using Traefik in Kubernetes without certificate warnings on Windows and Linux clients.
## Overview
To avoid self-signed certificate warnings, you need to:
1. Create your own Certificate Authority (CA)
2. Generate SSL certificates signed by your CA
3. Configure Traefik to use these certificates
4. Install the CA certificate on all client machines
## Part 1: Create Your Own Certificate Authority
### 1.1. Generate CA Private Key and Certificate
On your Linux server or workstation:
```bash
# Create a directory for certificates
mkdir -p ~/certs/naval-ca
cd ~/certs/naval-ca
# Generate CA private key (4096-bit RSA)
openssl genrsa -out ca-key.pem 4096
# Generate CA certificate (valid for 10 years)
openssl req -new -x509 -days 3650 -key ca-key.pem -out ca-cert.pem \
-subj "/C=US/ST=State/L=City/O=Naval Local CA/OU=IT/CN=Naval Local Root CA"
```
**Important**: Keep `ca-key.pem` secure! This is your root CA private key.
## Part 2: Generate SSL Certificate for naval.lan
### 2.1. Create OpenSSL Configuration File
Create a file named `naval-lan.conf`:
```bash
cat > naval-lan.conf <<EOF
[req]
default_bits = 2048
prompt = no
default_md = sha256
req_extensions = req_ext
distinguished_name = dn
[dn]
C = US
ST = State
L = City
O = Naval Local
OU = IT Department
CN = *.naval.lan
[req_ext]
subjectAltName = @alt_names
[alt_names]
DNS.1 = naval.lan
DNS.2 = *.naval.lan
DNS.3 = localhost
IP.1 = 127.0.0.1
EOF
```
### 2.2. Generate Certificate Signing Request (CSR)
```bash
# Generate private key for naval.lan
openssl genrsa -out naval-lan-key.pem 2048
# Generate CSR
openssl req -new -key naval-lan-key.pem -out naval-lan.csr -config naval-lan.conf
```
### 2.3. Sign the Certificate with Your CA
```bash
# Sign the certificate (valid for 2 years)
openssl x509 -req -in naval-lan.csr -CA ca-cert.pem -CAkey ca-key.pem \
-CAcreateserial -out naval-lan-cert.pem -days 730 \
-extensions req_ext -extfile naval-lan.conf
# Verify the certificate
openssl x509 -in naval-lan-cert.pem -text -noout
```
## Part 3: Configure Traefik in Kubernetes
### 3.1. Create Kubernetes Secret with Certificates
```bash
# Create a namespace for Traefik (if not exists)
kubectl create namespace traefik --dry-run=client -o yaml | kubectl apply -f -
# Create secret with your certificates
kubectl create secret tls naval-lan-tls \
--cert=naval-lan-cert.pem \
--key=naval-lan-key.pem \
-n traefik
```
### 3.2. Update Traefik Configuration
Create or update your Traefik Helm values file (`traefik-values.yaml`):
```yaml
# traefik-values.yaml
additionalArguments:
- "--providers.kubernetescrd"
- "--entrypoints.websecure.http.tls=true"
- "--entrypoints.web.address=:80"
- "--entrypoints.websecure.address=:443"
ports:
web:
port: 80
exposedPort: 80
websecure:
port: 443
exposedPort: 443
tls:
enabled: true
# Mount the TLS certificate
volumes:
- name: naval-lan-tls
mountPath: "/certs"
type: secret
persistence:
enabled: true
```
### 3.3. Create IngressRoute for Your Services
Example IngressRoute configuration:
```yaml
apiVersion: traefik.containo.us/v1alpha1
kind: IngressRoute
metadata:
name: myapp-ingressroute
namespace: default
spec:
entryPoints:
- websecure
routes:
- match: Host(`myapp.naval.lan`)
kind: Rule
services:
- name: myapp-service
port: 80
tls:
secretName: naval-lan-tls
---
# Optional: HTTP to HTTPS redirect
apiVersion: traefik.containo.us/v1alpha1
kind: IngressRoute
metadata:
name: myapp-http-redirect
namespace: default
spec:
entryPoints:
- web
routes:
- match: Host(`myapp.naval.lan`)
kind: Rule
services:
- name: myapp-service
port: 80
middlewares:
- name: redirect-to-https
---
apiVersion: traefik.containo.us/v1alpha1
kind: Middleware
metadata:
name: redirect-to-https
namespace: default
spec:
redirectScheme:
scheme: https
permanent: true
```
### 3.4. Apply Traefik Configuration
```bash
# If using Helm
helm upgrade --install traefik traefik/traefik \
-n traefik \
-f traefik-values.yaml
# Apply IngressRoute
kubectl apply -f ingressroute.yaml
```
## Part 4: Install CA Certificate on Client Machines
### 4.1. Linux Clients
#### Ubuntu/Debian:
```bash
# Copy ca-cert.pem to your Linux client
sudo cp ca-cert.pem /usr/local/share/ca-certificates/naval-ca.crt
# Update CA certificates
sudo update-ca-certificates
# Verify
openssl s_client -connect myapp.naval.lan:443 -CAfile /usr/local/share/ca-certificates/naval-ca.crt
```
#### RHEL/CentOS/Fedora:
```bash
# Copy ca-cert.pem to your Linux client
sudo cp ca-cert.pem /etc/pki/ca-trust/source/anchors/naval-ca.crt
# Update CA certificates
sudo update-ca-trust
# Verify
openssl s_client -connect myapp.naval.lan:443
```
#### For Firefox (uses its own certificate store):
1. Open Firefox
2. Go to **Settings****Privacy & Security**
3. Scroll to **Certificates** → Click **View Certificates**
4. Go to **Authorities** tab
5. Click **Import**
6. Select `ca-cert.pem`
7. Check "Trust this CA to identify websites"
8. Click OK
### 4.2. Windows Clients
#### Method 1: Using MMC (Microsoft Management Console)
1. Copy `ca-cert.pem` to your Windows machine
2. Rename it to `ca-cert.crt` (optional, for easier recognition)
3. Right-click on `ca-cert.crt`**Install Certificate**
4. Choose **Local Machine** (requires admin rights)
5. Click **Next**
6. Select **Place all certificates in the following store**
7. Click **Browse** → Select **Trusted Root Certification Authorities**
8. Click **Next****Finish**
9. Click **Yes** on the security warning
#### Method 2: Using Command Line (Admin PowerShell)
```powershell
# Import certificate to Trusted Root CA store
Import-Certificate -FilePath "C:\path\to\ca-cert.pem" -CertStoreLocation Cert:\LocalMachine\Root
# Verify
Get-ChildItem -Path Cert:\LocalMachine\Root | Where-Object {$_.Subject -like "*Naval*"}
```
#### Method 3: Using certutil (Command Prompt as Admin)
```cmd
certutil -addstore -f "ROOT" ca-cert.pem
```
#### For Firefox on Windows:
Same steps as Linux Firefox above.
### 4.3. Verify Installation
#### Linux:
```bash
# Test with curl
curl -v https://myapp.naval.lan
# Test with openssl
openssl s_client -connect myapp.naval.lan:443 -showcerts
```
#### Windows:
```powershell
# Test with PowerShell
Invoke-WebRequest -Uri https://myapp.naval.lan
# Or use browser
# Navigate to https://myapp.naval.lan
```
## Part 5: DNS Configuration
Ensure your clients can resolve `naval.lan` domains:
### 5.1. Option 1: Local DNS Server (Recommended)
Set up a local DNS server (dnsmasq, Pi-hole, or Windows DNS) with:
```
*.naval.lan → [Traefik Ingress IP]
```
### 5.2. Option 2: Hosts File
#### Linux: `/etc/hosts`
```bash
sudo nano /etc/hosts
```
#### Windows: `C:\Windows\System32\drivers\etc\hosts` (as Administrator)
```
notepad C:\Windows\System32\drivers\etc\hosts
```
Add entries:
```
192.168.1.100 myapp.naval.lan
192.168.1.100 dashboard.naval.lan
```
Replace `192.168.1.100` with your Traefik ingress IP.
## Part 6: Certificate Renewal
Your certificates will expire. To renew:
```bash
cd ~/certs/naval-ca
# Generate new CSR (or reuse existing key)
openssl req -new -key naval-lan-key.pem -out naval-lan-new.csr -config naval-lan.conf
# Sign with CA
openssl x509 -req -in naval-lan-new.csr -CA ca-cert.pem -CAkey ca-key.pem \
-CAcreateserial -out naval-lan-cert-new.pem -days 730 \
-extensions req_ext -extfile naval-lan.conf
# Update Kubernetes secret
kubectl create secret tls naval-lan-tls \
--cert=naval-lan-cert-new.pem \
--key=naval-lan-key.pem \
-n traefik \
--dry-run=client -o yaml | kubectl apply -f -
# Restart Traefik pods to reload certificate
kubectl rollout restart deployment traefik -n traefik
```
## Troubleshooting
### Certificate not trusted after installation
- **Clear browser cache**: Some browsers cache certificate validation
- **Restart browser**: Required for Chrome/Edge on Windows
- **Check certificate chain**: `openssl s_client -connect myapp.naval.lan:443 -showcerts`
### "NET::ERR_CERT_AUTHORITY_INVALID" error
- Verify CA certificate is in the correct store
- On Windows, ensure it's in "Trusted Root Certification Authorities", not "Intermediate"
- Check that the certificate's Subject Alternative Names include your domain
### Firefox still shows warning
- Firefox uses its own certificate store on all platforms
- Must import CA certificate directly into Firefox
### Certificate expired
- Check certificate validity: `openssl x509 -in naval-lan-cert.pem -noout -dates`
- Follow renewal steps in Part 6
## Security Considerations
1. **Protect your CA private key** (`ca-key.pem`):
- Store it securely
- Consider encrypting it with a passphrase
- Keep backups in secure locations
2. **Certificate validity period**:
- Don't make it too long (2 years max recommended)
- Set up calendar reminders for renewal
3. **Access control**:
- Only install the CA certificate on machines you control
- Don't share your CA private key
4. **Network isolation**:
- Keep your `.lan` domain isolated from the internet
- Use firewall rules to prevent external access
## Quick Reference Commands
```bash
# Check certificate details
openssl x509 -in naval-lan-cert.pem -text -noout
# Test HTTPS connection
curl -v https://myapp.naval.lan
# View installed CA on Linux
awk -v cmd='openssl x509 -noout -subject' '/BEGIN/{close(cmd)};{print | cmd}' < /etc/ssl/certs/ca-certificates.crt | grep -i naval
# View installed CA on Windows (PowerShell)
Get-ChildItem -Path Cert:\LocalMachine\Root | Where-Object {$_.Subject -like "*Naval*"}
# Get Traefik ingress IP
kubectl get svc -n traefik traefik -o jsonpath='{.status.loadBalancer.ingress[0].ip}'
```
## Additional Resources
- [Traefik Documentation](https://doc.traefik.io/traefik/)
- [OpenSSL Documentation](https://www.openssl.org/docs/)
- [Kubernetes TLS Secrets](https://kubernetes.io/docs/concepts/configuration/secret/#tls-secrets)
---
**Created**: January 9, 2026
**Last Updated**: January 9, 2026
File diff suppressed because one or more lines are too long
Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.1 KiB

File diff suppressed because one or more lines are too long
Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.9 KiB

+9
View File
@@ -0,0 +1,9 @@
(function(w,d,c,k,a,b,t,e,h,s) {
var cs = d.currentScript;
if (cs) {
var uo = cs.getAttribute('data-ueto');
if (uo && w[uo] && typeof w[uo].setUserSignals === 'function') {
w[uo].setUserSignals({'ea': c, 'kc': k, 'at': a, 'bi': b, 'pt': t, 'ec': e, 'ah': h, 'sb': s});
}
}
})(window, document, false, false, true, false, false, true, true, false);
Binary file not shown.

After

Width:  |  Height:  |  Size: 638 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 554 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 738 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 KiB

@@ -0,0 +1 @@
(function(){"use strict";function a(a){const b=new RegExp("(^|;)\\s*"+a+"\\s*=\\s*([^;]*)\\s*(;|$)").exec(window.document.cookie);return b?decodeURIComponent(b[2]):null}function b({key:a,expires:b,domain:c,value:d}){const e=c&&""!==c?";domain="+encodeURIComponent(c):"",f=b&&"number"==typeof b?";expires="+new Date(new Date().getTime()+b).toUTCString():"";document.cookie=a+"="+encodeURIComponent(d)+f+";path=/"+e+";SameSite=None;Secure"}function c(a){return window.localStorage.getItem(a)}function d(a,b){window.localStorage.setItem(a,b)}function e(a){return window.sessionStorage.getItem(a)}function f(a,b){window.sessionStorage.setItem(a,b)}function g(a){window.localStorage.removeItem(a),window.sessionStorage.removeItem(a)}function h(b){const d=e(b);return d?d:a(b)||c(b)}function i({key:a,value:c,expires:e,domain:g}){a&&c&&(b({key:a,value:c,expires:e,domain:g}),d(a,c),f(a,c))}function j(a){try{return null===a?null:JSON.parse(a)}catch{return null}}function k(){const a="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789".length;let b="";for(let c=0;20>c;c++)b+="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789".charAt(Math.floor(Math.random()*a));return b}function l(a){return"function"==typeof a?a:()=>{}}function m(a){return!a?.url||!a?.type}function n(a,b){return a.reduce((a,c)=>{const d=c.hash?c.hash:b;return d?(a[d]||(a[d]=[]),a[d].push(c),a):a},{})}function o(){const a=window[F].find(a=>a.eventType&&"init"===a.eventType);return a||null}function p(a=null){return a?.value?a.value:null}function q(a=null){return a?.dc&&["ams","us","phx","sin","ash","asia"].includes(a.dc)?a.dc:"ams"}function r(a){try{const b=JSON.parse(a),c=Array.isArray(b)?b:[];for(const a of c){const b=m(a);if(!b)if("img"===(a.type+"").toLowerCase()){const b=new Image;b.src=a.url,b.setAttribute("width","1"),b.setAttribute("height","1"),b.setAttribute("scrolling","no"),b.setAttribute("frameBorder","0"),b.setAttribute("style","display:none"),document.body.appendChild(b)}else if("iframe"===(a.type+"").toLowerCase()){const b=document.createElement("iframe");b.onload=()=>{setTimeout(()=>b.parentNode?.removeChild(b),3e4)},b.setAttribute("width","1"),b.setAttribute("height","1"),b.setAttribute("scrolling","no"),b.setAttribute("frameBorder","0"),b.setAttribute("style","display:none"),b.setAttribute("src",a.url),document.body.appendChild(b)}}}catch{}}function s(a){return!!a&&new Date(a)<new Date}function t(a){if(!a)return!1;const b=j(a);return!("string"!=typeof b?.expiryDate)&&s(b.expiryDate)}function u(){return new Date(new Date().getTime()+J).toISOString()}function v(a,b=null){const c=document.referrer?document.referrer:"";return{v:K,sr:c,su:location.href,th:b?b:a}}function w(){const a=[];for(const b of I){const c=h(G+b),d=j(c);d?.eventType&&a.push(d)}return a}function x(a,b){a.forEach(a=>{b.test(a?.eventType+"")&&i({key:G+a.eventType,value:JSON.stringify({...a,expiryDate:u()}),expires:J})})}function y(){const a=w();for(const b of a){if(b&&!b.expiryDate){i({key:G+b.eventType,value:JSON.stringify({...b,expiryDate:u()}),expires:J});continue}if(H.includes(b?.eventType)&&s(b?.expiryDate)){const a=G+b.eventType;g(a)}}const b=h("__rtbh.lid"),c=t(b);if(!b||c)i({key:"__rtbh.lid",value:JSON.stringify({eventType:"lid",id:k(),expiryDate:u()}),expires:J});else{const a=j(b);a?.expiryDate&&i({key:"__rtbh.lid",value:JSON.stringify({...a,expiryDate:u()}),expires:J})}}function z(){for(const a of I){const b=G+a,c=h(`__rtbhouse.${a}`),d=h(b),e=window[F].find(b=>b.eventType===a&&b.id);if(e&&i({key:b,value:JSON.stringify(e),expires:J}),!d&&c&&!c.includes("eventType")){i({key:G+a,value:JSON.stringify({eventType:a,id:c}),expires:J})}}}async function A(a,b,c,d){try{const e=l(c),f=await fetch(a,b),g=f.status;if(200<=g&&300>g)return e(d?await f.json():await f.text(),f)}catch{}}function B(a,b,c){try{const d=n(a,c),e=Object.keys(d),f=w();for(const a of e)b&&b(r,d[a],f,a)}catch{}}function C(a,b,c){if(null===a)return;return function(d,e,f,g=null){const h=e.filter(a=>!b.includes(a.eventType)&&"init"!==a.eventType);return A(`https://${c}.creativecdn.com/tags/v2?type=json`,{method:"POST",mode:"cors",credentials:"include",referrerPolicy:"no-referrer-when-downgrade",headers:{"Content-Type":"application/json"},redirect:"follow",body:JSON.stringify({...v(a,g),tags:[...h,...f]})},d)}}function D(){const a=o(),b=q(a),c=p(a),d=C(c,I,b);return{taggingHash:c,sendTags:d}}function E(a,b){const c=new RegExp(`^(${I.join("|")})$`);return function(...d){try{if(x(d,c),null===a){const{taggingHash:c,sendTags:d}=D();a=c,b=d}return Array.prototype.push.apply(this,d),B(d,b,a),!0}catch{return!1}}}const F="rtbhEvents",G="__rtbh.",H=["uid","sid","aid","eid"],I=[...H,"lid"],J=31536000000,K="v0.2.1";(function(){if(Array.isArray(window[F])||(window[F]=[]),window[F].length&&!window[F].push.prototype)try{const{taggingHash:a,sendTags:b}=D();z(),y(),B(window[F],b,a),window[F].push=E(a,b)}catch{}})()})();
@@ -0,0 +1 @@
<svg width="29" height="29" xmlns="http://www.w3.org/2000/svg"><g fill="none" fill-rule="evenodd"><path d="M-9-9h48v48H-9z"/><path d="M14.728 12.607L26.395.939a1.5 1.5 0 1 1 2.122 2.122L16.849 14.728l11.668 11.667a1.5 1.5 0 0 1-2.122 2.122L14.728 16.849 3.06 28.517a1.5 1.5 0 0 1-2.122-2.122l11.668-11.667L.939 3.06A1.5 1.5 0 0 1 3.061.939l11.667 11.668z" fill-opacity=".54" fill="#000" fill-rule="nonzero"/></g></svg>

After

Width:  |  Height:  |  Size: 418 B

+2
View File
@@ -0,0 +1,2 @@
<html><head>
<meta http-equiv="content-type" content="text/html; charset=UTF-8"><script src="prompt.js"></script></head><body></body></html>
+2
View File
@@ -0,0 +1,2 @@
<html><head>
<meta http-equiv="content-type" content="text/html; charset=UTF-8"><script src="prompt.js"></script></head><body><iframe height="0" width="0" style="display: none; visibility: hidden;" src="a_data_002/sw_iframe.htm"></iframe></body></html>
@@ -0,0 +1,21 @@
<!DOCTYPE html>
<html><head>
<meta http-equiv="content-type" content="text/html; charset=windows-1252">
<link rel="shortcut icon" href="data:image/x-icon;," type="image/x-icon">
<script src="../prompt.js"></script></head>
<body>
<script>
'use strict';var m={};class n{constructor(a){this.j=a;this.g={};this.h={};this.i=0;this.id=String(Math.floor(Number.MAX_SAFE_INTEGER*Math.random()))}}function p(a){return a.performance&&a.performance.now()||Date.now()}
var q=function(a,c){class d{constructor(b,f,g){this.failureType=b;this.data=f;this.g=g;this.h=new n(p(g))}u(b,f){const g=b.clientId;if(b.type===0){b.isDead=!0;var e=this.h,h=p(this.g);e.g[g]==null&&(e.g[g]=0,e.h[g]=h,e.i++);e.g[g]++;b.stats={targetId:e.id,clientCount:e.i,totalLifeMs:Math.round(h-e.j),heartbeatCount:e.g[g],clientLifeMs:Math.round(h-e.h[g])}}b.failure={failureType:this.failureType,data:this.data};f(b)}}return new d(5,a,c)};/*
Copyright Google LLC
SPDX-License-Identifier: Apache-2.0
*/
let r=globalThis.trustedTypes,t;function u(){let a=null;if(!r)return a;try{const c=d=>d;a=r.createPolicy("goog#html",{createHTML:c,createScript:c,createScriptURL:c})}catch(c){}return a};var v=class{constructor(a){this.g=a}toString(){return this.g+""}};function w(a){const c=a;var d;t===void 0&&(t=u());var b=(d=t)?d.createScriptURL(c):c;return new v(b)}function x(a){if(a instanceof v)return a.g;throw Error("");};function y(a,...c){if(c.length===0)return w(a[0]);let d=a[0];for(let b=0;b<c.length;b++)d+=encodeURIComponent(c[b])+a[b+1];return w(d)}function z(a){var c=y`sw.js`,d=x(c).toString();const b=d.split(/[?#]/),f=/[?]/.test(d)?"?"+b[1]:"";return A(b[0],f,/[#]/.test(d)?"#"+(f?b[2]:b[1]):"",a)}
function A(a,c,d,b){function f(e,h){e!=null&&(Array.isArray(e)?e.forEach(l=>f(l,h)):(c+=g+encodeURIComponent(h)+"="+encodeURIComponent(e),g="&"))}let g=c.length?"&":"?";b.constructor===Object&&(b=Object.entries(b));Array.isArray(b)?b.forEach(e=>f(e[1],e[0])):b.forEach(f);return w(a+c+d)};const B=/Chrome\/(\d+)/;var D=function(a){const c=a.origin;if(c){var d=a.o?"swe.js":"sw.js",b=a.g?y`/static/service_worker/${a.g}/${d}?origin=${c}`:y`/gtm/static/${d}?origin=${c}`,f=new Map([["origin",c]]);a.h&&f.set("path",a.h);var g=a.l?z(f):b,e=()=>{const k=B.exec(a.window.navigator.userAgent);return k&&Number(k[1])<119},h=a.window.document.location.href;a.g&&(a.l?h=`${a.h}/_/service_worker`:e()||(h="/static/service_worker"));var l={scope:h};a.g&&(l.updateViaCache="all");a.window.navigator.serviceWorker.register(x(g),
l).then(()=>{a.window.navigator.serviceWorker.ready.then(k=>{a.i=k.active;C(a)})},k=>{a.j=q(k==null?void 0:k.toString(),a.window);C(a)});a.window.navigator.serviceWorker.addEventListener("message",k=>{a.window.parent.postMessage(k.data,a.origin)})}},C=function(a){const c=a.m.slice();a.m=[];for(const d of c)a.handleEvent(d)};
(new class{constructor(a){this.window=a;this.origin="";this.o=this.l=!1;this.h="";this.j=this.i=null;this.m=[];this.g=""}init(){if((f=>{try{return f!==f.top}catch(g){return!0}})(this.window)){var a=new URL(this.window.document.location.href),c=a.searchParams.get("origin");if(c){this.origin=c;this.l=!!a.searchParams.get("1p");this.o=!!a.searchParams.get("e");this.h=a.searchParams.get("path")||"";var d=a.pathname.match(RegExp(".*/service_worker/(\\w+)/"));d&&d.length&&(this.g=d[1]);var b=this.window.document.location.ancestorOrigins;
b&&b[0]!==this.origin||(D(this),this.window.addEventListener("message",f=>{this.handleEvent(f)}))}}}handleEvent(a){a.origin===this.origin&&(this.i?this.i.postMessage(a.data):this.j?this.j.u(a.data,c=>{this.window.parent.postMessage(c,this.origin)}):this.m.push(a))}}(window)).init();
</script>
</body></html>
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -0,0 +1 @@
!function(t){var n="https://",e="aHR0cHM6Ly9waXBzLnRhYm9vbGEuY29t",r=["YXJjaGl0ZWN0dXJl","cGxhdGZvcm1WZXJzaW9u","dWFGdWxsVmVyc2lvbg=="],a=["YnJhbmRz","bW9iaWxl","bW9kZWw=","cGxhdGZvcm0=","cGxhdGZvcm1WZXJzaW9u","dWFGdWxsVmVyc2lvbg=="],s="dc";function o(){return"currentScript"in t.document&&t.document.currentScript&&"src"in t.document.currentScript&&"URL"in t&&"parse"in t.URL}function i(){var n=null;if(o()){var e=t.URL.parse(t.document.currentScript.src);e&&(n=e.searchParams)}return n||{get:function t(){return null}}}function c(){return{get:function t(){return null}}}function u(t){return t?"&dc=".concat(t):""}try{t.TRC.cdsPips={userId:null,getHttpsPrefix:function t(){return n},doNothing:function t(){return!0},safeGetTfaConfig:function n(e,r,a){return t._tfa&&t._tfa.config&&t._tfa.config.safeGet&&t._tfa.config.safeGet(e,r,a)},safeGetRboxConfig:function t(n){var e;return(TRCImpl?TRCImpl.global:{})[n]},prepareGenericRequest:function n(e,r){var a,s=new(t.XDomainRequest||t.XMLHttpRequest);return s.open(e,r),s.onload=this.doNothing,s.onerror=this.doNothing,s.onprogress=this.doNothing,s},tryToReadUserIdFromLocalStorage:function t(){try{return window.localStorage["taboola global:user-id"]}catch(t){return null}},getUserId:function n(){var e=t.TFASC&&t.TFASC.tfaUserId&&"function"==typeof t.TFASC.tfaUserId.getUserId?t.TFASC.tfaUserId.getUserId():null,r=t.TRC.pageManager&&"function"==typeof t.TRC.pageManager.getUserId?t.TRC.pageManager.getUserId():null,a=TRC.cdsPips.tryToReadUserIdFromLocalStorage();return e||r||a},sendFinalReq:function n(e,r){var a="".concat(this.getHttpsPrefix(),"cds.taboola.com?uid=").concat(this.userId),s;(null!==e[0]&&(a+="&uad=".concat(e[0])),e[1]&&(e[1].platform&&(a+="&ptf=".concat(t.btoa(e[1].platform)),e[1].platformVersion&&(a+="&ptfv=".concat(t.btoa(e[1].platformVersion)))),e[1].model&&(a+="&mdl=".concat(t.btoa(e[1].model))),e[1].uaFullVersion&&(a+="&ufv=".concat(t.btoa(e[1].uaFullVersion))),e[1].brands&&(a+=this.parseFullVersionList(e[1].brands)),"mobile"in e[1]&&(a+="&mbl=".concat(t.btoa(e[1].mobile)))),(a+=u(r))!=="".concat(this.getHttpsPrefix(),"cds.taboola.com?uid=").concat(this.userId))&&this.prepareGenericRequest("GET",a).send()},parseFullVersionList:function n(e){for(var r="",a=0;a<e.length;a++)r+="&bnd=".concat(t.btoa(e[a].brand),"&bndv=").concat(t.btoa(e[a].version));return r},sendSimpleReq:function t(n){var e="".concat(this.getHttpsPrefix(),"cds.taboola.com?uid=").concat(this.userId).concat(u(n)),r;this.prepareGenericRequest("GET",e).send()},fetchUserAgentData:function n(){return new Promise(function(n){try{navigator&&navigator.userAgentData&&navigator.userAgentData.getHighEntropyValues?navigator.userAgentData.getHighEntropyValues(r.map(function(n){return t.atob(n)})).then(function(e){var r={};a.forEach(function(n){var a=t.atob(n);a in e&&(r[a]=e[a])}),Object.keys(r).length>0?n(r):n(null)}):n(null)}catch(t){n(null)}})},sendUadRequest:function n(){var r=this;return new Promise(function(n,a){if(r.safeGetTfaConfig("cds:send-uad-req",!1)||r.safeGetRboxConfig("cds:send-uad")){var s=r.prepareGenericRequest("GET",t.atob(e));s.onreadystatechange=function(){if(4===this.readyState)if(200===this.status){var t=s.responseText;t?n("NULL"!==t?t:null):(__trcWarn("cds: error in pips - status ".concat(this.status,", return null")),n(null))}else __trcWarn("cds: error in pips - status ".concat(this.status,", return null")),n(null)},s.timeout=3e4,s.responseType="text",s.ontimeout=function(){__trcWarn("cds: error in pips - timeout"),n(null)},s.send()}else n(null)})},init:function n(){var e=this,r,a=i().get(s);t.TRC.cdsPips.cdsInitialized||(t.Promise?(t.__trcWarn=t.__trcWarn||function t(){},this.userId=this.getUserId(),this.userId&&Promise.all([this.sendUadRequest(),this.fetchUserAgentData()]).then(function(t){return e.sendFinalReq(t,a)},function(){return e.sendSimpleReq(a)}),t.TRC.cdsPips.cdsInitialized=!0):t.TRC.cdsPips.cdsInitialized=!0)}},window._trcIsUTactive&&(t.TRC.cdsPips.unitestsHelpers={parseQueryParams:i}),t.TRC.cdsPips.init()}catch(t){__trcError("Error running cds",t)}}(window);
+1
View File
@@ -0,0 +1 @@
!function(i){var t={};function c(n){var e;return(t[n]||(e=t[n]={i:n,l:!1,exports:{}},i[n].call(e.exports,e,e.exports,c),e.l=!0,e)).exports}c.m=i,c.c=t,c.d=function(n,e,i){c.o(n,e)||Object.defineProperty(n,e,{enumerable:!0,get:i})},c.r=function(n){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(n,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(n,"u",{value:!0})},c.t=function(e,n){if(1&n&&(e=c(e)),8&n)return e;if(4&n&&"object"==typeof e&&e&&e.u)return e;var i=Object.create(null);if(c.r(i),Object.defineProperty(i,"default",{enumerable:!0,value:e}),2&n&&"string"!=typeof e)for(var t in e)c.d(i,t,function(n){return e[n]}.bind(null,t));return i},c.n=function(n){var e=n&&n.u?function(){return n.default}:function(){return n};return c.d(e,"a",e),e},c.o=function(n,e){return Object.prototype.hasOwnProperty.call(n,e)},c.p="",c(c.s=2)}([function(n,e){var i,t,c={};c.LIST={DERIVED_EPIK:{chance:100,uri:"pin-derived-epik"},SCRAPE_LISTENERS:{chance:100,uri:"pin-scrape-listeners"},SEND_LOGS:{chance:100,uri:"pin-log-errors"},CHECK_CSP:{chance:5,uri:"pin-check-csp"},DEDUPE_AEM_ELIGIBLE_ARRAY:{chance:100,uri:"pin-dedupe-aem-eligible-array"},CHECK_AUTO_UPGRADED:{chance:100,uri:"pin-check-auto-upgraded"},CHECK_DOCUMENT_COOKIE:{chance:0,uri:"pin-check-document-cookie"},SEND_TO_STAGING:{chance:0,uri:"pin-send-to-staging"},CHROME_TRIAL_EPIK_LOCALSTORAGE:{chance:100,uri:"pin-trial-epik-localstorage"},NO_CODE_CAPI_ENABLED:{chance:100,uri:"nocodecapi-enabled"},IAB_IOS_REFERRER_ENABLED:{chance:100,uri:"iab-ios-referrer-enabled"}};for([i,t]of Object.entries(c.LIST))"true"===new URLSearchParams(window.location.search).get(t.uri)&&(c.LIST[i].chance=100);c.isInRampPercentage=function(n){return 100*Math.random()<(n||0)},n.exports=c},function(n,e,i){let t=i(0);var c={},o="unknown";function a(n){n.version=o,100*Math.random()<(t.LIST.SEND_LOGS.chance||0)&&c._(n)}c.setVersion=function(n){o=n},c._=function(n){var e=new window.XMLHttpRequest;e.withCredentials=!1,e.onerror=function(){console.info("Error message failed to send")},e.open("POST","https://ct.pinterest.com/stats/",!1),e.setRequestHeader("Content-Type","application/json"),e.send(JSON.stringify(n))},c.error=function(n,e){var i={messageType:"ERROR",message:n,log:"[".concat(2<arguments.length&&void 0!==arguments[2]?arguments[2]:"Empty","]")};e.hasOwnProperty("stack")?i.log+="[".concat(e.stack,"]"):i.log+="[".concat(e.message,"]"),a(i)},c.info=function(n,e){a({messageType:"INFO",message:n,log:"[".concat(2<arguments.length&&void 0!==arguments[2]?arguments[2]:"Empty","][").concat(e,"]")})},n.exports=c},function(n,e,i){{var t=document,c=i(0);let n=i(1),e=i(3);(i=t.createElement("script")).async=!0,n.setVersion("e258cfd2"),c.isInRampPercentage(c.LIST.SEND_LOGS.chance)&&(i.onerror=function(){n.error("Failed to load ".concat("e258cfd2"),new Error("failed to load main.js"))}),c.isInRampPercentage(c.LIST.CHECK_CSP.chance)&&(document.onsecuritypolicyviolation=function(n){e.sendEventInfo(n)}),i.src="https://s.pinimg.com/ct/lib/main.e258cfd2.js",(c=t.getElementsByTagName("script")[0]).parentNode.insertBefore(i,c)}},function(n,e,i){var t={};let c=i(1);const o=/https?:\/\/s\.pinimg\.com\/ct\/lib\/main\.[0-9a-f]{8}\.js/g;t.sendEventInfo=function(e){if(e&&e.blockedURI&&"https://s.pinimg.com/ct/lib/main.e258cfd2.js"===e.blockedURI){let n="Directive: "+e.effectiveDirective+" Disposition: "+e.disposition+" Blocked URI: "+e.blockedURI;var i;e.originalPolicy?(i=t.v(e.originalPolicy))&&0<i.length?(n+=" main file(s) allowed: "+i.join(" "),c.info("csp violation main file(s) allowed - "+e.disposition,n)):c.info("csp violation no main file allowed - "+e.disposition,n):c.info("csp violation original policy not available",n)}},t.v=function(n){return n?n.match(o):null},n.exports=t}]);
File diff suppressed because one or more lines are too long
+1
View File
@@ -0,0 +1 @@
window.goldlog=(window.goldlog||{});goldlog.Etag="EkCwIfpA7mMCAVvZmpQm0ol4";goldlog.stag=1;
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -0,0 +1,2 @@
#J_xiaomi_dialog{padding-top:72px}#J_xiaomi_dialog .J_strong{overflow:visible!important}#J_xiaomi_dialog .J_strong .alime-question-list li{margin-left:0;padding-left:30px;font-size:12px;line-height:20px}#J_xiaomi_dialog .J_strong .alime-strong-header img{display:none;width:72px!important;height:72px;position:absolute;top:-72px;left:50%;transform:translateX(-50%);-ms-transform:translateX(-50%)}#J_xiaomi_dialog .J_weak{overflow:visible!important;position:relative}#J_xiaomi_dialog .J_weak img{width:48px!important;height:48px;position:absolute;top:-48px;left:50%;transform:translateX(-50%);-ms-transform:translateX(-50%)}
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -0,0 +1 @@
.slick-list,.slick-slider,.slick-track{position:relative;display:block}.slick-loading .slick-slide,.slick-loading .slick-track{visibility:hidden}.slick-slider{box-sizing:border-box;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;-webkit-touch-callout:none;-khtml-user-select:none;-ms-touch-action:pan-y;touch-action:pan-y;-webkit-tap-highlight-color:transparent}.slick-list{overflow:hidden;margin:0;padding:0}.slick-list:focus{outline:0}.slick-list.dragging{cursor:pointer;cursor:hand}.slick-slider .slick-list,.slick-slider .slick-track{-ms-transform:translateZ(0);transform:translateZ(0)}.slick-track{top:0;left:0}.slick-track:after,.slick-track:before{display:table;content:""}.slick-track:after{clear:both}.slick-slide{display:none;float:left;height:100%;min-height:1px}[dir=rtl] .slick-slide{float:right}.slick-slide img{display:block}.slick-slide.slick-loading img{display:none}.slick-slide.dragging img{pointer-events:none}.slick-initialized .slick-slide{display:block}.slick-vertical .slick-slide{display:block;height:auto;border:1px solid transparent}.slick-arrow.slick-hidden{display:none}.slick-dots,.slick-next,.slick-prev{position:absolute;display:block;padding:0;z-index:99}.slick-dots li button:before,.slick-next:before,.slick-prev:before{font-family:slick;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.slick-next,.slick-prev{top:50%;-ms-transform:translateY(-50%);transform:translateY(-50%);cursor:pointer;border:none;outline:0;transition:all .4s ease-in-out;overflow:hidden}.slick-next-default,.slick-prev-default{font-size:0;line-height:0;width:30px;height:50px;color:transparent;background:rgba(0,0,0,.25)}.slick-next-default:focus,.slick-next-default:hover,.slick-prev-default:focus,.slick-prev-default:hover{color:transparent;outline:0;background:rgba(0,0,0,.5)}.slick-next-default:before,.slick-prev-default:before{content:" ";position:absolute;top:0;left:0;width:60px;height:50px;background:url(//ae01.alicdn.com/kf/H3a2170950d3848dd85531682a4dc5ef21.png) no-repeat}.slick-prev{left:0}[dir=rtl] .slick-prev{right:0;left:auto}.slick-next-default:before,[dir=rtl] .slick-prev-default:before{left:-30px}.slick-next{right:0}[dir=rtl] .slick-next{right:auto;left:0}.slick-prev-default.slick-outer{left:-40px}[dir=rtl] .slick-prev-default.slick-outer{right:-40px;left:auto}.slick-next-default.slick-outer{right:-40px}[dir=rtl] .slick-next-default.slick-outer{right:auto;left:-40px}.slick-next-default.slick-disabled,.slick-next-default.slick-disabled:hover,.slick-prev-default.slick-disabled,.slick-prev-default.slick-disabled:hover{background:rgba(0,0,0,.13);cursor:not-allowed}.slick-dotted.slick-slider{margin-bottom:30px}.slick-dots{bottom:0;width:100%;margin:0;list-style:none;text-align:center}.slick-dots li{position:relative;display:inline-block;margin:0 5px;padding:0}.slick-dots li,.slick-dots li button{width:20px;height:20px;cursor:pointer}.slick-dots li button{font-size:0;line-height:0;display:block;padding:5px;color:transparent;border:0;outline:0;background:0 0}.slick-dots li button:focus,.slick-dots li button:hover{outline:0}.slick-dots li button:before{content:" ";position:absolute;top:0;left:0;width:10px;height:10px;border-radius:50%;text-align:center;background:#fff}.slick-dots li.slick-active button:before{opacity:1;background:#ff4747}
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
+276
View File
@@ -0,0 +1,276 @@
/*
* Copyright 2017 SideeX committers
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
const originalPrompt = window.prompt
let nextPromptResult = false
let recordedPrompt = null
const originalConfirmation = window.confirm
let nextConfirmationResult = false
let recordedConfirmation = null
const originalAlert = window.alert
let recordedAlert = null
function getFrameLocation() {
let frameLocation = ''
let currentWindow = window
let currentParentWindow
while (currentWindow !== window.top) {
currentParentWindow = currentWindow.parent
for (let idx = 0; idx < currentParentWindow.frames.length; idx++)
if (currentParentWindow.frames[idx] === currentWindow) {
frameLocation = ':' + idx + frameLocation
currentWindow = currentParentWindow
break
}
}
frameLocation = 'root' + frameLocation
return frameLocation
}
//before record prompt
// Not a top window
if (window !== window.top) {
window.prompt = function(text, defaultText) {
if (document.body.hasAttribute('SideeXPlayingFlag')) {
return window.top.prompt(text, defaultText)
} else {
let result = originalPrompt(text, defaultText)
let frameLocation = getFrameLocation()
window.top.postMessage(
{
direction: 'from-page-script',
recordedType: 'prompt',
recordedMessage: text,
recordedResult: result,
frameLocation: frameLocation,
},
'*'
)
return result
}
}
window.confirm = function(text) {
if (document.body.hasAttribute('SideeXPlayingFlag')) {
return window.top.confirm(text)
} else {
let result = originalConfirmation(text)
let frameLocation = getFrameLocation()
window.top.postMessage(
{
direction: 'from-page-script',
recordedType: 'confirm',
recordedMessage: text,
recordedResult: result,
frameLocation: frameLocation,
},
'*'
)
return result
}
}
window.alert = function(text) {
if (document.body.hasAttribute('SideeXPlayingFlag')) {
recordedAlert = text
// Response directly
window.top.postMessage(
{
direction: 'from-page-script',
response: 'alert',
value: recordedAlert,
},
'*'
)
return
} else {
let result = originalAlert(text)
let frameLocation = getFrameLocation()
window.top.postMessage(
{
direction: 'from-page-script',
recordedType: 'alert',
recordedMessage: text,
recordedResult: result,
frameLocation: frameLocation,
},
'*'
)
return result
}
}
} else {
// top window
window.prompt = function(text, defaultText) {
recordedPrompt = text
if (document.body.hasAttribute('setPrompt')) {
document.body.removeAttribute('setPrompt')
return nextPromptResult
} else {
let result = originalPrompt(text, defaultText)
let frameLocation = getFrameLocation()
window.top.postMessage(
{
direction: 'from-page-script',
recordedType: 'prompt',
recordedMessage: text,
recordedResult: result,
frameLocation: frameLocation,
},
'*'
)
return result
}
}
window.confirm = function(text) {
recordedConfirmation = text
if (document.body.hasAttribute('setConfirm')) {
document.body.removeAttribute('setConfirm')
return nextConfirmationResult
} else {
let result = originalConfirmation(text)
let frameLocation = getFrameLocation()
window.top.postMessage(
{
direction: 'from-page-script',
recordedType: 'confirm',
recordedMessage: text,
recordedResult: result,
frameLocation: frameLocation,
},
'*'
)
return result
}
}
window.alert = function(text) {
recordedAlert = text
if (document.body.hasAttribute('SideeXPlayingFlag')) {
// Response directly
window.top.postMessage(
{
direction: 'from-page-script',
response: 'alert',
value: recordedAlert,
},
'*'
)
return
} else {
let result = originalAlert(text)
let frameLocation = getFrameLocation()
window.top.postMessage(
{
direction: 'from-page-script',
recordedType: 'alert',
recordedMessage: text,
recordedResult: result,
frameLocation: frameLocation,
},
'*'
)
return result
}
}
}
//play window methods
if (window == window.top) {
window.addEventListener('message', handler)
}
function handler(event) {
if (
event.source == window &&
event.data &&
event.data.direction == 'from-content-script'
) {
if (event.data.detach) {
window.removeEventListener('message', handler)
window.prompt = originalPrompt
window.confirm = originalConfirmation
window.alert = originalAlert
return
}
let result = undefined
switch (event.data.command) {
case 'setNextPromptResult':
nextPromptResult = event.data.target
document.body.setAttribute('setPrompt', true)
window.postMessage(
{
direction: 'from-page-script',
response: 'prompt',
},
'*'
)
break
case 'getPromptMessage':
result = recordedPrompt
recordedPrompt = null
window.postMessage(
{
direction: 'from-page-script',
response: 'prompt',
value: result,
},
'*'
)
break
case 'setNextConfirmationResult':
nextConfirmationResult = event.data.target
document.body.setAttribute('setConfirm', true)
window.postMessage(
{
direction: 'from-page-script',
response: 'confirm',
},
'*'
)
break
case 'getConfirmationMessage':
result = recordedConfirmation
recordedConfirmation = null
try {
window.postMessage(
{
direction: 'from-page-script',
response: 'confirm',
value: result,
},
'*'
)
} catch (e) {} // eslint-disable-line no-empty
break
case 'setNextAlertResult':
document.body.setAttribute('setAlert', true)
window.postMessage(
{
direction: 'from-page-script',
response: 'alert',
},
'*'
)
break
}
}
}
@@ -0,0 +1 @@
(window["webpackJsonp-ae-fe/cosmos-1"]=window["webpackJsonp-ae-fe/cosmos-1"]||[]).push([[38],{1245:function(e,r,n){"use strict";n.r(r);var t=n(36),o=n(7);r.default=function(){var e,r,n=function(e){return e.replace(/</g,"&lt;").replace(/"/g,"&quot;")},i=n(window.location.search),a=function(){if(!document.referrer)return"";try{return new URL(document.referrer).host}catch(e){console.error(e)}return""}();if(/isdl=y/.test(i)||/aff_short_key=/.test(i)||/(google|bing|yahoo|yandex|baidu|naver|msn|rambler)/.test(null==a?void 0:a.toLowerCase())){var c,d=window.location.href,s=encodeURIComponent(n(d.substring(0,Math.min(1e3,d.indexOf("?"))))),l=[];a&&l.push("__referer__="+a),window.dmtrack_pageid&&l.push("__page_id__="+window.dmtrack_pageid),s&&l.push("current_url="+s),e="//s.click.aliexpress.com/direct_landing.htm"+(c=i?i+"&":"?")+l.join("&"),(r=document.createElement("img")).src=e,r.alt="affiliate",r.style.display="none",document.body.appendChild(r),r.addEventListener("load",(function(){document.body.removeChild(r)})),function(e){t.a.request({api:"mtop.aliexpress.traffic.web.direct.landing.click.report",v:"1.0",type:"GET",data:{browserId:o.a.get("xman_us_f","acs_rt"),currentUrl:e}})}("//s.click.aliexpress.com/direct_landing.htm"+c+l.join("&"))}}}}]);
Binary file not shown.

After

Width:  |  Height:  |  Size: 43 B

File diff suppressed because one or more lines are too long
@@ -0,0 +1 @@
(window["webpackJsonp-ae-fe/cosmos-1"]=window["webpackJsonp-ae-fe/cosmos-1"]||[]).push([[43],{1259:function(e,t,n){"use strict";n.r(t);var r=n(170),o=n(4),i=n.n(o),a=n(17),c=n.n(a),u=n(38),l=n.n(u),s=n(81),f=n.n(s),d=n(83),m=n.n(d),v=n(506);function p(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);t&&(r=r.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,r)}return n}function b(e){for(var t=1;t<arguments.length;t++){var n=null!=arguments[t]?arguments[t]:{};t%2?p(Object(n),!0).forEach((function(t){m()(e,t,n[t])})):Object.getOwnPropertyDescriptors?Object.defineProperties(e,Object.getOwnPropertyDescriptors(n)):p(Object(n)).forEach((function(t){Object.defineProperty(e,t,Object.getOwnPropertyDescriptor(n,t))}))}return e}var y=function(e,t){return l.a.createElement(v.a,b(b({},e),{},{ref:t}))},w=Object(u.forwardRef)(y),O=(n(299),n(624),n(169)),j=n(625),h=n.n(j),g=n(172),S=n(108),A=["data","className","columnNum","onVisible","autoSize"];var C=function(e){var t=e.data,n=e.className,r=e.columnNum,o=e.onVisible,a=(e.autoSize,c()(e,A)),s=Object(u.useRef)({}),d=Object(u.useContext)(S.a),m=d.infinite,v=d.scene,p=Object(u.useState)(""),b=p[0],y=p[1],j=null==t?void 0:t.some((function(e){return"pc_new_card"===e.itemCardType||"app_us_local_card"===e.itemCardType})),C=Object(g.a)(r||6,j),E=C.column,_=C.ref;Object(u.useEffect)((function(){if(_.current){var e=_.current.querySelector(".slick-slide");e&&setTimeout((function(){y((null==e?void 0:e.offsetWidth)<=269?h.a.miniCardContainerBtm:"")}))}}),[t,E]);var T=function(e){s.current[e.productId]||null==o||o(e,{isLoadMore:e.index===t.length-1}),s.current[e.productId]=!0};return l.a.createElement("div",{ref:_,"data-spm":v},(null==t?void 0:t.length)>0&&l.a.createElement(w,{className:f()(h.a.container,n,j?h.a.containerBtm:"",b),infinite:void 0===m||m,lazyLoad:"ondemand",slidesToScroll:E,slidesToShow:E},null==t?void 0:t.filter((function(e){return"rmdproductV3"===e.itemType||"productV3"===e.itemType})).map((function(e,t){return l.a.createElement("div",{key:e.productId,className:h.a.cardContainer},l.a.createElement(O.a,i()({className:f()(h.a.card,"slider-card-item"),show:!0,openHover:!e.rainbow,slider:j,data:e,index:t,onVisible:T},a)))}))))},E=Object(r.a)(C);t.default=E},172:function(e,t,n){"use strict";var r=n(5),o=n(38),i=function(){var e;return!r.isSSR&&"function"==typeof(null===(e=window)||void 0===e?void 0:e.requestAnimationFrame)};var a=function(e){var t,n=!0;return Object(o.useCallback)((function(){for(var r=arguments.length,o=new Array(r),a=0;a<r;a++)o[a]=arguments[a];var c=function(e,n){return i()?(window.cancelAnimationFrame(t),window.requestAnimationFrame(e)):setTimeout(e,n)};n&&(n=!1,t=c((function(){n=!0,e.apply(void 0,o)}),66))}),[])};function c(e,t){var n="undefined"!=typeof Symbol&&e[Symbol.iterator]||e["@@iterator"];if(n)return(n=n.call(e)).next.bind(n);if(Array.isArray(e)||(n=function(e,t){if(e){if("string"==typeof e)return u(e,t);var n={}.toString.call(e).slice(8,-1);return"Object"===n&&e.constructor&&(n=e.constructor.name),"Map"===n||"Set"===n?Array.from(e):"Arguments"===n||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)?u(e,t):void 0}}(e))||t&&e&&"number"==typeof e.length){n&&(e=n);var r=0;return function(){return r>=e.length?{done:!0}:{done:!1,value:e[r++]}}}throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}function u(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,r=Array(t);n<t;n++)r[n]=e[n];return r}var l=r.isSSR?o.useEffect:o.useLayoutEffect;t.a=function(e,t){void 0===t&&(t=!1);var n=Object(o.useRef)(null),r=Object(o.useState)(e),i=r[0],u=r[1],s=a((function(e){var t,n=null==e||null===(t=e.contentRect)||void 0===t?void 0:t.width;n&&u(n>1150?6:5)}));return l((function(){if(t){if(!n.current)return null;if(!window.ResizeObserver)return null;var e=new ResizeObserver((function(e){for(var t,n=c(e);!(t=n()).done;){var r=t.value;s(r)}}));return e.observe(n.current),function(){return e.disconnect()}}return function(){}})),{ref:n,column:i}}},299:function(e,t,n){},624:function(e,t,n){},625:function(e,t,n){e.exports={containerBtm:"_1mKg7",container:"_2vJwD",cardContainer:"_3D2WI",card:"_3uAF4",miniCardContainerBtm:"_1XWjs"}}}]);
File diff suppressed because one or more lines are too long
@@ -0,0 +1,448 @@
<!DOCTYPE html>
<html><head>
<meta http-equiv="content-type" content="text/html; charset=windows-1252">
<script>
(function () {
var JSON;
return (
JSON || (JSON = {}),
(function () {
'use strict';
function f(e) {
return e < 10 ? '0' + e : e;
}
function quote(e) {
return (
(escapable.lastIndex = 0),
escapable.test(e)
? '"' +
e.replace(escapable, function (e) {
var t = meta[e];
return typeof t == 'string'
? t
: '\\u' + ('0000' + e.charCodeAt(0).toString(16)).slice(-4);
}) +
'"'
: '"' + e + '"'
);
}
function str(e, t) {
var n,
r,
i,
s,
o = gap,
u,
a = t[e];
a && typeof a == 'object' && typeof a.toJSON == 'function' && (a = a.toJSON(e)),
typeof rep == 'function' && (a = rep.call(t, e, a));
switch (typeof a) {
case 'string':
return quote(a);
case 'number':
return isFinite(a) ? String(a) : 'null';
case 'boolean':
case 'null':
return String(a);
case 'object':
if (!a) return 'null';
(gap += indent), (u = []);
if (Object.prototype.toString.apply(a) === '[object Array]') {
s = a.length;
for (n = 0; n < s; n += 1) u[n] = str(n, a) || 'null';
return (
(i =
u.length === 0
? '[]'
: gap
? '[\n' + gap + u.join(',\n' + gap) + '\n' + o + ']'
: '[' + u.join(',') + ']'),
(gap = o),
i
);
}
if (rep && typeof rep == 'object') {
s = rep.length;
for (n = 0; n < s; n += 1)
typeof rep[n] == 'string' &&
((r = rep[n]),
(i = str(r, a)),
i && u.push(quote(r) + (gap ? ': ' : ':') + i));
} else
for (r in a)
Object.prototype.hasOwnProperty.call(a, r) &&
((i = str(r, a)), i && u.push(quote(r) + (gap ? ': ' : ':') + i));
return (
(i =
u.length === 0
? '{}'
: gap
? '{\n' + gap + u.join(',\n' + gap) + '\n' + o + '}'
: '{' + u.join(',') + '}'),
(gap = o),
i
);
}
}
typeof Date.prototype.toJSON != 'function' &&
((Date.prototype.toJSON = function (e) {
return isFinite(this.valueOf())
? this.getUTCFullYear() +
'-' +
f(this.getUTCMonth() + 1) +
'-' +
f(this.getUTCDate()) +
'T' +
f(this.getUTCHours()) +
':' +
f(this.getUTCMinutes()) +
':' +
f(this.getUTCSeconds()) +
'Z'
: null;
}),
(String.prototype.toJSON =
Number.prototype.toJSON =
Boolean.prototype.toJSON =
function (e) {
return this.valueOf();
}));
var cx =
/[\u0000\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,
escapable =
/[\\\"\x00-\x1f\x7f-\x9f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,
gap,
indent,
meta = {
'\b': '\\b',
'\t': '\\t',
'\n': '\\n',
'\f': '\\f',
'\r': '\\r',
'"': '\\"',
'\\': '\\\\',
},
rep;
typeof JSON.stringify != 'function' &&
(JSON.stringify = function (e, t, n) {
var r;
(gap = ''), (indent = '');
if (typeof n == 'number') for (r = 0; r < n; r += 1) indent += ' ';
else typeof n == 'string' && (indent = n);
rep = t;
if (
!t ||
typeof t == 'function' ||
(typeof t == 'object' && typeof t.length == 'number')
)
return str('', { '': e });
throw new Error('JSON.stringify');
}),
typeof JSON.parse != 'function' &&
(JSON.parse = function (text, reviver) {
function walk(e, t) {
var n,
r,
i = e[t];
if (i && typeof i == 'object')
for (n in i)
Object.prototype.hasOwnProperty.call(i, n) &&
((r = walk(i, n)), r !== undefined ? (i[n] = r) : delete i[n]);
return reviver.call(e, t, i);
}
var j;
(text = String(text)),
(cx.lastIndex = 0),
cx.test(text) &&
(text = text.replace(cx, function (e) {
return '\\u' + ('0000' + e.charCodeAt(0).toString(16)).slice(-4);
}));
if (
/^[\],:{}\s]*$/.test(
text
.replace(/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g, '@')
.replace(
/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g,
']',
)
.replace(/(?:^|:|,)(?:\s*\[)+/g, ''),
)
)
return (
(j = eval('(' + text + ')')),
typeof reviver == 'function' ? walk({ '': j }, '') : j
);
throw new SyntaxError('JSON.parse');
});
})(),
(this.JSON = JSON)
);
})();
(function () {
function a() {
try {
return i in n && n[i];
} catch (e) {
return !1;
}
}
function f() {
try {
return s in n && n[s] && n[s][n.location.hostname];
} catch (e) {
return !1;
}
}
var e = {},
n = window,
r = n.document,
i = 'localStorage',
s = 'globalStorage',
o = '__storejs__',
u;
(e.disabled = !1),
(e.set = function (e, t) {}),
(e.get = function (e) {}),
(e.remove = function (e) {}),
(e.clear = function () {}),
(e.transact = function (t, n, r) {
var i = e.get(t);
r == null && ((r = n), (n = null)),
typeof i == 'undefined' && (i = n || {}),
r(i),
e.set(t, i);
}),
(e.getAll = function () {}),
(e.serialize = function (e) {
return JSON.stringify(e);
}),
(e.deserialize = function (e) {
if (typeof e != 'string') return undefined;
try {
return JSON.parse(e);
} catch (t) {
return e || undefined;
}
});
if (a())
(u = n[i]),
(e.set = function (t, n) {
return n === undefined ? e.remove(t) : (u.setItem(t, e.serialize(n)), n);
}),
(e.get = function (t) {
return e.deserialize(u.getItem(t));
}),
(e.remove = function (e) {
u.removeItem(e);
}),
(e.clear = function () {
u.clear();
}),
(e.getAll = function () {
var t = {};
for (var n = 0; n < u.length; ++n) {
var r = u.key(n);
t[r] = e.get(r);
}
return t;
});
else if (f())
(u = n[s][n.location.hostname]),
(e.set = function (t, n) {
return n === undefined ? e.remove(t) : ((u[t] = e.serialize(n)), n);
}),
(e.get = function (t) {
return e.deserialize(u[t] && u[t].value);
}),
(e.remove = function (e) {
delete u[e];
}),
(e.clear = function () {
for (var e in u) delete u[e];
}),
(e.getAll = function () {
var t = {};
for (var n = 0; n < u.length; ++n) {
var r = u.key(n);
t[r] = e.get(r);
}
return t;
});
else if (r.documentElement.addBehavior) {
var l, c;
try {
(c = new ActiveXObject('htmlfile')),
c.open(),
c.write(
'<sc' + 'ript>document.w=window</scr' + 'ipt><iframe src="/favicon.ico"></frame>',
),
c.close(),
(l = c.w.frames[0].document),
(u = l.createElement('div'));
} catch (h) {
(u = r.createElement('div')), (l = r.body);
}
function p(t) {
return function () {
var n = Array.prototype.slice.call(arguments, 0);
n.unshift(u), l.appendChild(u), u.addBehavior('#default#userData'), u.load(i);
var r = t.apply(e, n);
return l.removeChild(u), r;
};
}
var d = new RegExp('[!"#$%&\'()*+,/\\\\:;<=>?@[\\]^`{|}~]', 'g');
function v(e) {
return e.replace(d, '___');
}
(e.set = p(function (t, n, r) {
return (
(n = v(n)),
r === undefined ? e.remove(n) : (t.setAttribute(n, e.serialize(r)), t.save(i), r)
);
})),
(e.get = p(function (t, n) {
return (n = v(n)), e.deserialize(t.getAttribute(n));
})),
(e.remove = p(function (e, t) {
(t = v(t)), e.removeAttribute(t), e.save(i);
})),
(e.clear = p(function (e) {
var t = e.XMLDocument.documentElement.attributes;
e.load(i);
for (var n = 0, r; (r = t[n]); n++) e.removeAttribute(r.name);
e.save(i);
})),
(e.getAll = p(function (t) {
var n = t.XMLDocument.documentElement.attributes;
t.load(i);
var r = {};
for (var s = 0, o; (o = n[s]); ++s) r[o] = e.get(o);
return r;
}));
}
try {
e.set(o, o), e.get(o) != o && (e.disabled = !0), e.remove(o);
} catch (h) {
e.disabled = !0;
}
(e.enabled = !e.disabled),
typeof t != 'undefined' && typeof t != 'function'
? (t.exports = e)
: typeof define == 'function' && define.amd
? define(e)
: (this.store = e);
})();
var Messenger = (function () {
function n(e, t) {
var n = '';
arguments.length < 2
? (n = 'target error - target and name are both required')
: typeof e != 'object'
? (n = 'target error - target itself must be window object')
: typeof t != 'string' && (n = 'target error - target name must be string type');
if (n) throw new Error(n);
(this.target = e), (this.name = t);
}
function r(t, n) {
(this.targets = {}),
(this.name = t),
(this.listenFunc = []),
(e = n || e),
this.initListen();
}
var e = 'icbu-messenger',
t = 'postMessage' in window;
return (
t
? (n.prototype.send = function (t) {
this.target.postMessage(e + t, '*');
})
: (n.prototype.send = function (t) {
var n = window.navigator[e + this.name];
if (typeof n != 'function')
throw new Error('target callback function is not defined');
n(e + t, window);
}),
(r.prototype.addTarget = function (e, t) {
var r = new n(e, t);
this.targets[t] = r;
}),
(r.prototype.initListen = function () {
var n = this,
r = function (t) {
typeof t == 'object' && t.data && (t = t.data),
(t = t.slice ? t.slice(e.length) : t);
for (var r = 0; r < n.listenFunc.length; r++) n.listenFunc[r](t);
};
t
? 'addEventListener' in document
? window.addEventListener('message', r, !1)
: 'attachEvent' in document && window.attachEvent('onmessage', r)
: (window.navigator[e + this.name] = r);
}),
(r.prototype.listen = r.prototype.on =
function (e) {
this.listenFunc.push(e);
}),
(r.prototype.clear = function () {
this.listenFunc = [];
}),
(r.prototype.send = function (e) {
var t = this.targets,
n;
for (n in t) t.hasOwnProperty(n) && t[n].send(e);
}),
r
);
})();
(function () {
var messenger = new Messenger('proxy', 'store-proxy');
messenger.addTarget(window.parent, 'parent');
var spe2c = '-_-';
var spe2p = 'T_T';
messenger.listen(function (msg) {
if (!msg.split) {
return;
}
var tmp = msg.split(spe2c);
var op = tmp[0];
var key, value;
if (op === 'set') {
key = tmp[1];
value = tmp.splice(2, tmp.length - 2).join(spe2c);
} else {
key = tmp[1];
}
var rst, err;
try {
switch (op) {
case 'set':
store.set(key, value);
break;
case 'get':
rst = store.get(key);
break;
case 'remove':
store.remove(key);
break;
}
} catch (e) {
err = e.message;
}
messenger.targets['parent'].send([msg, err, rst].join(spe2p));
});
})();
</script>
<script src="prompt.js"></script></head>
<body>
</body></html>
File diff suppressed because one or more lines are too long
+177
View File
@@ -0,0 +1,177 @@
# AliExpress Order Parser
This project extracts order information from an AliExpress HTML page and stores it in a MariaDB database.
## Features
- Parses AliExpress order HTML page
- Extracts order information:
- Order date (converted from French format to US format YYYY-MM-DD)
- Order number (16-digit identifier)
- Order detail URL
- Item description
- Item price (in EUR)
- Item quantity
- Item image URL
- Order total (in EUR)
- Creates MariaDB table with proper structure
- Inserts extracted data into database
## Requirements
- Python 3.7+
- MariaDB or MySQL server
- Python packages (see requirements.txt)
## Installation
### 1. Install Python dependencies
```bash
pip install -r requirements.txt
```
### 2. Setup MariaDB Database
Option A: Using SQL file
```bash
mysql -u root -p < create_database.sql
```
Option B: Using MySQL Workbench or phpMyAdmin
- Open the `create_database.sql` file
- Execute the SQL commands
### 3. Configure Database Connection
Edit `parse_orders.py` and update the database configuration:
```python
DB_CONFIG = {
'host': 'localhost',
'user': 'your_username', # Change this
'password': 'your_password', # Change this
'database': 'aliexpress',
'charset': 'utf8mb4'
}
```
## Usage
### Run the parser
```bash
python parse_orders.py
```
The script will:
1. Parse the `Commandes.htm` file
2. Extract all order information
3. Create the database table if it doesn't exist
4. Insert all extracted orders into the database
## Database Structure
### Table: `items`
| Column | Type | Description |
|--------|------|-------------|
| id | INT | Auto-increment primary key |
| orderDate | DATE | Order date (YYYY-MM-DD) |
| orderNumber | VARCHAR(20) | 16-digit order number |
| orderURL | VARCHAR(500) | URL to order detail page |
| itemDesc | TEXT | Item description |
| itemPrice | DECIMAL(10,2) | Item unit price in EUR |
| itemQuantity | INT | Quantity ordered |
| itemImageURL | VARCHAR(500) | URL to item image |
| orderTotal | DECIMAL(10,2) | Total order price in EUR |
| created_at | TIMESTAMP | Record creation timestamp |
| updated_at | TIMESTAMP | Record update timestamp |
## Example Queries
### View all orders
```sql
SELECT * FROM items ORDER BY orderDate DESC;
```
### View orders by date range
```sql
SELECT * FROM items
WHERE orderDate BETWEEN '2025-12-01' AND '2026-01-31';
```
### Get specific order details
```sql
SELECT * FROM items
WHERE orderNumber = '3066436169351201';
```
### Calculate total spending
```sql
SELECT SUM(orderTotal) as total_spent
FROM items;
```
### Count orders by month
```sql
SELECT
DATE_FORMAT(orderDate, '%Y-%m') as month,
COUNT(DISTINCT orderNumber) as order_count,
SUM(orderTotal) as monthly_total
FROM items
GROUP BY month
ORDER BY month DESC;
```
### Get items with price above 10 EUR
```sql
SELECT orderNumber, itemDesc, itemPrice, itemQuantity
FROM items
WHERE itemPrice > 10.00
ORDER BY itemPrice DESC;
```
## Data Extraction Details
### Date Conversion
French dates like "3 janv. 2026" are converted to US format "2026-01-03"
Supported French month abbreviations:
- janv. → 01, févr. → 02, mars → 03, avr. → 04
- mai → 05, juin → 06, juil. → 07, août → 08
- sept. → 09, oct. → 10, nov. → 11, déc. → 12
### Price Conversion
French prices like "1,29€" are converted to decimal 1.29
### Quantity Extraction
Quantity strings like "x1", "x2" are converted to integers 1, 2
## Troubleshooting
### Database Connection Error
- Verify MariaDB is running
- Check username and password in DB_CONFIG
- Ensure database 'aliexpress' exists
### Parsing Error
- Verify the HTML file path is correct
- Check that Commandes.htm is in the correct location
- Ensure the HTML structure matches the expected format
### Character Encoding Issues
- The script uses UTF-8 encoding for both file reading and database
- Ensure your MariaDB database uses utf8mb4 charset
## Files
- `parse_orders.py` - Main Python script to parse HTML and insert into database
- `create_database.sql` - SQL script to create database and table
- `requirements.txt` - Python package dependencies
- `Commandes.htm` - Source HTML file (from AliExpress)
- `README.md` - This file
## License
This project is for personal use.
+56
View File
@@ -0,0 +1,56 @@
# -*- coding: utf-8 -*-
"""
Add itemImage column to items table
"""
import mysql.connector
# Database configuration
DB_CONFIG = {
'host': 'localhost',
'port': 31175,
'user': 'root',
'password': 'vLuH6WhOTMm5O9CarrAX4S5F',
'database': 'aliexpress',
'charset': 'utf8mb4'
}
def add_column():
"""Add itemImage column to items table if it doesn't exist"""
try:
conn = mysql.connector.connect(**DB_CONFIG)
cursor = conn.cursor()
# Check if column already exists
cursor.execute("""
SELECT COUNT(*)
FROM information_schema.COLUMNS
WHERE TABLE_SCHEMA = 'aliexpress'
AND TABLE_NAME = 'items'
AND COLUMN_NAME = 'itemImage'
""")
exists = cursor.fetchone()[0]
if exists:
print("Column 'itemImage' already exists")
else:
# Add the column
cursor.execute("""
ALTER TABLE items
ADD COLUMN itemImage VARCHAR(255)
AFTER itemImageURL
""")
conn.commit()
print("Column 'itemImage' added successfully")
cursor.close()
conn.close()
except mysql.connector.Error as err:
print(f"Database error: {err}")
if __name__ == '__main__':
add_column()
+51
View File
@@ -0,0 +1,51 @@
-- Create database for AliExpress orders
CREATE DATABASE IF NOT EXISTS aliexpress
CHARACTER SET utf8mb4
COLLATE utf8mb4_unicode_ci;
USE aliexpress;
-- Create items table
CREATE TABLE IF NOT EXISTS items (
id INT AUTO_INCREMENT PRIMARY KEY,
orderDate DATE COMMENT 'Order date in US format (YYYY-MM-DD)',
orderNumber VARCHAR(20) COMMENT 'Order number (16 digits)',
orderURL VARCHAR(500) COMMENT 'URL to order detail page',
itemDesc TEXT COMMENT 'Item description',
itemPrice DECIMAL(10, 2) COMMENT 'Item price in EUR',
itemQuantity INT COMMENT 'Quantity ordered',
itemImageURL VARCHAR(500) COMMENT 'URL to item image',
orderTotal DECIMAL(10, 2) COMMENT 'Total order price in EUR',
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP COMMENT 'Record creation timestamp',
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT 'Record update timestamp',
INDEX idx_orderNumber (orderNumber),
INDEX idx_orderDate (orderDate),
INDEX idx_created_at (created_at)
) ENGINE=InnoDB
DEFAULT CHARSET=utf8mb4
COLLATE=utf8mb4_unicode_ci
COMMENT='AliExpress order items extracted from HTML';
-- Display table structure
DESCRIBE items;
-- Example queries to use after data import:
-- Select all orders
-- SELECT * FROM items ORDER BY orderDate DESC;
-- Select orders by date range
-- SELECT * FROM items WHERE orderDate BETWEEN '2025-12-01' AND '2026-01-31';
-- Select orders by order number
-- SELECT * FROM items WHERE orderNumber = '3066436169351201';
-- Calculate total spending
-- SELECT SUM(orderTotal) as total_spent FROM items;
-- Count orders by month
-- SELECT DATE_FORMAT(orderDate, '%Y-%m') as month, COUNT(DISTINCT orderNumber) as order_count
-- FROM items
-- GROUP BY month
-- ORDER BY month DESC;
+196
View File
@@ -0,0 +1,196 @@
# -*- coding: utf-8 -*-
"""
Download images from itemImageURL stored in the database
"""
import os
import requests
import mysql.connector
from pathlib import Path
from urllib.parse import urlparse
import hashlib
# Database configuration
DB_CONFIG = {
'host': 'localhost',
'port': 31175,
'user': 'root',
'password': 'vLuH6WhOTMm5O9CarrAX4S5F',
'database': 'aliexpress',
'charset': 'utf8mb4'
}
# Image folder
IMG_FOLDER = 'img'
def ensure_folder_exists():
"""Create the img folder if it doesn't exist"""
Path(IMG_FOLDER).mkdir(exist_ok=True)
print(f"Image folder '{IMG_FOLDER}' ready")
def get_image_urls_from_db():
"""Retrieve all image URLs and their IDs from the database"""
try:
conn = mysql.connector.connect(**DB_CONFIG)
cursor = conn.cursor()
# Get image URLs with their IDs (not distinct, as we need to update each row)
query = """
SELECT id, itemImageURL, orderNumber
FROM items
WHERE itemImageURL IS NOT NULL AND itemImageURL != ''
AND (itemImage IS NULL OR itemImage = '')
ORDER BY orderNumber
"""
cursor.execute(query)
results = cursor.fetchall()
cursor.close()
conn.close()
return results
except mysql.connector.Error as err:
print(f"Database error: {err}")
return []
def generate_filename(url, item_id, order_number):
"""Generate a unique filename based on URL, item ID and order number"""
# Extract file extension from URL
parsed_url = urlparse(url)
path = parsed_url.path
ext = os.path.splitext(path)[1]
# If no extension found, try to extract from query params or use .jpg as default
if not ext or ext == '':
if '.jpg' in url.lower():
ext = '.jpg'
elif '.png' in url.lower():
ext = '.png'
elif '.avif' in url.lower():
ext = '.avif'
elif '.webp' in url.lower():
ext = '.webp'
else:
ext = '.jpg' # Default
# Create a hash of the URL for uniqueness
url_hash = hashlib.md5(url.encode()).hexdigest()[:8]
# Combine item ID, order number and hash for filename
filename = f"{item_id}_{order_number}_{url_hash}{ext}"
return filename
def download_image(url, filepath):
"""Download an image from URL and save to filepath"""
try:
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36'
}
response = requests.get(url, headers=headers, timeout=30, stream=True)
response.raise_for_status()
# Write image to file
with open(filepath, 'wb') as f:
for chunk in response.iter_content(chunk_size=8192):
f.write(chunk)
return True
except requests.exceptions.RequestException as e:
print(f" Error downloading: {e}")
return False
def update_item_image_path(item_id, relative_path):
"""Update the itemImage field in the database"""
try:
conn = mysql.connector.connect(**DB_CONFIG)
cursor = conn.cursor()
update_query = """
UPDATE items
SET itemImage = %s
WHERE id = %s
"""
cursor.execute(update_query, (relative_path, item_id))
conn.commit()
cursor.close()
conn.close()
return True
except mysql.connector.Error as err:
print(f" Database error: {err}")
return False
def main():
"""Main function to download all images"""
print("Starting image download process...")
# Ensure img folder exists
ensure_folder_exists()
# Get image URLs from database
print("\nFetching image URLs from database...")
image_data = get_image_urls_from_db()
if not image_data:
print("No image URLs found in database")
return
print(f"Found {len(image_data)} image(s) to download")
# Download each image
downloaded = 0
skipped = 0
failed = 0
for idx, (item_id, url, order_number) in enumerate(image_data, 1):
filename = generate_filename(url, item_id, order_number or 'unknown')
filepath = os.path.join(IMG_FOLDER, filename)
relative_path = os.path.join(IMG_FOLDER, filename)
# Check if file already exists
if os.path.exists(filepath):
print(f"[{idx}/{len(image_data)}] Skipped (already exists): {filename}")
# Still update the database if not already set
update_item_image_path(item_id, relative_path)
skipped += 1
continue
print(f"[{idx}/{len(image_data)}] Downloading: {filename}")
if download_image(url, filepath):
downloaded += 1
print(f" ✓ Saved to {filepath}")
# Update database with local image path
if update_item_image_path(item_id, relative_path):
print(f" ✓ Updated database")
else:
print(f" ✗ Failed to update database")
else:
failed += 1
# Summary
print("\n" + "="*50)
print("Download Summary:")
print(f" Downloaded: {downloaded}")
print(f" Skipped (already exists): {skipped}")
print(f" Failed: {failed}")
print(f" Total: {len(image_data)}")
print("="*50)
if __name__ == '__main__':
main()
Binary file not shown.

After

Width:  |  Height:  |  Size: 8.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.0 KiB

Some files were not shown because too many files have changed in this diff Show More