示例#1
0
文件: views.py 项目: HaNeul-Kim/hue
def listdir(request, path, chooser):
    """
    Implements directory listing (or index).

    Intended to be called via view().

    TODO: Remove?
    """
    if not request.fs.isdir(path):
        raise PopupException(_("Not a directory: %(path)s") % {'path': path})

    file_filter = request.REQUEST.get('file_filter', 'any')

    assert file_filter in ['any', 'file', 'dir']

    home_dir_path = request.user.get_home_directory()

    breadcrumbs = parse_breadcrumbs(path)

    data = {
        'path': path,
        'file_filter': file_filter,
        'breadcrumbs': breadcrumbs,
        'current_dir_path': path,
        'current_request_path': request.path,
        'home_directory': request.fs.isdir(home_dir_path) and home_dir_path or None,
        'cwd_set': True,
        'is_superuser': request.user.username == request.fs.superuser,
        'groups': request.user.username == request.fs.superuser and [str(x) for x in Group.objects.values_list('name', flat=True)] or [],
        'users': request.user.username == request.fs.superuser and [str(x) for x in User.objects.values_list('username', flat=True)] or [],
        'superuser': request.fs.superuser,
        'show_upload': (request.REQUEST.get('show_upload') == 'false' and (False,) or (True,))[0],
        'show_download_button': SHOW_DOWNLOAD_BUTTON.get(),
        'show_upload_button': SHOW_UPLOAD_BUTTON.get()
    }

    stats = request.fs.listdir_stats(path)

    # Include parent dir, unless at filesystem root.
    if not request.fs.isroot(path):
        parent_path = request.fs.join(path, "..")
        parent_stat = request.fs.stats(parent_path)
        # The 'path' field would be absolute, but we want its basename to be
        # actually '..' for display purposes. Encode it since _massage_stats expects byte strings.
        parent_stat['path'] = parent_path
        stats.insert(0, parent_stat)

    data['files'] = [_massage_stats(request, stat) for stat in stats]
    if chooser:
        return render('chooser.mako', request, data)
    else:
        return render('listdir.mako', request, data)
示例#2
0
文件: views.py 项目: HaNeul-Kim/hue
def display(request, path):
    """
    Implements displaying part of a file.

    GET arguments are length, offset, mode, compression and encoding
    with reasonable defaults chosen.

    Note that display by length and offset are on bytes, not on characters.

    TODO(philip): Could easily built-in file type detection
    (perhaps using something similar to file(1)), as well
    as more advanced binary-file viewing capability (de-serialize
    sequence files, decompress gzipped text files, etc.).
    There exists a python-magic package to interface with libmagic.
    """
    if not request.fs.isfile(path):
        raise PopupException(_("Not a file: '%(path)s'") % {'path': path})

    # display inline files just if it's not an ajax request
    if not request.is_ajax():
      mimetype = mimetypes.guess_type(path)[0]

      if mimetype is not None and INLINE_DISPLAY_MIMETYPE.search(mimetype):
        return redirect(reverse('filebrowser.views.download', args=[path]) + '?disposition=inline')

    stats = request.fs.stats(path)
    encoding = request.GET.get('encoding') or i18n.get_site_encoding()

    # I'm mixing URL-based parameters and traditional
    # HTTP GET parameters, since URL-based parameters
    # can't naturally be optional.

    # Need to deal with possibility that length is not present
    # because the offset came in via the toolbar manual byte entry.
    end = request.GET.get("end")
    if end:
        end = int(end)
    begin = request.GET.get("begin", 1)
    if begin:
        # Subtract one to zero index for file read
        begin = int(begin) - 1
    if end:
        offset = begin
        length = end - begin
        if begin >= end:
            raise PopupException(_("First byte to display must be before last byte to display."))
    else:
        length = int(request.GET.get("length", DEFAULT_CHUNK_SIZE_BYTES))
        # Display first block by default.
        offset = int(request.GET.get("offset", 0))

    mode = request.GET.get("mode")
    compression = request.GET.get("compression")

    if mode and mode not in ["binary", "text"]:
        raise PopupException(_("Mode must be one of 'binary' or 'text'."))
    if offset < 0:
        raise PopupException(_("Offset may not be less than zero."))
    if length < 0:
        raise PopupException(_("Length may not be less than zero."))
    if length > MAX_CHUNK_SIZE_BYTES:
        raise PopupException(_("Cannot request chunks greater than %(bytes)d bytes.") % {'bytes': MAX_CHUNK_SIZE_BYTES})

    # Do not decompress in binary mode.
    if mode == 'binary':
        compression = 'none'
        # Read out based on meta.
    compression, offset, length, contents =\
    read_contents(compression, path, request.fs, offset, length)

    # Get contents as string for text mode, or at least try
    uni_contents = None
    if not mode or mode == 'text':
        uni_contents = unicode(contents, encoding, errors='replace')
        is_binary = uni_contents.find(i18n.REPLACEMENT_CHAR) != -1
        # Auto-detect mode
        if not mode:
            mode = is_binary and 'binary' or 'text'

    # Get contents as bytes
    if mode == "binary":
        xxd_out = list(xxd.xxd(offset, contents, BYTES_PER_LINE, BYTES_PER_SENTENCE))

    dirname = posixpath.dirname(path)
    # Start with index-like data:
    data = _massage_stats(request, request.fs.stats(path))
    # And add a view structure:
    data["success"] = True
    data["view"] = {
        'offset': offset,
        'length': length,
        'end': offset + len(contents),
        'dirname': dirname,
        'mode': mode,
        'compression': compression,
        'size': stats['size'],
        'max_chunk_size': str(MAX_CHUNK_SIZE_BYTES)
    }
    data["filename"] = os.path.basename(path)
    data["editable"] = stats['size'] < MAX_FILEEDITOR_SIZE
    if mode == "binary":
        # This might be the wrong thing for ?format=json; doing the
        # xxd'ing in javascript might be more compact, or sending a less
        # intermediate representation...
        logger.debug("xxd: " + str(xxd_out))
        data['view']['xxd'] = xxd_out
        data['view']['masked_binary_data'] = False
    else:
        data['view']['contents'] = uni_contents
        data['view']['masked_binary_data'] = is_binary

    data['breadcrumbs'] = parse_breadcrumbs(path)
    data['show_download_button'] = SHOW_DOWNLOAD_BUTTON.get()

    return render("display.mako", request, data)
示例#3
0
文件: views.py 项目: HaNeul-Kim/hue
def listdir_paged(request, path):
    """
    A paginated version of listdir.

    Query parameters:
      pagenum           - The page number to show. Defaults to 1.
      pagesize          - How many to show on a page. Defaults to 15.
      sortby=?          - Specify attribute to sort by. Accepts:
                            (type, name, atime, mtime, size, user, group)
                          Defaults to name.
      descending        - Specify a descending sort order.
                          Default to false.
      filter=?          - Specify a substring filter to search for in
                          the filename field.
    """
    if not request.fs.isdir(path):
        raise PopupException("Not a directory: %s" % (path,))

    pagenum = int(request.GET.get('pagenum', 1))
    pagesize = int(request.GET.get('pagesize', 30))
    do_as = None
    if request.user.is_superuser or request.user.has_hue_permission(action="impersonate", app="security"):
      do_as = request.GET.get('doas', request.user.username)
    if hasattr(request, 'doas'):
      do_as = request.doas

    home_dir_path = request.user.get_home_directory()
    breadcrumbs = parse_breadcrumbs(path)

    if do_as:
      all_stats = request.fs.do_as_user(do_as, request.fs.listdir_stats, path)
    else:
      all_stats = request.fs.listdir_stats(path)


    # Filter first
    filter_str = request.GET.get('filter', None)
    if filter_str:
        filtered_stats = filter(lambda sb: filter_str in sb['name'], all_stats)
        all_stats = filtered_stats

    # Sort next
    sortby = request.GET.get('sortby', None)
    descending_param = request.GET.get('descending', None)
    if sortby is not None:
        if sortby not in ('type', 'name', 'atime', 'mtime', 'user', 'group', 'size'):
            logger.info("Invalid sort attribute '%s' for listdir." %
                        (sortby,))
        else:
            all_stats = sorted(all_stats,
                               key=operator.attrgetter(sortby),
                               reverse=coerce_bool(descending_param))


    # Do pagination
    page = paginator.Paginator(all_stats, pagesize).page(pagenum)
    shown_stats = page.object_list

    # Include parent dir always as second option, unless at filesystem root.
    if not request.fs.isroot(path):
        parent_path = request.fs.join(path, "..")
        parent_stat = request.fs.stats(parent_path)
        # The 'path' field would be absolute, but we want its basename to be
        # actually '..' for display purposes. Encode it since _massage_stats expects byte strings.
        parent_stat['path'] = parent_path
        parent_stat['name'] = ".."
        shown_stats.insert(0, parent_stat)

    # Include same dir always as first option to see stats of the current folder
    current_stat = request.fs.stats(path)
    # The 'path' field would be absolute, but we want its basename to be
    # actually '.' for display purposes. Encode it since _massage_stats expects byte strings.
    current_stat['path'] = path
    current_stat['name'] = "."
    shown_stats.insert(1, current_stat)

    page.object_list = [ _massage_stats(request, s) for s in shown_stats ]

    is_fs_superuser = _is_hdfs_superuser(request)
    data = {
        'path': path,
        'breadcrumbs': breadcrumbs,
        'current_request_path': request.path,
        'files': page.object_list,
        'page': _massage_page(page),
        'pagesize': pagesize,
        'home_directory': request.fs.isdir(home_dir_path) and home_dir_path or None,
        'sortby': sortby,
        'descending': descending_param,
        # The following should probably be deprecated
        'cwd_set': True,
        'file_filter': 'any',
        'current_dir_path': path,
        'is_fs_superuser': is_fs_superuser,
        'groups': is_fs_superuser and [str(x) for x in Group.objects.values_list('name', flat=True)] or [],
        'users': is_fs_superuser and [str(x) for x in User.objects.values_list('username', flat=True)] or [],
        'superuser': request.fs.superuser,
        'supergroup': request.fs.supergroup,
        'is_sentry_managed': request.fs.is_sentry_managed(path),
        'apps': appmanager.get_apps_dict(request.user).keys(),
        'show_download_button': SHOW_DOWNLOAD_BUTTON.get(),
        'show_upload_button': SHOW_UPLOAD_BUTTON.get()
    }
    return render('listdir.mako', request, data)
示例#4
0
文件: views.py 项目: HaNeul-Kim/hue
            finally:
                f.close()
        else:
            current_contents = u""

        form = EditorForm(dict(path=path, contents=current_contents, encoding=encoding))

    data = dict(
        exists=(stats is not None),
        stats=stats,
        form=form,
        path=path,
        filename=os.path.basename(path),
        dirname=os.path.dirname(path),
        breadcrumbs = parse_breadcrumbs(path),
        show_download_button = SHOW_DOWNLOAD_BUTTON.get())
    return render("edit.mako", request, data)

def save_file(request):
    """
    The POST endpoint to save a file in the file editor.

    Does the save and then redirects back to the edit page.
    """
    form = EditorForm(request.POST)
    is_valid = form.is_valid()
    path = form.cleaned_data.get('path')

    if request.POST.get('save') == "Save As":
        if not is_valid:
            return edit(request, path, form=form)