#!/usr/bin/env python # # Copyright 2010 Wojciech 'KosciaK' Pietrzok # # 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. # # ---------------------------------------------------------------------- # # Icons used: # famfamfam's "Silk" icon set - http://www.famfamfam.com/lab/icons/silk/ # __author__ = "Wojciech 'KosciaK' Pietrzok (kosciak@kosciak.net), Tommy MacWilliam (macwilliamt@gmail.com)" __version__ = "0.4.3" import sys import os import time import locale import re from optparse import OptionParser locale.setlocale(locale.LC_ALL, '') LANG, ENCODING = locale.getlocale() DATE_FORMAT = '%Y-%m-%d %H:%M:%S' TABLE_HEADERS = {'en_GB': ('Name', 'Size', 'Last Modified'), 'pl_PL': ('Nazwa', 'Rozmiar', 'Czas modyfikacji')} SCRIPT_WWW = 'http://code.google.com/p/kosciak-misc/wiki/DropboxIndex' #FILES_URL = 'http://dl.dropboxusercontent.com/u/69843/dropbox-index' FILES_URL = 'http://bspk.rs/dropbox-index' ICONS = ( '%s/icons/back.png' % FILES_URL, '%s/icons/folder.png' % FILES_URL, '%s/icons/file.png' % FILES_URL, '%s/icons/image.png' % FILES_URL, '%s/icons/video.png' % FILES_URL, '%s/icons/music.png' % FILES_URL, '%s/icons/archive.png' % FILES_URL, '%s/icons/package.png' % FILES_URL, '%s/icons/pdf.png' % FILES_URL, '%s/icons/txt.png' % FILES_URL, '%s/icons/markup.png' % FILES_URL, '%s/icons/code.png' % FILES_URL, '%s/icons/font.png' % FILES_URL, '%s/icons/document.png' % FILES_URL, '%s/icons/spreadsheet.png' % FILES_URL, '%s/icons/presentation.png' % FILES_URL, '%s/icons/application.png' % FILES_URL, '%s/icons/plugin.png' % FILES_URL, '%s/icons/iso.png' % FILES_URL, ) FILE_TYPES = { ('gif', 'jpg', 'jpeg', 'png', 'bmp', 'tif', 'tiff', 'raw', 'img', 'ico', ): 'image', ('avi', 'ram', 'mpg', 'mpeg', 'mov', 'asf', 'wmv', 'asx', 'ogm', 'vob', '3gp', ): 'video', ('mp3', 'ogg', 'mpc', 'wav', 'wave', 'flac', 'shn', 'ape', 'mid', 'midi', 'wma', 'rm', 'aac', 'mka', ): 'music', ('tar', 'bz2', 'gz', 'arj', 'rar', 'zip', '7z', ): 'archive', ('deb', 'rpm', 'pkg', 'jar', 'war', 'ear', ): 'package', ('pdf', ): 'pdf', ('txt', ): 'txt', ('html', 'htm', 'xml', 'css', 'rss', 'yaml', 'php', 'php3', 'php4', 'php5', ): 'markup', ('js', 'py', 'pl', 'java', 'c', 'h', 'cpp', 'hpp', 'sql', ): 'code', ('ttf', 'otf', 'fnt', ): 'font', ('doc', 'rtf', 'odt', 'abw', 'docx', 'sxw', ): 'document', ('xls', 'ods', 'csv', 'sdc', 'xlsx', ): 'spreadsheet', ('ppt', 'odp', 'pptx', ): 'presentation', ('exe', 'msi', 'bin', 'dmg', ): 'application', ('xpi', ): 'plugin', ('iso', 'nrg', ): 'iso', } HTML_STYLE = ''' ''' % ICONS HTML_JAVASCRIPT = ''' ''' % (FILES_URL, FILES_URL) FAVICON = '' % FILES_URL HTML_START = ''' %(PATH)s %(FAVICON)s %(HTML_STYLE)s %(HTML_JAVASCRIPT)s ''' HTML_HEADER = '

%s

' HTML_TABLE_START = ''' ''' HTML_BACK = '' HTML_DIR = '\n' HTML_FILE = '\n' HTML_TABLE_END = '''
%s%s%s
..  
%(file_name)s %(file_time)s
%(file_base_name)s%(file_size)s%(file_time)s
''' HTML_DIR_INFO = '''
%(DIR_INFO)s
''' HTML_END = ''' ''' def sorted_nicely( l ): """ Sort the given iterable in the way that humans expect.""" convert = lambda text: int(text) if text.isdigit() else text alphanum_key = lambda key: [ convert(c) for c in re.split('([0-9]+)', key) ] return sorted(l, key = alphanum_key) def table_headers(): if LANG in TABLE_HEADERS: return TABLE_HEADERS[LANG] else: return TABLE_HEADERS['en_GB'] def get_size(file): size = os.path.getsize(file) if size < 1000: return '%s bytes' % size kilo = size / 1024 if kilo < 1000: return '%s KB' % round(float(size) / 1024, 1) mega = kilo / 1024 return '%s MB' % round(float(kilo) / 1024, 1) def get_filetype(file_name): filetype = file_name.split('.')[-1].lower() for keys, value in FILE_TYPES.items(): if filetype in keys: return ' %s' % value return '' def html_render(path, back, dirs, files, template_file=None): global PATH PATH = os.path.basename(os.path.realpath(path)) adfly_url = os.environ['ADFLYURL'] dropbox_url = None public_path = os.environ['DROPBOXPUBLICHOME'] use_adfly = True dir_info = None for file in files: file_name = os.path.basename(file) if 'dir-info' in file_name: dir_info = open(file, 'r').read() continue if 'no-adfly' in file_name: use_adfly = False continue if use_adfly: dropbox_url = 'http://' + adfly_url + os.environ['DROPBOXPUBLICURL'] else: dropbox_url = 'http://' + os.environ['DROPBOXPUBLICURL'] index = open(os.path.join(path, 'index.html'), 'w') if template_file: global DIR_INFO DIR_INFO = dir_info or '' template = open(template_file, 'r').read() head_start = template.find('') + 6 table_start = template.find('%(FILES)s') index.write(template[0:head_start] % globals()) index.write(HTML_STYLE + HTML_JAVASCRIPT) index.write(template[head_start:table_start] % globals()) else: index.write(HTML_START % globals()) index.write(HTML_HEADER % PATH) index.write(HTML_TABLE_START % table_headers()) if back: index.write(HTML_BACK) for file in dirs: file_name = os.path.basename(file) file_time = time.strftime(DATE_FORMAT, time.localtime(os.path.getmtime(file))) file_time_sort = os.path.getmtime(file) index.write(HTML_DIR % locals()) for file in files: file_base_name = os.path.basename(file) file_name = dropbox_url + os.path.relpath(file, public_path).replace('\\','/') if 'dir-info' in file_name or 'no-adfly' in file_name: continue file_type = get_filetype(file_name) file_size = get_size(file) file_size_sort = os.path.getsize(file) file_time = time.strftime(DATE_FORMAT, time.localtime(os.path.getmtime(file))) file_time_sort = os.path.getmtime(file) index.write(HTML_FILE % locals()) now = time.strftime(DATE_FORMAT, time.localtime()) index.write(HTML_TABLE_END % (now, SCRIPT_WWW, __version__)) if template_file: DIR_INFO = dir_info or '' index.write(template[table_start+9:] % globals()) DIR_INFO = None else: index.write(HTML_DIR_INFO % {'DIR_INFO': dir_info or ''}) index.write(HTML_END) def crawl(path, back=None, recursive=False, template_file=None): if not os.path.exists(path): print 'ERROR: Path %s does not exists' % path return if not os.path.isdir(path): print 'ERROR: Path %s is not a directory' % path return # get contents of the directory contents = [os.path.join(path, file) for file in os.listdir(path) if not file.endswith('index.html')] # remove hidden files # TODO: identify Windows hidden files contents = [file for file in contents if not os.path.basename(file).startswith('.')] # get only files # filename sort: files = [file for file in contents if os.path.isfile(file)] #files.sort(key=str.lower) files = sorted_nicely(files) # date sort (changed to natural sort 9/24/2013): # files = [(file, os.path.getmtime(file)) for file in contents if os.path.isfile(file)] # file_date_tuple_list = [(x,os.path.getmtime(x)) for x in files] <- not sure what this is # files.sort(key=lambda file: file[1]) files.reverse() # get only directories if recursive: dirs = [file for file in contents if os.path.isdir(file)] dirs.sort(key=str.lower) else: dirs = []; # render directory contents html_render(path, back, dirs, files, template_file) print 'Created index.html for %s' % os.path.realpath(path) # crawl subdirectories for dir in dirs: crawl(dir, path, recursive, template_file) def run(): epilog = '''ATTENTION: Script will overwrite any existing index.html file(s)! ''' parser = OptionParser(version='%prog ' + __version__, usage="%prog [options] DIRECTORY", epilog=epilog) parser.add_option('-R', '--recursive', action='store_true', default=False, help='Include subdirectories [default: %default]') parser.add_option('-T', '--template', help='Use HTML file as template') options, args = parser.parse_args() if not args: parser.print_help() sys.exit() crawl(path=args[0], recursive=options.recursive, template_file=options.template) if __name__ == '__main__': run()