bspkrs

_init_.py

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