func transferFile(typeName, method string, typeID uint8, o *overlay.Overlay) dom.Node { name := xform.InputText("name", "") url := xform.InputRadio("url", "switch", true) upload := xform.InputRadio("upload", "switch", false) fileI := xform.InputUpload("") urlI := xform.InputURL("", "") s := xform.InputSubmit(method) name.Required = true typeFunc := func(dom.Event) { if url.Checked { urlI.Style().RemoveProperty("display") fileI.Style().SetProperty("display", "none", "") urlI.Required = true fileI.Required = false fileI.SetID("") urlI.SetID("file") } else { fileI.Style().RemoveProperty("display") urlI.Style().SetProperty("display", "none", "") fileI.Required = true urlI.Required = false urlI.SetID("") fileI.SetID("file") } } typeFunc(nil) url.AddEventListener("change", false, typeFunc) upload.AddEventListener("change", false, typeFunc) f := xjs.AppendChildren(xdom.Form(), xjs.AppendChildren(xdom.Fieldset(), xjs.SetInnerText(xdom.Legend(), method+" "+typeName), xform.Label(typeName+" Name", "name"), name, xdom.Br(), xform.Label("URL", "url"), url, xdom.Br(), xform.Label("Upload", "upload"), upload, xdom.Br(), xform.Label("File", "file"), fileI, urlI, xdom.Br(), s, )) s.AddEventListener("click", false, func(e dom.Event) { if name.Value == "" { return } if url.Checked { if urlI.Value == "" { return } } else if len(fileI.Files()) != 1 { return } s.Disabled = true name.Disabled = true url.Disabled = true upload.Disabled = true fileI.Disabled = true urlI.Disabled = true e.PreventDefault() go func() { d := xdom.Div() uo := overlay.New(d) uo.OnClose(func() { o.Close() }) xjs.Body().AppendChild(uo) status := xdom.Div() d.AppendChild(xjs.SetInnerText(status, "Transferring...")) conn, err := websocket.Dial("ws://" + js.Global.Get("location").Get("host").String() + "/transfer") if err != nil { xjs.SetInnerText(status, err.Error()) return } defer conn.Close() w := byteio.StickyWriter{Writer: byteio.LittleEndianWriter{Writer: conn}} r := byteio.StickyReader{Reader: byteio.LittleEndianReader{Reader: conn}} pb := progress.New(color.RGBA{255, 0, 0, 0}, color.RGBA{0, 0, 255, 0}, 400, 50) d.AppendChild(pb) if url.Checked { w.WriteUint8(typeID << 1) data.WriteString(&w, urlI.Value) length := int(r.ReadInt32()) total := 0 for total < length { switch v := r.ReadUint8(); v { case 1: i := int(r.ReadInt32()) total += i pb.Percent(100 * total / length) default: xjs.SetInnerText(status, ReadError(&r).Error()) return } } } else { f := files.NewFileReader(files.NewFile(fileI.Files()[0])) l := f.Len() if l == 0 { xjs.SetInnerText(status, "Zero-length file") return } w.WriteUint8(typeID<<1 | 1) w.WriteInt32(int32(l)) io.Copy(&w, pb.Reader(f, l)) } d.RemoveChild(pb) xjs.SetInnerText(status, "Checking File") data.WriteString(&w, name.Value) var ctx *dom.CanvasRenderingContext2D for { switch v := r.ReadUint8(); v { case 0: if r.Err != nil { xjs.SetInnerText(status, r.Err.Error()) } else { xjs.SetInnerText(status, ReadError(&r).Error()) } return case 1: files := make([]xform.Option, r.ReadInt16()) for i := range files { files[i] = xform.Option{ Value: strconv.Itoa(i), Label: data.ReadString(&r), } } j := xform.SelectBox("files", files...) sel := xjs.SetInnerText(xdom.Button(), "Select") fo := overlay.New(xjs.AppendChildren(xdom.Div(), xjs.AppendChildren(xdom.Fieldset(), xjs.SetInnerText(xdom.Legend(), "Please select the "+typeName+" file"), xform.Label("File", "files"), j, xdom.Br(), sel, ))) c := make(chan int16, 0) done := false fo.OnClose(func() { if !done { done = true c <- -1 } }) sel.AddEventListener("click", false, func(dom.Event) { if !done { done = true v, err := strconv.Atoi(j.Value) if err != nil { v = -1 } c <- int16(v) fo.Close() } }) xjs.Body().AppendChild(fo) w.WriteInt16(<-c) close(c) case 2: w := r.ReadInt32() h := r.ReadInt32() canvas := xdom.Canvas() canvas.Width = int(w) * 8 canvas.Height = int(h) * 8 d.AppendChild(canvas) ctx = canvas.GetContext2d() ctx.Scale(8, 8) case 3: xjs.SetInnerText(status, data.ReadString(&r)) case 4: x := r.ReadInt32() y := r.ReadInt32() red := r.ReadUint8() green := r.ReadUint8() blue := r.ReadUint8() alpha := r.ReadUint8() ctx.FillStyle = "rgba(" + strconv.Itoa(int(red)) + ", " + strconv.Itoa(int(green)) + ", " + strconv.Itoa(int(blue)) + ", " + strconv.FormatFloat(float64(alpha)/255, 'f', -1, 32) + ")" ctx.FillRect(int(x), int(y), 1, 1) case 255: uo.Close() return } } }() }) return f }
func (t Transfer) generator(name string, r *byteio.StickyReader, w *byteio.StickyWriter, f *os.File, size int64) error { g := t.c.Generators.New(t.c.Settings().DirGenerators) if g == nil { return errors.New("error creating generator") } g.Name = name done := false defer func() { if !done { t.c.RemoveGenerator(g.ID) } go t.c.Save() }() zr, err := zip.NewReader(f, size) if err != nil { f.Seek(0, 0) e := json.NewDecoder(f).Decode(new(data.GeneratorData)) if e != nil { return err } err = moveFile(f.Name(), path.Join(g.Path, "data.gen")) if err != nil { return err } done = true return nil } gens := make([]*zip.File, 0, 16) for _, file := range zr.File { if file.Name == "data.gen" { gens = []*zip.File{file} break } if strings.HasSuffix(file.Name, ".gen") || strings.HasSuffix(file.Name, ".json") { gens = append(gens, file) } } if len(gens) == 0 { return errors.New("cannot find generator data in zip") } if len(gens) > 1 { w.WriteUint8(1) w.WriteInt16(int16(len(gens))) for _, gen := range gens { data.WriteString(w, gen.Name) } if w.Err != nil { return w.Err } p := r.ReadInt16() if r.Err != nil { return r.Err } if int(p) >= len(gens) || p < 0 { return errors.New("error selecting generator data") } gens[0] = gens[p] } gd, err := gens[0].Open() if err != nil { return err } err = json.NewDecoder(gd).Decode(new(data.GeneratorData)) if err != nil { return err } err = unzip(zr, g.Path) if err != nil { return err } err = os.Rename(path.Join(g.Path, gens[0].Name), path.Join(g.Path, "data.gen")) if err != nil { return err } done = true return nil }
func (t Transfer) server(name string, r *byteio.StickyReader, w *byteio.StickyWriter, f *os.File, size int64) error { zr, err := zip.NewReader(f, size) if err != nil { return err } jars := make([]*zip.File, 0, 16) for _, file := range zr.File { if file.Name == "server.jar" { jars = []*zip.File{file} break } if strings.HasSuffix(file.Name, ".jar") { jars = append(jars, file) } } s := t.c.NewServer() done := false defer func() { if !done { t.c.RemoveServer(s.ID) } go t.c.Save() }() if s == nil { return errors.New("error creating server") } s.Lock() s.Name = name d := s.Path s.Unlock() if len(jars) == 0 { err = moveFile(f.Name(), path.Join(d, "server.jar")) } else { if len(jars) > 1 { w.WriteUint8(1) w.WriteInt16(int16(len(jars))) for _, jar := range jars { data.WriteString(w, jar.Name) } if w.Err != nil { return w.Err } p := r.ReadInt16() if r.Err != nil { return r.Err } if int(p) >= len(jars) || p < 0 { return errors.New("error selecting server jar") } jars[0] = jars[p] } if err == nil { err = unzip(zr, d) if err == nil { err = os.Rename(path.Join(d, jars[0].Name), path.Join(d, "server.jar")) } } } if err != nil { return err } serverProperties := DefaultServerSettings() ps, err := os.OpenFile(path.Join(d, "properties.server"), os.O_WRONLY|os.O_CREATE|os.O_EXCL, 0644) defer ps.Close() if err != nil { if !os.IsExist(err) { return err } } else { err = serverProperties.WriteTo(ps) if err != nil { return err } } done = true return nil }
func (t Transfer) generate(name string, r *byteio.StickyReader, w *byteio.StickyWriter, f *os.File, size int64) error { gp.Add(1) defer gp.Done() mp := t.c.NewMap() if mp == nil { return errors.New("failed to create map") } done := false defer func() { if !done { t.c.RemoveMap(mp.ID) } t.c.Save() }() mp.Lock() mp.Name = name mapPath := mp.Path mp.Server = -2 mp.Unlock() t.c.Generators.mu.RLock() gs := make([]data.Generator, len(t.c.Generators.List)) for n, g := range t.c.Generators.List { gs[n] = *g } t.c.Generators.mu.RUnlock() var g data.Generator if len(gs) == 0 { return errors.New("no generators installed") } else if len(gs) == 1 { g = gs[0] } else { w.WriteUint8(1) w.WriteInt16(int16(len(gs))) for _, tg := range gs { data.WriteString(w, tg.Name) } if w.Err != nil { return w.Err } gID := r.ReadInt16() if r.Err != nil { return r.Err } if gID < 0 || int(gID) >= len(gs) { return errors.New("unknown generator") } g = gs[gID] } ms := DefaultMapSettings() ms["level-type"] = minecraft.FlatGenerator ms["generator-settings"] = "0" ms["motd"] = name j, err := os.Open(path.Join(g.Path, "data.gen")) if err != nil { return err } var gj data.GeneratorData err = json.NewDecoder(j).Decode(&gj) j.Close() if err != nil { return err } for k, v := range gj.Options { ms[k] = v } pf, err := os.Create(path.Join(mapPath, "properties.map")) if err != nil { return err } if err = ms.WriteTo(pf); err != nil { return err } pf.Close() cmd := exec.Command(t.c.Settings().GeneratorExecutable) cmd.ExtraFiles = append(cmd.ExtraFiles, f) cmd.Dir, err = os.Getwd() if err != nil { return err } cmd.Stdout = w pw, err := cmd.StdinPipe() if err != nil { return err } err = gp.Start(cmd) if err != nil { return err } defer gp.Remove(cmd) pww := byteio.StickyWriter{Writer: &byteio.LittleEndianWriter{pw}} pww.WriteUint64(t.c.Settings().GeneratorMaxMem) pww.WriteInt64(size) data.WriteString(&pww, g.Path) data.WriteString(&pww, name) data.WriteString(&pww, mapPath) if pww.Err != nil { return pww.Err } err = cmd.Wait() if err != nil { return err } done = true mp.Lock() mp.Server = -1 mp.Unlock() return nil }