Integrate htmx and dropzone for file Section
This commit is contained in:
parent
0e79fdcb36
commit
5abbf367ab
3
.gitignore
vendored
3
.gitignore
vendored
@ -1,5 +1,5 @@
|
||||
*__pycache__/
|
||||
base.db
|
||||
*.db
|
||||
log.txt
|
||||
config.py
|
||||
users/
|
||||
@ -8,3 +8,4 @@ sys
|
||||
*#*
|
||||
.*
|
||||
base.db.new
|
||||
public/*
|
||||
|
||||
2
static/vendors/dropzone/dropzone-min.js
vendored
Normal file
2
static/vendors/dropzone/dropzone-min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
1
static/vendors/dropzone/dropzone-min.js.map
vendored
Normal file
1
static/vendors/dropzone/dropzone-min.js.map
vendored
Normal file
File diff suppressed because one or more lines are too long
1
static/vendors/dropzone/dropzone.css
vendored
Normal file
1
static/vendors/dropzone/dropzone.css
vendored
Normal file
@ -0,0 +1 @@
|
||||
@keyframes passing-through{0%{opacity:0;transform:translateY(40px)}30%,70%{opacity:1;transform:translateY(0px)}100%{opacity:0;transform:translateY(-40px)}}@keyframes slide-in{0%{opacity:0;transform:translateY(40px)}30%{opacity:1;transform:translateY(0px)}}@keyframes pulse{0%{transform:scale(1)}10%{transform:scale(1.1)}20%{transform:scale(1)}}.dropzone,.dropzone *{box-sizing:border-box}.dropzone{min-height:150px;border:1px solid rgba(0,0,0,.8);border-radius:5px;padding:20px 20px}.dropzone.dz-clickable{cursor:pointer}.dropzone.dz-clickable *{cursor:default}.dropzone.dz-clickable .dz-message,.dropzone.dz-clickable .dz-message *{cursor:pointer}.dropzone.dz-started .dz-message{display:none}.dropzone.dz-drag-hover{border-style:solid}.dropzone.dz-drag-hover .dz-message{opacity:.5}.dropzone .dz-message{text-align:center;margin:3em 0}.dropzone .dz-message .dz-button{background:none;color:inherit;border:none;padding:0;font:inherit;cursor:pointer;outline:inherit}.dropzone .dz-preview{position:relative;display:inline-block;vertical-align:top;margin:16px;min-height:100px}.dropzone .dz-preview:hover{z-index:1000}.dropzone .dz-preview:hover .dz-details{opacity:1}.dropzone .dz-preview.dz-file-preview .dz-image{border-radius:20px;background:#999;background:linear-gradient(to bottom, #eee, #ddd)}.dropzone .dz-preview.dz-file-preview .dz-details{opacity:1}.dropzone .dz-preview.dz-image-preview{background:#fff}.dropzone .dz-preview.dz-image-preview .dz-details{transition:opacity .2s linear}.dropzone .dz-preview .dz-remove{font-size:14px;text-align:center;display:block;cursor:pointer;border:none}.dropzone .dz-preview .dz-remove:hover{text-decoration:underline}.dropzone .dz-preview:hover .dz-details{opacity:1}.dropzone .dz-preview .dz-details{z-index:20;position:absolute;top:0;left:0;opacity:0;font-size:13px;min-width:100%;max-width:100%;padding:2em 1em;text-align:center;color:rgba(0,0,0,.9);line-height:150%}.dropzone .dz-preview .dz-details .dz-size{margin-bottom:1em;font-size:16px}.dropzone .dz-preview .dz-details .dz-filename{white-space:nowrap}.dropzone .dz-preview .dz-details .dz-filename:hover span{border:1px solid rgba(200,200,200,.8);background-color:hsla(0,0%,100%,.8)}.dropzone .dz-preview .dz-details .dz-filename:not(:hover){overflow:hidden;text-overflow:ellipsis}.dropzone .dz-preview .dz-details .dz-filename:not(:hover) span{border:1px solid rgba(0,0,0,0)}.dropzone .dz-preview .dz-details .dz-filename span,.dropzone .dz-preview .dz-details .dz-size span{background-color:hsla(0,0%,100%,.4);padding:0 .4em;border-radius:3px}.dropzone .dz-preview:hover .dz-image img{transform:scale(1.05, 1.05);filter:blur(8px)}.dropzone .dz-preview .dz-image{border-radius:20px;overflow:hidden;width:120px;height:120px;position:relative;display:block;z-index:10}.dropzone .dz-preview .dz-image img{display:block}.dropzone .dz-preview.dz-success .dz-success-mark{animation:passing-through 3s cubic-bezier(0.77, 0, 0.175, 1)}.dropzone .dz-preview.dz-error .dz-error-mark{opacity:1;animation:slide-in 3s cubic-bezier(0.77, 0, 0.175, 1)}.dropzone .dz-preview .dz-success-mark,.dropzone .dz-preview .dz-error-mark{pointer-events:none;opacity:0;z-index:500;position:absolute;display:block;top:50%;left:50%;margin-left:-27px;margin-top:-27px;background:rgba(0,0,0,.8);border-radius:50%}.dropzone .dz-preview .dz-success-mark svg,.dropzone .dz-preview .dz-error-mark svg{display:block;width:54px;height:54px;fill:#fff}.dropzone .dz-preview.dz-processing .dz-progress{opacity:1;transition:all .2s linear}.dropzone .dz-preview.dz-complete .dz-progress{opacity:0;transition:opacity .4s ease-in}.dropzone .dz-preview:not(.dz-processing) .dz-progress{animation:pulse 6s ease infinite}.dropzone .dz-preview .dz-progress{opacity:1;z-index:1000;pointer-events:none;position:absolute;height:20px;top:50%;margin-top:-10px;left:15%;right:15%;border:3px solid rgba(0,0,0,.8);background:rgba(0,0,0,.8);border-radius:10px;overflow:hidden}.dropzone .dz-preview .dz-progress .dz-upload{background:#fff;display:block;position:relative;height:100%;width:0;transition:width 300ms ease-in-out;border-radius:17px}.dropzone .dz-preview.dz-error .dz-error-message{display:block}.dropzone .dz-preview.dz-error:hover .dz-error-message{opacity:1;pointer-events:auto}.dropzone .dz-preview .dz-error-message{pointer-events:none;z-index:1000;position:absolute;display:block;display:none;opacity:0;transition:opacity .3s ease;border-radius:8px;font-size:13px;top:130px;left:-10px;width:140px;background:#b10606;padding:.5em 1em;color:#fff}.dropzone .dz-preview .dz-error-message:after{content:"";position:absolute;top:-6px;left:64px;width:0;height:0;border-left:6px solid rgba(0,0,0,0);border-right:6px solid rgba(0,0,0,0);border-bottom:6px solid #b10606}/*# sourceMappingURL=dropzone.css.map */
|
||||
1
static/vendors/htmx/htmx.min.js
vendored
Normal file
1
static/vendors/htmx/htmx.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
26
templates/_js_dropzone.html
Normal file
26
templates/_js_dropzone.html
Normal file
@ -0,0 +1,26 @@
|
||||
|
||||
<script>
|
||||
window.onload = function () {
|
||||
|
||||
var dropzoneOptions = {
|
||||
dictDefaultMessage: 'Déposez vos fichiers ici!',
|
||||
paramName: "file",
|
||||
maxFilesize: 1024, // MB
|
||||
url: "/upload-dropzone",
|
||||
chunking: true,
|
||||
forceChunking: true,
|
||||
chunkSize: 1000000,
|
||||
autoProcessQueue: true,
|
||||
init: function () {
|
||||
this.on("success", function (file) {
|
||||
console.log("success > " + file.name);
|
||||
setTimeout(() => { this.removeFile(file); }, 2000);
|
||||
});
|
||||
}
|
||||
};
|
||||
var uploader = document.querySelector('#uploader');
|
||||
var myDropzone = new Dropzone(uploader, dropzoneOptions);
|
||||
console.log("Loaded");
|
||||
};
|
||||
</script>
|
||||
|
||||
4
templates/_js_htmx.html
Normal file
4
templates/_js_htmx.html
Normal file
@ -0,0 +1,4 @@
|
||||
|
||||
|
||||
<script src="{{ url_for('static', filename='vendors/htmx/htmx.min.js') }}"> </script>
|
||||
|
||||
3
templates/css/dropzone.html
Normal file
3
templates/css/dropzone.html
Normal file
@ -0,0 +1,3 @@
|
||||
<script src="{{ url_for('static', filename='vendors/dropzone/dropzone-min.js') }}"></script>
|
||||
<link href="{{ url_for('static', filename='vendors/dropzone/dropzone.css') }}" rel="stylesheet">
|
||||
|
||||
@ -26,83 +26,19 @@
|
||||
<h5>
|
||||
Vous pouvez partager des liens de vos fichiers avec les autres membres de ce serveur uniquement. Si vous partagez un lien avec une personne non inscrite elle ne pourra pas y avoir accès
|
||||
</h5>
|
||||
<div hx-get="/files/private/" hx-trigger="load, every 10s">
|
||||
Chargement ...
|
||||
</div>
|
||||
|
||||
{% if listFilesPrivate %}
|
||||
<table class="table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th></th>
|
||||
<th>Fichier(s) <span class="badge">{{ nb_pv }}</span></th>
|
||||
<th>Taille (en Megaoctect)</th>
|
||||
<th></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
|
||||
{% for file in listFilesPrivate %}
|
||||
<tr>
|
||||
<td>{{ file[0] }}</td>
|
||||
<td><a href="/myfiles/{{ username }}/{{ file[1] }}">{{ file[1] }}</a></td>
|
||||
<td>{{ file[2] }}</td>
|
||||
<td>
|
||||
<a href="{{ url_for('filesupload.remove_privateFile', filename=file[1]) }}">
|
||||
<button type="button" title="Supprimer"> <span class="icons delete"></span></button>
|
||||
</a>
|
||||
|
||||
<a href="{{ url_for('filesupload.move_public', filename=file[1]) }}">
|
||||
<button type="button" title="Passer ce fichier en status public"><span class="icons share"></span></button>
|
||||
</a>
|
||||
<button type="button" onclick="navigator.clipboard.writeText('{{BASE_URL}}{{ url_for('filesupload.publicfiles', username=username, filename=file[1]) }}');" title="Copier le lien du fichier">
|
||||
<span class="icons copy-link"> </span>
|
||||
</button>
|
||||
</td>
|
||||
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
{% else %}
|
||||
<p> Vous n'avez aucun fichier privé </p>
|
||||
{% endif %}
|
||||
<br />
|
||||
<hr />
|
||||
<br />
|
||||
|
||||
<h2> Fichiers publics </h2>
|
||||
<h5> Vous pouvez partager les liens de ces fichiers avec n'importe qui sur Internet ils y auront accès </h5>
|
||||
{% if listFilesPublic %}
|
||||
<table class="table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th></th>
|
||||
<th>Fichier(s) <span class="badge">{{ nb_pu }}</span></th>
|
||||
<th>Taille (en Megaoctets)</th>
|
||||
<th></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for file in listFilesPublic %}
|
||||
<tr>
|
||||
<td>{{ file[0] }}</td>
|
||||
<td><a href="/public/{{ username }}/{{ file[1] }}">{{ file[1] }}</a></td>
|
||||
<td>{{ file[2] }}</td>
|
||||
<td>
|
||||
<a href="{{ url_for('filesupload.remove_publicFile', filename=file[1]) }}">
|
||||
<button type="button" title="Supprimer"> <span class="icons delete"></span></button>
|
||||
</a>
|
||||
<a href="{{ url_for('filesupload.move_private', filename=file[1]) }}">
|
||||
<button type="button" title="Passer ce fichier en status privé"><span class="icons share"></span></button>
|
||||
</a>
|
||||
<button type="button" onclick="navigator.clipboard.writeText('{{BASE_URL}}{{ url_for('filesupload.publicfiles', username=username, filename=file[1]) }}');" title="Copier le lien du fichier">
|
||||
<span class="icons copy-link"> </span>
|
||||
</button>
|
||||
</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
{% else %}
|
||||
<p> Vous n'avez aucun fichier public </p>
|
||||
{% endif %}
|
||||
|
||||
<div hx-get="/files/public/" hx-trigger="load, every 10s">
|
||||
Chargement ...
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
@ -110,4 +46,5 @@
|
||||
|
||||
{% block js %}
|
||||
{% include '_js_dropzone.html' %}
|
||||
{% include '_js_htmx.html' %}
|
||||
{% endblock %}
|
||||
|
||||
54
templates/list_files.html
Normal file
54
templates/list_files.html
Normal file
@ -0,0 +1,54 @@
|
||||
|
||||
{% if listFiles %}
|
||||
<table class="table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th></th>
|
||||
<th>Fichier(s) <span class="badge">{{ nb_files }}</span></th>
|
||||
<th>Taille (en Megaoctect)</th>
|
||||
<th></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
|
||||
{% for file in listFiles %}
|
||||
<tr>
|
||||
<td>{{ file[0] }}</td>
|
||||
<td><a href="/myfiles/{{ username }}/{{ file[1] }}">{{ file[1] }}</a></td>
|
||||
<td>{{ file[2] }}</td>
|
||||
<td>
|
||||
{% if status == "public" %}
|
||||
<td>
|
||||
<a href="{{ url_for('filesupload.remove_publicFile', filename=file[1]) }}">
|
||||
<button type="button" title="Supprimer"> <span class="icons delete"></span></button>
|
||||
</a>
|
||||
<a href="{{ url_for('filesupload.move_private', filename=file[1]) }}">
|
||||
<button type="button" title="Passer ce fichier en status privé"><span class="icons share"></span></button>
|
||||
</a>
|
||||
<button type="button" onclick="navigator.clipboard.writeText('{{BASE_URL}}{{ url_for('filesupload.publicfiles', username=username, filename=file[1]) }}');" title="Copier le lien du fichier">
|
||||
<span class="icons copy-link"> </span>
|
||||
</button>
|
||||
</td>
|
||||
{% else %}
|
||||
|
||||
<td>
|
||||
<a href="{{ url_for('filesupload.remove_privateFile', filename=file[1]) }}">
|
||||
<button type="button" title="Supprimer"> <span class="icons delete"></span></button>
|
||||
</a>
|
||||
|
||||
<a href="{{ url_for('filesupload.move_public', filename=file[1]) }}">
|
||||
<button type="button" title="Passer ce fichier en status public"><span class="icons share"></span></button>
|
||||
</a>
|
||||
<button type="button" onclick="navigator.clipboard.writeText('{{BASE_URL}}{{ url_for('filesupload.publicfiles', username=username, filename=file[1]) }}');" title="Copier le lien du fichier">
|
||||
<span class="icons copy-link"> </span>
|
||||
</button>
|
||||
</td>
|
||||
|
||||
{% endif %}
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
{% else %}
|
||||
<h5> Aucun fichier ici </h5>
|
||||
{% endif %}
|
||||
@ -1,86 +0,0 @@
|
||||
{% extends 'up_squelette.html' %}
|
||||
|
||||
|
||||
{% block main %}
|
||||
|
||||
|
||||
<p>Quand tu envoies des images, elles se retrouveront directement dans la <a href="/gallery/"> Gallerie</a>. </p>
|
||||
<p>Ayez bien conscience que ce site est une expérience est qu'il est indispensable d'avoir
|
||||
une sauvegarde de tous les fichiers qui vous mettrez ici. Nous ne pourrons, en aucun cas, être tenu responsable de la perte de vos
|
||||
données. Merci de votre compréhension.
|
||||
</p>
|
||||
|
||||
<br />
|
||||
<h3>Choisissez un ou plusieurs fichiers à téléverser </h3>
|
||||
|
||||
|
||||
<form action="" method="post" enctype="multipart/form-data">
|
||||
<input type="file" class="center" name="fic"id="fic" multiple>
|
||||
<br>
|
||||
<button type="submit" id="tada" class="btn btn btn-success"> Téléverser !</button>
|
||||
</form>
|
||||
|
||||
|
||||
|
||||
|
||||
<h2> Fichiers privés (Seul les personnes connectées et l'administrateur de l'ordinateur peuvent les voirs) </h2>
|
||||
{% if listFilesPrivate %}
|
||||
<table class="table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th></th>
|
||||
<th>Fichier(s) <span class="badge">{{ nb_pv }}</span></th>
|
||||
<th>Taille (en Megaoctect)</th>
|
||||
<th></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
|
||||
{% for file in listFilesPrivate %}
|
||||
<tr>
|
||||
<td>{{ file[0] }}</td>
|
||||
<td><a href="/myfiles/{{ username }}/{{ file[1] }}">{{ file[1] }}</a></td>
|
||||
<td>{{ file[2] }}</td>
|
||||
<td><a href="{{ url_for('filesupload.remove_privateFile', filename=file[1]) }}"><button type="button" class="btn btn-sm btn-danger">Supprimer</button></a></td>
|
||||
<td><a href="{{ url_for('filesupload.move_public', filename=file[1]) }}"><button type="button" class="btn btn-sm btn-success"> Rendre Publique </button></a></td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
{% else %}
|
||||
<p> Vous n'avez aucun fichiers privés </p>
|
||||
{% endif %}
|
||||
<br />
|
||||
<hr />
|
||||
<br />
|
||||
<h2> Fichiers publics (Tout le monde peut les voirs) </h2>
|
||||
{% if listFilesPublic %}
|
||||
<table class="table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th></th>
|
||||
<th>Fichier(s) <span class="badge">{{ nb_pu }}</span></th>
|
||||
<th>Taille (en Megaoctets)</th>
|
||||
<th></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
|
||||
{% for file in listFilesPublic %}
|
||||
<tr>
|
||||
<td>{{ file[0] }}</td>
|
||||
<td><a href="/public/{{ username }}/{{ file[1] }}">{{ file[1] }}</a></td>
|
||||
<td>{{ file[2] }}</td>
|
||||
<td><a href="{{ url_for('filesupload.remove_publicFile', filename=file[1]) }}"><button type="button" class="btn btn-sm btn-danger">Supprimer</button></a></td>
|
||||
<td><a href="{{ url_for('filesupload.move_private', filename=file[1]) }}"><button type="button" class="btn btn-sm btn-success"> Rendre Privée </button></a></td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
{% else %}
|
||||
<p> Vous n'avez aucun fichiers publics </p>
|
||||
{% endif %}
|
||||
|
||||
|
||||
|
||||
{% endblock %}
|
||||
@ -2,6 +2,7 @@
|
||||
<html lang="fr">
|
||||
<head>
|
||||
{% include '_head.html' %}
|
||||
{% block css %} {% endblock %}
|
||||
{% include 'css/simple_editor.html' %}
|
||||
</head>
|
||||
|
||||
|
||||
@ -39,6 +39,28 @@ def append_to_log(log_line, user):
|
||||
log.close()
|
||||
|
||||
|
||||
|
||||
def valid_email(mail):
|
||||
valid=True
|
||||
# Caractères non autorisés dans la RFC #822
|
||||
invalid_char = { '(', ')', '<', '>', ',', ';', ':', '"', '[', ']', '|', 'ç', '%', '&', ' ' }
|
||||
mail_cut = mail.split('@')
|
||||
tld = mail_cut[-1].split('.')
|
||||
|
||||
for character in invalid_char:
|
||||
if character in mail:
|
||||
valid=False
|
||||
|
||||
print(tld)
|
||||
if len(mail_cut) > 1 and len(tld) > 1 and valid:
|
||||
if len(tld[0]) < 1 or len(tld[-1]) < 2 :
|
||||
valid=False
|
||||
else:
|
||||
valid=False
|
||||
|
||||
return valid
|
||||
|
||||
|
||||
def valid_username(username):
|
||||
valid=True
|
||||
# Caractères non autorisés dans la RFC #822
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
from flask import Blueprint, Flask, request, flash, render_template, url_for, session, redirect, abort, make_response, flash, abort, send_file, send_from_directory
|
||||
|
||||
from werkzeug.utils import secure_filename
|
||||
from markupsafe import escape
|
||||
from PIL import Image
|
||||
@ -16,15 +17,14 @@ filesupload = Blueprint('filesupload', __name__, template_folder='templates')
|
||||
app = Flask( 'pywallter' )
|
||||
app.config.from_pyfile('config.py')
|
||||
|
||||
#### Variables ##################################################################################
|
||||
|
||||
#### Variables ####################################################################################
|
||||
DOSSIER_PERSO= app.config.get('DOSSIER_APP')
|
||||
DOSSIER_PUBLIC= app.config.get('DOSSIER_PUBLIC')
|
||||
|
||||
DOSSIER_PERSO= app.config['DOSSIER_APP']+'/'
|
||||
DOSSIER_PUBLIC= app.config['DOSSIER_PUBLIC']+'/'
|
||||
|
||||
extensionimg = app.config['EXT_IMG']
|
||||
DATABASE = app.config['DATABASE']
|
||||
BASE_URL= app.config['BASE_URL']
|
||||
extensionimg = app.config.get('EXT_IMG')
|
||||
DATABASE = app.config.get('DATABASE')
|
||||
BASE_URL= app.config.get('BASE_URL')
|
||||
##################################################################################################
|
||||
|
||||
|
||||
@ -46,19 +46,20 @@ def upload():
|
||||
files = request.files.getlist('fic')
|
||||
for f in files :
|
||||
nom = secure_filename(f.filename)
|
||||
check_and_create(DOSSIER_PERSO+ user + '/files')
|
||||
check_and_create(DOSSIER_PERSO+ user + '/images')
|
||||
if os.path.isfile(DOSSIER_PERSO + user + '/files/' + nom) or os.path.isfile(DOSSIER_PERSO + user + '/images/' + nom):
|
||||
check_and_create(os.path.join(DOSSIER_PERSO, user, 'files'))
|
||||
check_and_create(os.path.join(DOSSIER_PERSO, user, 'images'))
|
||||
if os.path.isfile(os.path.join(DOSSIER_PERSO,user, 'files', nom) or
|
||||
os.path.isfile(DOSSIER_PERSO, user, 'images', nom)):
|
||||
alert = "Le fichier "+str(f.filename)+" avec le même nom existe déjà, merci de spécifier un autre nom de fichier \n"
|
||||
flash(alert, 'error')
|
||||
else:
|
||||
file, ext = os.path.splitext(nom)
|
||||
if ext in extensionimg :
|
||||
f.save(DOSSIER_PERSO + user + '/images/' + nom)
|
||||
image = DOSSIER_PERSO + user + '/images/' + nom
|
||||
f.save(os.path.join(DOSSIER_PERSO, user, 'images', nom))
|
||||
image = os.path.join(DOSSIER_PERSO, user, 'images', nom)
|
||||
with Image.open(image) as img :
|
||||
img.thumbnail((300,300))
|
||||
img.save( DOSSIER_PERSO + user + '/images/thumbnails/' + nom )
|
||||
img.save(os.path.join(DOSSIER_PERSO, user, 'images','thumbnails', nom ))
|
||||
time_img_create=time.strftime("%A %d %B %Y %H:%M:%S")
|
||||
IP=request.environ['REMOTE_ADDR']
|
||||
client_platform=request.headers.get('User-Agent')
|
||||
@ -68,9 +69,9 @@ def upload():
|
||||
log.close()
|
||||
|
||||
else:
|
||||
f.save(DOSSIER_PERSO + user + '/files/' + nom)
|
||||
f.save(os.path.join(DOSSIER_PERSO, user, 'files', nom))
|
||||
time_file_upload=time.strftime("%A %d %B %Y %H:%M:%S")
|
||||
IP=request.environ['REMOTE_ADDR']
|
||||
IP=request.environ.get('REMOTE_ADDR')
|
||||
client_platform=request.headers.get('User-Agent')
|
||||
log=open("log.txt", "a") # Ouvre fichier log.txt
|
||||
log.write (time_file_upload + ' - ' + IP + ' - ' + user + ' - ' + client_platform + '\n' + '---> ' + nom + '\n') # Écrit dans log
|
||||
@ -80,43 +81,101 @@ def upload():
|
||||
|
||||
return redirect(url_for('filesupload.list'))
|
||||
|
||||
@filesupload.route( '/upload-dropzone', methods=['POST'])
|
||||
@login_required
|
||||
def drop_upload():
|
||||
user = '%s'% escape(session['username'])
|
||||
file = request.files['file']
|
||||
check_and_create(os.path.join(DOSSIER_PERSO, user, 'files'))
|
||||
check_and_create(os.path.join(DOSSIER_PERSO, user, 'images' ))
|
||||
filename = secure_filename(file.filename)
|
||||
ext = os.path.splitext(filename)
|
||||
is_image = False
|
||||
print("nom du fichier :" +filename)
|
||||
if ext in extensionimg :
|
||||
save_path = os.path.join(DOSSIER_PERSO, user, 'images', filename )
|
||||
is_image = True
|
||||
else:
|
||||
save_path = os.path.join(DOSSIER_PERSO, user, 'files', filename )
|
||||
|
||||
@filesupload.route('/view/')
|
||||
current_chunk = int(request.form['dzchunkindex'])
|
||||
print (current_chunk)
|
||||
|
||||
if (os.path.isfile(save_path) or os.path.isfile( os.path.join(DOSSIER_PERSO, user, 'images', filename ))) and current_chunk == 0:
|
||||
return make_response(('Un fichier avec le même nom existe déjà', 400))
|
||||
|
||||
try:
|
||||
with open(save_path, 'ab') as f:
|
||||
f.seek(int(request.form['dzchunkbyteoffset']))
|
||||
f.write(file.stream.read())
|
||||
except OSError:
|
||||
return make_response(("Une erreur est survenue,"
|
||||
" Impossible d'écrire le fichier sur le disque", 500))
|
||||
total_chunks = int(request.form['dztotalchunkcount'])
|
||||
if current_chunk + 1 == total_chunks:
|
||||
# This was the last chunk, the file should be complete and the size we expect
|
||||
if os.path.getsize(save_path) != int(request.form['dztotalfilesize']):
|
||||
return make_response(('La taille du fichier source est différentes', 500))
|
||||
else:
|
||||
time_file_upload=time.strftime("%A %d %B %Y %H:%M:%S")
|
||||
IP=request.environ['REMOTE_ADDR']
|
||||
client_platform=request.headers.get('User-Agent')
|
||||
log=open("log.txt", "a") # Ouvre fichier log.txt
|
||||
log.write (time_file_upload + ' - ' + IP + ' - ' + user + ' - ' + client_platform + '\n' + '---> ' + filename + '\n') # Écrit dans log
|
||||
log.close() # Ferme log.txt
|
||||
|
||||
if is_image :
|
||||
with Image.open(save_path) as img :
|
||||
img.thumbnail((300,300))
|
||||
img.save(os.path.join(DOSSIER_PERSO, user, 'images', 'thumbnails', filename ) )
|
||||
|
||||
return make_response(('Chunk upload succesfull', 200))
|
||||
|
||||
@filesupload.route('/view/', methods=['GET'])
|
||||
@login_required
|
||||
def list():
|
||||
|
||||
user = '%s'% escape(session['username'])
|
||||
|
||||
check_and_create(DOSSIER_PUBLIC + user + '/files/')
|
||||
check_and_create(DOSSIER_PERSO + user + '/files/')
|
||||
files_public = os.listdir(DOSSIER_PUBLIC + user + '/files/')
|
||||
files_private = os.listdir(DOSSIER_PERSO + user + '/files/')
|
||||
listFilesPublic = []
|
||||
listFilesPrivate = []
|
||||
nb_pv = 0
|
||||
size=0
|
||||
if files_private:
|
||||
for fich in files_private:
|
||||
nb_pv += 1
|
||||
size = getFileSizeMo(DOSSIER_PERSO + user + '/files/' + fich) # size = taille des fichiers
|
||||
listFilesPrivate.append([nb_pv, fich, size]) # On implémente la listeFichiers avec le num le ficier et sa taille
|
||||
|
||||
nb_pu = 0
|
||||
if files_public:
|
||||
for fich in files_public:
|
||||
nb_pu += 1
|
||||
size = getFileSizeMo(DOSSIER_PUBLIC + user + '/files/' + fich) # size = taille des fichiers
|
||||
listFilesPublic.append([nb_pu, fich, size])
|
||||
check_and_create(os.path.join(DOSSIER_PUBLIC, user, 'files'))
|
||||
check_and_create(os.path.join(DOSSIER_PERSO, user, 'files'))
|
||||
|
||||
return render_template('files.html',
|
||||
section="Files",
|
||||
BASE_URL=BASE_URL,
|
||||
username=user)
|
||||
|
||||
|
||||
@filesupload.route('/files/<status>/', methods=['GET'])
|
||||
@login_required
|
||||
def list_files(status: str ):
|
||||
user = '%s' % escape(session['username'])
|
||||
listFiles = []
|
||||
nb_files = 0
|
||||
size=0
|
||||
folder=""
|
||||
|
||||
if status == "public":
|
||||
folder=DOSSIER_PUBLIC
|
||||
else:
|
||||
folder=DOSSIER_PERSO
|
||||
|
||||
files = os.listdir(os.path.join(folder, user, 'files'))
|
||||
|
||||
if files:
|
||||
for fich in files:
|
||||
nb_files += 1
|
||||
size = getFileSizeMo(os.path.join(folder, user, 'files', fich)) # size = taille des fichiers
|
||||
listFiles.append([nb_files, fich, size]) # On implémente la listeFichiers avec le num le ficier et sa taille
|
||||
resp = "<h2> Bonjour " + user +" ça va bien putain ca marche ? </h2>"
|
||||
|
||||
return render_template('list_files.html',
|
||||
BASE_URL=BASE_URL,
|
||||
status=status,
|
||||
size=size,
|
||||
username=user,
|
||||
nb_pv=nb_pv,
|
||||
nb_pu=nb_pu,
|
||||
listFilesPrivate=listFilesPrivate,
|
||||
listFilesPublic=listFilesPublic)
|
||||
nb_files=nb_files,
|
||||
listFiles=listFiles)
|
||||
|
||||
|
||||
@filesupload.route('/myfiles/<username>/<filename>')
|
||||
@ -130,11 +189,9 @@ def myfiles(username, filename):
|
||||
@login_required
|
||||
def move_public(filename):
|
||||
user = '%s' % escape(session['username'])
|
||||
check_and_create(DOSSIER_PUBLIC + user + '/files/')
|
||||
check_and_create(DOSSIER_PERSO + user + '/files/')
|
||||
|
||||
src = os.path.join(DOSSIER_PERSO, user, 'files', filename)
|
||||
dst = os.path.join(DOSSIER_PUBLIC, user, 'files/')
|
||||
dst = os.path.join(DOSSIER_PUBLIC, user, 'files')
|
||||
move (src, dst)
|
||||
return redirect(url_for('filesupload.list', _external=True))
|
||||
|
||||
@ -142,10 +199,8 @@ def move_public(filename):
|
||||
@login_required
|
||||
def move_private(filename):
|
||||
user = '%s' % escape(session['username'])
|
||||
check_and_create(DOSSIER_PUBLIC + user + '/files/')
|
||||
check_and_create(DOSSIER_PERSO + user + '/files/')
|
||||
src = os.path.join(DOSSIER_PUBLIC, user, 'files', filename)
|
||||
dst = os.path.join(DOSSIER_PERSO, user, 'files/')
|
||||
dst = os.path.join(DOSSIER_PERSO, user, 'files')
|
||||
move (src, dst)
|
||||
return redirect(url_for('filesupload.list', _external=True))
|
||||
|
||||
@ -158,7 +213,7 @@ def remove_privateFile(filename):
|
||||
user = '%s' % escape(session['username'])
|
||||
filename = secure_filename(filename)
|
||||
try:
|
||||
os.remove(DOSSIER_PERSO + user + '/files/' + filename) # on le supprime
|
||||
os.remove( os.path.join(DOSSIER_PERSO, user, 'files', filename)) # on le supprime
|
||||
except FileNotFoundError:
|
||||
flash(u'Fichier {filename} inexistant.'.format(filename=filename), 'error')
|
||||
return redirect(url_for('filesupload.list', _external=True))
|
||||
@ -170,7 +225,7 @@ def remove_publicFile(filename):
|
||||
user = '%s' % escape(session['username'])
|
||||
filename = secure_filename(filename)
|
||||
try:
|
||||
os.remove(DOSSIER_PUBLIC + user + '/files/' + filename) # on le supprime
|
||||
os.remove( os.path.join(DOSSIER_PUBLIC, user, 'files', filename)) # on le supprime
|
||||
except FileNotFoundError:
|
||||
flash(u'Fichier {filename} inexistant.'.format(filename=filename), 'error')
|
||||
return redirect(url_for('filesupload.list', _external=True))
|
||||
@ -179,8 +234,8 @@ def remove_publicFile(filename):
|
||||
@filesupload.route('/<author>/blog.css')
|
||||
def blog_theme(author):
|
||||
user = author
|
||||
if os.path.isfile(DOSSIER_PERSO+ user +'/blog.css'):
|
||||
return send_file(DOSSIER_PERSO+ user +'/blog.css', mimetype='text/css')
|
||||
if os.path.isfile(os.path.join(DOSSIER_PERSO, user,'blog.css')):
|
||||
return send_file(os.path.join(DOSSIER_PERSO, user, 'blog.css'), mimetype='text/css')
|
||||
else:
|
||||
return send_file("/static/blog.css", mimetype='text/css')
|
||||
|
||||
@ -188,8 +243,8 @@ def blog_theme(author):
|
||||
def theme():
|
||||
if 'username' in session:
|
||||
user = '%s' % escape(session['username'])
|
||||
if os.path.isfile(DOSSIER_PERSO+ user +'/theme.min.css'):
|
||||
return send_file(DOSSIER_PERSO+ user +'/theme.min.css', mimetype='text/css')
|
||||
if os.path.isfile(os.path.join(DOSSIER_PERSO, user,'theme.min.css')):
|
||||
return send_file(os.path.join(DOSSIER_PERSO, user,'theme.min.css'), mimetype='text/css')
|
||||
|
||||
return send_file("static/default.min.css", mimetype='text/css')
|
||||
|
||||
|
||||
@ -9,7 +9,7 @@ import subprocess
|
||||
from shutil import copy
|
||||
from socket import gethostname
|
||||
from flask_bcrypt import Bcrypt
|
||||
from tools.utils import email_disp, append_to_log, gen_token, valid_passwd, valid_token_register, get_user_by_token, totp_is_valid, login_required
|
||||
from tools.utils import email_disp, append_to_log, gen_token, valid_passwd, valid_token_register, get_user_by_token, totp_is_valid, login_required, valid_email
|
||||
from pyotp import random_base32
|
||||
from tools.filesutils import check_and_create
|
||||
import qrcode
|
||||
@ -73,18 +73,20 @@ def profile() :
|
||||
os.path.join(DOSSIER_PERSO, user ,'theme.min.css') )
|
||||
|
||||
if request.form['nom']:
|
||||
profil_user['nom'] = request.form['nom']
|
||||
profil_user['nom'] = str(request.form['nom'])
|
||||
if request.form['prenom']:
|
||||
profil_user['prenom'] = request.form['prenom']
|
||||
profil_user['prenom'] = str(request.form['prenom'])
|
||||
if request.form['age']:
|
||||
profil_user['age'] = request.form['age']
|
||||
if '@' in request.form['mail_rescue']:
|
||||
if len(request.form['mail_rescue']) > 4:
|
||||
profil_user['mail_rescue'] = request.form['mail_rescue']
|
||||
profil_user['age'] = str(request.form['age'])
|
||||
|
||||
if request.form['mail_rescue'] :
|
||||
new_mail_rescue = str(request.form['mail_rescue'])
|
||||
if valid_email(new_mail_rescue):
|
||||
profil_user['mail_rescue']=new_mail_rescue
|
||||
else:
|
||||
flash(u'Adresse de courriel invalide', 'error')
|
||||
else:
|
||||
flash(u'Adresse de courriel de secour invalide', 'error')
|
||||
|
||||
|
||||
if f: # On vérifie qu'un fichier a bien été envoyé
|
||||
nom = secure_filename(f.filename)
|
||||
f.save(os.path.join(DOSSIER_PERSO, user, 'profile', nom))
|
||||
@ -98,7 +100,6 @@ def profile() :
|
||||
cursor.execute("UPDATE users SET avatar=? WHERE name=?",
|
||||
(filename, user))
|
||||
conn.commit()
|
||||
cursor = conn.cursor() # Création de l'objet "curseur"
|
||||
conn.close()
|
||||
flash(u'Image de profil mise à jour', 'success')
|
||||
|
||||
@ -109,7 +110,7 @@ def profile() :
|
||||
(profil_user['nom'], profil_user['prenom'], profil_user['age'], profil_user['mail_rescue'],
|
||||
user))
|
||||
conn.commit()
|
||||
flash(u'Le profil a été mis à jour', 'succes')
|
||||
flash(u'Le profil a été mis à jour', 'success')
|
||||
|
||||
|
||||
|
||||
@ -195,7 +196,7 @@ def change_passwd() :
|
||||
if not(account['totp']):
|
||||
account['totp'] = random_base32()
|
||||
img = qrcode.make('otpauth://totp/'+BASE_URL+'?secret='+account['totp'])
|
||||
img.save(DOSSIER_PERSO + user + "/totp.png")
|
||||
img.save(os.path.join(DOSSIER_PERSO, user, "totp.png"))
|
||||
shared_key_validate = False
|
||||
|
||||
return render_template('mypassword.html',
|
||||
@ -302,7 +303,7 @@ def set_totp():
|
||||
cursor.execute("""UPDATE users SET totp=? WHERE name=?""", (shared_key, user,))
|
||||
conn.commit()
|
||||
img = qrcode.make('otpauth://totp/'+BASE_URL+'?secret='+shared_key)
|
||||
img.save(DOSSIER_PERSO + user + "/totp.png")
|
||||
img.save(os.path.join(DOSSIER_PERSO, user, "totp.png"))
|
||||
flash(u'Votre mot de passe à usage unique est configuré et actif.', 'success')
|
||||
else:
|
||||
flash(u'Le code de validation totp n\'est pas valide.', 'error')
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user