| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -15,7 +15,7 @@ Gokapi is a lightweight server to share files, which expire after a set amount o | |||
| 15 | 15 | ||
| 16 | 16 | This enables companies or individuals to share their files very easily and having them removed afterwards, therefore saving disk space and having control over who downloads the file from the server. | |
| 17 | 17 | ||
| 18 | - Customization is very easy with HTML/CSS knowledge. Identical files will be deduplicated. An API is available to interact with Gokapi. | ||
| 18 | + Identical files will be deduplicated. An API is available to interact with Gokapi. Customization is very easy with HTML/CSS knowledge. | ||
| 19 | 19 | ||
| 20 | 20 | ||
| 21 | 21 | ## Screenshots | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -30,8 +30,9 @@ import ( | |||
| 30 | 30 | // it into the global configuration. | |
| 31 | 31 | func NewFile(fileContent io.Reader, fileHeader *multipart.FileHeader, uploadRequest models.UploadRequest) (models.File, error) { | |
| 32 | 32 | id := helper.GenerateRandomString(configuration.GetLengthId()) | |
| 33 | + var hasBeenRenamed bool | ||
| 33 | 34 | reader, hash, tempFile := generateHash(fileContent, fileHeader, uploadRequest) | |
| 34 | - defer deleteTempFile(tempFile) | ||
| 35 | + defer deleteTempFile(tempFile, &hasBeenRenamed) | ||
| 35 | 36 | file := models.File{ | |
| 36 | 37 | Id: id, | |
| 37 | 38 | Name: fileHeader.Filename, | |
@@ -50,36 +51,46 @@ func NewFile(fileContent io.Reader, fileHeader *multipart.FileHeader, uploadRequ | |||
| 50 | 51 | file.AwsBucket = settings.AwsBucket | |
| 51 | 52 | settings.Files[id] = file | |
| 52 | 53 | configuration.ReleaseAndSave() | |
| 53 | - if !aws.IsCredentialProvided(false) { | ||
| 54 | - if !helper.FileExists(dataDir + "/" + file.SHA256) { | ||
| 55 | - destinationFile, err := os.OpenFile(filename, os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0644) | ||
| 56 | - if err != nil { | ||
| 57 | - return models.File{}, err | ||
| 58 | - } | ||
| 59 | - defer destinationFile.Close() | ||
| 60 | - _, err = io.Copy(destinationFile, reader) | ||
| 61 | - if err != nil { | ||
| 62 | - return models.File{}, err | ||
| 63 | - } | ||
| 64 | - } | ||
| 65 | - } else { | ||
| 54 | + if aws.IsCredentialProvided(false) { | ||
| 66 | 55 | _, err := aws.Upload(reader, file) | |
| 67 | 56 | if err != nil { | |
| 68 | 57 | return models.File{}, err | |
| 69 | 58 | } | |
| 59 | + return file, nil | ||
| 60 | + } | ||
| 61 | + if !helper.FileExists(dataDir + "/" + file.SHA256) { | ||
| 62 | + if tempFile != nil { | ||
| 63 | + err := tempFile.Close() | ||
| 64 | + helper.Check(err) | ||
| 65 | + err = os.Rename(tempFile.Name(), dataDir+"/"+file.SHA256) | ||
| 66 | + helper.Check(err) | ||
| 67 | + hasBeenRenamed = true | ||
| 68 | + return file, nil | ||
| 69 | + } | ||
| 70 | + destinationFile, err := os.OpenFile(filename, os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0644) | ||
| 71 | + if err != nil { | ||
| 72 | + return models.File{}, err | ||
| 73 | + } | ||
| 74 | + defer destinationFile.Close() | ||
| 75 | + _, err = io.Copy(destinationFile, reader) | ||
| 76 | + if err != nil { | ||
| 77 | + return models.File{}, err | ||
| 78 | + } | ||
| 70 | 79 | } | |
| 71 | 80 | return file, nil | |
| 72 | 81 | } | |
| 73 | 82 | ||
| 74 | - func deleteTempFile(file *os.File) { | ||
| 75 | - if file == nil { | ||
| 76 | - return | ||
| 83 | + func deleteTempFile(file *os.File, hasBeenRenamed *bool) { | ||
| 84 | + if file != nil && !*hasBeenRenamed { | ||
| 85 | + err := file.Close() | ||
| 86 | + helper.Check(err) | ||
| 87 | + err = os.Remove(file.Name()) | ||
| 88 | + helper.Check(err) | ||
| 77 | 89 | } | |
| 78 | - file.Close() | ||
| 79 | - err := os.Remove(file.Name()) | ||
| 80 | - helper.Check(err) | ||
| 81 | 90 | } | |
| 82 | 91 | ||
| 92 | + // Generates the SHA1 hash of an uploaded file and returns a reader for the file, the hash and if a temporary file was created the | ||
| 93 | + // reference to that file. | ||
| 83 | 94 | func generateHash(fileContent io.Reader, fileHeader *multipart.FileHeader, uploadRequest models.UploadRequest) (io.Reader, []byte, *os.File) { | |
| 84 | 95 | hash := sha1.New() | |
| 85 | 96 | if fileHeader.Size <= int64(uploadRequest.MaxMemory)*1024*1024 { | |
@@ -90,12 +101,12 @@ func generateHash(fileContent io.Reader, fileHeader *multipart.FileHeader, uploa | |||
| 90 | 101 | } | |
| 91 | 102 | tempFile, err := os.CreateTemp(uploadRequest.DataDir, "upload") | |
| 92 | 103 | helper.Check(err) | |
| 93 | - _, err = io.Copy(tempFile, fileContent) | ||
| 94 | - helper.Check(err) | ||
| 95 | - _, err = io.Copy(hash, tempFile) | ||
| 104 | + multiWriter := io.MultiWriter(tempFile, hash) | ||
| 105 | + _, err = io.Copy(multiWriter, fileContent) | ||
| 96 | 106 | helper.Check(err) | |
| 97 | 107 | _, err = tempFile.Seek(0, io.SeekStart) | |
| 98 | 108 | helper.Check(err) | |
| 109 | + // Instead of returning a reference to the file as the 3rd result, one could use reflections. However that would be more expensive. | ||
| 99 | 110 | return tempFile, hash.Sum(nil), tempFile | |
| 100 | 111 | } | |
| 101 | 112 | ||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -8,6 +8,7 @@ import ( | |||
| 8 | 8 | "Gokapi/internal/test" | |
| 9 | 9 | "Gokapi/internal/test/testconfiguration" | |
| 10 | 10 | "bytes" | |
| 11 | + "io" | ||
| 11 | 12 | "io/ioutil" | |
| 12 | 13 | "mime/multipart" | |
| 13 | 14 | "net/http/httptest" | |
@@ -116,10 +117,17 @@ func TestNewFile(t *testing.T) { | |||
| 116 | 117 | MaxMemory: 10, | |
| 117 | 118 | DataDir: "test/data", | |
| 118 | 119 | } | |
| 120 | + // Also testing renaming of temp file | ||
| 119 | 121 | file, err = NewFile(bigFile, &header, request) | |
| 120 | 122 | test.IsNil(t, err) | |
| 121 | 123 | test.IsEqualString(t, file.Name, "bigfile") | |
| 122 | - test.IsEqualString(t, file.SHA256, "da39a3ee5e6b4b0d3255bfef95601890afd80709") | ||
| 124 | + test.IsEqualString(t, file.SHA256, "9674344c90c2f0646f0b78026e127c9b86e3ad77") | ||
| 125 | + test.IsEqualString(t, file.Size, "20.0 MB") | ||
| 126 | + _, err = bigFile.Seek(0, io.SeekStart) | ||
| 127 | + test.IsNil(t, err) | ||
| 128 | + // Testing removal of temp file | ||
| 129 | + test.IsEqualString(t, file.Name, "bigfile") | ||
| 130 | + test.IsEqualString(t, file.SHA256, "9674344c90c2f0646f0b78026e127c9b86e3ad77") | ||
| 123 | 131 | test.IsEqualString(t, file.Size, "20.0 MB") | |
| 124 | 132 | bigFile.Close() | |
| 125 | 133 | os.Remove("bigfile") | |
@@ -129,7 +137,7 @@ func TestNewFile(t *testing.T) { | |||
| 129 | 137 | file, err = NewFile(bytes.NewReader(content), &header, request) | |
| 130 | 138 | test.IsNil(t, err) | |
| 131 | 139 | test.IsEqualString(t, file.Name, "bigfile") | |
| 132 | - test.IsEqualString(t, file.SHA256, "da39a3ee5e6b4b0d3255bfef95601890afd80709") | ||
| 140 | + test.IsEqualString(t, file.SHA256, "f1474c19eff0fc8998fa6e1b1f7bf31793b103a6") | ||
| 133 | 141 | test.IsEqualString(t, file.Size, "20.0 MB") | |
| 134 | 142 | testconfiguration.DisableS3() | |
| 135 | 143 | } | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -18,17 +18,20 @@ import ( | |||
| 18 | 18 | ||
| 19 | 19 | type MockT interface { | |
| 20 | 20 | Errorf(format string, args ...interface{}) | |
| 21 | + Helper() | ||
| 21 | 22 | } | |
| 22 | 23 | ||
| 23 | 24 | // IsEqualString fails test if got and want are not identical | |
| 24 | 25 | func IsEqualString(t MockT, got, want string) { | |
| 26 | + t.Helper() | ||
| 25 | 27 | if got != want { | |
| 26 | 28 | t.Errorf("Assertion failed, got: %s, want: %s.", got, want) | |
| 27 | 29 | } | |
| 28 | 30 | } | |
| 29 | 31 | ||
| 30 | 32 | // ResponseBodyContains fails test if http response does contain string | |
| 31 | 33 | func ResponseBodyContains(t MockT, got *httptest.ResponseRecorder, want string) { | |
| 34 | + t.Helper() | ||
| 32 | 35 | result, _ := io.ReadAll(got.Result().Body) | |
| 33 | 36 | if !strings.Contains(string(result), want) { | |
| 34 | 37 | t.Errorf("Assertion failed, got: %s, want: %s.", got, want) | |
@@ -37,55 +40,63 @@ func ResponseBodyContains(t MockT, got *httptest.ResponseRecorder, want string) | |||
| 37 | 40 | ||
| 38 | 41 | // IsNotEqualString fails test if got and want are not identical | |
| 39 | 42 | func IsNotEqualString(t MockT, got, want string) { | |
| 43 | + t.Helper() | ||
| 40 | 44 | if got == want { | |
| 41 | 45 | t.Errorf("Assertion failed, got: %s, want: not %s.", got, want) | |
| 42 | 46 | } | |
| 43 | 47 | } | |
| 44 | 48 | ||
| 45 | 49 | // IsEqualBool fails test if got and want are not identical | |
| 46 | 50 | func IsEqualBool(t MockT, got, want bool) { | |
| 51 | + t.Helper() | ||
| 47 | 52 | if got != want { | |
| 48 | 53 | t.Errorf("Assertion failed, got: %t, want: %t.", got, want) | |
| 49 | 54 | } | |
| 50 | 55 | } | |
| 51 | 56 | ||
| 52 | 57 | // IsEqualInt fails test if got and want are not identical | |
| 53 | 58 | func IsEqualInt(t MockT, got, want int) { | |
| 59 | + t.Helper() | ||
| 54 | 60 | if got != want { | |
| 55 | 61 | t.Errorf("Assertion failed, got: %d, want: %d.", got, want) | |
| 56 | 62 | } | |
| 57 | 63 | } | |
| 58 | 64 | ||
| 59 | 65 | // IsNotEmpty fails test if string is empty | |
| 60 | 66 | func IsNotEmpty(t MockT, s string) { | |
| 67 | + t.Helper() | ||
| 61 | 68 | if s == "" { | |
| 62 | 69 | t.Errorf("Assertion failed, got: %s, want: empty.", s) | |
| 63 | 70 | } | |
| 64 | 71 | } | |
| 65 | 72 | ||
| 66 | 73 | // IsEmpty fails test if string is not empty | |
| 67 | 74 | func IsEmpty(t MockT, s string) { | |
| 75 | + t.Helper() | ||
| 68 | 76 | if s != "" { | |
| 69 | 77 | t.Errorf("Assertion failed, got: %s, want: empty.", s) | |
| 70 | 78 | } | |
| 71 | 79 | } | |
| 72 | 80 | ||
| 73 | 81 | // IsNil fails test if error not nil | |
| 74 | 82 | func IsNil(t MockT, got error) { | |
| 83 | + t.Helper() | ||
| 75 | 84 | if got != nil { | |
| 76 | 85 | t.Errorf("Assertion failed, got: %s, want: nil.", got.(error).Error()) | |
| 77 | 86 | } | |
| 78 | 87 | } | |
| 79 | 88 | ||
| 80 | 89 | // IsNotNil fails test if error is nil | |
| 81 | 90 | func IsNotNil(t MockT, got error) { | |
| 91 | + t.Helper() | ||
| 82 | 92 | if got == nil { | |
| 83 | 93 | t.Errorf("Assertion failed, got: nil, want: not nil.") | |
| 84 | 94 | } | |
| 85 | 95 | } | |
| 86 | 96 | ||
| 87 | 97 | // HttpPageResult tests if a http server is outputting the correct result | |
| 88 | 98 | func HttpPageResult(t MockT, config HttpTestConfig) []*http.Cookie { | |
| 99 | + t.Helper() | ||
| 89 | 100 | config.init(t) | |
| 90 | 101 | client := &http.Client{} | |
| 91 | 102 | ||
@@ -148,6 +159,7 @@ type HttpTestConfig struct { | |||
| 148 | 159 | } | |
| 149 | 160 | ||
| 150 | 161 | func (c *HttpTestConfig) init(t MockT) { | |
| 162 | + t.Helper() | ||
| 151 | 163 | if c.Url == "" { | |
| 152 | 164 | t.Errorf("No url passed!") | |
| 153 | 165 | } | |
@@ -183,6 +195,7 @@ type PostBody struct { | |||
| 183 | 195 | ||
| 184 | 196 | // HttpPostRequest sends a post request | |
| 185 | 197 | func HttpPostRequest(t MockT, config HttpTestConfig) { | |
| 198 | + t.Helper() | ||
| 186 | 199 | file, err := os.Open(config.UploadFileName) | |
| 187 | 200 | IsNil(t, err) | |
| 188 | 201 | defer file.Close() | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -23,6 +23,8 @@ type MockTest struct { | |||
| 23 | 23 | func (t MockTest) Errorf(format string, args ...interface{}) { | |
| 24 | 24 | isFailed = true | |
| 25 | 25 | } | |
| 26 | + func (t MockTest) Helper() { | ||
| 27 | + } | ||
| 26 | 28 | ||
| 27 | 29 | func (t *MockTest) WantFail() { | |
| 28 | 30 | t.Check() | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -29,6 +29,7 @@ func isCertificatePresent() bool { | |||
| 29 | 29 | return helper.FileExists(certificate) && helper.FileExists(key) | |
| 30 | 30 | } | |
| 31 | 31 | ||
| 32 | + // GetCertificateLocations returns the filepath of the public certificate and private key | ||
| 32 | 33 | func GetCertificateLocations() (string, string) { | |
| 33 | 34 | if configDir == "" { | |
| 34 | 35 | env := environment.New() | |
@@ -37,16 +38,17 @@ func GetCertificateLocations() (string, string) { | |||
| 37 | 38 | return configDir + "/ssl.crt", configDir + "/ssl.key" | |
| 38 | 39 | } | |
| 39 | 40 | ||
| 41 | + // GenerateIfInvalidCert checks validity of the SSL certificate and generates a new one if none is present or if it is expired | ||
| 40 | 42 | func GenerateIfInvalidCert(extUrl string, forceGeneration bool) { | |
| 41 | 43 | if !isCertificatePresent() || forceGeneration { | |
| 42 | 44 | generateCertificates(extUrl) | |
| 43 | 45 | } else { | |
| 44 | 46 | days := getDaysRemaining() | |
| 45 | - if days < 15 { | ||
| 46 | - fmt.Println("Certificate is valid for less than 15 days.") | ||
| 47 | + if days < 8 { | ||
| 48 | + fmt.Println("Certificate is valid for less than 8 days.") | ||
| 47 | 49 | generateCertificates(extUrl) | |
| 48 | 50 | } else { | |
| 49 | - fmt.Printf("Certificate is valid for %d days. A new one will be generated 14 days before expiration.\n", days) | ||
| 51 | + fmt.Printf("Certificate is valid for %d days. A new one will be generated 7 days before expiration.\n", days) | ||
| 50 | 52 | } | |
| 51 | 53 | } | |
| 52 | 54 | } | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -69,6 +69,3 @@ func TestGenerateIfInvalidCert(t *testing.T) { | |||
| 69 | 69 | GenerateIfInvalidCert("http://127.0.0.1/", false) | |
| 70 | 70 | test.IsEqualInt(t, getDaysRemaining(), 365) | |
| 71 | 71 | } | |
| 72 | - | ||
| 73 | - // fingerprint 79294C898BB086DCCC8CCA1509849F482A4981978907A00E7BD1DE86B4B87F4F | ||
| 74 | - // valid until | ||
| Back | FazBrowse Home | New Git URL |
0 commit comments