fileBrowser.py 8.86 KB
Newer Older
1
# -*- coding: utf-8 -*-
Marco Mariani's avatar
Marco Mariani committed
2
# vim: set et sts=2:
3 4 5

import datetime
import hashlib
Marco Mariani's avatar
Marco Mariani committed
6
import os
7
import re
Marco Mariani's avatar
Marco Mariani committed
8 9
import shutil
import urllib
10 11
import zipfile

Marco Mariani's avatar
Marco Mariani committed
12 13 14 15
import werkzeug
from slapos.runner.utils import realpath, tail, isText


16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42
class fileBrowser(object):
  """This class contain all bases function for file browser"""

  def __init__(self, config):
    self.config = config

  def listDirs(self, dir, all=False):
    """List elements of directory 'dir' taken"""
    html = ''
    html += 'var gsdirs = new Array();'
    html += 'var gsfiles = new Array();'
    dir = urllib.unquote(str(dir))
    realdir = realpath(self.config, dir)
    if not realdir:
      raise NameError('Could not load directory %s: Permission denied' % dir)

    ldir = sorted(os.listdir(realdir), key=str.lower)
    for f in ldir:
      if f.startswith('.') and not all: #do not display this file/folder
        continue
      ff = os.path.join(dir,f)
      realfile = os.path.join(realdir, f)
      mdate = datetime.datetime.fromtimestamp(os.path.getmtime(realfile)
                    ).strftime("%Y-%d-%m %I:%M")
      md5 = hashlib.md5(realfile).hexdigest()
      if not os.path.isdir(realfile):
        size = os.path.getsize(realfile)
Marco Mariani's avatar
Marco Mariani committed
43 44 45 46 47 48 49
        regex = re.compile("(^.*)\.(.*)", re.VERBOSE)
        ext = regex.sub(r'\2', f)
        if ext == f:
          ext = "unknow"
        else:
          ext = str.lower(ext)
        html += 'gsfiles.push(new gsItem("1", "' + f + '", "' + \
50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100
                  ff + '", "' + str(size) + '", "' + md5 + \
                  '", "' + ext + '", "' + mdate + '"));';
      else:
        html += 'gsdirs.push(new gsItem("2", "' + f + '", "' + \
                  ff + '", "0", "' + md5 + '", "dir", "' + mdate + '"));';
    return html


  def makeDirectory(self, dir, filename):
    """Create a directory"""
    realdir = realpath(self.config, urllib.unquote(dir))
    if not realdir:
      raise NameError('Could not load directory %s: Permission denied' % dir)
    folder = os.path.join(realdir, filename)
    if not os.path.exists(folder):
      os.mkdir(folder, 0744)
      return '{result: \'1\'}'
    else:
      return '{result: \'0\'}'

  def makeFile(self, dir, filename):
    """Create a file in a directory dir taken"""
    realdir = realpath(self.config, urllib.unquote(dir))
    if not realdir:
      raise NameError('Could not load directory %s: Permission denied' % dir)
    file = os.path.join(realdir, filename)
    if not os.path.exists(file):
      open(file, 'w').write('')
      return 'var responce = {result: \'1\'}'
    else:
      return '{result: \'0\'}'

  def deleteItem(self, dir, files):
    """Delete a list of files or directories"""
    realdir = realpath(self.config, urllib.unquote(dir))
    if not realdir:
      raise NameError('Could not load directory %s: Permission denied' % dir)
    lfiles = urllib.unquote(files).split(',,,')
    try:
      for file in lfiles:
        file = os.path.join(realdir, file)
        if not os.path.exists(file):
          continue #silent skip file....
        details = file.split('/')
        last = details[len(details) - 1]
        if last and last.startswith('.'):
          continue #cannot delete this file/directory, to prevent security
        if os.path.isdir(file):
          shutil.rmtree(file)
        else:
          os.unlink(file)
Marco Mariani's avatar
Marco Mariani committed
101
    except Exception as e:
102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128
      return str(e)
    return '{result: \'1\'}'

  def copyItem(self, dir, files, del_source=False):
    """Copy a list of files or directory to dir"""
    realdir = realpath(self.config, urllib.unquote(dir))
    if not realdir:
      raise NameError('Could not load directory %s: Permission denied' % dir)
    lfiles = urllib.unquote(files).split(',,,')
    try:
      for file in lfiles:
        realfile = realpath(self.config, file)
        if not realfile:
          raise NameError('Could not load file or directory %s: Permission denied' % file)
        #prepare destination file
        details = realfile.split('/')
        dest = os.path.join(realdir, details[len(details) - 1])
        if os.path.exists(dest):
          raise NameError('NOT ALLOWED OPERATION : File or directory already exist')
        if os.path.isdir(realfile):
          shutil.copytree(realfile, dest)
          if del_source:
            shutil.rmtree(realfile)
        else:
          shutil.copy(realfile, dest)
          if del_source:
            os.unlink(realfile)
Marco Mariani's avatar
Marco Mariani committed
129
    except Exception as e:
130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167
      return str(e)
    return '{result: \'1\'}'

  def rename(self, dir, filename, newfilename):
    """Rename file or directory to dir/filename"""
    realdir = realpath(self.config, urllib.unquote(dir))
    if not realdir:
      raise NameError('Could not load directory %s: Permission denied' % dir)
    realfile = realpath(self.config, urllib.unquote(filename))
    if not realfile:
      raise NameError('Could not load directory %s: Permission denied' % filename)
    tofile = os.path.join(realdir, newfilename)
    if not os.path.exists(tofile):
      os.rename(realfile, tofile)
      return '{result: \'1\'}'
    raise NameError('NOT ALLOWED OPERATION : File or directory already exist')

  def copyAsFile(self, dir, filename, newfilename):
    """Copy file or directory to dir/filename"""
    realdir = realpath(self.config, urllib.unquote(dir))
    if not realdir:
      raise NameError('Could not load directory %s: Permission denied' % dir)
    fromfile = os.path.join(realdir, filename)
    tofile = os.path.join(realdir, newfilename)
    if not os.path.exists(fromfile):
      raise NameError('NOT ALLOWED OPERATION : File or directory not exist')
    if not os.path.exists(tofile):
      shutil.copy(fromfile, tofile)
      return '{result: \'1\'}'
    raise NameError('NOT ALLOWED OPERATION : File or directory already exist')

  def uploadFile(self, dir, files):
    """Upload a list of file in directory dir"""
    realdir = realpath(self.config, urllib.unquote(dir))
    if not realdir:
      raise NameError('Could not load directory %s: Permission denied' % dir)
    for file in files:
      if files[file]:
Marco Mariani's avatar
Marco Mariani committed
168
        filename = werkzeug.secure_filename(files[file].filename)
169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238
        if not os.path.exists(os.path.join(dir, filename)):
          files[file].save(os.path.join(realdir, filename))
    return '{result: \'1\'}'

  def downloadFile(self, dir, filename):
    """Download file dir/filename"""
    realdir = realpath(self.config, urllib.unquote(dir))
    if not realdir:
      raise NameError('Could not load directory %s: Permission denied' % dir)
    file = os.path.join(realdir, urllib.unquote(filename))
    if not os.path.exists(file):
      raise NameError('NOT ALLOWED OPERATION : File or directory does not exist %s'
                      % os.path.join(dir, filename))
    return file

  def zipFile(self, dir, filename, newfilename):
    """Add filename to archive as newfilename"""
    realdir = realpath(self.config, urllib.unquote(dir))
    if not realdir:
      raise NameError('Could not load directory %s: Permission denied' % dir)
    tozip = os.path.join(realdir, newfilename)
    fromzip = os.path.join(realdir, filename)
    if not os.path.exists(fromzip):
      raise NameError('NOT ALLOWED OPERATION : File or directory not exist')
    if not os.path.exists(tozip):
      zip = zipfile.ZipFile(tozip, 'w', zipfile.ZIP_DEFLATED)
      if os.path.isdir(fromzip):
        rootlen = len(fromzip) + 1
        for base, dirs, files in os.walk(fromzip):
          for file in files:
            fn = os.path.join(base, file).encode("utf-8")
            zip.write(fn, fn[rootlen:])
      else:
        zip.write(fromzip)
      zip.close()
      return '{result: \'1\'}'
    raise NameError('NOT ALLOWED OPERATION : File or directory already exist')

  def unzipFile(self, dir, filename, newfilename):
    """Extract a zipped archive"""
    realdir = realpath(self.config, urllib.unquote(dir))
    if not realdir:
      raise NameError('Could not load directory %s: Permission denied' % dir)
    target = os.path.join(realdir, newfilename)
    archive = os.path.join(realdir, filename)
    if not os.path.exists(archive):
      raise NameError('NOT ALLOWED OPERATION : File or directory not exist')
    if not os.path.exists(target):
      zip = zipfile.ZipFile(archive)
      #member = zip.namelist()
      zip.extractall(target)
      #if len(member) > 1:
      #  zip.extractall(target)
      #else:
      #  zip.extract(member[0], newfilename)
      return '{result: \'1\'}'
    raise NameError('NOT ALLOWED OPERATION : File or directory already exist')

  def readFile(self, dir, filename, truncate=0):
    """Read file dir/filename and return content"""
    realfile = realpath(self.config, os.path.join(urllib.unquote(dir),
                        urllib.unquote(filename)))
    if not realfile:
      raise NameError('Could not load directory %s: Permission denied' % dir)
    if not isText(realfile):
      return "FILE ERROR: Cannot display binary file, please open a text file only!"
    if truncate == 0:
      return open(realfile, 'r').read()
    else:
      tail(open(realfile, 'r'), 0)