filesystem.py 10.7 KB
Newer Older
1
# @package FileSystem
murban's avatar
murban committed
2
# @package FileSystem
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27

# Imports
import os
from datetime import datetime
from distutils import dir_util
import locale
import shutil
import random
import cStringIO
from mimetypes import guess_type
import shutil
from zipfile import ZipFile
import xmlrpclib

class FileSystem(object):

    FILE_EXTENSIONS = ["png", "jpg", "jpeg", "bmp", "ps", "eps", "pdf", "txt", "xml", "py", "c", "cpp", "root", "pxlio"]
    BROWSER_EXTENSIONS = ["png", "jpg", "jpeg", "bmp", "pdf"]
    ADDITIONAL_MIMES = {"pxlio": "text/plain",
                        "root" : "text/plain"}

    def __init__(self):
        # allowed extensions
        self.allowed_extensions = FileSystem.FILE_EXTENSIONS

28
29
30
    def setup(self, basedir=None):
        if basedir==None:
            basedir = os.path.expanduser("~")
murban's avatar
murban committed
31
32
33
34
        if not os.path.isdir(basedir):
            raise Exception("Basedir ("+str(basedir)+") does not exist!")
        # the basedir
        self.basedir = os.path.join(basedir, ".vispa")
35
36
37
38
39
        if os.path.isdir(self.basedir):
            return "Basedir already exists"
        else: 
            os.makedirs(self.basedir, 0700)
            return "Basedir now exists"
40

murban's avatar
murban committed
41
    def get_mime_type(self, filepath):
42
43
44
45
46
47
48
49
        mime, encoding = guess_type(filepath)
        if mime is not None:
            return mime
        ext = filepath.split(".")[-1]
        if ext is not None and ext != "" and ext.lower() in FileSystem.ADDITIONAL_MIMES.keys():
            return FileSystem.ADDITIONAL_MIMES[ext]
        return None

murban's avatar
murban committed
50
    def check_file_extension(self, path, extensions=[]):
51
52
53
54
55
56
57
58
        if (len(extensions) == 0):
            return True
        for elem in extensions:
            elem = elem if elem.startswith(".") else "." + elem
            if path.lower().endswith(elem.lower()):
                return True
        return False

murban's avatar
murban committed
59
    def exists(self, path, pathtype=None, fileextension=None, permissionmode="r"):
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
        if isinstance(permissionmode, str) and permissionmode.lower() not in ["r", "w"]:
            return False

        # path exists physically?
        if not os.path.exists(path):
            return False

        # pathtype correct? (file, folder, or None)
        if pathtype is not None:
            pathtype = pathtype.lower()
            if not pathtype in ["file", "folder"]:
                return False
            if os.path.isdir(path) and pathtype == "file":
                return False
            elif not os.path.isdir(path) and pathtype == "folder":
                return False

        # file extension correct?
        if fileextension is not None:
            fileextension = fileextension if isinstance(fileextension, list) else [fileextension]
            hit = False
            for fileext in fileextension:
                fileext = fileext if fileext.startswith(".") else "." + fileext
                if path.endswith(fileext):
                    hit = True
            if not hit:
                return False

        # permission?
        if permissionmode is not None:
            return False

        return True


murban's avatar
murban committed
95
    def get_file_list(self, path, deep, ext_filter=[], reverse=False):
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
        dirlist = os.listdir(path)
        returnlist = []
        for elem in dirlist:
            fullPath = os.path.join(path, elem)
            locale.setlocale(locale.LC_ALL, '')
            stats = os.stat(path + ('' if path.endswith('/') else '/') + elem)
            size = stats.st_size
            size = locale.format("%d", size, grouping=True)
            mtime = stats.st_mtime
            mtime = datetime.fromtimestamp(mtime).strftime("%Y-%m-%d %H:%M:%S")
            if os.path.isdir(fullPath):
                if elem.startswith("."):
                    continue
                returnlist.append({'name': elem, 'type': 'folder', 'parent': path + '/', 'extension': '', 'mtime': mtime, 'size': size, "path": os.path.join(path, elem)})
                if deep:
murban's avatar
murban committed
111
                    returnlist.extend(self.get_file_list(fullPath, deep, ext_filter, reverse))
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
            else:
                if elem.startswith("."):
                    continue
                extension = elem.split(".")[-1]
                returnlist.append({'name': elem, 'type': 'file', 'parent': path + '/', 'extension': extension, 'mtime': mtime, 'size': size, "path": os.path.join(path, elem)})
        # apply filters
        filelist = []
        # delete "." in file extensions
        ext_filter = map(lambda ext: ext if not ext.startswith(".") else ext[1:], ext_filter)
        for elem in returnlist:
            if (elem["type"] == "folder"):
                filelist.append(elem)
                continue
            if not reverse:
                if str(elem["extension"]) not in ext_filter:
                    filelist.append(elem)
            else:
                if str(elem["extension"]) in ext_filter:
                    filelist.append(elem)
        return filelist


murban's avatar
murban committed
134
    def cut_slashs(self, path):
135
136
137
138
139
140
        path = path[1:] if path.startswith("/") else path
        if path == "":
            return path
        path = path[:-1] if path.endswith("/") else path
        return path

murban's avatar
murban committed
141
    def create_folder(self, path, name):
142
143
144
145
146
147
148
149
150
151
        # folder with the same name existent?
        fullpath = os.path.join(path, name)
        if os.path.isdir(fullpath):
            raise Exception("Name already in use!")
        try:
            os.mkdir(fullpath)
        except Exception as e:
            #raise Exception("You don't have the permission to create this folder!")
            raise Exception(str(e))

murban's avatar
murban committed
152
    def create_file(self, path, name):
153
154
155
156
157
158
159
160
161
162
163
        # file with the same name existent?
        fullpath = os.path.join(path, name)
        if os.path.exists(fullpath):
            raise Exception("Name already in use!")
        try:
            f = file(fullpath, "w")
            f.close()
        except Exception as e:
            raise Exception(str(e))
        

murban's avatar
murban committed
164
    def rename_folder(self, path, name):
165
166
167
168
169
170
171
172
173
174
175
176
        # file or folder
        if not os.path.isdir(path):
            raise Exception("Renaming file with folder function!")

        # folder with the same name existent?
        path = path if not path.endswith("/") else path[:-1]
        fullpath = os.path.join("/".join(path.split("/")[:-1]), name)
        if os.path.exists(fullpath):
            raise Exception("Name already in use!")

        os.renames(path, fullpath)

murban's avatar
murban committed
177
    def rename_file(self, path, name):
178
179
180
181
182
183
184
185
186
187
188
        # file or folder
        if os.path.isdir(path):
            raise Exception("Renaming folder with file function!")

        # file with the same name existent?
        fullpath = os.path.join("/".join(path.split("/")[:-1]), name)
        if os.path.exists(fullpath):
            raise Exception("Name already in use!")

        os.renames(path, fullpath)

murban's avatar
murban committed
189
190
    def remove(self, path):
        if isinstance(path, list):
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
            for p in path:
                self.remove(p)
            return True

        if os.path.isdir(path):
            shutil.rmtree(path)
        else:
            os.remove(path)

    def compress(self, path, paths, name):
        # paths has to be a list of strings
        paths = paths if isinstance(paths, list) else [paths]

        path = path if not path.endswith("/") else path[:-1]

        fullpath = os.path.join(path, "%s.zip" % name)

        if os.path.exists(fullpath):
            raise Exception("Name already in use!")

        archive = ZipFile(fullpath, "w")

murban's avatar
murban committed
213
        path = path if path.startswith("/") else path
214
215
216
        for p in paths:
            if p is None or p == "":
                continue
murban's avatar
murban committed
217
            p = p if p.startswith(os.sep) else os.sep + path
218
219
220
221
222
223
224
225
226
227
228
229
230
231
            if os.path.isdir(p):
                for elem in os.listdir(p):
                    fullp = os.path.join(p, elem)
                    if os.path.isdir(fullp):
                        paths.append(fullp)
                    else:
                        ap = fullp[len(path):] if fullp.startswith(path) else fullp
                        archive.write(fullpp, ap)

            ap = p[len(path):] if p.startswith(path) else p
            archive.write(p, ap)

        archive.close()

murban's avatar
murban committed
232
233
234
235
    def paste(self, path, target, cut):
        if isinstance(target, list):
            for p in target:
                self.paste(path, p, cut)
236
237
            return True

murban's avatar
murban committed
238
        fulltarget = os.path.join(path, target.split("/")[-1])
239
240
241
242

        if os.path.exists(fulltarget):
            raise Exception("Name already in use!")

murban's avatar
murban committed
243
244
        if os.path.isdir(target):
            shutil.copytree(target, fulltarget)
245
            if cut:
murban's avatar
murban committed
246
                shutil.rmtree(target)
247
        else:
murban's avatar
murban committed
248
            shutil.copy2(target, path)
249
            if cut:
murban's avatar
murban committed
250
                os.remove(target)
251
252


murban's avatar
murban committed
253
    def save_file_content(self, path, content, force=True):
254
        #check if file already exists
murban's avatar
murban committed
255
256
        if os.path.exists(path) and not force:
            return False, "The file '%s' already exists!" % path
257

murban's avatar
murban committed
258
        out = open(path, "w")
259
260
261
262
263
264
        for line in content.data:
            out.write(line)
        out.close()

        return True, "File saved!"

murban's avatar
murban committed
265
266
    def get_file_content(self, path):
        f = open(path, "r")
267
268
269
270
271
        content = f.read()
        f.close()
        content = " " if content == "" else content
        return xmlrpclib.Binary(content), "File opened!"

murban's avatar
murban committed
272
    def is_browser_file(self, path):
273
        extension = path.split(".")[-1]
murban's avatar
murban committed
274
        return extension in FileSystem.BROWSER_EXTENSIONS
275

murban's avatar
murban committed
276
    def handle_file_name_collision(self, name, path):
277
        # collision?
murban's avatar
murban committed
278
        files = os.listdir(path)
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
        if name not in files:
            return name

        # when this line is reached, there is a collision!

        # cut the file extension
        extension = name.split(".")[-1]
        prename = None
        if name == extension:
            extension = ""
            prename = name
        else:
            prename = name.split("." + extension)[0]

        # has the name already a counter at its end?
        hasCounter = False
        preprename = None
        counter = prename.split("_")[-1]

        if counter != prename:
            try:
                counter = int(counter)
                hasCounter = True
                preprename = "_".join(prename.split("_")[:-1])
            except:
                pass

        if hasCounter:
            # increment and try again
            counter += 1
            newname = "%s_%d%s" % (preprename, counter, "" if extension == "" else "." + extension)
        else:
            newname = "%s_1%s" % (prename, "" if extension == "" else "." + extension)

        # return
murban's avatar
murban committed
314
        return self.handle_file_name_collision(newname, path)
315
316
317
318
319
320
321
322
323
324
325
326
327

##
# Creates a unique ID
# p = 1e-18
def uniqueId(l=10):
    chars = "abcdefghijklmnopqrstuvwxyz"
    chars += "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
    chars += "0123456789"
    code = ""
    for i in range(l):
        rnd = int(round(random.uniform(0, len(chars) - 1)))
        code += chars[rnd]
    return code