def test_join_fb_root(self): self.assertEqual( utils.join_fb_root("file.txt"), os.path.abspath(os.path.join(settings.FILEBROWSER_ROOT, "file.txt"))) self.assertEqual( utils.join_fb_root("dir/file.txt"), os.path.abspath( os.path.join(settings.FILEBROWSER_ROOT, "dir/file.txt")))
def get_resources(request): """Returns home + lib directory structure.""" try: lib = walkdir(join_fb_root('lib'), request.user) home = walkdir(join_fb_root("Yggdrasil"), request.user) home["name"] = 'home' return HttpResponse(json.dumps([home, lib]), content_type='application/json') except Exception as e: # pragma: no cover return HttpResponseNotFound(str(e))
def git_clone(request): """Execute a git clone on the targeted entry with the informations of POST.""" post = json.loads(request.body.decode()) username = post.get('username') password = post.get('password') destination = post.get('destination') path = post.get('path') url = post.get('url') if not url: return HttpResponseBadRequest("Missing 'url' parameter") if '@' in url: return HttpResponseNotFound( "SSH link is not supported, please use HTTPS") path = join_fb_root(path) try: ret, out, err = gitcmd.clone(path, url, destination, username, password) if ret: # pragma: no cover raise Exception(err + out) else: path = (os.path.join(path, destination) if destination else os.path.join( path, os.path.basename(os.path.splitext(url)[0]))) ret, out, err = gitcmd.set_url(path, url) if not ret: request.method = 'GET' request.META['REQUEST_METHOD'] = "GET" return get_resources(request) else: # pragma: no cover shutil.rmtree(path, ignore_errors=True) raise Exception(err + out) except Exception as e: # pragma: no cover return HttpResponseNotFound(str(e))
def rename_resource(request): """Rename a file or folder """ post = json.loads(request.body.decode()) path = post.get('path') target = post.get('target') if not path: return HttpResponseBadRequest(missing_parameter('path')) if not target: return HttpResponseBadRequest(missing_parameter('target')) path = join_fb_root(path) name = os.path.basename(path) new_path = os.path.join(os.path.dirname(path), target) try: if any(c in target for c in settings.FILEBROWSER_DISALLOWED_CHAR): msg = "Can't rename '{0}' to '{1}': name should not contain any of {2}." \ .format(name, target, settings.FILEBROWSER_DISALLOWED_CHAR) return HttpResponseBadRequest(msg) if os.path.exists(new_path): msg = "Can't rename '{0}' to '{1}': this name is already used.".format(name, target) return HttpResponseBadRequest(msg) os.rename(path, new_path) return JsonResponse( {'path': rm_fb_root(new_path), 'status': 200}) except Exception as e: # pragma: no cover msg = "Impossible to rename '{0}' to '{1}': {2}".format(name, target, htmlprint.code( str(type(e)) + ' - ' + str(e))) if settings.DEBUG: msg += ("DEBUG set to True: " + htmlprint.html_exc()) return HttpResponseNotFound(msg)
def create_resource(request): """Create a new file or folder """ post = json.loads(request.body.decode()) path = post.get('path') if not path: return HttpResponseBadRequest(missing_parameter('path')) path = join_fb_root(path) name = os.path.basename(path) try: if any(c in name for c in settings.FILEBROWSER_DISALLOWED_CHAR): msg = "Can't create '%s': name should not contain any of %s." return HttpResponseBadRequest(msg % (name, str(settings.FILEBROWSER_DISALLOWED_CHAR))) if os.path.exists(path): return HttpResponseBadRequest("Can't create '%s': this name is already used." % name) if post.get('type', '') == 'file': with open(path, "w") as f: print(post.get('content', ''), file=f) return JsonResponse({'path': rm_fb_root(path)}) else: os.mkdir(path) return JsonResponse({'path': rm_fb_root(path)}) except Exception as e: # pragma: no cover msg = "Impossible to create '{0}' : {1}".format(name, htmlprint.code( str(type(e)) + ' - ' + str(e))) messages.error(request, msg) if settings.DEBUG: msg += ("DEBUG set to True: " + htmlprint.html_exc()) return HttpResponseNotFound(msg)
def compile_pl(request): """ Used by the PL editor to compile a PL""" post = json.loads(request.body.decode()) path = post.get('path') if not path: return HttpResponseBadRequest(missing_parameter('path')) path_components = path.split('/') directory = path_components[0] response = {'compiled': True} try: path = join_fb_root(path) with open(path, 'r') as f: content = f.read() shutil.copyfile(path, path + ".bk") with open(path, 'w+') as f: # Writting editor content into the file print(content, file=f) directory = Directory.objects.get(name=directory) relative = os.path.join(*(path_components[1:])) pl, warnings = load_file(directory, relative) if not pl: response['compiled'] = False else: response['json'] = pl.json response['warnings'] = warnings except Exception: # pragma: no cover response['compiled'] = False finally: shutil.move(path + ".bk", path) return HttpResponse( json.dumps(response), content_type='application/json', status=200 )
def commit(request): """ Execute an add and commit of the targeted entry with the informations of POST. """ post = json.loads(request.body.decode()) path = post.get('path') if not path: return HttpResponseBadRequest(missing_parameter('path')) commit = post.get('commit') if not commit: return HttpResponseBadRequest(missing_parameter('commit')) user = request.user if not user.email: return HttpResponseBadRequest("User must have an email") if user.first_name and user.last_name: name = user.get_full_name() else: name = user.get_username() ret, out, err = gitcmd.commit(join_fb_root(path), commit, name=name, mail=request.user.email) if not ret: return HttpResponse(htmlprint.code(out + err)) else: # pragma: no cover return HttpResponseNotFound(htmlprint.code(err + out))
def upload_resource(request): # TODO ADD TEST """ Allow the user to upload a file in the filebrowser """ if request.method != 'POST': return HttpResponseNotAllowed(['POST']) f = request.FILES.get('file') if not f: return HttpResponseBadRequest(missing_parameter('file')) path = request.POST.get('path') if not path: return HttpResponseBadRequest(missing_parameter('path')) name = f.name try: path = os.path.join(join_fb_root(path), name) if os.path.exists(path): return HttpResponseBadRequest("This file's name is already used : " + name) else: with open(path, 'wb+') as dest: for chunk in f.chunks(): dest.write(chunk) return HttpResponse() except Exception as e: # pragma: no cover msg = "Impossible to upload '" + path + "' : " + htmlprint.code( str(type(e)) + ' - ' + str(e)) if settings.DEBUG: messages.error(request, "DEBUG set to True: " + htmlprint.html_exc()) return HttpResponseNotFound(msg)
def delete_resource(request): """Delete a file or folder """ post = json.loads(request.body.decode()) path = post.get('path') if not path: return HttpResponseBadRequest(missing_parameter('path')) if is_root(path): return HttpResponseBadRequest('cannot delete a root folder') try: path = join_fb_root(path) shutil.rmtree( path, ignore_errors=True) if os.path.isdir(path) else os.remove(path) if not path.startswith("lib/"): add_commit_path(request, path, action="deleted") return JsonResponse({'success': True}) except Exception as e: # pragma: no cover path = path.replace(settings.FILEBROWSER_ROOT, '') error = htmlprint.code(str(e).replace(settings.FILEBROWSER_ROOT, '')) msg = "Impossible to delete '%s' : %s" % (path, error) if settings.DEBUG: msg += ("DEBUG: " + htmlprint.html_exc()) return HttpResponseNotFound(msg)
def search_in_files(request): # TODO ADD TEST path = request.GET.get('path') if not path: return HttpResponseBadRequest(missing_parameter('path')) query = request.GET.get('query') if not query: return HttpResponseBadRequest(missing_parameter('query')) cwd = os.getcwd() try: if (not path.startswith(HOME_DIR) and not path.startswith(LIB_DIR)): return HttpResponseBadRequest('cannot search outside of root directories') path = join_fb_root(path) if not os.path.isdir(path): return HttpResponseBadRequest('path should point to a directory') os.chdir(path) p = subprocess.Popen("grep -nr '{0}' .".format(query), stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True) out, err = p.communicate() finally: os.chdir(cwd) ret, out, err = p.returncode, out.decode().strip("\n"), err.decode() if not ret: return HttpResponse(out) else: # pragma: no cover return HttpResponseNotFound(htmlprint.code(out + err))
def changes_in_directory(directory): subdirs = os.listdir(join_fb_root(directory)) for subdir in subdirs: abspath = join_fb_root(os.path.join(directory, subdir)) if not os.path.isdir(abspath) or not in_repository(abspath): continue def parse_change(change): # print(abspath + ' :: ' + change) tmp = change.strip().split(' ') ftype = tmp[0] fpath = os.path.join(directory, subdir, tmp[-1]) # Yggdrasil + Repo + File isdir = fpath.endswith('/') name = fpath.split('/')[-2] if isdir else os.path.basename( fpath) return { 'name': name, 'type': ftype, 'path': fpath, 'isdir': isdir } ret, out, err = exec_command(abspath, 'git status --short') if not ret: changes = out.split("\n") changes = [ parse_change(x) for x in changes if x and '..' not in x ] # only result in home/ changes = [x for x in changes if x['type'] != 'A'] # remove added entries key = repository_url(abspath) value = response.get(key) if value: value['changes'] = value['changes'] + changes if value.get( 'changes') else changes else: value = { 'path': os.path.join(directory, subdir), 'branch': repository_branch(abspath), 'changes': changes } response[key] = value else: # pragma: no cover return False return True
def move_resource(request): """ Move post.get('path'] to POST['dst').""" post = json.loads(request.body.decode()) src = post.get('path') if not src: return HttpResponseBadRequest(missing_parameter('path')) dst = post.get('dst') if not dst: return HttpResponseBadRequest(missing_parameter('dst')) try: src_path = join_fb_root(src) dst_path = join_fb_root(dst) if src == dst: return HttpResponseNotFound("Can't move a directory inside itself") elif not os.path.isdir(dst_path): return HttpResponseNotFound('"{0}" is not a directory'.format(dst)) elif dst_path.startswith(src_path): return HttpResponseNotFound("Can't move {0} inside {1}".format( src, dst)) else: destination = os.path.join(dst_path, os.path.basename(src)) if os.path.exists(destination): return HttpResponseNotFound( "{0} already exists inside {1}".format( os.path.basename(src), dst)) else: if post.get('copy'): if os.path.isdir(src_path): shutil.copytree(src_path, destination) else: shutil.copyfile(src_path, destination) else: os.rename(src_path, destination) return JsonResponse( {'path': os.path.join(dst, os.path.basename(src))}) except Exception as e: # pragma: no cover msg = "Impossible to copy '" + os.path.basename( src) + "' : " + htmlprint.code(str(type(e)) + ' - ' + str(e)) return HttpResponseNotFound(msg)
def status(request): """ Execute a git status on the targeted entry.""" path = request.GET.get('path') if not path: return HttpResponseBadRequest(missing_parameter('path')) ret, out, err = gitcmd.status(join_fb_root(path)) if not ret: return HttpResponse(htmlprint.code(out + err)) else: # pragma: no cover return HttpResponseNotFound(htmlprint.code(out + err))
def add(request): """ Execute a git add on the targeted entry.""" path = request.GET.get('path') if not path: return HttpResponseBadRequest(missing_parameter('path')) ret, out, err = gitcmd.add(join_fb_root(path)) if not ret: return HttpResponse("Entry successfully added to the index.") else: # pragma: no cover return HttpResponseNotFound( "Nothing to add." if not err else htmlprint.code(err + out))
def abspath(self, ref): """ Converts the given path 'ref' to an absolute path in the file system. :param ref: the path to resolve relative to ``self.relative`` :return: the absolute path of the resolved reference. """ directory, path = get_location(self.directory, ref.strip(), current=dirname(self.relative)) path = join_fb_root(join(directory, path)) return path
def checkout(request): """ Execute a checkout of the targeted entry with the informations of POST. """ path = request.GET.get('path') if not path: return HttpResponseBadRequest(missing_parameter('path')) ret, out, err = gitcmd.checkout(join_fb_root(path)) if not ret: return HttpResponse("Entry successfully checked out.") else: # pragma: no cover return HttpResponseNotFound( "Nothing to checked out." if not err else htmlprint.code(err + out))
def update_resource(request): """ View used to update a resource (file). """ post = json.loads(request.body.decode()) path = post.get("path") if path is None: return HttpResponseBadRequest('"path" parameter is missing') try: with open(join_fb_root(path), 'w') as f: print(post.get('content', ''), file=f) return JsonResponse({'success': True}) except Exception as e: # pragma: no cover return HttpResponseNotFound(str(e))
def show(request): """ Execute a git show on the targeted entry.""" path = request.GET.get('path') if not path: return HttpResponseBadRequest(missing_parameter('path')) try: ret, out, err = gitcmd.show_last_revision(join_fb_root(path)) if not ret: return HttpResponse(out) else: # pragma: no cover return HttpResponseNotFound(htmlprint.code(out + err)) except Exception as e: # pragma: no cover error = htmlprint.code(str(type(e)) + ' - ' + str(e)) return HttpResponseNotFound(error)
def update_resource(request): """ View used to update a resource (file). """ post = json.loads(request.body.decode()) path = post.get("path") if path is None: return HttpResponseBadRequest(missing_parameter('path')) try: with open(join_fb_root(path), 'w') as f: print(post.get('content', ''), file=f) if not path.startswith("lib/"): add_commit_path(request, path, action="modified") return JsonResponse({'success': True}) except Exception as e: # pragma: no cover return HttpResponseNotFound(str(e))
def git_commit(request): """ Execute an add and commit of the targeted entry with the informations of POST. """ post = json.loads(request.body.decode()) path = post.get('path') if not path: return HttpResponseBadRequest("parameter 'path' is missing") commit = post.get('commit') if not commit: return HttpResponseBadRequest("Missing 'commit' parameter") ret, out, err = gitcmd.commit(join_fb_root(path), commit) if not ret: return HttpResponse(htmlprint.code(out + err)) else: # pragma: no cover return HttpResponseNotFound(htmlprint.code(err + out))
def push(request): """ Execute a git push on the targeted entry with the informations of POST.""" post = json.loads(request.body.decode()) username = post.get('username', None) password = post.get('password', None) path = post.get('path', None) if not path: return HttpResponseBadRequest(missing_parameter('path')) ret, out, err = gitcmd.push(join_fb_root(path), username=username, password=password) if not ret: return HttpResponse(htmlprint.code(out + err)) else: # pragma: no cover return HttpResponseNotFound(htmlprint.code(err + out))
def get_resource(request): """Return the content of <path>.""" path = request.GET.get('path') if not path: return HttpResponseBadRequest('"path" parameter is missing') try: with open(join_fb_root(path)) as f: content = f.read() return JsonResponse({'content': content}) except Exception as e: # pragma: no cover msg = "Impossible to open '" + path + "' : " + htmlprint.code( str(type(e)) + ' - ' + str(e)) if settings.DEBUG: messages.error(request, "DEBUG set to True: " + htmlprint.html_exc()) return HttpResponseNotFound(msg)
def parse(self, path, directory=None, extends=False, debug=0): """ Parses data stored in file and return an AST in JSON format.. """ paths = path.split('/') self.lineno = 1 self.path = path self.directory = directory if not directory: self.directory = Directory.objects.get(name=paths[0]) self.relative = join(*(paths[1:])) self.absolute = join_fb_root(path) with open(self.absolute, 'r') as f: data = f.read() self.ast = { '__path': self.path, '__files': {}, '__errors': [], '__extends': [], '__warnings': [], '__definitions': {}, '__dependencies': [], '__comments': [] } self.add_depend(self.path) self.parsing = True self.lexer.reset() self.parser.parse( input=data, lexer=self.lexer, debug=debug ) self.compile(extends) self.parsing = False return self.ast
def get_resource(request): """Return the content of <path>.""" path = request.GET.get('path') if not path: return HttpResponseBadRequest(missing_parameter('path')) try: path = join_fb_root(path) return JsonResponse({ 'content': get_content(path), 'meta': get_meta(path) }) except Exception as e: # pragma: no cover msg = f"Impossible to open '{rm_fb_root(path)}' : {htmlprint.code(str(e))}" if settings.DEBUG: messages.error(request, "DEBUG set to True: " + htmlprint.html_exc()) msg += f"{request} : DEBUG set to True: {htmlprint.html_exc()}" return HttpResponseNotFound(msg)
def git_pull(request): """ Execute a git pull on the targeted entry with the informations of POST.""" post = json.loads(request.body.decode()) username = post.get('username') password = post.get('password') url = post.get('url') path = post.get('path') ret, out, err = gitcmd.pull(join_fb_root(path), username=username, password=password, url=url) if not ret: request.method = 'GET' request.META['REQUEST_METHOD'] = "GET" return get_resources(request) else: # pragma: no cover return HttpResponseNotFound(htmlprint.code(err + out))
def blame(request): """ Execute a git blame on the targeted entry.""" path = request.GET.get('path') if not path: return HttpResponseBadRequest(missing_parameter('path')) path = join_fb_root(path) base = os.path.basename(path) command = 'git blame {0} -w --show-email --contents {1}'.format(base, path) ret, out, err = exec_command(path, command) response = [] if not ret: regex = r'(?P<sha1>[^\s]+)\s+(?P<filename>[^\s]+)\s+\(<(?P<email>[^>]+)>\s+(?P<day>[' \ r'^\s]+)\s+(?P<hour>[^\s]+)\s+(?P<gmt>[^\s]+)\s+(?P<line>[^\)]+)\)(?P<text>[^\n]+)' matches = re.findall(regex, out) for match in matches: sha1 = match[1] command = 'git show --no-patch --oneline {0}'.format(sha1) ret, out, err = exec_command(path, command) if not ret: commit = ' '.join(out.split()[1:]) else: commit = '' response.append({ "sha1": sha1, "email": match[2], "day": match[3], "hour": match[4], "gmt": match[5], "line": int(match[6]), "commit": commit, "text": match[0] }) return HttpResponse(json.dumps(response), content_type='application/json') else: # pragma: no cover if "fatal: no such path" in err: return HttpResponse(json.dumps([]), content_type='application/json') return HttpResponseNotFound(htmlprint.code(out + err))
def download_resource(request): """Returns a download url to the resource at GET['path'] """ path = request.GET.get('path') if not path: return HttpResponseBadRequest(missing_parameter('path')) path = join_fb_root(path) filename = os.path.basename(path) if os.path.isdir(path): archive = shutil.make_archive(path, 'zip', path) response = HttpResponse(FileWrapper(open(archive, 'rb')), content_type='application/zip') response[ 'Content-Disposition'] = 'attachment; filename=%s.zip' % filename else: with open(path, 'rb') as fp: data = fp.read() response = HttpResponse(content_type="application/force-download") response[ 'Content-Disposition'] = 'attachment; filename=%s' % filename # force browser to # download file response.write(data) return response
def pl_tuto(request): post = json.loads(request.body.decode()) content = post.get('student') if not content: return HttpResponseBadRequest(missing_parameter('student')) path = post.get("path") if not path: path = 'Yggdrasil/conceptexo/pltuto.pl' path_components = path.split('/') directory = path_components[0] try: path = join_fb_root(path) with open(path, 'w') as f: print(content, file=f) directory = Directory.objects.get(name=directory) relative = os.path.join(*(path_components[1:])) pl, warnings = load_file(directory, relative) response = {'compiled': True} if not pl: response['compiled'] = False response['warnings'] = warnings else: response['json'] = pl.json response['warnings'] = warnings except Exception: # pragma: no cover response['compiled'] = False finally: os.remove(path) return HttpResponse( json.dumps(response), content_type='application/json', status=200 ) return HttpResponseBadRequest(content="Couldn't resolve ajax request")
def clone(request): """Execute a git clone on the targeted entry with the informations of POST.""" post = json.loads(request.body.decode()) username = post.get('username') password = post.get('password') destination = post.get('destination') path = post.get('path') if not path: return HttpResponseBadRequest(settings.missing_parameter('path')) url = post.get('url') if not url: return HttpResponseBadRequest(missing_parameter('url')) if '@' in url: return HttpResponseNotFound( "SSH link is not supported, please use HTTPS") path = join_fb_root(path) try: ret, out, err = gitcmd.clone(path, url, destination, username, password) if ret: # pragma: no cover raise Exception(err + out) else: path = (os.path.join(path, destination) if destination else os.path.join( path, os.path.basename(os.path.splitext(url)[0]))) message = htmlprint.code(out + err) ret, out, err = gitcmd.set_url(path, url) if not ret: return HttpResponse(message + htmlprint.code(out + err)) else: # pragma: no cover shutil.rmtree(path, ignore_errors=True) raise Exception(err + out) except Exception as e: # pragma: no cover return HttpResponseNotFound(str(e))