From 43f00e12d6c60c97f8f26f8480334e64c677f6ac Mon Sep 17 00:00:00 2001 From: Mickael KERJEAN Date: Tue, 8 Jan 2019 23:51:11 +1100 Subject: [PATCH] feature (orgmode): use emacs to export org documents --- client/components/dropdown.js | 3 + client/helpers/index.js | 2 +- client/helpers/path.js | 6 +- client/pages/filespage/thing-new.js | 2 +- client/pages/sharepage.js | 17 ++- client/pages/viewerpage.js | 1 + client/pages/viewerpage/ide.js | 39 ++++++- client/pages/viewerpage/ide.scss | 22 ++++ client/pages/viewerpage/menubar.js | 2 +- config/emacs.el | 12 ++ config/mime.json | 1 + server/common/constants.go | 1 + server/common/error.go | 3 + server/ctrl/export.go | 149 +++++++++++++++++++++++++ server/ctrl/files.go | 2 +- server/ctrl/share.go | 2 +- server/main.go | 22 ++-- server/middleware/session.go | 96 ++++++++++------ server/model/share.go | 2 +- server/plugin/plg_image_light/index.go | 2 +- 20 files changed, 328 insertions(+), 58 deletions(-) create mode 100644 config/emacs.el create mode 100644 server/ctrl/export.go diff --git a/client/components/dropdown.js b/client/components/dropdown.js index a501b6c4..29cf14dd 100644 --- a/client/components/dropdown.js +++ b/client/components/dropdown.js @@ -45,6 +45,9 @@ export class Dropdown extends React.Component { } toggleDropdown(e){ + if(this.props.enable === false){ + return + } document.body.removeEventListener("click", this.closeDropdown); this.setState({button: !this.state.button}, () => { if(this.state.button === true){ diff --git a/client/helpers/index.js b/client/helpers/index.js index 3d4f1d85..eb42e6bd 100644 --- a/client/helpers/index.js +++ b/client/helpers/index.js @@ -4,7 +4,7 @@ export { debounce, throttle } from './backpressure'; export { encrypt, decrypt, bcrypt_password } from './crypto'; export { event } from './events'; export { cache } from './cache'; -export { pathBuilder, basename, dirname, absoluteToRelative, filetype, currentShare, appendShareToUrl } from './path'; +export { pathBuilder, basename, dirname, absoluteToRelative, filetype, currentShare, findParams, appendShareToUrl } from './path'; export { memory } from './memory'; export { prepare } from './navigate'; export { invalidate, http_get, http_post, http_delete } from './ajax'; diff --git a/client/helpers/path.js b/client/helpers/path.js index 10b7760e..a49e53fc 100644 --- a/client/helpers/path.js +++ b/client/helpers/path.js @@ -37,7 +37,11 @@ export function absoluteToRelative(from, to){ } export function currentShare(){ - return new window.URL(location.href).searchParams.get("share") || "" + return findParams("share"); +} + +export function findParams(p){ + return new window.URL(location.href).searchParams.get(p) || "" } export function appendShareToUrl(link) { diff --git a/client/pages/filespage/thing-new.js b/client/pages/filespage/thing-new.js index d825eb4c..e39b0965 100644 --- a/client/pages/filespage/thing-new.js +++ b/client/pages/filespage/thing-new.js @@ -1,7 +1,7 @@ import React from 'react'; import PropTypes from 'prop-types'; -import { Card, NgIf, Icon, EventEmitter, EventReceiver, Dropdown, DropdownButton, DropdownList, DropdownItem } from '../../components/'; +import { Card, NgIf, Icon, EventEmitter, EventReceiver } from '../../components/'; import { pathBuilder, debounce } from '../../helpers/'; import "./thing.scss"; diff --git a/client/pages/sharepage.js b/client/pages/sharepage.js index 75b62ca3..d07481b2 100644 --- a/client/pages/sharepage.js +++ b/client/pages/sharepage.js @@ -2,7 +2,7 @@ import React from 'react'; import { Redirect } from 'react-router'; import { Share } from '../model/'; -import { notify, basename, filetype } from '../helpers/'; +import { notify, basename, filetype, findParams } from '../helpers/'; import { Loader, Input, Button, Container, ErrorPage, Icon, NgIf } from '../components/'; import './error.scss'; import './sharepage.scss'; @@ -67,7 +67,20 @@ export class SharePage extends React.Component { let className = this.state.error ? "error rand-"+Math.random().toString() : ""; if(this.state.path !== null){ - if(filetype(this.state.path) === "directory"){ + if(!!findParams("next")){ + const url = findParams("next"); + if(url[0] === "/"){ + requestAnimationFrame(() => { + window.location.pathname = url; + }); + return ( +
+ +
+ ); + } + notify.send("You can't do that :)", "error"); + }else if(filetype(this.state.path) === "directory"){ return ( ); }else{ return ( ); diff --git a/client/pages/viewerpage.js b/client/pages/viewerpage.js index 5284a99e..73f9f585 100644 --- a/client/pages/viewerpage.js +++ b/client/pages/viewerpage.js @@ -133,6 +133,7 @@ export class ViewerPage extends React.Component { onSave={this.save.bind(this)} content={this.state.content || ""} url={this.state.url} + path={this.state.path} filename={this.state.filename}/> diff --git a/client/pages/viewerpage/ide.js b/client/pages/viewerpage/ide.js index 9d6ad135..203b75db 100644 --- a/client/pages/viewerpage/ide.js +++ b/client/pages/viewerpage/ide.js @@ -4,8 +4,8 @@ import { withRouter } from 'react-router'; import { Prompt } from "react-router-dom"; import { Subject } from 'rxjs/Subject'; -import { NgIf, Fab, Icon } from '../../components/'; -import { confirm } from '../../helpers/'; +import { NgIf, Fab, Icon, Dropdown, DropdownButton, DropdownList, DropdownItem } from '../../components/'; +import { confirm, currentShare } from '../../helpers/'; import { Editor } from './editor'; import { MenuBar } from './menubar'; import { OrgTodosViewer, OrgEventsViewer } from './org_viewer'; @@ -48,6 +48,7 @@ export class IDE extends React.Component { } componentWillUnmount(){ this.unblock(); + window.clearInterval(this.state.id); } save(){ @@ -70,7 +71,6 @@ export class IDE extends React.Component { }); } - /* Org Viewer specific stuff */ toggleAgenda(force = null){ this.setState({appear_agenda: force === null ? !this.state.appear_agenda : !!force}); @@ -85,10 +85,25 @@ export class IDE extends React.Component { this.state.event.next(["goTo", lineNumber]); } + download(){ + document.cookie = "download=yes; path=/; max-age=120;"; + this.setState({random: Math.random()}); + this.state.id = window.setInterval(() => { + if(/download=yes/.test(document.cookie) === false){ + window.clearInterval(this.state.id); + this.setState({random: Math.random()}); + } + }, 100); + } + render(){ + const changeExt = function(filename, ext){ + return filename.replace(/\.org$/, "."+ext); + }; + return (
- + @@ -101,6 +116,22 @@ export class IDE extends React.Component { + this.download()} enable={/download=yes/.test(document.cookie) ? false : true}> + + + + + Save current file + Export as HTML + Export as PDF + Export as Text + Export as Latex + Export as Calendar + Export as Beamer + Export as Open office + Export as Markdown + + diff --git a/client/pages/viewerpage/ide.scss b/client/pages/viewerpage/ide.scss index 4dd43fe7..3c9d5412 100644 --- a/client/pages/viewerpage/ide.scss +++ b/client/pages/viewerpage/ide.scss @@ -9,6 +9,28 @@ // https://stackoverflow.com/questions/44948158/flexbox-overflow-issue-in-firefox min-height: 0; } + + .component_menubar{ + .component_dropdown{ + float: right; + .dropdown_button{ + border: none; + padding: 0; margin: 0; + } + &.active .dropdown_button{ + box-shadow: none; + } + .dropdown_container ul li > div{ + padding: 0; + a { + padding: 7px 5px 7px 10px; + display: inline-block; + width: 100%; + box-sizing: border-box; + } + } + } + } } diff --git a/client/pages/viewerpage/menubar.js b/client/pages/viewerpage/menubar.js index 8d98a828..131f4d90 100644 --- a/client/pages/viewerpage/menubar.js +++ b/client/pages/viewerpage/menubar.js @@ -16,7 +16,7 @@ export const MenuBar = (props) => { {props.children} - + { props.download === null ? null : }
diff --git a/config/emacs.el b/config/emacs.el new file mode 100644 index 00000000..efc681e4 --- /dev/null +++ b/config/emacs.el @@ -0,0 +1,12 @@ +;; this is the config that's loaded by emacs when using the org mode export + +;; org mode keywords +(setq org-todo-keywords (quote ((sequence "TODO(t)" "DOING(d)" "WAITING(w)" "|" "CANCEL(C)" "DEFERRED(F)" "DONE(D)")))) + +;; html export +(setq org-html-head "") +(setq org-html-validation-link nil) +(setq org-html-creator-string "Using Filestash") + +(setq org-export-use-babel nil) +(setq org-confirm-babel-evaluate nil) diff --git a/config/mime.json b/config/mime.json index 19dcc554..c56b1afa 100644 --- a/config/mime.json +++ b/config/mime.json @@ -90,6 +90,7 @@ "ogg": "audio/ogg", "ogv": "application/ogg", "orf": "image/x-olympus-orf", + "org": "text/org", "pdb": "application/x-pilot", "pdf": "application/pdf", "pef": "image/x-pentax-pef", diff --git a/server/common/constants.go b/server/common/constants.go index 5dc7cc63..bd3517cc 100644 --- a/server/common/constants.go +++ b/server/common/constants.go @@ -5,6 +5,7 @@ const ( CONFIG_PATH = "data/config/" PLUGIN_PATH = "data/plugin/" LOG_PATH = "data/log/" + TMP_PATH = "data/tmp/" COOKIE_NAME_AUTH = "auth" COOKIE_NAME_PROOF = "proof" COOKIE_NAME_ADMIN = "admin" diff --git a/server/common/error.go b/server/common/error.go index 9eaf2b1e..dafda0be 100644 --- a/server/common/error.go +++ b/server/common/error.go @@ -15,6 +15,9 @@ var ( ErrNotValid error = NewError("Not Valid", 405) ErrNotReachable error = NewError("Cannot Reach Destination", 502) ErrInvalidPassword = NewError("Invalid Password", 403) + ErrNotImplemented = NewError("Not Implemented", 501) + ErrFilesystemError = NewError("Can't use filesystem", 503) + ErrMissingDependency = NewError("Missing dependency", 424) ) type AppError struct { diff --git a/server/ctrl/export.go b/server/ctrl/export.go new file mode 100644 index 00000000..7549a606 --- /dev/null +++ b/server/ctrl/export.go @@ -0,0 +1,149 @@ +package ctrl + +import ( + "fmt" + . "github.com/mickael-kerjean/filestash/server/common" + "github.com/mickael-kerjean/filestash/server/model" + "github.com/gorilla/mux" + "io" + "net/http" + "os" + "os/exec" + "runtime" + "strings" +) + + +var EXPORT_PATH string +func init() { + EXPORT_PATH = GetAbsolutePath(TMP_PATH) + os.RemoveAll(EXPORT_PATH) + os.MkdirAll(EXPORT_PATH, os.ModePerm) +} +func FileExport(ctx App, res http.ResponseWriter, req *http.Request) { + query := req.URL.Query() + p := mux.Vars(req) + mimeType := fmt.Sprintf("%s/%s", p["mtype0"], p["mtype1"]) + path, err := pathBuilder(ctx, strings.Replace(req.URL.Path, fmt.Sprintf("/api/export/%s/%s/%s", p["share"], p["mtype0"], p["mtype1"]), "", 1)) + if err != nil { + SendErrorResult(res, err) + return + } else if model.CanRead(&ctx) == false { + SendErrorResult(res, ErrPermissionDenied) + return + } + http.SetCookie(res, &http.Cookie{ + Name: "download", + Value: "", + MaxAge: -1, + Path: "/", + }) + + var tmpPath string = EXPORT_PATH + "/export_" + QuickString(10) + var cmd *exec.Cmd + var emacsPath string + var outPath string + if GetMimeType(path) == "text/org" { + if emacsPath, err = exec.LookPath("emacs"); err != nil { + SendErrorResult(res, ErrMissingDependency) + return + } + if runtime.GOOS == "darwin" { + // on OSX, the default emacs isn't usable so we default to the one provided by `brew` + if f, err := os.OpenFile("/usr/local/Cellar/emacs/", os.O_RDONLY, os.ModePerm); err == nil { + if dirs, err := f.Readdirnames(0); err == nil { + if len(dirs) > 0 { + emacsPath = "/usr/local/Cellar/emacs/" + dirs[0] + "/bin/emacs" + } + } + } + } + + if mimeType == "text/html" { + cmd = exec.Command( + emacsPath, "--no-init-file", "--batch", + "--load", GetAbsolutePath(CONFIG_PATH + "emacs.el"), + "--eval", "(setq org-html-extension \"org\")", + tmpPath + "/index.org", "-f", "org-html-export-to-html", + ) + outPath = "index.org.org" + } else if mimeType == "application/pdf" { + cmd = exec.Command( + emacsPath, "--no-init-file", "--batch", + tmpPath + "/index.org", "-f", "org-latex-export-to-pdf", + ) + if query.Get("mode") == "beamer" { + cmd = exec.Command( + emacsPath, "--no-init-file", "--batch", + tmpPath + "/index.org", "-f", "org-beamer-export-to-pdf", + ) + } + outPath = "index.pdf" + } else if mimeType == "text/calendar" { + cmd = exec.Command( + emacsPath, "--no-init-file", "--batch", + tmpPath + "/index.org", "-f", "org-icalendar-export-to-ics", + ) + outPath = "index.ics" + } else if mimeType == "text/plain" { + cmd = exec.Command( + emacsPath, "--no-init-file", "--batch", + tmpPath + "/index.org", "-f", "org-ascii-export-to-ascii", + ) + outPath = "index.txt" + } else if mimeType == "text/x-latex" { + cmd = exec.Command( + emacsPath, "--no-init-file", "--batch", + tmpPath + "/index.org", "-f", "org-latex-export-to-latex", + ) + outPath = "index.tex" + } else if mimeType == "text/markdown" { + cmd = exec.Command( + emacsPath, "--no-init-file", "--batch", + tmpPath + "/index.org", "-f", "org-md-export-to-markdown", + ) + outPath = "index.md" + } else if mimeType == "application/vnd.oasis.opendocument.text" { + cmd = exec.Command( + emacsPath, "--no-init-file", "--batch", + tmpPath + "/index.org", "-f", "org-odt-export-to-odt", + ) + outPath = "index.odt" + }else { + SendErrorResult(res, ErrNotImplemented) + return + } + + os.MkdirAll(tmpPath, os.ModePerm) + defer os.RemoveAll(tmpPath) + f, err := os.OpenFile(tmpPath + "/index.org", os.O_WRONLY|os.O_CREATE, os.ModePerm) + if err != nil { + SendErrorResult(res, ErrFilesystemError) + return + } + file, err := ctx.Backend.Cat(path) + if err != nil { + SendErrorResult(res, err) + return + } + io.Copy(f, file) + // TODO: insert related resources: eg: images + + if err = cmd.Run(); err != nil { + SendErrorResult(res, NewError("emacs has quit with error: '%s'" + err.Error(), 400)) + return + } + + f, err = os.OpenFile(tmpPath + "/"+outPath, os.O_RDONLY, os.ModePerm) + if err != nil { + SendErrorResult(res, ErrFilesystemError) + return + } + res.Header().Set("Content-Type", mimeType) + io.Copy(res, f) + return + } + + SendErrorResult(res, ErrNotImplemented) + return +} diff --git a/server/ctrl/files.go b/server/ctrl/files.go index eb498305..bde5d465 100644 --- a/server/ctrl/files.go +++ b/server/ctrl/files.go @@ -106,7 +106,7 @@ func FileCat(ctx App, res http.ResponseWriter, req *http.Request) { Path: "/", }) if model.CanRead(&ctx) == false { - SendErrorResult(res, NewError("Permission denied", 403)) + SendErrorResult(res, ErrPermissionDenied) return } diff --git a/server/ctrl/share.go b/server/ctrl/share.go index 4ad0de4b..d7e929d4 100644 --- a/server/ctrl/share.go +++ b/server/ctrl/share.go @@ -151,7 +151,7 @@ func ShareVerifyProof(ctx App, res http.ResponseWriter, req *http.Request) { Key: fmt.Sprint(ctx.Body["type"]), Value: fmt.Sprint(ctx.Body["value"]), } - verifiedProof = model.ShareProofGetAlreadyVerified(req, &ctx) + verifiedProof = model.ShareProofGetAlreadyVerified(req) requiredProof = model.ShareProofGetRequired(s) // 2) validate the current context diff --git a/server/main.go b/server/main.go index ab253b54..277dda8a 100644 --- a/server/main.go +++ b/server/main.go @@ -66,21 +66,27 @@ func Init(a *App) { // API for File management files := r.PathPrefix("/api/files").Subrouter() middlewares = []Middleware{ ApiHeaders, SecureHeaders, SessionStart, LoggedInOnly } - files.HandleFunc("/ls", NewMiddlewareChain(FileLs, middlewares, *a)).Methods("GET") - files.HandleFunc("/cat", NewMiddlewareChain(FileCat, middlewares, *a)).Methods("GET") - files.HandleFunc("/cat", NewMiddlewareChain(FileSave, middlewares, *a)).Methods("POST") - files.HandleFunc("/mv", NewMiddlewareChain(FileMv, middlewares, *a)).Methods("GET") - files.HandleFunc("/rm", NewMiddlewareChain(FileRm, middlewares, *a)).Methods("GET") - files.HandleFunc("/mkdir", NewMiddlewareChain(FileMkdir, middlewares, *a)).Methods("GET") - files.HandleFunc("/touch", NewMiddlewareChain(FileTouch, middlewares, *a)).Methods("GET") + files.HandleFunc("/ls", NewMiddlewareChain(FileLs, middlewares, *a)).Methods("GET") + files.HandleFunc("/cat", NewMiddlewareChain(FileCat, middlewares, *a)).Methods("GET") + files.HandleFunc("/cat", NewMiddlewareChain(FileSave, middlewares, *a)).Methods("POST") + files.HandleFunc("/mv", NewMiddlewareChain(FileMv, middlewares, *a)).Methods("GET") + files.HandleFunc("/rm", NewMiddlewareChain(FileRm, middlewares, *a)).Methods("GET") + files.HandleFunc("/mkdir", NewMiddlewareChain(FileMkdir, middlewares, *a)).Methods("GET") + files.HandleFunc("/touch", NewMiddlewareChain(FileTouch, middlewares, *a)).Methods("GET") + + // API for exporter + middlewares = []Middleware{ ApiHeaders, SecureHeaders, RedirectSharedLoginIfNeeded, SessionStart, LoggedInOnly } + r.PathPrefix("/api/export/{share}/{mtype0}/{mtype1}").Handler(NewMiddlewareChain(FileExport, middlewares, *a)) + // API for Shared link share := r.PathPrefix("/api/share").Subrouter() middlewares = []Middleware{ ApiHeaders, SecureHeaders, SessionStart, LoggedInOnly } share.HandleFunc("", NewMiddlewareChain(ShareList, middlewares, *a)).Methods("GET") share.HandleFunc("/{share}", NewMiddlewareChain(ShareDelete, middlewares, *a)).Methods("DELETE") - middlewares = []Middleware{ ApiHeaders, SecureHeaders, SessionStart, BodyParser, LoggedInOnly } + middlewares = []Middleware{ ApiHeaders, SecureHeaders, SessionStart, LoggedInOnly, BodyParser } share.HandleFunc("/{share}", NewMiddlewareChain(ShareUpsert, middlewares, *a)).Methods("POST") + middlewares = []Middleware{ ApiHeaders, SecureHeaders, BodyParser } share.HandleFunc("/{share}/proof", NewMiddlewareChain(ShareVerifyProof, middlewares, *a)).Methods("POST") // Webdav server / Shared Link diff --git a/server/middleware/session.go b/server/middleware/session.go index 293fd1d6..2c9ea8ec 100644 --- a/server/middleware/session.go +++ b/server/middleware/session.go @@ -2,6 +2,7 @@ package middleware import ( "encoding/json" + "fmt" . "github.com/mickael-kerjean/filestash/server/common" "github.com/mickael-kerjean/filestash/server/model" "github.com/gorilla/mux" @@ -46,45 +47,18 @@ func AdminOnly(fn func(App, http.ResponseWriter, *http.Request)) func(ctx App, r } func SessionStart (fn func(App, http.ResponseWriter, *http.Request)) func(ctx App, res http.ResponseWriter, req *http.Request) { - extractShare := func(req *http.Request, ctx *App, share_id string) (Share, error) { - if share_id == "" { - return Share{}, nil - } - - if Config.Get("features.share.enable").Bool() == false { - Log.Debug("Share feature isn't enable, contact your administrator") - return Share{}, NewError("Feature isn't enable, contact your administrator", 405) - } - - s, err := model.ShareGet(share_id) - if err != nil { - return Share{}, nil - } - if err = s.IsValid(); err != nil { - return Share{}, err - } - return s, nil - } extractSession := func(req *http.Request, ctx *App) (map[string]string, error) { var str string var err error var res map[string]string = make(map[string]string) if ctx.Share.Id != "" { - var verifiedProof []model.Proof = model.ShareProofGetAlreadyVerified(req, ctx) - var requiredProof []model.Proof = model.ShareProofGetRequired(ctx.Share) - var remainingProof []model.Proof = model.ShareProofCalculateRemainings(requiredProof, verifiedProof) - if len(remainingProof) != 0 { - return res, NewError("Unauthorized Shared space", 400) - } - str = ctx.Share.Auth - str, err = DecryptString(SECRET_KEY, str) + str, err = DecryptString(SECRET_KEY, ctx.Share.Auth) if err != nil { // This typically happen when changing the secret key return res, nil } err = json.Unmarshal([]byte(str), &res) - if ctx.Share.Path[len(ctx.Share.Path)-1:] == "/" { res["path"] = ctx.Share.Path } else { @@ -116,14 +90,7 @@ func SessionStart (fn func(App, http.ResponseWriter, *http.Request)) func(ctx Ap return func(ctx App, res http.ResponseWriter, req *http.Request) { var err error - share_id := func() string { - if len(req.URL.Path) > 3 && req.URL.Path[:3] == "/s/" { - // this runs while using a link as a webdav server - return mux.Vars(req)["share"] - } - return req.URL.Query().Get("share") - }() - if ctx.Share, err = extractShare(req, &ctx, share_id); err != nil { + if ctx.Share, err = _findShare(req, _extractShareId(req)); err != nil { SendErrorResult(res, err) return } @@ -138,3 +105,60 @@ func SessionStart (fn func(App, http.ResponseWriter, *http.Request)) func(ctx Ap fn(ctx, res, req) } } + +func RedirectSharedLoginIfNeeded(fn func(App, http.ResponseWriter, *http.Request)) func(ctx App, res http.ResponseWriter, req *http.Request) { + return func(ctx App, res http.ResponseWriter, req *http.Request) { + share_id := _extractShareId(req) + if share_id == "" { + SendErrorResult(res, ErrNotValid) + return + } + + share, err := _findShare(req, share_id); + if err != nil || share_id != share.Id { + http.Redirect(res, req, fmt.Sprintf("/s/%s?next=%s", share_id, req.URL.Path), http.StatusTemporaryRedirect) + return + } + fn(ctx, res, req) + } +} + +func _extractShareId(req *http.Request) string { + share := req.URL.Query().Get("share") + if share != "" { + return share + } + m := mux.Vars(req)["share"] + if m == "me" { + return "" + } + return m +} + +func _findShare(req *http.Request, share_id string) (Share, error) { + var err error + if share_id == "" { + return Share{}, nil + } + + if Config.Get("features.share.enable").Bool() == false { + Log.Debug("Share feature isn't enable, contact your administrator") + return Share{}, NewError("Feature isn't enable, contact your administrator", 405) + } + + s, err := model.ShareGet(share_id) + if err != nil { + return Share{}, nil + } + if err = s.IsValid(); err != nil { + return Share{}, err + } + + var verifiedProof []model.Proof = model.ShareProofGetAlreadyVerified(req) + var requiredProof []model.Proof = model.ShareProofGetRequired(s) + var remainingProof []model.Proof = model.ShareProofCalculateRemainings(requiredProof, verifiedProof) + if len(remainingProof) != 0 { + return Share{}, NewError("Unauthorized Shared space", 400) + } + return s, nil +} diff --git a/server/model/share.go b/server/model/share.go index 3845fc0f..f173741f 100644 --- a/server/model/share.go +++ b/server/model/share.go @@ -249,7 +249,7 @@ func ShareProofVerifier(ctx *App, s Share, proof Proof) (Proof, error) { return p, nil } -func ShareProofGetAlreadyVerified(req *http.Request, ctx *App) []Proof { +func ShareProofGetAlreadyVerified(req *http.Request) []Proof { var p []Proof var cookieValue string diff --git a/server/plugin/plg_image_light/index.go b/server/plugin/plg_image_light/index.go index 579212ef..5b205c13 100644 --- a/server/plugin/plg_image_light/index.go +++ b/server/plugin/plg_image_light/index.go @@ -165,7 +165,7 @@ func Init(conf *Configuration) { // => lower RAM usage while processing file, err := os.OpenFile(transform.Temporary, os.O_WRONLY|os.O_CREATE, os.ModePerm) if err != nil { - return reader, NewError("Can't use filesystem", 500) + return reader, ErrFilesystemError } io.Copy(file, reader) file.Close()