├── demo-ui ├── public │ ├── testFs │ │ ├── thisIsAnEmptyFile │ │ ├── thisIsADir │ │ │ ├── anotherDir │ │ │ │ └── empty │ │ │ ├── txt.txt │ │ │ └── thisIsAlsoAMeme.jpg │ │ ├── thisIsATXTWithNoExtension │ │ ├── thisIsALongNameThatIsVeryVeryLongReallyLong.txt │ │ ├── thisIsAMeme.jpg │ │ ├── thisIsAPDF.pdf │ │ ├── thisIsAudio.mp3 │ │ ├── thisIsABigPic.jpg │ │ ├── thisIsAVideo.mp4 │ │ ├── thisIsUnicode汉字卡片.jpg │ │ ├── thisIsHTML.html │ │ └── thisIsASourceFile.go │ ├── favicon.png │ ├── mocks │ │ ├── ls3.json │ │ ├── features.json │ │ ├── ls1.json │ │ ├── ls2.json │ │ └── ls0.json │ ├── icons │ │ ├── 16x16 │ │ │ ├── text-x-generic.svg │ │ │ ├── video-x-generic.svg │ │ │ ├── audio-x-generic.svg │ │ │ ├── image-x-generic.svg │ │ │ ├── application-octet-stream.svg │ │ │ ├── file-manager.svg │ │ │ └── application-pdf.svg │ │ └── 48x48 │ │ │ ├── text-x-generic.svg │ │ │ ├── audio-x-generic.svg │ │ │ ├── video-x-generic.svg │ │ │ ├── application-pdf.svg │ │ │ └── image-x-generic.svg │ └── index.html ├── src │ ├── global.d.ts │ ├── SVG │ │ ├── IconDownload.svelte │ │ ├── IconList.svelte │ │ ├── IconSortSizeAsc.svelte │ │ ├── IconSortSizeDesc.svelte │ │ ├── IconGrid.svelte │ │ ├── IconSortAlphAsc.svelte │ │ ├── IconSortAlphDesc.svelte │ │ ├── IconNewFolder.svelte │ │ ├── IconSortDateDesc.svelte │ │ ├── IconLogout.svelte │ │ ├── IconReload.svelte │ │ ├── IconSortDateAsc.svelte │ │ ├── IconPaste.svelte │ │ ├── IconUnpaste.svelte │ │ ├── IconUpload.svelte │ │ ├── IconShare.svelte │ │ ├── IconLink.svelte │ │ └── IconInvalidLink.svelte │ ├── Utils.svelte │ ├── main.ts │ ├── Snippets │ │ ├── TextShower.svelte │ │ └── Breadcrumb.svelte │ ├── FileManager │ │ ├── Grid.svelte │ │ ├── GridCell.svelte │ │ ├── ListRow.svelte │ │ └── List.svelte │ ├── Preview │ │ ├── Preview.svelte │ │ ├── FullSize.svelte │ │ └── FullScreen.svelte │ ├── MimeTypes.svelte │ ├── global.css │ └── Auth.svelte ├── tsconfig.json ├── package.json └── rollup.config.js ├── web-ui ├── src │ ├── global.d.ts │ ├── SVG │ │ ├── IconDownload.svelte │ │ ├── IconList.svelte │ │ ├── IconSortSizeAsc.svelte │ │ ├── IconSortSizeDesc.svelte │ │ ├── IconGrid.svelte │ │ ├── IconSortAlphAsc.svelte │ │ ├── IconSortAlphDesc.svelte │ │ ├── IconNewFolder.svelte │ │ ├── IconSortDateAsc.svelte │ │ ├── IconSortDateDesc.svelte │ │ ├── IconLogout.svelte │ │ ├── IconReload.svelte │ │ ├── IconPaste.svelte │ │ ├── IconUnpaste.svelte │ │ ├── IconUpload.svelte │ │ ├── IconShare.svelte │ │ ├── IconLink.svelte │ │ └── IconInvalidLink.svelte │ ├── Utils.svelte │ ├── main.ts │ ├── Snippets │ │ ├── TextShower.svelte │ │ └── Breadcrumb.svelte │ ├── FileManager │ │ ├── Grid.svelte │ │ ├── GridCell.svelte │ │ ├── ListRow.svelte │ │ └── List.svelte │ ├── Preview │ │ ├── Preview.svelte │ │ ├── FullSize.svelte │ │ └── FullScreen.svelte │ ├── MimeTypes.svelte │ ├── global.css │ └── Auth.svelte ├── public │ ├── favicon.png │ ├── icons │ │ ├── 16x16 │ │ │ ├── text-x-generic.svg │ │ │ ├── video-x-generic.svg │ │ │ ├── audio-x-generic.svg │ │ │ ├── image-x-generic.svg │ │ │ ├── application-octet-stream.svg │ │ │ ├── file-manager.svg │ │ │ └── application-pdf.svg │ │ └── 48x48 │ │ │ ├── text-x-generic.svg │ │ │ ├── audio-x-generic.svg │ │ │ ├── video-x-generic.svg │ │ │ ├── application-pdf.svg │ │ │ └── image-x-generic.svg │ └── index.html ├── tsconfig.json ├── build_notes.md ├── package.json └── rollup.config.js ├── version.json ├── ROADMAP.md ├── src ├── static │ ├── favicon.png │ ├── icons │ │ ├── 16x16 │ │ │ ├── text-x-generic.svg │ │ │ ├── video-x-generic.svg │ │ │ ├── audio-x-generic.svg │ │ │ ├── image-x-generic.svg │ │ │ ├── application-octet-stream.svg │ │ │ ├── file-manager.svg │ │ │ └── application-pdf.svg │ │ └── 48x48 │ │ │ ├── text-x-generic.svg │ │ │ ├── audio-x-generic.svg │ │ │ ├── video-x-generic.svg │ │ │ ├── application-pdf.svg │ │ │ └── image-x-generic.svg │ └── index.html ├── go.mod ├── files │ ├── file_users_windows.go │ ├── file_users.go │ ├── mimetypes.go │ └── files.go ├── commons │ └── commons.go ├── crypgo │ └── crypgo.go └── go.sum ├── .gitignore ├── Dockerfile ├── CONTRIBUTING.md ├── Makefile └── Changelog.md /demo-ui/public/testFs/thisIsAnEmptyFile: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /demo-ui/public/testFs/thisIsADir/anotherDir/empty: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /demo-ui/public/testFs/thisIsADir/txt.txt: -------------------------------------------------------------------------------- 1 | ciao 2 | -------------------------------------------------------------------------------- /demo-ui/public/testFs/thisIsATXTWithNoExtension: -------------------------------------------------------------------------------- 1 | ciao 2 | -------------------------------------------------------------------------------- /demo-ui/src/global.d.ts: -------------------------------------------------------------------------------- 1 | /// -------------------------------------------------------------------------------- /web-ui/src/global.d.ts: -------------------------------------------------------------------------------- 1 | /// -------------------------------------------------------------------------------- /demo-ui/public/testFs/thisIsALongNameThatIsVeryVeryLongReallyLong.txt: -------------------------------------------------------------------------------- 1 | Ciao -------------------------------------------------------------------------------- /version.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "v0.8.0", 3 | "releaseCode": 29 4 | } -------------------------------------------------------------------------------- /ROADMAP.md: -------------------------------------------------------------------------------- 1 | #### [Moved to Wiki](https://github.com/proofrock/pupcloud/wiki/Roadmap) -------------------------------------------------------------------------------- /src/static/favicon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/proofrock/pupcloud/HEAD/src/static/favicon.png -------------------------------------------------------------------------------- /demo-ui/public/favicon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/proofrock/pupcloud/HEAD/demo-ui/public/favicon.png -------------------------------------------------------------------------------- /web-ui/public/favicon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/proofrock/pupcloud/HEAD/web-ui/public/favicon.png -------------------------------------------------------------------------------- /demo-ui/public/testFs/thisIsAMeme.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/proofrock/pupcloud/HEAD/demo-ui/public/testFs/thisIsAMeme.jpg -------------------------------------------------------------------------------- /demo-ui/public/testFs/thisIsAPDF.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/proofrock/pupcloud/HEAD/demo-ui/public/testFs/thisIsAPDF.pdf -------------------------------------------------------------------------------- /demo-ui/public/testFs/thisIsAudio.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/proofrock/pupcloud/HEAD/demo-ui/public/testFs/thisIsAudio.mp3 -------------------------------------------------------------------------------- /demo-ui/public/testFs/thisIsABigPic.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/proofrock/pupcloud/HEAD/demo-ui/public/testFs/thisIsABigPic.jpg -------------------------------------------------------------------------------- /demo-ui/public/testFs/thisIsAVideo.mp4: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/proofrock/pupcloud/HEAD/demo-ui/public/testFs/thisIsAVideo.mp4 -------------------------------------------------------------------------------- /demo-ui/public/testFs/thisIsUnicode汉字卡片.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/proofrock/pupcloud/HEAD/demo-ui/public/testFs/thisIsUnicode汉字卡片.jpg -------------------------------------------------------------------------------- /demo-ui/public/testFs/thisIsADir/thisIsAlsoAMeme.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/proofrock/pupcloud/HEAD/demo-ui/public/testFs/thisIsADir/thisIsAlsoAMeme.jpg -------------------------------------------------------------------------------- /demo-ui/public/mocks/ls3.json: -------------------------------------------------------------------------------- 1 | { 2 | "path": [ 3 | "thisIsADir", 4 | "anotherDir", 5 | "a3rdDir" 6 | ], 7 | "items": [] 8 | } -------------------------------------------------------------------------------- /src/static/icons/16x16/text-x-generic.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /demo-ui/public/icons/16x16/text-x-generic.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /web-ui/public/icons/16x16/text-x-generic.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/static/icons/16x16/video-x-generic.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /demo-ui/public/icons/16x16/video-x-generic.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/static/icons/16x16/audio-x-generic.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /web-ui/public/icons/16x16/video-x-generic.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /demo-ui/public/icons/16x16/audio-x-generic.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /web-ui/public/icons/16x16/audio-x-generic.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /web-ui/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "@tsconfig/svelte/tsconfig.json", 3 | "include": [ 4 | "src/**/*" 5 | ], 6 | "exclude": [ 7 | "node_modules/*", 8 | "__sapper__/*", 9 | "public/*" 10 | ], 11 | "compilerOptions": { 12 | "sourceMap": true, 13 | } 14 | } -------------------------------------------------------------------------------- /demo-ui/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "@tsconfig/svelte/tsconfig.json", 3 | "include": [ 4 | "src/**/*" 5 | ], 6 | "exclude": [ 7 | "node_modules/*", 8 | "__sapper__/*", 9 | "public/*" 10 | ], 11 | "compilerOptions": { 12 | "sourceMap": true, 13 | } 14 | } -------------------------------------------------------------------------------- /demo-ui/public/mocks/features.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "v0.8.0", 3 | "title": "🐶 Pupcloud Demo", 4 | "readOnly": false, 5 | "maxReqSize": 1048576, 6 | "hasPassword": false, 7 | "sharing": { 8 | "allowRW": true, 9 | "profiles": [ 10 | "John", 11 | "Mary", 12 | "Loreena" 13 | ] 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /src/static/icons/16x16/image-x-generic.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /demo-ui/public/icons/16x16/image-x-generic.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /web-ui/public/icons/16x16/image-x-generic.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /demo-ui/src/SVG/IconDownload.svelte: -------------------------------------------------------------------------------- 1 | 5 | 6 | 7 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /web-ui/src/SVG/IconDownload.svelte: -------------------------------------------------------------------------------- 1 | 5 | 6 | 7 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | 3 | pupcloud 4 | /bin 5 | /testFs 6 | /.vscode 7 | /.idea 8 | /TODO.md 9 | 10 | /web-ui/node_modules/ 11 | /web-ui/public/build/ 12 | 13 | /demo-ui/node_modules/ 14 | 15 | # Binaries for programs and plugins 16 | *.exe 17 | *.exe~ 18 | *.dll 19 | *.so 20 | *.dylib 21 | 22 | # Test binary, built with `go test -c` 23 | *.test 24 | 25 | # Output of the go coverage tool, specifically when used with LiteIDE 26 | *.out 27 | 28 | # Dependency directories (remove the comment below to include it) 29 | # vendor/ 30 | -------------------------------------------------------------------------------- /demo-ui/src/Utils.svelte: -------------------------------------------------------------------------------- 1 | 13 | -------------------------------------------------------------------------------- /web-ui/src/Utils.svelte: -------------------------------------------------------------------------------- 1 | 13 | -------------------------------------------------------------------------------- /demo-ui/public/icons/16x16/application-octet-stream.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/static/icons/16x16/application-octet-stream.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /web-ui/public/icons/16x16/application-octet-stream.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | FROM alpine:edge AS build 2 | 3 | RUN apk update 4 | RUN apk upgrade 5 | RUN apk add --update go git make 6 | WORKDIR /app 7 | ENV GOPATH /app 8 | RUN git clone https://github.com/proofrock/pupcloud 9 | WORKDIR /app/pupcloud 10 | RUN make build-static 11 | 12 | FROM alpine:latest 13 | 14 | ENV PUID=1000 15 | ENV PGID=1000 16 | EXPOSE 12321 17 | VOLUME /data 18 | 19 | COPY --from=build /app/pupcloud/bin/pupcloud / 20 | 21 | RUN addgroup -g $PGID pup 22 | RUN adduser -u $PUID -G pup -D pup 23 | 24 | USER pup:pup 25 | 26 | ENTRYPOINT ["/pupcloud", "-r", "/data"] 27 | -------------------------------------------------------------------------------- /demo-ui/src/SVG/IconList.svelte: -------------------------------------------------------------------------------- 1 | 5 | 6 | 7 | 14 | 17 | 18 | -------------------------------------------------------------------------------- /web-ui/src/SVG/IconList.svelte: -------------------------------------------------------------------------------- 1 | 5 | 6 | 7 | 14 | 17 | 18 | -------------------------------------------------------------------------------- /demo-ui/src/SVG/IconSortSizeAsc.svelte: -------------------------------------------------------------------------------- 1 | 5 | 6 | 7 | 14 | 17 | 18 | -------------------------------------------------------------------------------- /demo-ui/src/SVG/IconSortSizeDesc.svelte: -------------------------------------------------------------------------------- 1 | 5 | 6 | 7 | 14 | 17 | 18 | -------------------------------------------------------------------------------- /web-ui/src/SVG/IconSortSizeAsc.svelte: -------------------------------------------------------------------------------- 1 | 5 | 6 | 7 | 14 | 17 | 18 | -------------------------------------------------------------------------------- /web-ui/src/SVG/IconSortSizeDesc.svelte: -------------------------------------------------------------------------------- 1 | 5 | 6 | 7 | 14 | 17 | 18 | -------------------------------------------------------------------------------- /demo-ui/src/SVG/IconGrid.svelte: -------------------------------------------------------------------------------- 1 | 5 | 6 | 7 | 14 | 17 | 18 | -------------------------------------------------------------------------------- /web-ui/src/SVG/IconGrid.svelte: -------------------------------------------------------------------------------- 1 | 5 | 6 | 7 | 14 | 17 | 18 | -------------------------------------------------------------------------------- /demo-ui/src/SVG/IconSortAlphAsc.svelte: -------------------------------------------------------------------------------- 1 | 5 | 6 | 7 | 14 | 17 | 18 | -------------------------------------------------------------------------------- /demo-ui/src/SVG/IconSortAlphDesc.svelte: -------------------------------------------------------------------------------- 1 | 5 | 6 | 7 | 14 | 17 | 18 | -------------------------------------------------------------------------------- /web-ui/src/SVG/IconSortAlphAsc.svelte: -------------------------------------------------------------------------------- 1 | 5 | 6 | 7 | 14 | 17 | 18 | -------------------------------------------------------------------------------- /web-ui/src/SVG/IconSortAlphDesc.svelte: -------------------------------------------------------------------------------- 1 | 5 | 6 | 7 | 14 | 17 | 18 | -------------------------------------------------------------------------------- /src/go.mod: -------------------------------------------------------------------------------- 1 | module github.com/proofrock/pupcloud 2 | 3 | go 1.18 4 | 5 | require ( 6 | github.com/gofiber/fiber/v2 v2.33.0 7 | github.com/otiai10/copy v1.7.0 8 | github.com/spf13/pflag v1.0.5 9 | golang.org/x/crypto v0.0.0-20220507011949-2cf3adece122 10 | golang.org/x/exp v0.0.0-20220428152302-39d4317da171 11 | ) 12 | 13 | require ( 14 | github.com/andybalholm/brotli v1.0.4 // indirect 15 | github.com/klauspost/compress v1.15.3 // indirect 16 | github.com/valyala/bytebufferpool v1.0.0 // indirect 17 | github.com/valyala/fasthttp v1.36.0 // indirect 18 | github.com/valyala/tcplisten v1.0.0 // indirect 19 | golang.org/x/sys v0.0.0-20220503163025-988cb79eb6c6 // indirect 20 | ) 21 | -------------------------------------------------------------------------------- /demo-ui/src/SVG/IconNewFolder.svelte: -------------------------------------------------------------------------------- 1 | 5 | 6 | 7 | 14 | 17 | 18 | -------------------------------------------------------------------------------- /web-ui/src/SVG/IconNewFolder.svelte: -------------------------------------------------------------------------------- 1 | 5 | 6 | 7 | 14 | 17 | 18 | -------------------------------------------------------------------------------- /demo-ui/public/mocks/ls1.json: -------------------------------------------------------------------------------- 1 | { 2 | "path": [ 3 | "thisIsADir" 4 | ], 5 | "items": [ 6 | { 7 | "mimeType": "#directory", 8 | "name": "anotherDir", 9 | "size": -1, 10 | "chDate": 1645859613, 11 | "owner": "mano (1000)", 12 | "group": "mano (1000)", 13 | "permissions": "drwxr-xr-x" 14 | }, 15 | { 16 | "mimeType": "text/plain", 17 | "name": "txt.txt", 18 | "size": 5, 19 | "chDate": 1632594862, 20 | "owner": "mano (1000)", 21 | "group": "mano (1000)", 22 | "permissions": "-rw-r--r--" 23 | } 24 | ] 25 | } 26 | -------------------------------------------------------------------------------- /demo-ui/src/SVG/IconSortDateDesc.svelte: -------------------------------------------------------------------------------- 1 | 5 | 6 | 7 | 14 | 17 | 18 | -------------------------------------------------------------------------------- /web-ui/src/SVG/IconSortDateAsc.svelte: -------------------------------------------------------------------------------- 1 | 5 | 6 | 7 | 14 | 17 | 18 | -------------------------------------------------------------------------------- /web-ui/src/SVG/IconSortDateDesc.svelte: -------------------------------------------------------------------------------- 1 | 5 | 6 | 7 | 14 | 17 | 18 | -------------------------------------------------------------------------------- /demo-ui/src/SVG/IconLogout.svelte: -------------------------------------------------------------------------------- 1 | 5 | 6 | 7 | 14 | 17 | 18 | -------------------------------------------------------------------------------- /demo-ui/src/SVG/IconReload.svelte: -------------------------------------------------------------------------------- 1 | 5 | 6 | 7 | 14 | 17 | 18 | -------------------------------------------------------------------------------- /demo-ui/src/SVG/IconSortDateAsc.svelte: -------------------------------------------------------------------------------- 1 | 5 | 6 | 7 | 14 | 17 | 18 | -------------------------------------------------------------------------------- /web-ui/src/SVG/IconLogout.svelte: -------------------------------------------------------------------------------- 1 | 5 | 6 | 7 | 14 | 17 | 18 | -------------------------------------------------------------------------------- /web-ui/src/SVG/IconReload.svelte: -------------------------------------------------------------------------------- 1 | 5 | 6 | 7 | 14 | 17 | 18 | -------------------------------------------------------------------------------- /demo-ui/src/SVG/IconPaste.svelte: -------------------------------------------------------------------------------- 1 | 5 | 6 | 7 | 14 | 17 | 18 | -------------------------------------------------------------------------------- /src/static/icons/16x16/file-manager.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /web-ui/src/SVG/IconPaste.svelte: -------------------------------------------------------------------------------- 1 | 5 | 6 | 7 | 14 | 17 | 18 | -------------------------------------------------------------------------------- /demo-ui/public/icons/16x16/file-manager.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /web-ui/public/icons/16x16/file-manager.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /demo-ui/public/mocks/ls2.json: -------------------------------------------------------------------------------- 1 | { 2 | "path": [ 3 | "thisIsADir", 4 | "anotherDir" 5 | ], 6 | "items": [ 7 | { 8 | "mimeType": "#directory", 9 | "name": "a3rdDir", 10 | "size": -1, 11 | "chDate": 1645297788, 12 | "owner": "mano (1000)", 13 | "group": "mano (1000)", 14 | "permissions": "drwxr-xr-x" 15 | }, 16 | { 17 | "mimeType": "text/plain", 18 | "name": "empty", 19 | "size": 0, 20 | "chDate": 1645859613, 21 | "owner": "mano (1000)", 22 | "group": "mano (1000)", 23 | "permissions": "-rw-r--r--" 24 | } 25 | ] 26 | } 27 | -------------------------------------------------------------------------------- /demo-ui/src/SVG/IconUnpaste.svelte: -------------------------------------------------------------------------------- 1 | 5 | 6 | 7 | 14 | 17 | 18 | -------------------------------------------------------------------------------- /web-ui/src/SVG/IconUnpaste.svelte: -------------------------------------------------------------------------------- 1 | 5 | 6 | 7 | 14 | 17 | 18 | -------------------------------------------------------------------------------- /demo-ui/src/SVG/IconUpload.svelte: -------------------------------------------------------------------------------- 1 | 5 | 6 | 7 | 14 | 17 | 18 | -------------------------------------------------------------------------------- /web-ui/src/SVG/IconUpload.svelte: -------------------------------------------------------------------------------- 1 | 5 | 6 | 7 | 14 | 17 | 18 | -------------------------------------------------------------------------------- /web-ui/build_notes.md: -------------------------------------------------------------------------------- 1 | ## Change port of `run dev` 2 | 3 | In `package.json`: 4 | 5 | ```json 6 | "scripts": { 7 | [...] 8 | "start": "sirv public --no-clear --port 17178 --host", 9 | ``` 10 | 11 | ## Rollup: avoid typescript map warning 12 | 13 | https://stackoverflow.com/questions/63128597/how-to-get-rid-of-the-rollup-plugin-typescript-rollup-sourcemap-option-must 14 | 15 | Change to `rollup.config.js`: 16 | 17 | ``` 18 | - output: { 19 | - sourcemap: true, 20 | + output: { 21 | + sourcemap: !production, 22 | ``` 23 | 24 | **NOTE**: this disables source maps in production. Not what you want? 25 | 26 | ## Include css framework 27 | 28 | https://stackoverflow.com/questions/56483209/import-css-in-node-modules-to-svelte 29 | 30 | In `App.svelte`: 31 | 32 | ``` 33 | import "../node_modules/axentix/dist/axentix.min.css"; 34 | ``` 35 | 36 | Where js module is needed: 37 | 38 | ``` 39 | import { Dropdown, destroy } from "axentix"; 40 | ``` 41 | -------------------------------------------------------------------------------- /demo-ui/src/main.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of PupCloud, Copyright (c) 2022-2078, Germano Rizzo 3 | * 4 | * PupCloud is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * PupCloud is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with PupCloud. If not, see . 16 | */ 17 | 18 | import Auth from "./Auth.svelte"; 19 | 20 | const app = new Auth({ 21 | target: document.getElementById("app"), 22 | }); 23 | 24 | export default app; 25 | -------------------------------------------------------------------------------- /web-ui/src/main.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of PupCloud, Copyright (c) 2022-2078, Germano Rizzo 3 | * 4 | * PupCloud is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * PupCloud is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with PupCloud. If not, see . 16 | */ 17 | 18 | import Auth from "./Auth.svelte"; 19 | 20 | const app = new Auth({ 21 | target: document.getElementById("app"), 22 | }); 23 | 24 | export default app; 25 | -------------------------------------------------------------------------------- /src/files/file_users_windows.go: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of PupCloud, Copyright (c) 2022-2078, Germano Rizzo 3 | * 4 | * PupCloud is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * PupCloud is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with PupCloud. If not, see . 16 | */ 17 | package files 18 | 19 | // Windows doesn't have this concept 20 | func getUserAndGroup(path string) (string, string) { 21 | return "n.a.", "n.a." 22 | } 23 | -------------------------------------------------------------------------------- /web-ui/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "pupcloud", 3 | "version": "0.8.0", 4 | "private": true, 5 | "scripts": { 6 | "build": "rollup -c", 7 | "dev": "rollup -c -w", 8 | "start": "sirv public --no-clear --port 17178 --host", 9 | "check": "svelte-check --tsconfig ./tsconfig.json" 10 | }, 11 | "devDependencies": { 12 | "@rollup/plugin-commonjs": "^17.0.0", 13 | "@rollup/plugin-node-resolve": "^11.0.0", 14 | "@rollup/plugin-typescript": "^8.0.0", 15 | "@tsconfig/svelte": "^2.0.0", 16 | "rollup": "^2.3.4", 17 | "rollup-plugin-css-only": "^3.1.0", 18 | "rollup-plugin-livereload": "^2.0.0", 19 | "rollup-plugin-svelte": "^7.0.0", 20 | "rollup-plugin-terser": "^7.0.2", 21 | "svelte": "^3.0.0", 22 | "svelte-check": "^2.0.0", 23 | "svelte-preprocess": "^4.0.0", 24 | "tslib": "^2.0.0", 25 | "typescript": "^4.0.0" 26 | }, 27 | "dependencies": { 28 | "axentix": "^2.0.1", 29 | "hammerjs": "^2.0.8", 30 | "sirv-cli": "^2.0.0", 31 | "sweetalert2": "^11.4.4" 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /demo-ui/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "pupcloud", 3 | "version": "0.8.0", 4 | "private": true, 5 | "scripts": { 6 | "build": "rollup -c", 7 | "dev": "rollup -c -w", 8 | "start": "sirv public --no-clear --port 17178 --host", 9 | "check": "svelte-check --tsconfig ./tsconfig.json" 10 | }, 11 | "devDependencies": { 12 | "@rollup/plugin-commonjs": "^17.0.0", 13 | "@rollup/plugin-node-resolve": "^11.0.0", 14 | "@rollup/plugin-typescript": "^8.0.0", 15 | "@tsconfig/svelte": "^2.0.0", 16 | "rollup": "^2.3.4", 17 | "rollup-plugin-css-only": "^3.1.0", 18 | "rollup-plugin-livereload": "^2.0.0", 19 | "rollup-plugin-svelte": "^7.0.0", 20 | "rollup-plugin-terser": "^7.0.2", 21 | "svelte": "^3.0.0", 22 | "svelte-check": "^2.0.0", 23 | "svelte-preprocess": "^4.0.0", 24 | "tslib": "^2.0.0", 25 | "typescript": "^4.0.0" 26 | }, 27 | "dependencies": { 28 | "axentix": "^2.0.1", 29 | "hammerjs": "^2.0.8", 30 | "sirv-cli": "^2.0.0", 31 | "sweetalert2": "^11.4.4" 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing 2 | 3 | When contributing to this repository, please first discuss the change you wish to make via issue, 4 | email, or any other method with the owners of this repository before making a change. 5 | 6 | Please note we have a code of conduct, please follow it in all your interactions with the project. 7 | 8 | ## Pull Request Process 9 | 10 | 1. Ensure any install or build dependencies are removed before the end of the layer when doing a 11 | build. 12 | 2. Update the README.md with details of changes to the interface, this includes new environment 13 | variables, exposed ports, useful file locations and container parameters. 14 | 3. Increase the version numbers in any examples files and the README.md to the new version that this 15 | Pull Request would represent. The versioning scheme we use is [SemVer](http://semver.org/). 16 | 4. You may merge the Pull Request in once you have the sign-off of two other developers, or if you 17 | do not have permission to do that, you may request the second reviewer to merge it for you. 18 | -------------------------------------------------------------------------------- /demo-ui/src/SVG/IconShare.svelte: -------------------------------------------------------------------------------- 1 | 5 | 6 | 7 | 14 | 17 | 18 | -------------------------------------------------------------------------------- /web-ui/src/SVG/IconShare.svelte: -------------------------------------------------------------------------------- 1 | 5 | 6 | 7 | 14 | 17 | 18 | -------------------------------------------------------------------------------- /demo-ui/src/SVG/IconLink.svelte: -------------------------------------------------------------------------------- 1 | 5 | 6 | 7 | 13 | 15 | 16 | -------------------------------------------------------------------------------- /web-ui/src/SVG/IconLink.svelte: -------------------------------------------------------------------------------- 1 | 5 | 6 | 7 | 13 | 15 | 16 | -------------------------------------------------------------------------------- /demo-ui/src/SVG/IconInvalidLink.svelte: -------------------------------------------------------------------------------- 1 | 5 | 6 | 7 | 14 | 16 | 17 | -------------------------------------------------------------------------------- /web-ui/src/SVG/IconInvalidLink.svelte: -------------------------------------------------------------------------------- 1 | 5 | 6 | 7 | 14 | 16 | 17 | -------------------------------------------------------------------------------- /demo-ui/public/testFs/thisIsHTML.html: -------------------------------------------------------------------------------- 1 | 2 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | Pupcloud 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | -------------------------------------------------------------------------------- /demo-ui/src/Snippets/TextShower.svelte: -------------------------------------------------------------------------------- 1 | 31 | 32 |
33 |
{contents}
34 |
35 | -------------------------------------------------------------------------------- /web-ui/src/Snippets/TextShower.svelte: -------------------------------------------------------------------------------- 1 | 31 | 32 |
33 |
{contents}
34 |
35 | -------------------------------------------------------------------------------- /src/static/icons/16x16/application-pdf.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /web-ui/public/icons/16x16/application-pdf.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /demo-ui/public/icons/16x16/application-pdf.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/static/index.html: -------------------------------------------------------------------------------- 1 | 2 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | Pupcloud 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 38 |
39 | 40 | 41 | 42 | -------------------------------------------------------------------------------- /demo-ui/public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | Pupcloud 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 38 |
39 | 40 | 41 | 42 | -------------------------------------------------------------------------------- /web-ui/public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | Pupcloud 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 38 |
39 | 40 | 41 | 42 | -------------------------------------------------------------------------------- /src/files/file_users.go: -------------------------------------------------------------------------------- 1 | //go:build !windows 2 | 3 | /* 4 | * This file is part of PupCloud, Copyright (c) 2022-2078, Germano Rizzo 5 | * 6 | * PupCloud is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * PupCloud is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with PupCloud. If not, see . 18 | */ 19 | package files 20 | 21 | import ( 22 | "fmt" 23 | "os" 24 | "os/user" 25 | "strconv" 26 | "syscall" 27 | ) 28 | 29 | // Adapted from https://pirivan.gitlab.io/post/how-to-retrieve-file-ownership-information-in-golang/ 30 | func getUserAndGroup(path string) (string, string) { 31 | fileInfo, err := os.Stat(path) 32 | if err != nil { 33 | return "--", "--" 34 | } 35 | 36 | stat, ok := fileInfo.Sys().(*syscall.Stat_t) 37 | if !ok { 38 | return "--", "--" 39 | } 40 | 41 | usr, err := user.LookupId(strconv.FormatUint(uint64(stat.Uid), 10)) 42 | if err != nil { 43 | return "--", "--" 44 | } 45 | group, err := user.LookupGroupId(strconv.FormatUint(uint64(stat.Gid), 10)) 46 | if err != nil { 47 | return "--", "--" 48 | } 49 | 50 | return fmt.Sprintf("%s (%s)", usr.Username, usr.Uid), 51 | fmt.Sprintf("%s (%s)", group.Name, group.Gid) 52 | } 53 | -------------------------------------------------------------------------------- /demo-ui/src/FileManager/Grid.svelte: -------------------------------------------------------------------------------- 1 | 33 | 34 |
35 | {#each itemList as item, i (item.uuid)} 36 | 38 |
40 | 41 |
42 | {/each} 43 |
44 | -------------------------------------------------------------------------------- /web-ui/src/FileManager/Grid.svelte: -------------------------------------------------------------------------------- 1 | 33 | 34 |
35 | {#each itemList as item, i (item.uuid)} 36 | 38 |
40 | 41 |
42 | {/each} 43 |
44 | -------------------------------------------------------------------------------- /src/static/icons/48x48/text-x-generic.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /demo-ui/public/icons/48x48/text-x-generic.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /web-ui/public/icons/48x48/text-x-generic.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /demo-ui/src/Preview/Preview.svelte: -------------------------------------------------------------------------------- 1 | 41 | 42 | {#if mode == 0} 43 | 44 | {:else if mode == 1} 45 | 46 | {:else} 47 | 48 | {/if} 49 | -------------------------------------------------------------------------------- /web-ui/src/Preview/Preview.svelte: -------------------------------------------------------------------------------- 1 | 41 | 42 | {#if mode == 0} 43 | 44 | {:else if mode == 1} 45 | 46 | {:else} 47 | 48 | {/if} 49 | -------------------------------------------------------------------------------- /demo-ui/src/Preview/FullSize.svelte: -------------------------------------------------------------------------------- 1 | 46 | 47 | 54 | 55 |
56 | {file.name} 58 | -------------------------------------------------------------------------------- /web-ui/src/Preview/FullSize.svelte: -------------------------------------------------------------------------------- 1 | 46 | 47 | 54 | 55 |
56 | {file.name} 58 | -------------------------------------------------------------------------------- /demo-ui/src/MimeTypes.svelte: -------------------------------------------------------------------------------- 1 | 63 | -------------------------------------------------------------------------------- /web-ui/src/MimeTypes.svelte: -------------------------------------------------------------------------------- 1 | 63 | -------------------------------------------------------------------------------- /src/files/mimetypes.go: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of PupCloud, Copyright (c) 2022-2078, Germano Rizzo 3 | * 4 | * PupCloud is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * PupCloud is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with PupCloud. If not, see . 16 | */ 17 | 18 | package files 19 | 20 | import ( 21 | "mime" 22 | "net/http" 23 | "os" 24 | "path/filepath" 25 | "strings" 26 | "sync" 27 | ) 28 | 29 | const mimeTypeTextPlain = "text/plain" 30 | 31 | var fileNames sync.Map 32 | var fileExts sync.Map 33 | 34 | func init() { 35 | fileNames.Store("Dockerfile", mimeTypeTextPlain) 36 | fileNames.Store("Makefile", mimeTypeTextPlain) 37 | fileNames.Store("LICENSE", mimeTypeTextPlain) 38 | fileNames.Store(".gitignore", mimeTypeTextPlain) 39 | 40 | fileExts.Store("txt", mimeTypeTextPlain) 41 | fileExts.Store("md", "text/markdown") 42 | } 43 | 44 | // Adapted from https://golangcode.com/get-the-content-type-of-file/ 45 | func getFileContentType(path string) string { 46 | base := filepath.Base(path) 47 | ext := strings.ToLower(filepath.Ext(path)) 48 | 49 | // First, local resolution 50 | if val, ok := fileNames.Load(base); ok { 51 | return val.(string) 52 | } 53 | if val, ok := fileExts.Load(ext); ok { 54 | return val.(string) 55 | } 56 | 57 | // Lookup with Go extensions resolutor 58 | if ext != "" { 59 | contentType := mime.TypeByExtension(ext) 60 | if contentType != "" { 61 | return contentType 62 | } 63 | } 64 | 65 | // If inconclusive, look up by contents 66 | file, err := os.Open(path) 67 | if err != nil { 68 | return mimeTypeTextPlain 69 | } 70 | defer file.Close() 71 | 72 | buffer := make([]byte, 512) 73 | 74 | _, err = file.Read(buffer) 75 | if err != nil { 76 | return mimeTypeTextPlain 77 | } 78 | 79 | contentType := http.DetectContentType(buffer) 80 | 81 | return contentType 82 | } 83 | -------------------------------------------------------------------------------- /demo-ui/rollup.config.js: -------------------------------------------------------------------------------- 1 | import svelte from 'rollup-plugin-svelte'; 2 | import commonjs from '@rollup/plugin-commonjs'; 3 | import resolve from '@rollup/plugin-node-resolve'; 4 | import livereload from 'rollup-plugin-livereload'; 5 | import { terser } from 'rollup-plugin-terser'; 6 | import sveltePreprocess from 'svelte-preprocess'; 7 | import typescript from '@rollup/plugin-typescript'; 8 | import css from 'rollup-plugin-css-only'; 9 | 10 | const production = !process.env.ROLLUP_WATCH; 11 | 12 | function serve() { 13 | let server; 14 | 15 | function toExit() { 16 | if (server) server.kill(0); 17 | } 18 | 19 | return { 20 | writeBundle() { 21 | if (server) return; 22 | server = require('child_process').spawn('npm', ['run', 'start', '--', '--dev'], { 23 | stdio: ['ignore', 'inherit', 'inherit'], 24 | shell: true 25 | }); 26 | 27 | process.on('SIGTERM', toExit); 28 | process.on('exit', toExit); 29 | } 30 | }; 31 | } 32 | 33 | export default { 34 | input: 'src/main.ts', 35 | output: { 36 | sourcemap: true, 37 | format: 'iife', 38 | name: 'app', 39 | file: 'public/build/bundle.js' 40 | }, 41 | plugins: [ 42 | svelte({ 43 | preprocess: sveltePreprocess({ sourceMap: !production }), 44 | compilerOptions: { 45 | // enable run-time checks when not in production 46 | dev: !production 47 | } 48 | }), 49 | // we'll extract any component CSS out into 50 | // a separate file - better for performance 51 | css({ output: 'bundle.css' }), 52 | 53 | // If you have external dependencies installed from 54 | // npm, you'll most likely need these plugins. In 55 | // some cases you'll need additional configuration - 56 | // consult the documentation for details: 57 | // https://github.com/rollup/plugins/tree/master/packages/commonjs 58 | resolve({ 59 | browser: true, 60 | dedupe: ['svelte'] 61 | }), 62 | commonjs(), 63 | typescript({ 64 | sourceMap: !production, 65 | inlineSources: !production 66 | }), 67 | 68 | // In dev mode, call `npm run start` once 69 | // the bundle has been generated 70 | !production && serve(), 71 | 72 | // Watch the `public` directory and refresh the 73 | // browser on changes when not in production 74 | !production && livereload('public'), 75 | 76 | // If we're building for production (npm run build 77 | // instead of npm run dev), minify 78 | production && terser() 79 | ], 80 | watch: { 81 | clearScreen: false 82 | } 83 | }; 84 | -------------------------------------------------------------------------------- /web-ui/rollup.config.js: -------------------------------------------------------------------------------- 1 | import svelte from 'rollup-plugin-svelte'; 2 | import commonjs from '@rollup/plugin-commonjs'; 3 | import resolve from '@rollup/plugin-node-resolve'; 4 | import livereload from 'rollup-plugin-livereload'; 5 | import { terser } from 'rollup-plugin-terser'; 6 | import sveltePreprocess from 'svelte-preprocess'; 7 | import typescript from '@rollup/plugin-typescript'; 8 | import css from 'rollup-plugin-css-only'; 9 | 10 | const production = !process.env.ROLLUP_WATCH; 11 | 12 | function serve() { 13 | let server; 14 | 15 | function toExit() { 16 | if (server) server.kill(0); 17 | } 18 | 19 | return { 20 | writeBundle() { 21 | if (server) return; 22 | server = require('child_process').spawn('npm', ['run', 'start', '--', '--dev'], { 23 | stdio: ['ignore', 'inherit', 'inherit'], 24 | shell: true 25 | }); 26 | 27 | process.on('SIGTERM', toExit); 28 | process.on('exit', toExit); 29 | } 30 | }; 31 | } 32 | 33 | export default { 34 | input: 'src/main.ts', 35 | output: { 36 | sourcemap: !production, 37 | format: 'iife', 38 | name: 'app', 39 | file: 'public/build/bundle.js' 40 | }, 41 | plugins: [ 42 | svelte({ 43 | preprocess: sveltePreprocess({ sourceMap: !production }), 44 | compilerOptions: { 45 | // enable run-time checks when not in production 46 | dev: !production 47 | } 48 | }), 49 | // we'll extract any component CSS out into 50 | // a separate file - better for performance 51 | css({ output: 'bundle.css' }), 52 | 53 | // If you have external dependencies installed from 54 | // npm, you'll most likely need these plugins. In 55 | // some cases you'll need additional configuration - 56 | // consult the documentation for details: 57 | // https://github.com/rollup/plugins/tree/master/packages/commonjs 58 | resolve({ 59 | browser: true, 60 | dedupe: ['svelte'] 61 | }), 62 | commonjs(), 63 | typescript({ 64 | sourceMap: !production, 65 | inlineSources: !production 66 | }), 67 | 68 | // In dev mode, call `npm run start` once 69 | // the bundle has been generated 70 | !production && serve(), 71 | 72 | // Watch the `public` directory and refresh the 73 | // browser on changes when not in production 74 | !production && livereload('public'), 75 | 76 | // If we're building for production (npm run build 77 | // instead of npm run dev), minify 78 | production && terser() 79 | ], 80 | watch: { 81 | clearScreen: false 82 | } 83 | }; 84 | -------------------------------------------------------------------------------- /web-ui/src/FileManager/GridCell.svelte: -------------------------------------------------------------------------------- 1 | 32 | 33 |
34 | 35 |
36 | {item.size} 37 |
38 | 39 |
40 |
 
41 |
42 | {#if !!item.icon[1]} 43 | {item.icon[0]} 44 | {#if item.icon[1] == "link"} 45 | 46 | {:else} 47 | 48 | {/if} 49 | {:else} 50 | {item.icon[0]} 51 | {/if} 52 |
53 |
 
54 |
{item.name}
55 |
56 |
57 | -------------------------------------------------------------------------------- /demo-ui/src/FileManager/GridCell.svelte: -------------------------------------------------------------------------------- 1 | 32 | 33 |
34 | 35 |
36 | {item.size} 37 |
38 | 39 |
40 |
 
41 |
42 | {#if !!item.icon[1]} 43 | {item.icon[0]} 44 | {#if item.icon[1] == "link"} 45 | 46 | {:else} 47 | 48 | {/if} 49 | {:else} 50 | {item.icon[0]} 51 | {/if} 52 |
53 |
 
54 |
{item.name}
55 |
56 |
57 | -------------------------------------------------------------------------------- /src/static/icons/48x48/audio-x-generic.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /demo-ui/public/icons/48x48/audio-x-generic.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /web-ui/public/icons/48x48/audio-x-generic.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /src/commons/commons.go: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of PupCloud, Copyright (c) 2022-2078, Germano Rizzo 3 | * 4 | * PupCloud is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * PupCloud is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with PupCloud. If not, see . 16 | */ 17 | package commons 18 | 19 | import ( 20 | "bytes" 21 | "encoding/binary" 22 | "fmt" 23 | "github.com/proofrock/pupcloud/crypgo" 24 | "os" 25 | ) 26 | 27 | type ErrorRes struct { 28 | Code int `json:"code"` 29 | Message string `json:"msg"` 30 | } 31 | 32 | func Abort(msg string) { 33 | fmt.Fprint(os.Stderr, msg, "\n") 34 | os.Exit(1) 35 | } 36 | 37 | func DirExists(filename string) bool { 38 | info, err := os.Stat(filename) 39 | return !os.IsNotExist(err) && info.IsDir() 40 | } 41 | 42 | func boolToBytes(b bool) byte { 43 | if b { 44 | return 1 45 | } 46 | return 0 47 | } 48 | 49 | func intToBytes(number uint32) []byte { 50 | var arr [4]byte 51 | binary.BigEndian.PutUint32(arr[0:4], number) 52 | return arr[:] 53 | } 54 | 55 | func bytesToInt(data []byte) uint32 { 56 | return binary.BigEndian.Uint32(data) 57 | } 58 | 59 | func EncryptSharingURL(profile, pwd, path, root string, readOnly bool, date *uint32) (string, error) { 60 | var b bytes.Buffer 61 | b.Write([]byte{boolToBytes(readOnly)}) 62 | b.WriteString(path) 63 | b.Write([]byte{byte(0x00)}) 64 | b.Write([]byte{boolToBytes(date != nil)}) 65 | if date != nil { 66 | b.Write(intToBytes(*date)) 67 | } 68 | return crypgo.EncryptBytes(pwd, b.Bytes(), []byte(profile+"|"+root)) 69 | } 70 | 71 | func DecryptSharingURL(profile, pwd, root, encoded string) (path string, readOnly bool, date *uint32, err error) { 72 | plain, err := crypgo.DecryptBytes(pwd, encoded, []byte(profile+"|"+root)) 73 | if err != nil { 74 | return 75 | } 76 | 77 | b := bytes.NewBuffer(plain) 78 | 79 | _readOnly, _ := b.ReadByte() 80 | readOnly = _readOnly == 1 81 | 82 | pathBytes, _ := b.ReadBytes(byte(0x00)) 83 | path = string(pathBytes[:len(pathBytes)-1]) 84 | 85 | if _hasDate, _ := b.ReadByte(); _hasDate == 1 { 86 | bDate := make([]byte, 4) 87 | b.Read(bDate) 88 | _date := bytesToInt(bDate) 89 | date = &_date 90 | } 91 | 92 | return 93 | } 94 | -------------------------------------------------------------------------------- /demo-ui/src/FileManager/ListRow.svelte: -------------------------------------------------------------------------------- 1 | 36 | 37 | 58 | 59 | 60 | 61 | 62 |
63 | {item.icon[0]} {item.icon[2]}{item.name} 65 |
66 |
67 | {item.icon[0]} {item.icon[2]}{item.name} 69 |
70 | 71 | {item.size} 72 | {item.chDate} 73 | 74 |
75 | 76 |
77 | 78 | 79 | -------------------------------------------------------------------------------- /web-ui/src/FileManager/ListRow.svelte: -------------------------------------------------------------------------------- 1 | 36 | 37 | 58 | 59 | 60 | 61 | 62 |
63 | {item.icon[0]} {item.icon[2]}{item.name} 65 |
66 |
67 | {item.icon[0]} {item.icon[2]}{item.name} 69 |
70 | 71 | {item.size} 72 | {item.chDate} 73 | 74 |
75 | 76 |
77 | 78 | 79 | -------------------------------------------------------------------------------- /demo-ui/src/global.css: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of PupCloud, Copyright (c) 2022-2078, Germano Rizzo 3 | * 4 | * PupCloud is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * PupCloud is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with PupCloud. If not, see . 16 | */ 17 | 18 | /* 19 | Demo-5 in 20 | https://stackoverflow.com/questions/26150963/how-to-make-this-css-hamburger-menu-entirely-clickable/26151061#26151061 21 | */ 22 | .menu { 23 | width: 16px; 24 | height: 14px; 25 | position: relative; 26 | display: inline-block; 27 | top: 3px; 28 | background-size: 5px 5px; 29 | background-image: -webkit-linear-gradient(rgba(0, 0, 0, 1) 50%, transparent 50%, transparent); 30 | background-image: -moz-linear-gradient(rgba(0, 0, 0, 1) 50%, transparent 50%, transparent); 31 | background-image: linear-gradient(rgba(0, 0, 0, 1) 50%, transparent 50%, transparent); 32 | } 33 | 34 | .triangle { 35 | position: relative; 36 | top: 12px; 37 | border-left: 6px solid transparent; 38 | border-right: 6px solid transparent; 39 | border-top: 6px solid black; 40 | } 41 | 42 | .blanket { 43 | position: fixed; 44 | width: 100%; 45 | height: 100%; 46 | left: 0px; 47 | top: 0px; 48 | background: #444444; 49 | z-index: 0; 50 | padding: 0px; 51 | } 52 | 53 | .blanket-clear { 54 | background: #888888; 55 | } 56 | 57 | .blanket-very-clear { 58 | background: #CCCCCC; 59 | } 60 | 61 | .centered-slide { 62 | position: absolute; 63 | top: 50%; 64 | left: 50%; 65 | transform: translate(-50%, -50%); 66 | } 67 | 68 | footer { 69 | position: fixed; 70 | bottom: 0; 71 | z-index: 65532 !important; 72 | } 73 | 74 | nav { 75 | z-index: 65532 !important; 76 | } 77 | 78 | .ax-overlay { 79 | z-index: 65533 !important; 80 | } 81 | 82 | .modal { 83 | z-index: 65534 !important; 84 | } 85 | 86 | .swal2-container { 87 | z-index: 65535 !important; 88 | } 89 | 90 | .pup-a { 91 | font-weight: bold; 92 | text-decoration: underline dotted; 93 | } 94 | 95 | .pup-a-nobold { 96 | text-decoration: underline dotted; 97 | } 98 | 99 | .ellipsis { 100 | white-space: nowrap; 101 | overflow: hidden; 102 | text-overflow: ellipsis; 103 | } 104 | 105 | .wid220 { 106 | width: 220px; 107 | } 108 | 109 | .noSelect { 110 | user-select: none; 111 | } 112 | -------------------------------------------------------------------------------- /web-ui/src/global.css: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of PupCloud, Copyright (c) 2022-2078, Germano Rizzo 3 | * 4 | * PupCloud is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * PupCloud is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with PupCloud. If not, see . 16 | */ 17 | 18 | /* 19 | Demo-5 in 20 | https://stackoverflow.com/questions/26150963/how-to-make-this-css-hamburger-menu-entirely-clickable/26151061#26151061 21 | */ 22 | .menu { 23 | width: 16px; 24 | height: 14px; 25 | position: relative; 26 | display: inline-block; 27 | top: 3px; 28 | background-size: 5px 5px; 29 | background-image: -webkit-linear-gradient(rgba(0, 0, 0, 1) 50%, transparent 50%, transparent); 30 | background-image: -moz-linear-gradient(rgba(0, 0, 0, 1) 50%, transparent 50%, transparent); 31 | background-image: linear-gradient(rgba(0, 0, 0, 1) 50%, transparent 50%, transparent); 32 | } 33 | 34 | .triangle { 35 | position: relative; 36 | top: 12px; 37 | border-left: 6px solid transparent; 38 | border-right: 6px solid transparent; 39 | border-top: 6px solid black; 40 | } 41 | 42 | .blanket { 43 | position: fixed; 44 | width: 100%; 45 | height: 100%; 46 | left: 0px; 47 | top: 0px; 48 | background: #444444; 49 | z-index: 0; 50 | padding: 0px; 51 | } 52 | 53 | .blanket-clear { 54 | background: #888888; 55 | } 56 | 57 | .blanket-very-clear { 58 | background: #CCCCCC; 59 | } 60 | 61 | .centered-slide { 62 | position: absolute; 63 | top: 50%; 64 | left: 50%; 65 | transform: translate(-50%, -50%); 66 | } 67 | 68 | footer { 69 | position: fixed; 70 | bottom: 0; 71 | z-index: 65532 !important; 72 | } 73 | 74 | nav { 75 | z-index: 65532 !important; 76 | } 77 | 78 | .ax-overlay { 79 | z-index: 65533 !important; 80 | } 81 | 82 | .modal { 83 | z-index: 65534 !important; 84 | } 85 | 86 | .swal2-container { 87 | z-index: 65535 !important; 88 | } 89 | 90 | .pup-a { 91 | font-weight: bold; 92 | text-decoration: underline dotted; 93 | } 94 | 95 | .pup-a-nobold { 96 | text-decoration: underline dotted; 97 | } 98 | 99 | .ellipsis { 100 | white-space: nowrap; 101 | overflow: hidden; 102 | text-overflow: ellipsis; 103 | } 104 | 105 | .wid220 { 106 | width: 220px; 107 | } 108 | 109 | .noSelect { 110 | user-select: none; 111 | } 112 | -------------------------------------------------------------------------------- /demo-ui/public/testFs/thisIsASourceFile.go: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of PupCloud, Copyright (c) 2022-2078, Germano Rizzo 3 | * 4 | * PupCloud is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * PupCloud is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with PupCloud. If not, see . 16 | */ 17 | package main 18 | 19 | import ( 20 | "fmt" 21 | "mime" 22 | "net/http" 23 | "os" 24 | "os/user" 25 | "path/filepath" 26 | "strconv" 27 | "strings" 28 | "syscall" 29 | ) 30 | 31 | const MIME_TYPE_TEXT_PLAIN = "text/plain" 32 | 33 | // Adapted from https://golangcode.com/get-the-content-type-of-file/ 34 | func getFileContentType(path string) string { 35 | // First, quick lookup by extension 36 | ext := filepath.Ext(path) 37 | if ext != "" { 38 | // IDK why, but .txt is not translated by Go :-( 39 | if strings.EqualFold(ext, ".txt") { 40 | return MIME_TYPE_TEXT_PLAIN 41 | } 42 | contentType := mime.TypeByExtension(ext) 43 | if contentType != "" { 44 | return contentType 45 | } 46 | } 47 | 48 | // If inconclusive, look up by contents 49 | file, err := os.Open(path) 50 | if err != nil { 51 | return MIME_TYPE_TEXT_PLAIN 52 | } 53 | defer file.Close() 54 | 55 | buffer := make([]byte, 512) 56 | 57 | _, err = file.Read(buffer) 58 | if err != nil { 59 | return MIME_TYPE_TEXT_PLAIN 60 | } 61 | 62 | contentType := http.DetectContentType(buffer) 63 | 64 | return contentType 65 | } 66 | 67 | // Adapted from https://pirivan.gitlab.io/post/how-to-retrieve-file-ownership-information-in-golang/ 68 | func getUserAndGroup(path string) (string, string) { 69 | fileInfo, err := os.Stat(path) 70 | if err != nil { 71 | return "--", "--" 72 | } 73 | 74 | stat, ok := fileInfo.Sys().(*syscall.Stat_t) 75 | if !ok { 76 | return "--", "--" 77 | } 78 | 79 | usr, err := user.LookupId(strconv.FormatUint(uint64(stat.Uid), 10)) 80 | if err != nil { 81 | return "--", "--" 82 | } 83 | group, err := user.LookupGroupId(strconv.FormatUint(uint64(stat.Gid), 10)) 84 | if err != nil { 85 | return "--", "--" 86 | } 87 | 88 | return fmt.Sprintf("%s (%s)", usr.Username, usr.Uid), 89 | fmt.Sprintf("%s (%s)", group.Name, group.Gid) 90 | } 91 | 92 | func getFileInfoForHTTP(path string) (present bool, contentType string, length int64) { 93 | info, err := os.Stat(path) 94 | if os.IsNotExist(err) || info.IsDir() { 95 | return false, "", 0 96 | } 97 | 98 | length = info.Size() 99 | 100 | return true, getFileContentType(path), length 101 | } 102 | -------------------------------------------------------------------------------- /src/static/icons/48x48/video-x-generic.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /demo-ui/public/icons/48x48/video-x-generic.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /web-ui/public/icons/48x48/video-x-generic.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /src/static/icons/48x48/application-pdf.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /demo-ui/public/icons/48x48/application-pdf.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /web-ui/public/icons/48x48/application-pdf.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /demo-ui/src/Snippets/Breadcrumb.svelte: -------------------------------------------------------------------------------- 1 | 42 | 43 |
44 | 45 | 📍 46 | {#if path.length > 0} 47 | root 48 | {/if} /  49 | {#each path as pItem, idx} 50 | {#if idx < path.length - 1} 51 | 52 | {pItem.replace('/', '')} 53 | {:else} 54 | {pItem.replace('/', '')} 55 | {/if} /  56 | {/each} 57 |
58 | 86 | -------------------------------------------------------------------------------- /web-ui/src/Snippets/Breadcrumb.svelte: -------------------------------------------------------------------------------- 1 | 42 | 43 |
44 | 45 | 📍 46 | {#if path.length > 0} 47 | root 48 | {/if} /  49 | {#each path as pItem, idx} 50 | {#if idx < path.length - 1} 51 | 52 | {pItem.replace('/', '')} 53 | {:else} 54 | {pItem.replace('/', '')} 55 | {/if} /  56 | {/each} 57 |
58 | 86 | -------------------------------------------------------------------------------- /src/crypgo/crypgo.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2022-, Germano Rizzo 3 | 4 | Permission to use, copy, modify, and/or distribute this software for any 5 | purpose with or without fee is hereby granted, provided that the above 6 | copyright notice and this permission notice appear in all copies. 7 | 8 | THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 9 | WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 10 | MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 11 | ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 12 | WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 13 | ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 14 | OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 15 | */ 16 | 17 | // copied here because I want to drop reliance on zstd, it's not used in this context and it complicates the build 18 | // It uses "normal" ChaCha20Poly1305, for shorter results; it also removes header and compression bytes, here they 19 | // aren't needed (further shortening the result). 20 | 21 | package crypgo 22 | 23 | import ( 24 | "crypto/rand" 25 | "crypto/sha256" 26 | "encoding/base64" 27 | "encoding/hex" 28 | "golang.org/x/crypto/chacha20poly1305" 29 | "golang.org/x/crypto/scrypt" 30 | ) 31 | 32 | const ivSize = chacha20poly1305.NonceSize 33 | const keySize = chacha20poly1305.KeySize 34 | 35 | const scryptSaltSize = 8 36 | const scryptN = 1024 37 | const scryptR = 8 38 | const scryptP = 1 39 | 40 | func Sha256(str string) string { 41 | hash := sha256.Sum256([]byte(str)) 42 | return hex.EncodeToString(hash[:]) 43 | } 44 | 45 | func pwdToKey(salt []byte, password string) ([]byte, error) { 46 | dk, err := scrypt.Key([]byte(password), salt, scryptN, scryptR, scryptP, keySize) 47 | if err != nil { 48 | return nil, err 49 | } 50 | return dk, nil 51 | } 52 | 53 | func EncryptBytes(password string, plainBytes, addData []byte) (string, error) { 54 | iv := make([]byte, ivSize) 55 | rand.Read(iv) 56 | 57 | salt := iv[:scryptSaltSize] 58 | 59 | key, err := pwdToKey(salt, password) 60 | if err != nil { 61 | return "", err 62 | } 63 | 64 | c, err := chacha20poly1305.New(key) 65 | if err != nil { 66 | return "", err 67 | } 68 | cypherBytes := c.Seal(nil, iv, plainBytes, addData) 69 | 70 | outBytes := append(iv, cypherBytes...) 71 | 72 | return base64.RawURLEncoding.EncodeToString(outBytes), nil 73 | } 74 | 75 | // This function receives a password and a cypher text (as produced by one of the *EncryptBytes methods) 76 | // and decodes the original plaintext (if the password is the one used for encryption). 77 | // 78 | // It will return it or an eventual error, and closes all related resources. 79 | // XChaCha20-Poly1305's authentication tag is used to detect any decryption error. It also 80 | // transparently decompress data, if needed. 81 | func DecryptBytes(password string, base64CipherText string, addData []byte) ([]byte, error) { 82 | inBytes, err := base64.RawURLEncoding.DecodeString(base64CipherText) 83 | if err != nil { 84 | return make([]byte, 0), err 85 | } 86 | 87 | iv := inBytes[:ivSize] 88 | salt := inBytes[:scryptSaltSize] 89 | cypherBytes := inBytes[ivSize:] 90 | 91 | key, err := pwdToKey(salt, password) 92 | if err != nil { 93 | return make([]byte, 0), err 94 | } 95 | 96 | c, err := chacha20poly1305.New(key) 97 | if err != nil { 98 | return make([]byte, 0), err 99 | } 100 | plainBytes, err := c.Open(nil, iv, cypherBytes, addData) 101 | 102 | if err != nil { 103 | return make([]byte, 0), err 104 | } 105 | 106 | return plainBytes, nil 107 | } 108 | -------------------------------------------------------------------------------- /web-ui/src/FileManager/List.svelte: -------------------------------------------------------------------------------- 1 | 70 | 71 |
72 | 73 | 74 | 77 | 78 | 80 | 81 | {#each itemList as item (item.uuid)} 82 | 83 | {/each} 84 |
{@html getCaret(WHERES.NAME, sorter)} 75 | Name 76 | {@html getCaret(WHERES.SIZE, sorter)}Size{@html getCaret(WHERES.DATE, sorter)}Mod. Date 79 |
85 |
86 | -------------------------------------------------------------------------------- /demo-ui/src/FileManager/List.svelte: -------------------------------------------------------------------------------- 1 | 70 | 71 |
72 | 73 | 74 | 77 | 78 | 80 | 81 | {#each itemList as item (item.uuid)} 82 | 83 | {/each} 84 |
{@html getCaret(WHERES.NAME, sorter)} 75 | Name 76 | {@html getCaret(WHERES.SIZE, sorter)}Size{@html getCaret(WHERES.DATE, sorter)}Mod. Date 79 |
85 |
86 | -------------------------------------------------------------------------------- /src/files/files.go: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of PupCloud, Copyright (c) 2022-2078, Germano Rizzo 3 | * 4 | * PupCloud is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * PupCloud is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with PupCloud. If not, see . 16 | */ 17 | 18 | package files 19 | 20 | import ( 21 | "github.com/gofiber/fiber/v2" 22 | "github.com/proofrock/pupcloud/commons" 23 | "io/ioutil" 24 | "os" 25 | "path/filepath" 26 | ) 27 | 28 | func FileExists(filename string) bool { 29 | info, err := os.Lstat(filename) 30 | return !os.IsNotExist(err) && !info.IsDir() 31 | } 32 | 33 | func cleanPath(path string, followLinks bool) (string, error) { 34 | var err error 35 | if followLinks { 36 | path, err = filepath.EvalSymlinks(path) 37 | if err != nil { 38 | return "", err 39 | } 40 | } else { 41 | path = filepath.Clean(path) 42 | } 43 | return path, nil 44 | } 45 | 46 | type Item struct { 47 | IsLink bool `json:"isLink"` 48 | MimeType string `json:"mimeType"` 49 | Name string `json:"name"` 50 | Size int64 `json:"size"` 51 | ChDate int64 `json:"chDate"` 52 | Owner string `json:"owner"` 53 | Group string `json:"group"` 54 | Permissions string `json:"permissions"` 55 | } 56 | 57 | func LsFile(path string, followLinks bool) *Item { 58 | info, errStating := os.Lstat(path) 59 | if os.IsNotExist(errStating) { 60 | return nil 61 | } 62 | 63 | var ret Item 64 | ret.Name = filepath.Base(path) 65 | ret.IsLink = false 66 | 67 | if info.IsDir() { 68 | ret.MimeType = "#directory" 69 | ret.Size = -1 70 | } else if info.Mode()&os.ModeSymlink != 0 { 71 | ret.IsLink = true 72 | if !followLinks { 73 | ret.MimeType = "#link" 74 | ret.Size = -1 75 | } else { 76 | resolved, errResolving := cleanPath(path, true) 77 | if errResolving != nil { 78 | ret.MimeType = "#unresolved" 79 | ret.Size = -1 80 | } else { 81 | target := LsFile(resolved, true) 82 | if target == nil { 83 | ret.MimeType = "#unresolved" 84 | } else { 85 | ret.MimeType = target.MimeType 86 | ret.Size = target.Size 87 | } 88 | } 89 | } 90 | } else { 91 | ret.MimeType = getFileContentType(path) 92 | ret.Size = info.Size() 93 | } 94 | 95 | ret.ChDate = info.ModTime().Unix() 96 | 97 | ret.Owner, ret.Group = getUserAndGroup(path) 98 | ret.Permissions = info.Mode().String() 99 | 100 | return &ret 101 | } 102 | 103 | func LsDir(path string, followLinks bool) ([]Item, *commons.ErrorRes) { 104 | var err error 105 | if followLinks { 106 | path, err = cleanPath(path, followLinks) 107 | if err != nil { 108 | return nil, &commons.ErrorRes{Code: fiber.StatusBadRequest, Message: err.Error()} 109 | } 110 | } 111 | 112 | file, errPath := os.Lstat(path) 113 | if errPath != nil || !file.IsDir() { 114 | return nil, &commons.ErrorRes{Code: fiber.StatusNotFound, Message: "Path not found"} 115 | } 116 | 117 | files, err := ioutil.ReadDir(path) 118 | ret := make([]Item, 0) 119 | for _, f := range files { 120 | item := LsFile(filepath.Join(path, f.Name()), followLinks) 121 | if item != nil { 122 | ret = append(ret, *item) 123 | } 124 | } 125 | return ret, nil 126 | } 127 | -------------------------------------------------------------------------------- /demo-ui/public/mocks/ls0.json: -------------------------------------------------------------------------------- 1 | { 2 | "path": [], 3 | "items": [ 4 | { 5 | "mimeType": "#directory", 6 | "name": "thisIsADir", 7 | "size": -1, 8 | "chDate": 1645859590, 9 | "owner": "mano (1000)", 10 | "group": "mano (1000)", 11 | "permissions": "drwxr-xr-x" 12 | }, 13 | { 14 | "mimeType": "text/plain", 15 | "name": "thisIsALongNameThatIsVeryVeryLongReallyLong.txt", 16 | "size": 4, 17 | "chDate": 1645859445, 18 | "owner": "mano (1000)", 19 | "group": "mano (1000)", 20 | "permissions": "-rw-r--r--" 21 | }, 22 | { 23 | "mimeType": "image/jpeg", 24 | "name": "thisIsAMeme.jpg", 25 | "size": 46789, 26 | "chDate": 1645859490, 27 | "owner": "mano (1000)", 28 | "group": "mano (1000)", 29 | "permissions": "-rw-r--r--" 30 | }, 31 | { 32 | "mimeType": "application/pdf", 33 | "name": "thisIsAPDF.pdf", 34 | "size": 3028, 35 | "chDate": 1645859526, 36 | "owner": "mano (1000)", 37 | "group": "mano (1000)", 38 | "permissions": "-rw-r--r--" 39 | }, 40 | { 41 | "mimeType": "text/plain; charset=utf-8", 42 | "name": "thisIsASourceFile.go", 43 | "size": 2511, 44 | "chDate": 1645859469, 45 | "owner": "mano (1000)", 46 | "group": "mano (1000)", 47 | "permissions": "-rw-r--r--" 48 | }, 49 | { 50 | "mimeType": "application/octet-stream", 51 | "name": "thisIsATXTWithNoExtension", 52 | "size": 5, 53 | "chDate": 1645859563, 54 | "owner": "mano (1000)", 55 | "group": "mano (1000)", 56 | "permissions": "-rw-r--r--" 57 | }, 58 | { 59 | "mimeType": "video/mp4", 60 | "name": "thisIsAVideo.mp4", 61 | "size": 574823, 62 | "chDate": 1645859516, 63 | "owner": "mano (1000)", 64 | "group": "mano (1000)", 65 | "permissions": "-rw-r--r--" 66 | }, 67 | { 68 | "mimeType": "text/plain", 69 | "name": "thisIsAnEmptyFile", 70 | "size": 0, 71 | "chDate": 1645859506, 72 | "owner": "mano (1000)", 73 | "group": "mano (1000)", 74 | "permissions": "-rw-r--r--" 75 | }, 76 | { 77 | "mimeType": "audio/mpeg", 78 | "name": "thisIsAudio.mp3", 79 | "size": 764176, 80 | "chDate": 1645859459, 81 | "owner": "mano (1000)", 82 | "group": "mano (1000)", 83 | "permissions": "-rw-r--r--" 84 | }, 85 | { 86 | "mimeType": "text/html; charset=utf-8", 87 | "name": "thisIsHTML.html", 88 | "size": 1086, 89 | "chDate": 1645859481, 90 | "owner": "mano (1000)", 91 | "group": "mano (1000)", 92 | "permissions": "-rw-r--r--" 93 | }, 94 | { 95 | "mimeType": "image/jpeg", 96 | "name": "thisIsUnicode汉字卡片.jpg", 97 | "size": 54828, 98 | "chDate": 1645859545, 99 | "owner": "mano (1000)", 100 | "group": "mano (1000)", 101 | "permissions": "-rw-r--r--" 102 | }, 103 | { 104 | "mimeType": "image/jpeg", 105 | "name": "thisIsABigPic.jpg", 106 | "size": 618098, 107 | "chDate": 1645859545, 108 | "owner": "mano (1000)", 109 | "group": "mano (1000)", 110 | "permissions": "-rw-r--r--" 111 | } 112 | ] 113 | } 114 | -------------------------------------------------------------------------------- /web-ui/src/Preview/FullScreen.svelte: -------------------------------------------------------------------------------- 1 | 97 | 98 | 104 | 105 |
106 | {files[fileIdx].name} 109 |
110 | -------------------------------------------------------------------------------- /demo-ui/src/Preview/FullScreen.svelte: -------------------------------------------------------------------------------- 1 | 97 | 98 | 104 | 105 |
106 | {files[fileIdx].name} 109 |
110 | -------------------------------------------------------------------------------- /src/go.sum: -------------------------------------------------------------------------------- 1 | github.com/andybalholm/brotli v1.0.4 h1:V7DdXeJtZscaqfNuAdSRuRFzuiKlHSC/Zh3zl9qY3JY= 2 | github.com/andybalholm/brotli v1.0.4/go.mod h1:fO7iG3H7G2nSZ7m0zPUDn85XEX2GTukHGRSepvi9Eig= 3 | github.com/gofiber/fiber/v2 v2.33.0 h1:U9om15fapDkQ2sd9JQMfZLOs52bagsMAoTomQDqyJtg= 4 | github.com/gofiber/fiber/v2 v2.33.0/go.mod h1:CMy5ZLiXkn6qwthrl03YMyW1NLfj0rhxz2LKl4t7ZTY= 5 | github.com/klauspost/compress v1.15.0/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk= 6 | github.com/klauspost/compress v1.15.3 h1:wmfu2iqj9q22SyMINp1uQ8C2/V4M1phJdmH9fG4nba0= 7 | github.com/klauspost/compress v1.15.3/go.mod h1:PhcZ0MbTNciWF3rruxRgKxI5NkcHHrHUDtV4Yw2GlzU= 8 | github.com/otiai10/copy v1.7.0 h1:hVoPiN+t+7d2nzzwMiDHPSOogsWAStewq3TwU05+clE= 9 | github.com/otiai10/copy v1.7.0/go.mod h1:rmRl6QPdJj6EiUqXQ/4Nn2lLXoNQjFCQbbNrxgc/t3U= 10 | github.com/otiai10/curr v0.0.0-20150429015615-9b4961190c95/go.mod h1:9qAhocn7zKJG+0mI8eUu6xqkFDYS2kb2saOteoSB3cE= 11 | github.com/otiai10/curr v1.0.0/go.mod h1:LskTG5wDwr8Rs+nNQ+1LlxRjAtTZZjtJW4rMXl6j4vs= 12 | github.com/otiai10/mint v1.3.0/go.mod h1:F5AjcsTsWUqX+Na9fpHb52P8pcRX2CI6A3ctIT91xUo= 13 | github.com/otiai10/mint v1.3.3 h1:7JgpsBaN0uMkyju4tbYHu0mnM55hNKVYLsXmwr15NQI= 14 | github.com/otiai10/mint v1.3.3/go.mod h1:/yxELlJQ0ufhjUwhshSj+wFjZ78CnZ48/1wtmBH1OTc= 15 | github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= 16 | github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= 17 | github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw= 18 | github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc= 19 | github.com/valyala/fasthttp v1.35.0/go.mod h1:t/G+3rLek+CyY9bnIE+YlMRddxVAAGjhxndDB4i4C0I= 20 | github.com/valyala/fasthttp v1.36.0 h1:NhqfO/cB7Ajn1czkKnWkMHyPYr5nyND14ZGPk23g0/c= 21 | github.com/valyala/fasthttp v1.36.0/go.mod h1:t/G+3rLek+CyY9bnIE+YlMRddxVAAGjhxndDB4i4C0I= 22 | github.com/valyala/tcplisten v1.0.0 h1:rBHj/Xf+E1tRGZyWIWwJDiRY0zc1Js+CV5DqwacVSA8= 23 | github.com/valyala/tcplisten v1.0.0/go.mod h1:T0xQ8SeCZGxckz9qRXTfG43PvQ/mcWh7FwZEA7Ioqkc= 24 | golang.org/x/crypto v0.0.0-20220214200702-86341886e292/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= 25 | golang.org/x/crypto v0.0.0-20220507011949-2cf3adece122 h1:NvGWuYG8dkDHFSKksI1P9faiVJ9rayE6l0+ouWVIDs8= 26 | golang.org/x/crypto v0.0.0-20220507011949-2cf3adece122/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= 27 | golang.org/x/exp v0.0.0-20220428152302-39d4317da171 h1:TfdoLivD44QwvssI9Sv1xwa5DcL5XQr4au4sZ2F2NV4= 28 | golang.org/x/exp v0.0.0-20220428152302-39d4317da171/go.mod h1:lgLbSvA5ygNOMpwM/9anMpWVlVJ7Z+cHWq/eFuinpGE= 29 | golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= 30 | golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= 31 | golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 32 | golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 33 | golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 34 | golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 35 | golang.org/x/sys v0.0.0-20220227234510-4e6760a101f9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 36 | golang.org/x/sys v0.0.0-20220503163025-988cb79eb6c6 h1:nonptSpoQ4vQjyraW20DXPAglgQfVnM9ZC6MmNLMR60= 37 | golang.org/x/sys v0.0.0-20220503163025-988cb79eb6c6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 38 | golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= 39 | golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= 40 | golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= 41 | golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= 42 | golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= 43 | -------------------------------------------------------------------------------- /web-ui/src/Auth.svelte: -------------------------------------------------------------------------------- 1 | 110 | 111 | {#if config != null} 112 | 113 | {:else} 114 |
115 | {/if} 116 | -------------------------------------------------------------------------------- /demo-ui/src/Auth.svelte: -------------------------------------------------------------------------------- 1 | 110 | 111 | {#if config != null} 112 | 113 | {:else} 114 |
115 | {/if} 116 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | .PHONY: list docker 2 | list: 3 | @LC_ALL=C $(MAKE) -pRrq -f $(lastword $(MAKEFILE_LIST)) : 2>/dev/null | awk -v RS= -F: '/^# File/,/^# Finished Make data base/ {if ($$1 !~ "^[#.]") {print $$1}}' | sort | egrep -v -e '^[^[:alnum:]]' -e '^$@$$' 4 | 5 | cleanup-ui: 6 | - rm -r web-ui/node_modules 7 | - rm -r web-ui/public/build 8 | 9 | cleanup-demo-ui: 10 | - rm -r demo-ui/node_modules 11 | 12 | cleanup-build: 13 | - rm -r bin 14 | - rm src/pupcloud 15 | 16 | cleanup: 17 | - make cleanup-ui 18 | - make cleanup-demo-ui 19 | - make cleanup-build 20 | 21 | build-ui: 22 | make cleanup-ui 23 | cd web-ui && npm install && npm run build 24 | - rm -r src/static/* 25 | cp -r web-ui/public/* src/static/ 26 | 27 | build-demo-ui: 28 | make cleanup-demo-ui 29 | - rm -r demo-ui/node_modules 30 | - rm -r demo-ui/public/build 31 | cd demo-ui && npm install && npm run build 32 | 33 | build-prepare: 34 | make cleanup 35 | mkdir bin 36 | 37 | build: 38 | make build-prepare 39 | cd src; CGO=0 go build -o ../bin/pupcloud 40 | 41 | zbuild: 42 | make build 43 | cd bin; 7zr a -mx9 -t7z pupcloud-v0.8.0-`uname -s|tr '[:upper:]' '[:lower:]'`-`uname -m`.7z pupcloud 44 | 45 | build-static: 46 | make build-prepare 47 | cd src; CGO=0 go build -a -tags netgo,osusergo -ldflags '-w -extldflags "-static"' -o ../bin/pupcloud 48 | 49 | zbuild-static: 50 | make build-static 51 | cd bin; 7zr a -mx9 -t7z pupcloud-v0.8.0-`uname -s|tr '[:upper:]' '[:lower:]'`-`uname -m`.7z pupcloud 52 | 53 | zbuild-all: 54 | make build-prepare 55 | make build-ui 56 | cd src; CGO=0 GOOS=linux GOARCH=amd64 go build -a -tags netgo,osusergo -ldflags '-w -extldflags "-static"' 57 | cd src; tar czf ../bin/pupcloud-v0.8.0-linux-amd64.tar.gz pupcloud 58 | rm src/pupcloud 59 | cd src; CGO=0 GOOS=linux GOARCH=arm go build -a -tags netgo,osusergo -ldflags '-w -extldflags "-static"' 60 | cd src; tar czf ../bin/pupcloud-v0.8.0-linux-arm.tar.gz pupcloud 61 | rm src/pupcloud 62 | cd src; CGO=0 GOOS=linux GOARCH=arm64 go build -a -tags netgo,osusergo -ldflags '-w -extldflags "-static"' 63 | cd src; tar czf ../bin/pupcloud-v0.8.0-linux-arm64.tar.gz pupcloud 64 | rm src/pupcloud 65 | cd src; CGO=0 GOOS=darwin GOARCH=amd64 go build 66 | cd src; zip -9 ../bin/pupcloud-v0.8.0-darwin-amd64.zip pupcloud 67 | rm src/pupcloud 68 | cd src; CGO=0 GOOS=darwin GOARCH=arm64 go build 69 | cd src; zip -9 ../bin/pupcloud-v0.8.0-darwin-arm64.zip pupcloud 70 | rm src/pupcloud 71 | cd src; CGO=0 GOOS=windows GOARCH=amd64 go build 72 | cd src; zip -9 ../bin/pupcloud-v0.8.0-win-amd64.zip pupcloud.exe 73 | rm src/pupcloud.exe 74 | cd src; CGO=0 GOOS=windows GOARCH=arm64 go build 75 | cd src; zip -9 ../bin/pupcloud-v0.8.0-win-arm64.zip pupcloud.exe 76 | rm src/pupcloud.exe 77 | cd src; CGO=0 GOOS=freebsd GOARCH=amd64 go build 78 | cd src; tar czf ../bin/pupcloud-v0.8.0-freebsd-arm64.tar.gz pupcloud 79 | rm src/pupcloud 80 | 81 | run: 82 | make build-ui 83 | make build 84 | bin/pupcloud -r demo-ui/public/testFs/ -E 85 | 86 | run-demo-ui: 87 | make cleanup-demo-ui 88 | cd demo-ui && npm install && npm run dev 89 | 90 | docker: 91 | sudo docker build --no-cache -t local_pupcloud:latest . 92 | 93 | docker-publish: 94 | ## Prepare system with: 95 | ## (verify which is latest at https://hub.docker.com/r/docker/binfmt/tags) 96 | sudo docker run --privileged --rm docker/binfmt:a7996909642ee92942dcd6cff44b9b95f08dad64 97 | sudo docker buildx build --no-cache -t germanorizzo/pupcloud:v0.8.0-amd64 . 98 | sudo docker buildx build --no-cache --platform linux/arm/v7 -t germanorizzo/pupcloud:v0.8.0-arm . 99 | sudo docker buildx build --no-cache --platform linux/arm64/v8 -t germanorizzo/pupcloud:v0.8.0-arm64 . 100 | sudo docker push germanorizzo/pupcloud:v0.8.0-amd64 101 | sudo docker push germanorizzo/pupcloud:v0.8.0-arm 102 | sudo docker push germanorizzo/pupcloud:v0.8.0-arm64 103 | sudo docker manifest create -a germanorizzo/pupcloud:v0.8.0 germanorizzo/pupcloud:v0.8.0-amd64 germanorizzo/pupcloud:v0.8.0-arm germanorizzo/pupcloud:v0.8.0-arm64 104 | sudo docker manifest push germanorizzo/pupcloud:v0.8.0 105 | sudo docker manifest create -a germanorizzo/pupcloud:latest germanorizzo/pupcloud:v0.8.0-amd64 germanorizzo/pupcloud:v0.8.0-arm germanorizzo/pupcloud:v0.8.0-arm64 106 | sudo docker manifest push germanorizzo/pupcloud:latest 107 | -------------------------------------------------------------------------------- /Changelog.md: -------------------------------------------------------------------------------- 1 | # Changelog 2 | 3 | ## Main features history 4 | 5 | | Feature | Version | 6 | |--------------------------------------------|---------| 7 | | Basic navigation | v0.1.x | 8 | | File preview/gallery | v0.1.x | 9 | | Authentication | v0.2.x | 10 | | Write operations (delete, copy, rename...) | v0.3.x | 11 | | Read-only mode | v0.3.x | 12 | | File upload | v0.4.x | 13 | | Folder sharing | v0.5.x | 14 | | Follow symlinks | v0.6.x | 15 | 16 | ## v0.8.0 17 | 18 | - Readonly mode is now the default, `-E` to make it read-write [#16] 19 | - Every CLI parameter can be specified as an env variable [addresses #10] 20 | - Added parameter `--share-profiles` to specify profiles as comma-separated [addresses #14] 21 | - Fixed back button management [addresses #15] 22 | - Copying the sharing link to clipboard wouldn't work if not in a secure context [#19] 23 | - Improvements to better support reverse proxies with subpaths [#18, #22] 24 | - Added path to the browser tab's title, so that it figures in the history list 25 | - Reduced number of columns in grid view for xl screens 26 | - Fix: Only the first sharing profile was selectable [#21] 27 | - Fix: Logout button wouldn't show when using a "normal" password [#23] 28 | - Ditch 7z format for distribution, use .tar.gz & zip instead (according to the OS) 29 | - Updates to libraries 30 | - Binaries for win/arm64 and freebsd/amd64 31 | 32 | ## v0.7.2 33 | 34 | - [#1] Support for browser's back/forward buttons navigation 35 | - [#11] Webservices allows paths with '..' 36 | - Docker cross-compiling for amd64, arm, arm64 and multiplatform manifest 37 | 38 | ## v0.7.1 39 | 40 | - [#2] Can't enter directory made by pupcloud 41 | - [#4] When cd to a dir fails, dir name gets appended to the breadcrumb "forever" 42 | - [#5] Provide systemd example/docs (in proofrock/pupcloud-docs) 43 | - [#6] More functional footer 44 | - [#7] Click on title to go to root 45 | - [#8] Listview's whole row should be clickable 46 | - [#9] Listviews' columns should be clickable to change sorting 47 | - Library upgrades 48 | 49 | ## v0.7.0 50 | 51 | - Plain-text password for auth (`-P`) 52 | - breaking change: old `-P` is now `-H` (for hashed password) 53 | - Shorter sharing links and better detection of failures (root changes after sharing, ...) 54 | - breaking change: you'll need to re-generate any sharing link you had from previous versions 55 | - Cross-compilation support (removed CGO dependency) 56 | - Manual mimetype resolution for problematic files 57 | 58 | ## v0.6.4 59 | 60 | - IPV6 support 61 | - "splash footer" disappears after 1,5s 62 | 63 | ## v0.6.1 - 0.6.3 64 | 65 | - fixes 66 | - library updates 67 | 68 | ## v0.6.0 69 | 70 | - Ability to follow symbolic links (`--follow-symlinks`) 71 | - Preview now switches between slideshow, full-screen and full size 72 | - Swipe support in slideshow screen, on mobile 73 | - It's now forbidden to run as root (unless `--allow-root`) 74 | - Logout (if password is required) 75 | - Session invalidation when preconditions fail after login (root deletion, expiration...) 76 | - Go 1.18 77 | - Minor fixes and improvements 78 | 79 | ## v0.5.0 80 | 81 | - Folder sharing 82 | - UserID/GroupID support in docker 83 | - Ability to specify max upload size on the CLI 84 | - Many fixes, refactorings and performance improvements 85 | 86 | ## v0.4.2 87 | 88 | - Fixed z-indexes 89 | - Improved performances when listing a huge number of items 90 | - Upgrade to libs 91 | 92 | ## v0.4.1 93 | 94 | - Fix: paste didn't work 95 | - Reload button 96 | 97 | ## v0.4.0 98 | 99 | - File upload 100 | - CSRF protection 101 | 102 | ## v0.3.0 103 | 104 | - "Write" operations 105 | - Cut/Copy/Paste 106 | - Delete 107 | - Rename 108 | - Create Folder 109 | - Read-only mode (`--readonly`) 110 | - Support for Windows 111 | - Minor UI fixes 112 | 113 | ## v0.2.0 114 | 115 | - Authentication (`-P`); 116 | - Updates to library (particularly Axentix and Fiber); 117 | - Workaround for dropdown triggers (`...`) being rendered over the dropdown 118 | itself. 119 | 120 | ## v0.1.2 121 | 122 | - Fixes to HTML layout. 123 | 124 | ## v0.1.1 125 | 126 | - Stable demo site; 127 | - Fixes to Dockerfile. 128 | 129 | ## v0.1.0 130 | 131 | - First version; 132 | - Navigation, preview, download of files. 133 | -------------------------------------------------------------------------------- /src/static/icons/48x48/image-x-generic.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /web-ui/public/icons/48x48/image-x-generic.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /demo-ui/public/icons/48x48/image-x-generic.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | --------------------------------------------------------------------------------