#!/usr/bin/env python3
# coding=utf-8
''' A script that creates an index for a folder.
'''
import os
import sys
import time
import string
import urllib.parse
from glob import fnmatch
import base64
import random
VERSION = "20200619"
IMAGE_EXTENSIONS = ['png', 'gif', 'jpg', 'jpeg', 'tif', 'tiff']
def setup():
''' Setup the command line options '''
from argparse import ArgumentParser
parser = ArgumentParser(
epilog = "Recursively generate indexes: \n# find . -type d -not -path '*/.*' -exec SimpleWebPage -f \{\} \;"
)
parser.add_argument("-f",action="store_true",dest="overwrite",default=False,
help="Overwrite existing index file, even if it's not generated with SimpleWebPage. By default, if file is generated with SimpleWebPage it will be overwritten!")
parser.add_argument("-H",action="store_true",dest="hidden",default=False,
help="Show hidden files")
parser.add_argument("-t",type=str,dest="title",default=None,
help="Name for the title (Default: Folder name)")
parser.add_argument("-o",type=str,dest="filename",default="index.html",
help="Output filename (Default: index.html)")
parser.add_argument("-p",action="store_false",dest="parent",default=True,
help="Do no print .. link for parent folder.")
parser.add_argument("--password",type=str,dest="password",default=None,
help="Set a password to view page. The file list will be written to a randomly generated filename. Note: this is not secure, as the target link will still be unprotected if known.")
parser.add_argument("-r",action="store_true",dest="recursive",default=False,
help="Include all files recursively in the list. Do not include any folders.")
parser.add_argument("--images",action="store_true",dest="images",default=False,
help="Show images with tags")
parser.add_argument("--include","-i",
action="store",
dest="includes",
default=['*'],
help="Glob match for files to be included in the table. ex. *.jpg. You can pass several includes.",
nargs = '*'
)
parser.add_argument("--version",action='version', version=VERSION)
parser.add_argument(
"path",
type=str,
action="store",
default=os.path.abspath('.'),
nargs='?',
help="Root path of the index"
)
options = parser.parse_args()
options.path = os.path.abspath(options.path)
if options.title == None:
options.title = os.path.basename(options.path)
return options
def setup2HTML(opts):
return ''%";".join([
'hidden=%s'%opts.hidden,
'parent=%s'%opts.parent,
'title=%s'%urllib.parse.quote(opts.title),
'images=%s'%opts.images
])
def HTML2setup(opts):
""" returns new opts and was it able to read HTML """
try:
read_config = False
with open(os.path.join(opts.path,opts.filename), 'rt') as f:
for l in f.readlines():
if l.find(' -1:
content = l[l.find('name="SimpleWebPageSetup"'):]
for s in content.split('"')[3].split(";"):
(k,v) = s.split('=',1)
if k == 'hidden': opts.hidden = v == "True"
if k == 'parent': opts.parent = v == "True"
if k == 'title': opts.title = urllib.parse.unquote(v)
if k == 'images': opts.images = v == "True"
read_config = True
print("Reading options from existing " + opts.filename)
break
return (opts, read_config)
except:
return (opts, False)
def get_files_and_folders(opts):
if opts.recursive:
rdirs = []
rfiles = []
rpath = None
for path, dirs, files in os.walk(opts.path):
if rpath == None:
rpath = path
if not opts.hidden:
files = [ f for f in files if not f.startswith(".")]
dirs[:] = [ d for d in dirs if not d.startswith(".")]
files = [os.path.join(os.path.relpath(path, opts.path), f) for f in files]
files = [f[2:] if f.startswith("./") else f for f in files ]
rfiles.extend(files)
return rdirs, rfiles, rpath
else:
for path, dirs, files in os.walk(opts.path):
if not opts.hidden:
files = [ f for f in files if not f.startswith(".")]
dirs = [ d for d in dirs if not d.startswith(".")]
return dirs, files, path
def generate_index(opts):
opts.password_filename = ""
dirs, files, path = get_files_and_folders(opts)
if opts.password != None:
opts.password_filename = opts.filename
opts.filename = generate_password_page(path, opts.filename, opts.password)
existing_config = False
if opts.filename in files:
opts, existing_config = HTML2setup(opts)
if not existing_config and not opts.overwrite:
print(opts.filename + " exists, and not generated with SimpleWebPage. Exiting.")
sys.exit(1)
files = [ f for f in files if f != opts.filename]
files = [ f for f in files if f != opts.password_filename]
files = match_files(files, opts.includes)
dirs.sort()
files.sort()
files.sort(key = lambda x: x.find("/") > 0)
with open(os.path.join(path,opts.filename), 'wt') as f:
f.write(get_header(opts))
if opts.parent:
f.write(get_pathlink(path, '..'))
for di in dirs:
f.write(get_pathlink(path, di))
for fi in files:
f.write(get_filelink(path, fi, opts.images))
f.write(get_footer())
f.write(get_wget_lines(files))
f.close()
return
def generate_password_page(path, password_file, password):
def ha(p):
h = 0
for c in p:
h = ((h<<5) - h) + ord(c)
h = h & 0xffffffff
if h > (1<<31) - 1:
h -= (1<<32)
return h
def scramble(p,t):
p += t
s = ''
for i in range(len(t)):
s += chr(ord(p[i]) + ord(t[i]))
return s
def enc(s):
return base64.b64encode(s.encode('latin1')).decode('ascii')
def random_string(stringLength=16):
letters = string.ascii_lowercase + string.digits
return ''.join(random.choice(letters) for i in range(stringLength))
def get_target(filename):
splitted = os.path.splitext(filename)
return (
splitted[0],
random_string(),
splitted[1]
)
target_base, target_middle, target_ext = get_target(password_file)
secret = "{}:{}".format(
ha(password),
enc(scramble(password, target_middle))
)
with open(os.path.join(path, password_file), 'wt') as f:
f.write(get_password_page(secret, target_base, target_ext))
return "{}.{}{}".format(
target_base,
target_middle,
target_ext
)
def get_filelink(path,fname,images=False):
if os.path.islink(os.path.join(path, fname)) and not os.path.exists(os.path.join(path, fname)):
(fsize, fsstr, fsstrb, fdstr)=(0, "NA", "NA", "NA")
else:
fsize = os.path.getsize(os.path.join(path, fname))
fsstr = sizeof(fsize)
fsstrb = str(fsize)
fdate = time.localtime(os.path.getmtime(os.path.join(path, fname)))
fdstr = time.strftime("%Y/%m/%d %H:%M:%S", fdate)
if images and is_imagefile(fname):
fname_str = get_imagestr(fname)
else:
fname_str = fname
return '
| Name | Size | Size B | Modified |
|---|