1 package main 2 3 import ( 4 "net/http" 5 "os" 6 "path" 7 "sort" 8 "strconv" 9 "sync" 10 11 "vimagination.zapto.org/minewebgen/internal/data" 12 ) 13 14 type Maps struct { 15 mu sync.RWMutex 16 List []*data.Map 17 } 18 19 func (m *Maps) Get(id int) *data.Map { 20 for _, maps := range m.List { 21 if maps.ID == id { 22 return maps 23 } 24 } 25 return nil 26 } 27 28 func (m *Maps) Remove(id int) { 29 m.mu.Lock() 30 m.mu.Unlock() 31 for n, mp := range m.List { 32 if mp.ID == id { 33 copy(m.List[n:], m.List[n+1:]) 34 m.List = m.List[:len(m.List)-1] 35 os.RemoveAll(mp.Path) 36 break 37 } 38 } 39 } 40 41 func (m *Maps) Download(w http.ResponseWriter, r *http.Request) { 42 b := path.Base(r.URL.Path) 43 if len(b) < 5 || b[len(b)-4:] != ".zip" { 44 http.Error(w, "not found", http.StatusNotFound) 45 return 46 } 47 id, err := strconv.Atoi(b[:len(b)-4]) 48 if err != nil { 49 http.Error(w, "not found", http.StatusNotFound) 50 } 51 mp := m.Get(id) 52 if mp == nil { 53 http.Error(w, "unknown map", http.StatusNotFound) 54 return 55 } 56 mp.Lock() 57 defer mp.Unlock() 58 if mp.Server != -1 { 59 http.Error(w, "server attached", http.StatusBadGateway) 60 return 61 } 62 mp.Server = -2 63 mp.Unlock() 64 w.Header().Set("Content-Type", "application/zip") 65 archive(w, mp.Path) 66 mp.Lock() 67 mp.Server = -1 68 } 69 70 func (m *Maps) New(path string) *data.Map { 71 mPath := freePath(path) 72 if mPath == "" { 73 return nil 74 } 75 m.mu.Lock() 76 defer m.mu.Unlock() 77 id := len(m.List) 78 for n, mp := range m.List { 79 if n != mp.ID { 80 id = n 81 break 82 } 83 } 84 mp := &data.Map{ 85 ID: id, 86 Path: mPath, 87 Name: "New Map", 88 Server: -1, 89 } 90 m.List = append(m.List, mp) 91 sort.Sort(m) 92 return mp 93 } 94 95 func (m *Maps) Len() int { 96 return len(m.List) 97 } 98 99 func (m *Maps) Less(i, j int) bool { 100 return m.List[i].ID < m.List[j].ID 101 } 102 103 func (m *Maps) Swap(i, j int) { 104 m.List[i], m.List[j] = m.List[j], m.List[i] 105 }