Initial commit

This commit is contained in:
NI
2019-08-07 15:56:51 +08:00
commit 02f14eb14f
206 changed files with 38863 additions and 0 deletions

146
application/rw/fetch.go Normal file
View File

@@ -0,0 +1,146 @@
// Sshwifty - A Web SSH client
//
// Copyright (C) 2019 Rui NI <nirui@gmx.com>
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as
// published by the Free Software Foundation, either version 3 of the
// License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
package rw
import "errors"
// Errors
var (
ErrFetchReaderNotEnoughBuffer = errors.New(
"Not enough buffer")
)
// FetchReaderFetcher generates data for SourceReader
type FetchReaderFetcher func() ([]byte, error)
// FetchReader read from the source and increase your lifespan if used correctly
type FetchReader struct {
source FetchReaderFetcher // Source data fetcher
data []byte // Fetched source data
dataUsed int // Used source data
}
// Fetch fetchs
type Fetch func(n int) ([]byte, error)
// FetchOneByte fetchs one byte from the Fetch, or return an error when it fails
func FetchOneByte(f Fetch) ([]byte, error) {
for {
d, dErr := f(1)
if dErr != nil {
return nil, dErr
}
if len(d) <= 0 {
continue
}
return d, nil
}
}
// NewFetchReader creates a new FetchReader
func NewFetchReader(g FetchReaderFetcher) FetchReader {
return FetchReader{
source: g,
data: nil,
dataUsed: 0,
}
}
func (r FetchReader) dataRemain() int {
return len(r.data) - r.dataUsed
}
// Remain Returns how many bytes is waiting to be readed
func (r *FetchReader) Remain() int {
return r.dataRemain()
}
// Export directly exports from buffer, never read from source
//
// Params:
// - n: Exact amount of bytes to fetch (0 to n, n included). If number n is
// unreachable, an error will be returned, and no internal status will
// be changed
//
// Returns:
// - Fetched data
// - Read error
func (r *FetchReader) Export(n int) ([]byte, error) {
remain := r.dataRemain()
if n > remain {
return nil, ErrFetchReaderNotEnoughBuffer
}
newUsed := r.dataUsed + n
data := r.data[r.dataUsed:newUsed]
r.dataUsed = newUsed
return data, nil
}
// Fetch fetchs data from the source
//
// Params:
// - n: Max bytes to fetch (0 to n, n included)
//
// Returns:
// - Fetched data
// - Read error
func (r *FetchReader) Fetch(n int) ([]byte, error) {
remain := r.dataRemain()
if remain <= 0 {
data, dataFetchErr := r.source()
if dataFetchErr != nil {
return nil, dataFetchErr
}
r.data = data
r.dataUsed = 0
remain = r.dataRemain()
}
if n > remain {
n = remain
}
newUsed := r.dataUsed + n
data := r.data[r.dataUsed:newUsed]
r.dataUsed = newUsed
return data, nil
}
// Read implements io.Read
func (r *FetchReader) Read(b []byte) (int, error) {
d, dErr := r.Fetch(len(b))
if dErr != nil {
return 0, dErr
}
return copy(b, d), nil
}

View File

@@ -0,0 +1,59 @@
// Sshwifty - A Web SSH client
//
// Copyright (C) 2019 Rui NI <nirui@gmx.com>
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as
// published by the Free Software Foundation, either version 3 of the
// License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
package rw
import (
"bytes"
"io"
"testing"
)
func testDummyFetchGen(data []byte) FetchReaderFetcher {
current := 0
return func() ([]byte, error) {
if current >= len(data) {
return nil, io.EOF
}
oldCurrent := current
current = oldCurrent + 1
return data[oldCurrent:current], nil
}
}
func TestFetchReader(t *testing.T) {
r := NewFetchReader(testDummyFetchGen([]byte("Hello World")))
b := make([]byte, 11)
_, rErr := io.ReadFull(&r, b)
if rErr != nil {
t.Error("Failed to read due to error:", rErr)
return
}
if !bytes.Equal(b, []byte("Hello World")) {
t.Errorf("Expecting data to be %s, got %s instead",
[]byte("Hello World"), b)
return
}
}

130
application/rw/limited.go Normal file
View File

@@ -0,0 +1,130 @@
// Sshwifty - A Web SSH client
//
// Copyright (C) 2019 Rui NI <nirui@gmx.com>
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as
// published by the Free Software Foundation, either version 3 of the
// License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
package rw
import (
"errors"
"io"
)
// Errors
var (
ErrReadUntilCompletedBufferFull = errors.New(
"Cannot read more, not enough data buffer")
)
// LimitedReader reads only n bytes of data
type LimitedReader struct {
r *FetchReader
n int
}
// ReadUntilCompleted read until the reader is completed
func ReadUntilCompleted(r *LimitedReader, b []byte) (int, error) {
bCur := 0
bLen := len(b)
for !r.Completed() {
if bCur >= bLen {
return bCur, ErrReadUntilCompletedBufferFull
}
rLen, rErr := r.Read(b[bCur:])
if rErr != nil {
return bCur + rLen, rErr
}
bCur += rLen
}
return bCur, nil
}
// NewLimitedReader creates a new LimitedReader
func NewLimitedReader(r *FetchReader, n int) LimitedReader {
return LimitedReader{
r: r,
n: n,
}
}
// Buffered exports the internal buffer
func (l *LimitedReader) Buffered() ([]byte, error) {
return l.Fetch(l.Remains())
}
// Fetch fetchs max n bytes from buffer
func (l *LimitedReader) Fetch(n int) ([]byte, error) {
if l.Completed() {
return nil, io.EOF
}
if n > l.Remains() {
n = l.Remains()
}
exported, eErr := l.r.Fetch(n)
l.n -= len(exported)
return exported, eErr
}
// Read read from the LimitedReader
func (l *LimitedReader) Read(b []byte) (int, error) {
if l.Completed() {
return 0, io.EOF
}
toRead := len(b)
if toRead > l.Remains() {
toRead = l.Remains()
}
rLen, rErr := l.r.Read(b[:toRead])
l.n -= rLen
return rLen, rErr
}
// Ditch ditchs all remaining data. Data will be written and overwritten to
// the given buf when ditching
func (l *LimitedReader) Ditch(buf []byte) error {
for !l.Completed() {
_, rErr := l.Read(buf)
if rErr != nil {
return rErr
}
}
return nil
}
// Remains returns how many bytes is waiting to be read
func (l LimitedReader) Remains() int {
return l.n
}
// Completed returns whether or not current reader is completed
func (l LimitedReader) Completed() bool {
return l.n <= 0
}

41
application/rw/rw.go Normal file
View File

@@ -0,0 +1,41 @@
// Sshwifty - A Web SSH client
//
// Copyright (C) 2019 Rui NI <nirui@gmx.com>
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as
// published by the Free Software Foundation, either version 3 of the
// License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
package rw
// ReaderFunc function of io.Reader
type ReaderFunc func(b []byte) (int, error)
// ReadFull Read until given b is fully loaded
func ReadFull(r ReaderFunc, b []byte) (int, error) {
bLen := len(b)
readed := 0
for {
rLen, rErr := r(b[readed:])
readed += rLen
if rErr != nil {
return readed, rErr
}
if readed >= bLen {
return readed, nil
}
}
}