bspkrs

dropbox-index

Dec 22nd, 2013
607
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 15.08 KB | None | 0 0
  1. #!/usr/bin/env python
  2. #
  3. # Copyright 2010 Wojciech 'KosciaK' Pietrzok
  4. #
  5. # Licensed under the Apache License, Version 2.0 (the "License");
  6. # you may not use this file except in compliance with the License.
  7. # You may obtain a copy of the License at
  8. #
  9. #     http://www.apache.org/licenses/LICENSE-2.0
  10. #
  11. # Unless required by applicable law or agreed to in writing, software
  12. # distributed under the License is distributed on an "AS IS" BASIS,
  13. # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  14. # See the License for the specific language governing permissions and
  15. # limitations under the License.
  16. #
  17. # ----------------------------------------------------------------------
  18. #
  19. # Icons used:
  20. # famfamfam's "Silk" icon set - http://www.famfamfam.com/lab/icons/silk/
  21. #
  22.  
  23. __author__ = "Wojciech 'KosciaK' Pietrzok ([email protected]), Tommy MacWilliam ([email protected])"
  24. __version__ = "0.4.3"
  25.  
  26. import sys
  27. import os
  28. import time
  29. import locale
  30. import re
  31. from optparse import OptionParser
  32.  
  33.  
  34. locale.setlocale(locale.LC_ALL, '')
  35. LANG, ENCODING = locale.getlocale()
  36.  
  37. DATE_FORMAT = '%Y-%m-%d %H:%M:%S'
  38.  
  39. TABLE_HEADERS = {'en_GB': ('Name', 'Size', 'Last Modified'),
  40.                  'pl_PL': ('Nazwa', 'Rozmiar', 'Czas modyfikacji')}
  41.  
  42. SCRIPT_WWW = 'http://code.google.com/p/kosciak-misc/wiki/DropboxIndex'
  43.  
  44. #FILES_URL = 'http://dl.dropboxusercontent.com/u/69843/dropbox-index'
  45. FILES_URL = 'http://bspk.rs/dropbox-index'
  46.  
  47. ICONS = (
  48.     '%s/icons/back.png' % FILES_URL,
  49.     '%s/icons/folder.png' % FILES_URL,
  50.     '%s/icons/file.png' % FILES_URL,
  51.     '%s/icons/image.png' % FILES_URL,
  52.     '%s/icons/video.png' % FILES_URL,
  53.     '%s/icons/music.png' % FILES_URL,
  54.     '%s/icons/archive.png' % FILES_URL,
  55.     '%s/icons/package.png' % FILES_URL,
  56.     '%s/icons/pdf.png' % FILES_URL,
  57.     '%s/icons/txt.png' % FILES_URL,
  58.     '%s/icons/markup.png' % FILES_URL,
  59.     '%s/icons/code.png' % FILES_URL,
  60.     '%s/icons/font.png' % FILES_URL,
  61.     '%s/icons/document.png' % FILES_URL,
  62.     '%s/icons/spreadsheet.png' % FILES_URL,
  63.     '%s/icons/presentation.png' % FILES_URL,
  64.     '%s/icons/application.png' % FILES_URL,
  65.     '%s/icons/plugin.png' % FILES_URL,
  66.     '%s/icons/iso.png' % FILES_URL,
  67.     )
  68.  
  69. FILE_TYPES = {
  70.     ('gif', 'jpg', 'jpeg', 'png', 'bmp', 'tif', 'tiff', 'raw', 'img', 'ico', ): 'image',
  71.     ('avi', 'ram', 'mpg', 'mpeg', 'mov', 'asf', 'wmv', 'asx', 'ogm', 'vob', '3gp', ): 'video',
  72.     ('mp3', 'ogg', 'mpc', 'wav', 'wave', 'flac', 'shn', 'ape', 'mid', 'midi', 'wma', 'rm', 'aac', 'mka', ): 'music',
  73.     ('tar', 'bz2', 'gz', 'arj', 'rar', 'zip', '7z', ): 'archive',
  74.     ('deb', 'rpm', 'pkg', 'jar', 'war', 'ear', ): 'package',
  75.     ('pdf', ): 'pdf',
  76.     ('txt', ): 'txt',
  77.     ('html', 'htm', 'xml', 'css', 'rss', 'yaml', 'php', 'php3', 'php4', 'php5', ): 'markup',
  78.     ('js', 'py', 'pl', 'java', 'c', 'h', 'cpp', 'hpp', 'sql', ): 'code',
  79.     ('ttf', 'otf', 'fnt', ): 'font',
  80.     ('doc', 'rtf', 'odt', 'abw', 'docx', 'sxw', ): 'document',
  81.     ('xls', 'ods', 'csv', 'sdc', 'xlsx', ): 'spreadsheet',
  82.     ('ppt', 'odp', 'pptx', ): 'presentation',
  83.     ('exe', 'msi', 'bin', 'dmg', ): 'application',
  84.     ('xpi', ): 'plugin',
  85.     ('iso', 'nrg', ): 'iso',
  86.     }
  87.  
  88. HTML_STYLE = '''
  89.    <style>
  90.        body { font-family: Verdana, sans-serif; font-size: 12px;}
  91.        a { text-decoration: none; color: #00A; }
  92.        a:hover { text-decoration: underline; }
  93.        #dropbox-index-header { padding: 0; margin: 0.5em auto 0.5em 1em; }
  94.        table#dropbox-index-list { text-align: center; margin: 0 auto 0 1.5em; border-collapse: collapse; }
  95.        #dropbox-index-list thead { border-bottom: 1px solid #555; }
  96.        #dropbox-index-list th:hover { cursor: pointer; cursor: hand; background-color: #EEE; }
  97.        #direction { border: 0; vertical-align: bottom; margin: 0 0.5em;}
  98.        #dropbox-index-list tbody { border-bottom: 1px solid #555;}
  99.        #dropbox-index-list tr, th { line-height: 1.7em; min-height: 25px; }
  100.        #dropbox-index-list tbody tr:hover { background-color: #EEE; }
  101.        .name { text-align: left; width: 35em; }
  102.        .name a, thead .name { padding-left: 22px; }
  103.        .name a { display: block; }
  104.        .size { text-align: right; width: 7em; padding-right: 1em;}
  105.        .date { text-align: right; width: 15em; padding-right: 1em;}
  106.        #dropbox-index-dir-info { margin: 1em auto 0.5em 2em; }
  107.        #dropbox-index-footer { margin: 1em auto 0.5em 2em; font-size: smaller;}
  108.        /* Icons */
  109.        .dir, .back, .file { background-repeat: no-repeat; background-position: 2px 4px;}
  110.        .back { background-image: url('%s'); }
  111.        .dir { background-image: url('%s'); }
  112.        .file { background-image: url('%s'); }
  113.        .image { background-image: url('%s'); }
  114.        .video { background-image: url('%s'); }
  115.        .music { background-image: url('%s'); }
  116.        .archive { background-image: url('%s'); }
  117.        .package { background-image: url('%s'); }
  118.        .pdf { background-image: url('%s'); }
  119.        .txt { background-image: url('%s'); }
  120.        .markup { background-image: url('%s'); }
  121.        .code { background-image: url('%s'); }
  122.        .font { background-image: url('%s'); }
  123.        .document { background-image: url('%s'); }
  124.        .spreadsheet { background-image: url('%s'); }
  125.        .presentation { background-image: url('%s'); }
  126.        .application { background-image: url('%s'); }
  127.        .plugin { background-image: url('%s'); }
  128.        .iso { background-image: url('%s'); }
  129.    </style>''' % ICONS
  130.  
  131. HTML_JAVASCRIPT = '''
  132.    <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js"></script>
  133.    <script>
  134.    function sort() {
  135.        column = $(this).attr("class").split(' ')[0];
  136.        $("#direction").remove();
  137.        if ($(this).hasClass("desc")) {
  138.            $("#dropbox-index-list thead tr th").each(function(i) { $(this).removeClass("asc").removeClass("desc") });
  139.            $(this).addClass("asc");
  140.            reverse = -1;
  141.        } else {
  142.            $("#dropbox-index-list thead tr th").each(function(i) { $(this).removeClass("asc").removeClass("desc") });
  143.            $(this).addClass("desc");
  144.            reverse = 1;
  145.        }
  146.        if (column == "name") {
  147.            $(this).append('<img src="%s/icons/'+((reverse == 1) ? 'desc' : 'asc')+'.png" id="direction" />');
  148.        } else {
  149.            $(this).prepend('<img src="%s/icons/'+((reverse == 1) ? 'desc' : 'asc')+'.png" id="direction" />');
  150.        }
  151.        rows = $("#dropbox-index-list tbody tr").detach()
  152.        rows.sort(function(a, b) {
  153.            result = $(a).data('type') - $(b).data('type')
  154.            if (result != 0) { return result }
  155.            
  156.            return (($(a).data(column) < $(b).data(column)) - ($(a).data(column) > $(b).data(column))) * reverse
  157.            
  158.        });
  159.        $("#dropbox-index-list tbody").append(rows);
  160.    }
  161.    
  162.    function prepare() {
  163.        $("#dropbox-index-list tbody tr").each(function(i) {
  164.            if ($(this).children(".name").hasClass("back")) {
  165.                $(this).data('type', 1);
  166.            } else if ($(this).children(".name").hasClass("dir")) {
  167.                $(this).data('type', 2);
  168.            } else {
  169.                $(this).data('type', 3);
  170.            }
  171.            $(this).data('name', $(this).children(".name").text().toLowerCase());
  172.            $(this).data('size', parseInt($(this).children(".size").attr("sort")));
  173.            $(this).data('date', parseInt($(this).children(".date").attr("sort")));
  174.        });
  175.        
  176.        $("#dropbox-index-list thead tr th").each(function(i) {
  177.            $(this).bind('click', sort);
  178.        });
  179.    }
  180.  
  181.    $(document).ready(function(){
  182.        prepare();
  183.    });
  184. </script>''' % (FILES_URL, FILES_URL)
  185.  
  186. FAVICON = '<link rel="shortcut icon" href="%s/icons/favicon.ico"/>' % FILES_URL
  187.  
  188. HTML_START = '''<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
  189. <html>
  190. <head>
  191.    <meta http-equiv="Content-Type" content="text/html; charset="%(ENCODING)s"/>
  192.    <title>%(PATH)s</title>
  193.    %(FAVICON)s
  194.    %(HTML_STYLE)s
  195.    %(HTML_JAVASCRIPT)s
  196. </head>
  197. <body>
  198. '''
  199. HTML_HEADER = '<h1 id="dropbox-index-header">%s</h1>'
  200. HTML_TABLE_START = '''
  201. <table id="dropbox-index-list">
  202.    <thead>
  203.        <tr>
  204.            <th class="name">%s</th><th class="size">%s</th><th class="date">%s</th>
  205.        </tr>
  206.    </thead>
  207.    <tbody>
  208. '''
  209. HTML_BACK = '<tr><td class="name back"><a href="../index.html">..</a></td><td class="size">&nbsp;</td><td class="date">&nbsp;</td></tr>'
  210. HTML_DIR = '<tr><td class="name dir"><a href="%(file_name)s/index.html">%(file_name)s</a></td><td class="size">&nbsp;</td><td class="date" sort="%(file_time_sort)s">%(file_time)s</td></tr>\n'
  211. HTML_FILE = '<tr><td class="name file%(file_type)s"><a href="%(file_name)s">%(file_base_name)s</a></td><td class="size" sort="%(file_size_sort)s">%(file_size)s</td><td class="date" sort="%(file_time_sort)s">%(file_time)s</td></tr>\n'
  212. HTML_TABLE_END = '''
  213.    </tbody>
  214. </table>
  215. <div id="dropbox-index-footer">Generated on <strong>%s</strong> using <a href="%s">Dropbox-index</a>-%s</a></div>'''
  216. HTML_DIR_INFO = '''
  217. <div id="dropbox-index-dir-info">
  218. %(DIR_INFO)s
  219. </div>'''
  220. HTML_END = '''
  221. </body>
  222. </html>'''
  223.  
  224. def sorted_nicely( l ):
  225.     """ Sort the given iterable in the way that humans expect."""
  226.     convert = lambda text: int(text) if text.isdigit() else text
  227.     alphanum_key = lambda key: [ convert(c) for c in re.split('([0-9]+)', key) ]
  228.     return sorted(l, key = alphanum_key)
  229.  
  230.  
  231. def table_headers():
  232.     if LANG in TABLE_HEADERS:
  233.         return TABLE_HEADERS[LANG]
  234.     else:
  235.         return TABLE_HEADERS['en_GB']
  236.    
  237.  
  238. def get_size(file):
  239.     size = os.path.getsize(file)
  240.    
  241.     if size < 1000:
  242.         return '%s bytes' % size
  243.    
  244.     kilo = size / 1024
  245.     if kilo < 1000:
  246.         return '%s KB' % round(float(size) / 1024, 1)
  247.    
  248.     mega = kilo / 1024
  249.     return '%s MB' % round(float(kilo) / 1024, 1)
  250.  
  251.  
  252. def get_filetype(file_name):
  253.     filetype = file_name.split('.')[-1].lower()
  254.     for keys, value in FILE_TYPES.items():
  255.         if filetype in keys:
  256.             return ' %s' % value
  257.     return ''
  258.  
  259.  
  260. def html_render(path, back, dirs, files, template_file=None):
  261.     global PATH
  262.     PATH = os.path.basename(os.path.realpath(path))
  263.    
  264.     adfly_url = os.environ['ADFLYURL']
  265.     dropbox_url = None
  266.     public_path = os.environ['DROPBOXPUBLICHOME']
  267.        
  268.     use_adfly = True
  269.     dir_info = None
  270.     for file in files:
  271.         file_name = os.path.basename(file)
  272.         if 'dir-info' in file_name:
  273.             dir_info = open(file, 'r').read()
  274.             continue
  275.         if 'no-adfly' in file_name:
  276.             use_adfly = False
  277.             continue
  278.            
  279.     if use_adfly:
  280.         dropbox_url = 'http://' + adfly_url + os.environ['DROPBOXPUBLICURL']
  281.     else:
  282.         dropbox_url = 'http://' + os.environ['DROPBOXPUBLICURL']
  283.    
  284.     index = open(os.path.join(path, 'index.html'), 'w')
  285.    
  286.     if template_file:
  287.         global DIR_INFO
  288.         DIR_INFO = dir_info or ''
  289.         template = open(template_file, 'r').read()
  290.         head_start = template.find('<head>') + 6
  291.         table_start = template.find('%(FILES)s')
  292.         index.write(template[0:head_start] % globals())
  293.         index.write(HTML_STYLE + HTML_JAVASCRIPT)
  294.         index.write(template[head_start:table_start] % globals())
  295.     else:
  296.         index.write(HTML_START % globals())
  297.         index.write(HTML_HEADER % PATH)
  298.    
  299.     index.write(HTML_TABLE_START % table_headers())
  300.    
  301.     if back:
  302.         index.write(HTML_BACK)
  303.    
  304.     for file in dirs:
  305.         file_name = os.path.basename(file)
  306.         file_time = time.strftime(DATE_FORMAT, time.localtime(os.path.getmtime(file)))
  307.         file_time_sort = os.path.getmtime(file)
  308.         index.write(HTML_DIR % locals())
  309.    
  310.     for file in files:
  311.         file_base_name = os.path.basename(file)
  312.         file_name = dropbox_url + os.path.relpath(file, public_path).replace('\\','/')
  313.         if 'dir-info' in file_name or 'no-adfly' in file_name:
  314.             continue
  315.         file_type = get_filetype(file_name)
  316.         file_size = get_size(file)
  317.         file_size_sort = os.path.getsize(file)
  318.         file_time = time.strftime(DATE_FORMAT, time.localtime(os.path.getmtime(file)))
  319.         file_time_sort = os.path.getmtime(file)
  320.         index.write(HTML_FILE % locals())
  321.    
  322.     now = time.strftime(DATE_FORMAT, time.localtime())
  323.     index.write(HTML_TABLE_END % (now, SCRIPT_WWW, __version__))
  324.    
  325.     if template_file:
  326.         DIR_INFO = dir_info or ''
  327.         index.write(template[table_start+9:] % globals())
  328.         DIR_INFO = None
  329.     else:
  330.         index.write(HTML_DIR_INFO % {'DIR_INFO': dir_info or ''})
  331.         index.write(HTML_END)
  332.    
  333.    
  334.  
  335. def crawl(path, back=None, recursive=False, template_file=None):
  336.     if not os.path.exists(path):
  337.         print 'ERROR: Path %s does not exists' % path
  338.         return
  339.    
  340.     if not os.path.isdir(path):
  341.         print 'ERROR: Path %s is not a directory' % path
  342.         return
  343.    
  344.     # get contents of the directory
  345.     contents = [os.path.join(path, file) for file in os.listdir(path) if not file.endswith('index.html')]
  346.     # remove hidden files
  347.     # TODO: identify Windows hidden files
  348.     contents = [file for file in contents if not os.path.basename(file).startswith('.')]
  349.    
  350.     # get only files
  351.     # filename sort:
  352.     files = [file for file in contents if os.path.isfile(file)]
  353.     #files.sort(key=str.lower)
  354.     files = sorted_nicely(files)
  355.    
  356.     # date sort (changed to natural sort 9/24/2013):
  357.     # files = [(file, os.path.getmtime(file)) for file in contents if os.path.isfile(file)]
  358.     # file_date_tuple_list = [(x,os.path.getmtime(x)) for x in files] <- not sure what this is
  359.     # files.sort(key=lambda file: file[1])
  360.    
  361.     files.reverse()
  362.    
  363.     # get only directories
  364.     if recursive:
  365.         dirs = [file for file in contents if os.path.isdir(file)]
  366.         dirs.sort(key=str.lower)
  367.     else:
  368.         dirs = [];
  369.    
  370.     # render directory contents
  371.     html_render(path, back, dirs, files, template_file)
  372.  
  373.     print 'Created index.html for %s' % os.path.realpath(path)
  374.  
  375.     # crawl subdirectories
  376.     for dir in dirs:
  377.         crawl(dir, path, recursive, template_file)
  378.    
  379.  
  380.  
  381. def run():
  382.  
  383.     epilog = '''ATTENTION:
  384. Script will overwrite any existing index.html file(s)!
  385.    '''
  386.  
  387.     parser = OptionParser(version='%prog ' + __version__,
  388.                           usage="%prog [options] DIRECTORY",
  389.                           epilog=epilog)
  390.     parser.add_option('-R', '--recursive',
  391.                       action='store_true', default=False,
  392.                       help='Include subdirectories [default: %default]')
  393.     parser.add_option('-T', '--template',
  394.                       help='Use HTML file as template')
  395.    
  396.     options, args = parser.parse_args()
  397.     if not args:
  398.         parser.print_help()
  399.         sys.exit()
  400.    
  401.     crawl(path=args[0],
  402.           recursive=options.recursive,
  403.           template_file=options.template)
  404.  
  405. if __name__ == '__main__':
  406.     run()
Advertisement
Add Comment
Please, Sign In to add comment