Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,8 @@ _testmain.go
*.prof

.project
gofe
gofe*
main
static/
tmp/

20 changes: 19 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,24 @@
## gofe - Go File Explorer
A golang backend for angular-filemanager - https://github.com/joni2back/angular-filemanager

### Todo
##### [API](https://github.com/joni2back/angular-filemanager/blob/master/API.md)
- [x] [Listing](https://github.com/joni2back/angular-filemanager/blob/master/API.md#listing-url-filemanagerconfiglisturl-method-post)
- [x] [Rename](https://github.com/joni2back/angular-filemanager/blob/master/API.md#rename-url-filemanagerconfigrenameurl-method-post)
- [x] [Move](https://github.com/joni2back/angular-filemanager/blob/master/API.md#move-url-filemanagerconfigmoveurl-method-post)
- [x] [Copy](https://github.com/joni2back/angular-filemanager/blob/master/API.md#copy-url-filemanagerconfigcopyurl-method-post)
- [x] [Remove/Delete](https://github.com/joni2back/angular-filemanager/blob/master/API.md#remove-url-filemanagerconfigremoveurl-method-post)
- [ ] [Edit](https://github.com/joni2back/angular-filemanager/blob/master/API.md#edit-file-url-filemanagerconfigediturl-method-post)
- [ ] [getContent](https://github.com/joni2back/angular-filemanager/blob/master/API.md#get-content-of-a-file-url-filemanagerconfiggetcontenturl-method-post)
- [x] [createFolder](https://github.com/joni2back/angular-filemanager/blob/master/API.md#create-folder-url-filemanagerconfigcreatefolderurl-method-post)
- [x] [changePermissions](https://github.com/joni2back/angular-filemanager/blob/master/API.md#set-permissions-url-filemanagerconfigpermissionsurl-method-post)
- [ ] [compress](https://github.com/joni2back/angular-filemanager/blob/master/API.md#compress-file-url-filemanagerconfigcompressurl-method-post)
- [ ] [extract](https://github.com/joni2back/angular-filemanager/blob/master/API.md#extract-file-url-filemanagerconfigextracturl-method-post)
- [x] [Upload](https://github.com/joni2back/angular-filemanager/blob/master/API.md#upload-file-url-filemanagerconfiguploadurl-method-post-content-type-multipartform-data)
- [x] [Download](https://github.com/joni2back/angular-filemanager/blob/master/API.md#download--preview-file-url-filemanagerconfigdownloadmultipleurl-method-get)
- [ ] [Download Many as Zip](https://github.com/joni2back/angular-filemanager/blob/master/API.md#download-multiples-files-in-ziptar-url-filemanagerconfigdownloadfileurl-method-get)


### Screenshots
![](https://raw.githubusercontent.com/kernel164/gofe/master/screenshot1.png)
![](https://raw.githubusercontent.com/kernel164/gofe/master/screenshot2.png)
Expand All @@ -20,4 +38,4 @@ STATICS = angular-filemanager/bower_components,angular-filemanager/dist,angular-

[backend.ssh]
HOST = localhost:22
```
```
2 changes: 1 addition & 1 deletion angular-filemanager
Submodule angular-filemanager updated 60 files
+0 −3 .gitmodules
+79 −58 API.md
+30 −17 README.md
+6 −6 bower.json
+0 −8 bower_components/angular-cookies/angular-cookies.min.js
+4 −4 bower_components/angular-translate/angular-translate.min.js
+303 −249 bower_components/angular/angular.min.js
+3 −2 bower_components/bootstrap/dist/css/bootstrap.min.css
+3 −3 bower_components/bootstrap/dist/js/bootstrap.min.js
+3 −3 bower_components/bootswatch/paper/bootstrap.min.css
+4 −5 bower_components/jquery/dist/jquery.min.js
+3 −0 bower_components/ng-file-upload/ng-file-upload.min.js
+70 −37 bridges/java/AngularFileManagerServlet.java
+478 −0 bridges/php-local/LocalBridge/FileManagerApi.php
+128 −0 bridges/php-local/LocalBridge/Response.php
+216 −0 bridges/php-local/LocalBridge/Rest.php
+34 −0 bridges/php-local/LocalBridge/Translate.php
+21 −0 bridges/php-local/index.php
+18 −0 bridges/php-local/lang/de.json
+18 −0 bridges/php-local/lang/en.json
+18 −0 bridges/php-local/lang/fr.json
+18 −0 bridges/php-local/lang/sk.json
+92 −24 bridges/php/handler.php
+122 −0 bridges/php/includes/ExceptionCatcher.php
+714 −0 bridges/php/includes/Ftp.php
+0 −1 bridges/php/php-classic
+0 −25 build.sh
+2 −2 dist/angular-filemanager.min.css
+4 −2 dist/angular-filemanager.min.js
+3 −3 gulpfile.js
+15 −6 index.html
+9 −8 package.json
+ screenshot.gif
+ screenshot1.png
+ screenshot2.png
+ screenshot3.png
+36 −5 src/css/dialogs.css
+199 −69 src/css/main.css
+35 −9 src/js/app.js
+253 −79 src/js/controllers/main.js
+43 −12 src/js/controllers/selector-controller.js
+6 −10 src/js/entities/chmod.js
+10 −236 src/js/entities/item.js
+27 −2 src/js/filters/filters.js
+23 −8 src/js/providers/config.js
+824 −14 src/js/providers/translations.js
+369 −0 src/js/services/apihandler.js
+135 −0 src/js/services/apimiddleware.js
+27 −42 src/js/services/filenavigator.js
+0 −53 src/js/services/fileuploader.js
+6 −5 src/templates/current-folder-breadcrumb.html
+53 −24 src/templates/item-context-menu.html
+0 −32 src/templates/item-toolbar.html
+11 −9 src/templates/main-icons.html
+4 −4 src/templates/main-table-modal.html
+15 −17 src/templates/main-table.html
+6 −5 src/templates/main.html
+162 −81 src/templates/modals.html
+70 −37 src/templates/navbar.html
+9 −3 src/templates/sidebar.html
16 changes: 10 additions & 6 deletions fe/fileexplorer.go
Original file line number Diff line number Diff line change
@@ -1,16 +1,20 @@
package fe

import (
models "../models"
"mime/multipart"

"github.com/md2k/gofe/models"
)

type FileExplorer interface {
Init() error
ListDir(path string) ([]models.ListDirEntry, error)
Move(path string, newPath string) error
Copy(path string, newPath string) error
Delete(path string) error
Chmod(path string, code string) error
Mkdir(path string, name string) error
Rename(path string, newPath string) error
Move(path []string, newPath string) (err error)
Copy(path []string, newPath string, singleFilename string) (err error)
Delete(path []string) (err error)
Chmod(path []string, code string, recursive bool) (err error)
Mkdir(path string) error
UploadFile(destination string, part *multipart.Part) (err error)
Close() error
}
112 changes: 96 additions & 16 deletions fe/ssh_fileexplorer.go
Original file line number Diff line number Diff line change
@@ -1,12 +1,20 @@
// TODO: Better handling of errors from SSH Back-end executions.
// ExecOnly() / Exec()
// 'Process exited with status 1' Not very informative :)

package fe

import (
models "../models"
"golang.org/x/crypto/ssh"
"fmt"
"io"
"log"
"mime/multipart"
"net"
"strings"
"time"

"github.com/md2k/gofe/models"
"golang.org/x/crypto/ssh"
)

const DefaultTimeout = 30 * time.Second
Expand Down Expand Up @@ -53,32 +61,97 @@ func normalizePath(path string) string {
return path
}

func (fe *SSHFileExplorer) Mkdir(path string, name string) error {
return fe.ExecOnly("mkdir " + normalizePath(path) + "/" + name)
func (fe *SSHFileExplorer) Mkdir(path string) error {
return fe.ExecOnly(fmt.Sprintf("mkdir -p \"%s\"", normalizePath(path)))
}

func (fe *SSHFileExplorer) ListDir(path string) ([]models.ListDirEntry, error) {
ls, err := fe.Exec("ls --time-style=long-iso -l " + normalizePath(path))
// Most ugliest Fix, but nothing other can be done here to able parse LS in correct way and support files with spaces in names :)
// Have another idea, but this is for later TODO
ls, err := fe.Exec("ls --time-style=long-iso -1 -q -l --hide-control-chars " + normalizePath(path) + " | awk '{n=split($0,array,\" \")} { for (i = 1; i <= 7; i++) {printf \"%s|\",array[i]}} { for (i = 8; i <= n; i++) {printf \"%s \",array[i]};print \"\"}'")
// ls, err := fe.Exec(fmt.Sprintf("ls --time-style=long-iso -l %s", normalizePath(path)))
if err != nil {
return nil, err
}
return parseLsOutput(string(ls)), nil
}

func (fe *SSHFileExplorer) Move(path string, newPath string) error {
return fe.ExecOnly("mv " + normalizePath(path) + " " + normalizePath(newPath))
func (fe *SSHFileExplorer) Rename(path string, newPath string) error {
return fe.ExecOnly(fmt.Sprintf("mv \"%s\" \"%s\"", normalizePath(path), normalizePath(newPath)))
}

func (fe *SSHFileExplorer) Copy(path string, newPath string) error {
return fe.ExecOnly("cp -r " + normalizePath(path) + " " + normalizePath(newPath))
func (fe *SSHFileExplorer) Move(path []string, newPath string) (err error) {
for _, target := range path {
err = fe.ExecOnly(fmt.Sprintf("mv \"%s\" \"%s\"", normalizePath(target), normalizePath(newPath)))
}
return err
}

func (fe *SSHFileExplorer) Delete(path string) error {
return fe.ExecOnly("rm -r " + normalizePath(path))
func (fe *SSHFileExplorer) Copy(path []string, newPath string, singleFilename string) (err error) {
for _, target := range path {
err = fe.ExecOnly(fmt.Sprintf("cp -r \"%s\" \"%s/%s\"", normalizePath(target), normalizePath(newPath), singleFilename))
}
return err
}

func (fe *SSHFileExplorer) Chmod(path string, code string) error {
return fe.ExecOnly("chmod " + code + " " + normalizePath(path))
func (fe *SSHFileExplorer) Delete(path []string) (err error) {
for _, target := range path {
err = fe.ExecOnly(fmt.Sprintf("rm --interactive=never -r \"%s\"", normalizePath(target)))
}
return err
}

func (fe *SSHFileExplorer) Chmod(path []string, code string, recursive bool) (err error) {
for _, target := range path {
recurs := ""
if recursive {
recurs = "-R"
}
err = fe.ExecOnly(fmt.Sprintf("chmod %s %s \"%s\"", recurs, code, normalizePath(target)))
}
return err
}

func (fe *SSHFileExplorer) UploadFile(destination string, part *multipart.Part) (err error) {
// Write directly to Disk
// dst, err := os.Create(fmt.Sprintf("%s/%s", destination, part.FileName()))
// defer dst.Close()
// if err != nil {
// return err
// }

// if _, err := io.Copy(dst, part); err != nil {
// return err
// }
// err = fe.ExecOnly(fmt.Sprintf("chmod 664 \"%s/%s\"", , destination, normalizePath(target)))
// return nil

// Write over SSH StdIn Pipe
session, err := fe.client.NewSession()
if err != nil {
return err
}
// defer session.Close()

input, err := session.StdinPipe()
if err != nil {
return err
}

// Open cat stdin input remotely
err = session.Start(fmt.Sprintf("cat - > \"%s/%s\"", destination, part.FileName()))
if err != nil {
return err
}

// Write to Session's Stdin
if _, err := io.Copy(input, part); err != nil {
return err
}
// Close on finish (Guess it is better to send signal , so for TODO)
session.Close()

return err
}

func (fe *SSHFileExplorer) Close() error {
Expand All @@ -105,7 +178,7 @@ func (fe *SSHFileExplorer) ExecOnly(cmd string) error {
defer session.Close()
_, err1 := session.CombinedOutput(cmd)
if err1 != nil {
return err // + " - " + string(out)
return err1 // + " - " + string(out)
}
return nil
}
Expand All @@ -114,9 +187,16 @@ func parseLsOutput(lsout string) []models.ListDirEntry {
lines := strings.Split(lsout, "\n")
results := []models.ListDirEntry{}
for _, line := range lines {
//fmt.Println(idx, line)
// fmt.Println(idx, line)
if len(line) != 0 && !strings.HasPrefix(line, "total") {
tokens := strings.Fields(line)
// our Dirty LS Fix with AWK return line as follow:
// drwxr-xr-x|2|root|root|4096|2016-07-13|17:47|bin
tmp_tokens := strings.SplitN(line, "|", 8)
var tokens []string
for _, token := range tmp_tokens {
tokens = append(tokens, strings.TrimSpace(token))
}
// fmt.Println(tokens)
if len(tokens) >= 8 {
ftype := "file"
if strings.HasPrefix(tokens[0], "d") {
Expand Down
12 changes: 10 additions & 2 deletions gofe.ini
Original file line number Diff line number Diff line change
@@ -1,9 +1,17 @@
BACKEND = ssh
SERVER = http
SERVER = https

[server.http]
BIND = localhost:4000
BIND = :4000
STATICS = angular-filemanager/bower_components,angular-filemanager/dist,angular-filemanager/src
CORSORIGINS =

[server.https]
BIND = :9044
STATICS = angular-filemanager/bower_components,angular-filemanager/dist,angular-filemanager/src
SSLKEY =
SSLCERT =
CORSORIGINS =

[backend.ssh]
HOST = localhost:22
Loading