You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

268 lines
6.1 KiB

package files
import (
"encoding/base64"
"fmt"
"godo/libs"
"io"
"net/http"
"os"
"path/filepath"
"strings"
"sync"
)
// 全局变量来存储 key 和 path 的映射关系
var OnlyOfficekeyPathMap = make(map[string]string)
var mapOnlyOfficeMutex sync.Mutex
func HandleReadFile(w http.ResponseWriter, r *http.Request) {
path := r.URL.Query().Get("path")
//log.Printf("read file: %s", path)
if path == "" {
libs.ErrorMsg(w, "文件路径不能为空")
return
}
stream := r.URL.Query().Get("stream")
isStream := false
if stream != "" {
isStream = true
mapOnlyOfficeMutex.Lock()
OnlyOfficekeyPathMap[stream] = path
mapOnlyOfficeMutex.Unlock()
}
basePath, err := libs.GetOsDir()
if err != nil {
libs.ErrorMsg(w, err.Error())
return
}
fullFilePath := filepath.Join(basePath, path)
file, err := os.Open(fullFilePath)
if err != nil {
libs.ErrorMsg(w, err.Error())
return
}
fileData, err := io.ReadAll(file)
if err != nil {
libs.ErrorMsg(w, err.Error())
return
}
text := string(fileData)
//log.Printf("isPwd: %v", strData)
if strings.HasPrefix(text, "link::") {
libs.SuccessMsg(w, text, "文件读取成功")
return
}
// 判断是否为加密文件
isPwd := libs.IsEncryptedFile(text)
if !isPwd {
// 未加密文件,直接返回
if isStream {
w.Header().Set("Content-Type", "application/octet-stream")
_, err := w.Write(fileData)
if err != nil {
libs.ErrorMsg(w, err.Error())
return
}
} else {
if len(fileData) > 0 {
text = base64.StdEncoding.EncodeToString(fileData)
}
//text = base64.StdEncoding.EncodeToString(fileData)
libs.SuccessMsg(w, text, "文件读取成功")
}
return
}
filePwd := r.Header.Get("pwd")
// 获取文件密钥
fileSecret := libs.GetConfigString("filePwd")
if filePwd == "" && fileSecret == "" {
libs.Error(w, "加密文件,需要密码", "needPwd")
return
}
decodeFile := ""
needPwd := false
if fileSecret != "" {
decodeFile, err = libs.DecodeFile(fileSecret, text)
if err != nil {
libs.Error(w, "请输入文件密码", "needPwd")
return
}
needPwd = true
}
if filePwd != "" && !needPwd {
decodeFile, err = libs.DecodeFile(filePwd, text)
if err != nil {
libs.Error(w, "文件密码输入错误", "needPwd")
return
}
}
if isStream {
w.Header().Set("Content-Type", "application/octet-stream")
_, err := w.Write([]byte(decodeFile))
if err != nil {
libs.ErrorMsg(w, err.Error())
return
}
} else {
if len(decodeFile) > 0 {
decodeFile = base64.StdEncoding.EncodeToString([]byte(decodeFile))
}
libs.SuccessMsg(w, decodeFile, "加密文件读取成功")
}
}
func HandleWriteFile(w http.ResponseWriter, r *http.Request) {
path := r.URL.Query().Get("path")
if err := validateFilePath(path); err != nil {
libs.HTTPError(w, http.StatusBadRequest, err.Error())
return
}
basePath, err := libs.GetOsDir()
if err != nil {
libs.HTTPError(w, http.StatusInternalServerError, err.Error())
return
}
fullFilePath := filepath.Join(basePath, path)
// 获取文件内容
fileContent, _, err := r.FormFile("content")
if err != nil {
libs.HTTPError(w, http.StatusBadRequest, err.Error())
return
}
defer fileContent.Close()
content, err := io.ReadAll(fileContent)
if err != nil {
libs.HTTPError(w, http.StatusInternalServerError, err.Error())
return
}
// 打开文件,如果不存在则创建
file, err := os.OpenFile(fullFilePath, os.O_RDWR|os.O_CREATE, 0644)
if err != nil {
libs.ErrorMsg(w, "Failed to create file.")
return
}
defer file.Close()
oldContent, err := io.ReadAll(file)
text := string(oldContent)
//log.Printf("text: %s", text)
if err != nil {
libs.ErrorMsg(w, err.Error())
return
}
isPwdFile := libs.IsEncryptedFile(text)
filePwd := r.Header.Get("pwd")
// 获取文件密钥
fileSecret := libs.GetConfigString("filePwd")
haslink := strings.HasPrefix(string(content), "link::")
//log.Printf("haslink:%v,fileSecret: %s,isPwdFile:%v,filePwd:%s", haslink, fileSecret, isPwdFile, filePwd)
needPwd := false
if fileSecret != "" || filePwd != "" {
needPwd = true
}
if isPwdFile {
needPwd = true
}
if haslink {
needPwd = false
}
//log.Printf("needPwd:%v", needPwd)
// 即不是加密用户又不是加密文件
if !needPwd {
// 直接写入新内容
file.Truncate(0)
file.Seek(0, 0)
//log.Printf("write file content%v", content)
_, err = file.Write(content)
if err != nil {
libs.ErrorMsg(w, "Failed to write file content.")
return
}
CheckAddDesktop(path)
libs.SuccessMsg(w, "", "文件写入成功")
return
}
//log.Printf("fileSecret:%s,filePwd:%s,ispwdfile:%v", fileSecret, filePwd, isPwdFile)
// 是加密文件,写入需继续加密
pwd := ""
if isPwdFile {
//先尝试系统解密
if fileSecret != "" {
_, err := libs.DecodeFile(fileSecret, text)
if err == nil {
pwd = fileSecret
}
}
//先用户输入解密
if pwd == "" && filePwd != "" {
_, err := libs.DecodeFile(filePwd, text)
if err == nil {
pwd = filePwd
}
}
} else {
// 不是加密文件,先判断是否有用户输入
if filePwd != "" {
pwd = filePwd
} else {
// 没有用户输入,则使用系统默认密码
if fileSecret != "" {
pwd = fileSecret
}
}
}
if pwd == "" {
libs.Error(w, "文件密码错误", "needPwd")
//log.Printf("pwd is empty, returning error")
return
}
//log.Printf("pwd: %s", pwd)
encryData, err := libs.EncodeFile(pwd, string(content))
if err != nil {
libs.ErrorMsg(w, err.Error())
return
}
// 清空文件内容
file.Truncate(0)
file.Seek(0, 0)
_, err = file.Write([]byte(encryData))
if err != nil {
libs.ErrorMsg(w, fmt.Sprintf("文件内容写入失败: %s", err.Error()))
return
}
CheckAddDesktop(path)
libs.SuccessMsg(w, "", "文件写入成功")
}
func HandleSetFilePwd(w http.ResponseWriter, r *http.Request) {
Pwd := r.Header.Get("Pwd")
if Pwd == "" {
err := libs.DeleteConfig("filePwd")
if err != nil {
libs.ErrorMsg(w, fmt.Sprintf("取消加密失败:%s", err.Error()))
return
}
libs.SuccessMsg(w, nil, "取消加密成功")
return
}
err := libs.SetConfigByName("filePwd", Pwd)
if err != nil {
libs.ErrorMsg(w, err.Error())
return
}
libs.SuccessMsg(w, nil, "设置密码成功")
}