#!/usr/bin/python3 # This file is part of Elixir, a source code cross-referencer. # # Copyright (C) 2017 Mikaƫl Bouillot # # # Elixir is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 2 of the License, or # (at your option) any later version. # # Elixir is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with Elixir. If not, see . from io import StringIO realprint = print outputBuffer = StringIO() def print (arg, end='\n'): global outputBuffer outputBuffer.write (arg + end) # enable debugging import cgitb cgitb.enable() import cgi import os from re import search, sub from collections import OrderedDict ident = '' status = 200 m = search ('^/([^/]*)/([^/]*)/([^/]*)(.*)$', os.environ['SCRIPT_URL']) if m: project = m.group (1) version = m.group (2) cmd = m.group (3) arg = m.group (4) if not (project and search ('^[A-Za-z0-9-]+$', project)) \ or not (version and search ('^[A-Za-z0-9._-]+$', version)): status = 302 location = '/linux/latest/'+cmd+arg cmd = '' if cmd == 'source': path = arg if len (path) > 0 and path[-1] == '/': path = path[:-1] status = 301 location = '/'+project+'/'+version+'/source'+path else: mode = 'source' if not search ('^[A-Za-z0-9_/.,+-]*$', path): path = 'INVALID' url = 'source'+path elif cmd == 'ident': ident = arg[1:] form = cgi.FieldStorage() ident2 = form.getvalue ('i') if ident == '' and ident2: status = 302 location = '/'+project+'/'+version+'/ident/'+ident2 else: mode = 'ident' if not (ident and search ('^[A-Za-z0-9_-]*$', ident)): ident = '' url = 'ident/'+ident else: status = 404 if status == 301: realprint ('Status: 301 Moved Permanently') realprint ('Location: '+location+'\n') exit() elif status == 302: realprint ('Status: 302 Found') realprint ('Location: '+location+'\n') exit() elif status == 404: realprint ('Status: 404 Not Found\n') exit() basedir = os.environ['LXR_PROJ_DIR'] os.environ['LXR_DATA_DIR'] = basedir + '/' + project + '/data'; os.environ['LXR_REPO_DIR'] = basedir + '/' + project + '/repo'; import sys sys.path = [ sys.path[0] + '/..' ] + sys.path import query def do_query (*args): cwd = os.getcwd() os.chdir ('..') a = query.query (*args) os.chdir (cwd) # decode('ascii') fails on special chars # FIXME: major hack until we handle everything as bytestrings try: a = a.decode ('utf-8') except UnicodeDecodeError: a = a.decode ('iso-8859-1') a = a.split ('\n') del a[-1] return a if version == 'latest': tag = do_query ('latest')[0] else: tag = version data = { 'baseurl': 'http://' + os.environ['HTTP_HOST'] + '/' + project + '/', 'tag': tag, 'version': version, 'url': url, } lines = do_query ('versions') va = OrderedDict() for l in lines: m = search ('^([^ ]*) ([^ ]*) ([^ ]*)$', l) if not m: continue m1 = m.group(1) m2 = m.group(2) l = m.group(3) if m1 not in va: va[m1] = OrderedDict() if m2 not in va[m1]: va[m1][m2] = [] va[m1][m2].append (l) v = '\n' data['versions'] = v if mode == 'source': breadcrumb = ''+project+'' p2 = '' p3 = path.split ('/') [1:] for p in p3: p2 += '/'+p breadcrumb += '/'+p+'' data['breadcrumb'] = breadcrumb data['ident'] = ident data['title'] = project+path+' - Elixir - Free Electrons' lines = ['null - -'] type = do_query ('type', tag, path) if len (type) == 1: type = type[0] if type == 'tree': lines += do_query ('dir', tag, path) elif type == 'blob': lines += do_query ('file', tag, path) else: print ('
This file does not exist.') status = 404 if type == 'tree': if path != '': lines[0] = 'back - -' print ('\n') for l in lines: type, name, size = l.split (' ') if type == 'null': continue elif type == 'tree': icon = 'folder.gif' size = '' path2 = path+'/'+name name = name elif type == 'blob': icon = 'text.gif' size = size+' bytes' path2 = path+'/'+name elif type == 'back': icon = 'back.gif' size = '' path2 = os.path.dirname (path[:-1]) if path2 == '/': path2 = '' name = 'Parent directory' print (' ') print (' ') print (' ') print (' ') print (' \n') print ('
'+icon+''+name+''+size+'
', end='') elif type == 'blob': del (lines[0]) print ('
') print ('
')

        width1 = len (str (len (lines)))
        num = 1
        width2 = len (str (num))
        space = ' ' * (width1 - width2)
        for l in lines:
            print ('  '+space+''+str(num)+' ')
            num += 1
            width2 = len (str (num))
            space = ' ' * (width1 - width2)

        print ('
')

        for l in lines:
            l = cgi.escape (l)
            l = sub ('"', '"', l)
            l = sub ('\033\[31m(.*?)\033\[0m', '\\1', l)
            l = sub ('\033\[32m', '', l)
            l = sub ('\033\[33m', '', l)
            l = sub ('\033\[0m', '', l)
            print (l)

        print ('
') print ('
', end='') elif mode == 'ident': field = '\n
\nIdentifier: \n\n
\n

' + ident data['breadcrumb'] = field data['title'] = ident+' - Elixir - Free Electrons' lines = do_query ('ident', tag, ident) lines = iter (lines) m = search ('Defined in (\d*) file', next (lines)) if m: num = int (m.group(1)) if num == 0: status = 404 print ('Defined in '+str(num)+' files:') print ('
    ') for i in range (0, num): l = next (lines) m = search ('^(.*): (\d*) \((.*)\)$', l) f, n, t = m.groups() print ('
  • '+f+', line '+n+' (as a '+t+')', end='') print ('
') next (lines) m = search ('Referenced in (\d*) file', next (lines)) num = int (m.group(1)) print ('Referenced in '+str(num)+' files:') print ('
    ') for i in range (0, num): l = next (lines) m = search ('^(.*): (.*)$', l) f = m.group (1) ln = m.group (2).split (',') if len (ln) == 1: n = ln[0] print ('
  • '+f+', line '+str(n)+'', end='') else: if num > 100: # Concise display n = len (ln) print ('
  • '+f+', '+str(n)+' times') else: # Verbose display print ('
  • '+f) print ('') print ('
') else: if ident != '': print ('
Not used') status = 404 else: print ('Invalid request') if status == 404: realprint ('Status: 404 Not Found') import jinja2 loader = jinja2.FileSystemLoader (os.path.join (os.path.dirname (__file__), '../templates/')) environment = jinja2.Environment (loader=loader) template = environment.get_template ('layout.html') realprint ('Content-Type: text/html;charset=utf-8\n') data['main'] = outputBuffer.getvalue() realprint (template.render(data), end='')