new
This commit is contained in:
230
code/utils/files.py
Normal file
230
code/utils/files.py
Normal file
@@ -0,0 +1,230 @@
|
||||
import os
|
||||
from datetime import datetime
|
||||
from flask import current_app as app
|
||||
import re
|
||||
import sys
|
||||
import json
|
||||
import stat
|
||||
import time
|
||||
import sqlite3
|
||||
from .misc import *
|
||||
from .crypt import *
|
||||
|
||||
|
||||
def get_db():
|
||||
db = sqlite3.connect(os.getenv("FLASK_DB"), timeout=5)
|
||||
c = db.cursor()
|
||||
return db, c
|
||||
|
||||
|
||||
def db_store_file(token, name, expires, max_dl):
|
||||
db, c = get_db()
|
||||
c.execute(
|
||||
"""
|
||||
insert into files(token,name,added,expires,downloads,max_downloads)
|
||||
values (?,?,?,?,?,?)
|
||||
""",
|
||||
(token, name, int(time.time()), expires, 0, max_dl),
|
||||
)
|
||||
if c.rowcount > 0:
|
||||
db.commit()
|
||||
return
|
||||
|
||||
|
||||
def db_get_file(token, name):
|
||||
db, c = get_db()
|
||||
return db.execute(
|
||||
"""
|
||||
SELECT added,expires,downloads,max_downloads
|
||||
FROM files WHERE token = ? AND name = ?
|
||||
""",
|
||||
(token, name),
|
||||
).fetchone()
|
||||
|
||||
def db_get_files():
|
||||
db, c = get_db()
|
||||
return db.execute(
|
||||
"""
|
||||
SELECT token,name,added,expires,downloads,max_downloads
|
||||
FROM files
|
||||
WHERE expires > ? and downloads < max_downloads
|
||||
""",
|
||||
(time.time(),),
|
||||
)
|
||||
|
||||
|
||||
def db_delete_file(token, name):
|
||||
db, c = get_db()
|
||||
c.execute(
|
||||
"""
|
||||
DELETE FROM files WHERE token = ? and name = ?
|
||||
""",
|
||||
(token, name),
|
||||
)
|
||||
if c.rowcount > 0:
|
||||
db.commit()
|
||||
|
||||
|
||||
def db_add_download(token, name):
|
||||
db, c = get_db()
|
||||
c.execute(
|
||||
"""
|
||||
UPDATE files SET downloads = downloads + 1 WHERE token = ? AND name = ?
|
||||
""",
|
||||
(token, name),
|
||||
)
|
||||
if c.rowcount > 0:
|
||||
db.commit()
|
||||
return
|
||||
|
||||
|
||||
def file_autoremove():
|
||||
db, c = get_db()
|
||||
rows = db.execute(
|
||||
"""
|
||||
select
|
||||
token, name
|
||||
from files
|
||||
where expires > ? or downloads >= max_downloads
|
||||
""",
|
||||
(int(time.time()),),
|
||||
)
|
||||
deleted_tokens = []
|
||||
for row in rows:
|
||||
try:
|
||||
os.remove(os.path.join(os.getenv("DATAFOLDER"), row[0], row[1]))
|
||||
except FileNotFoundError:
|
||||
pass
|
||||
try:
|
||||
os.rmdir(os.path.join(os.getenv("DATAFOLDER"), row[0]))
|
||||
except FileNotFoundError:
|
||||
pass
|
||||
deleted_tokens.append(row[0])
|
||||
if len(deleted_tokens) > 0:
|
||||
db, c = get_db()
|
||||
for token in deleted_tokens:
|
||||
c.execute(
|
||||
"""
|
||||
DELETE FROM files WHERE token = ?
|
||||
""",
|
||||
(token,),
|
||||
)
|
||||
db.commit()
|
||||
return
|
||||
|
||||
|
||||
def file_age(path):
|
||||
now = datetime.now()
|
||||
then = datetime.fromtimestamp(os.stat(path).st_mtime)
|
||||
diff = now - then
|
||||
return (
|
||||
diff,
|
||||
"%03d d %s"
|
||||
% (diff.days, datetime.utcfromtimestamp(diff.seconds).strftime("%H:%M:%S")),
|
||||
)
|
||||
|
||||
|
||||
def file_details(token, name):
|
||||
full_path = os.path.join(os.getenv("FLASK_DATAFOLDER"), token, name)
|
||||
try:
|
||||
s = os.stat(full_path)
|
||||
db_stat = db_get_file(token, name)
|
||||
if db_stat:
|
||||
added, expires, downloads, max_dl = db_stat
|
||||
else:
|
||||
return {}
|
||||
return {
|
||||
"size": file_size_MB(s.st_size),
|
||||
"hsize": file_size_human(s.st_size, HTML=False),
|
||||
"added": file_date_human(added),
|
||||
"name": name,
|
||||
"url": f"{app.config['PUBLIC_URL']}/dl/{token}/{name}",
|
||||
"expires": file_date_human(expires),
|
||||
"downloaded": downloads,
|
||||
"max-dl": max_dl,
|
||||
}
|
||||
except FileNotFoundError:
|
||||
return {}
|
||||
|
||||
def file_list():
|
||||
|
||||
files = list(db_get_files())
|
||||
details = []
|
||||
maxlen = 4
|
||||
for file in files:
|
||||
maxlen = max(maxlen, len(file[1]))
|
||||
details = []
|
||||
details.append(
|
||||
"Added/Expiry DL/MaxDL URL"
|
||||
)
|
||||
details.append("=" * 75)
|
||||
for file in files:
|
||||
details.append(
|
||||
" ".join((
|
||||
str(file[2]),str(file[3]),str(file[4]),str(file[5]),
|
||||
f"{app.config['PUBLIC_URL']}/dl/{file[0]}/{file[1]}"
|
||||
))
|
||||
)
|
||||
|
||||
return details
|
||||
|
||||
|
||||
def get_expiring_file(ehash):
|
||||
connection = apsw.Connection(app.config["SQLITE_FILE"])
|
||||
cursor = connection.cursor()
|
||||
|
||||
for row in cursor.execute(
|
||||
"SELECT file, expires FROM expiring WHERE hash = ?", (ehash,)
|
||||
):
|
||||
return row[0], row[1]
|
||||
return None, None
|
||||
|
||||
|
||||
def get_script_url(public_url, share, end_point, token="[TOKEN]"):
|
||||
cmd = None
|
||||
doc = None
|
||||
if get_or_none("direct_links", share) and end_point == "download":
|
||||
end_point = "direct"
|
||||
url = "%s/script/%s/%s/%s" % (public_url, end_point, share["name"], token)
|
||||
if end_point in ("download", "direct"):
|
||||
cmd = "curl -s %s | bash /dev/stdin [-f]" % (url,)
|
||||
doc = "Download all files in the share. -f to force overwrite existing files."
|
||||
if end_point == "client":
|
||||
cmd = "python <( curl -s %s )" % (url,)
|
||||
doc = "Console client to download and upload files."
|
||||
if end_point == "upload_split":
|
||||
cmd = (
|
||||
"curl -s %s | python - [-s split_size_in_Mb] file_to_upload.ext [second.file.ext]"
|
||||
% (url,)
|
||||
)
|
||||
doc = "Upload files to the share. -s to set splitting size."
|
||||
if end_point == "flip":
|
||||
cmd = "curl -s %s > flip && ./flip" % (url,)
|
||||
doc = "Use the share as a command line clipboard"
|
||||
return {"cmd": cmd, "doc": doc}
|
||||
|
||||
|
||||
def set_expiring_file(share, filename, expires):
|
||||
connection = apsw.Connection(app.config["SQLITE_FILE"])
|
||||
cursor = connection.cursor()
|
||||
|
||||
while True:
|
||||
ehash = random_expiring_hash()
|
||||
matches = len(
|
||||
list(cursor.execute("SELECT file FROM expiring WHERE hash = ?", (ehash,)))
|
||||
)
|
||||
if matches == 0:
|
||||
break
|
||||
|
||||
cursor.execute(
|
||||
"INSERT INTO expiring (hash, file, expires) VALUES (?,?,?)",
|
||||
(ehash, filename, expires),
|
||||
)
|
||||
return "/".join((app.config["PUBLIC_URL"], "e", ehash, os.path.basename(filename)))
|
||||
|
||||
|
||||
def remove_expiring_file(share, filename):
|
||||
connection = apsw.Connection(app.config["SQLITE_FILE"])
|
||||
cursor = connection.cursor()
|
||||
|
||||
cursor.execute("DELETE FROM expiring WHERE file = ?", (filename,))
|
||||
Reference in New Issue
Block a user