feat: files up to 512 MB as streams, a code editor with highlighting and find/replace, media preview, hex editing; touch selection in the terminal (0.0.7)

This commit is contained in:
redtea committed 2026-10-14 15:52:38 +03:00
1 parent 3e46116a9b
commit e1f5595afc
14 files changed
+1178 -94

No files matched your search

-44
View File
@@ -1,11 +1,8 @@
package server
import (
"encoding/base64"
"encoding/json"
"io"
"net/http"
"path"
"time"
"github.com/x-grk/longpolling-remote-access/internal/proto"
@@ -73,44 +70,3 @@ func (s *Server) handleFSOp(w http.ResponseWriter, r *http.Request) {
writeJSON(w, proto.TaskResult{Error: "таймаут ожидания агента"})
}
}
// GET /api/panel/agents/{id}/fs/download?path=... - stream a file as a download.
func (s *Server) handleFSDownload(w http.ResponseWriter, r *http.Request) {
agentID := r.PathValue("id")
p := r.URL.Query().Get("path")
a, err := s.db.GetAgent(agentID)
if err != nil || a == nil {
http.NotFound(w, r)
return
}
if !s.online(a) {
http.Error(w, "машина офлайн", http.StatusServiceUnavailable)
return
}
args, _ := json.Marshal(proto.FSPathArgs{Path: p})
taskID, ch := s.hub.CreateTask(agentID, proto.TaskFSDownload, args)
defer s.hub.DiscardTask(taskID)
select {
case res := <-ch:
if !res.OK {
http.Error(w, res.Error, http.StatusBadGateway)
return
}
var rr proto.FSReadResult
if err := json.Unmarshal(res.Data, &rr); err != nil {
http.Error(w, "bad result", http.StatusBadGateway)
return
}
data, _ := base64.StdEncoding.DecodeString(rr.Content)
name := path.Base(p)
w.Header().Set("Content-Type", "application/octet-stream")
w.Header().Set("Content-Disposition", "attachment; filename=\""+name+"\"")
if rr.Truncated {
w.Header().Set("X-Truncated", "1")
}
_, _ = w.Write(data)
case <-time.After(fsTaskTimeout):
http.Error(w, "таймаут ожидания агента", http.StatusGatewayTimeout)
}
}