func fetchFile(l *log.Logger, f types.File) ([]byte, error) { switch f.Contents.Source.Scheme { case "http": client := util.NewHttpClient(l) data, status, err := client.Get(f.Contents.Source.String()) if err != nil { return nil, err } l.Debug("GET result: %s", http.StatusText(status)) if status != http.StatusOK { return nil, ErrStatusBad } return data, nil case "data": url, err := dataurl.DecodeString(f.Contents.Source.String()) if err != nil { return nil, err } return url.Data, nil default: return nil, ErrSchemeUnsupported } }
func checkIfURLIsDataURL(testURL string, verbose bool) ([]byte, error) { // MarkerPos := strings.Index(testURL, "data:image/") MarkerPos := strings.Index(testURL, "/data:") if MarkerPos == -1 { return nil, nil } testURL = testURL[MarkerPos:] dataURL, err := dataurl.DecodeString(testURL) if err != nil { fmt.Println(err) return nil, err } if verbose { fmt.Printf("content type: %s, data size: %d\n", dataURL.MediaType.ContentType(), len(dataURL.Data)) } return dataURL.Data, nil }
func (u Url) Validate() report.Report { // Empty url is valid, indicates an empty file if u.String() == "" { return report.Report{} } switch url.URL(u).Scheme { case "http", "https", "oem": return report.Report{} case "data": if _, err := dataurl.DecodeString(u.String()); err != nil { return report.ReportFromError(err, report.EntryError) } return report.Report{} default: return report.ReportFromError(ErrInvalidScheme, report.EntryError) } }
func screeningService(ec *ab.EntityController) ab.Service { res := ab.EntityResource(ec, &Screening{}, ab.EntityResourceConfig{ DisablePost: true, DisableList: true, DisableGet: true, DisablePut: true, DisableDelete: true, }) res.ExtraEndpoints = func(srv *ab.Server) error { srv.Post("/api/walkthrough/:id/screening", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { wid := ab.GetParams(r).ByName("id") data := []string{} ab.MustDecode(r, &data) db := ab.GetDB(r) uid := ab.GetSession(r)["uid"] userEntity, err := ec.Load(db, "user", uid) ab.MaybeFail(http.StatusInternalServerError, err) user := userEntity.(*User) wt, err := LoadActualRevision(db, ec, wid) ab.MaybeFail(http.StatusBadRequest, err) if wt.UID != uid && !user.Admin { ab.Fail(http.StatusForbidden, nil) } if len(data) == 0 || len(data) != len(wt.Steps)-1 { ab.Fail(http.StatusBadRequest, fmt.Errorf("got %d images, expected: %d", len(data), len(wt.Steps)-1)) } screening := &Screening{ WID: wid, UID: uid, Steps: uint(len(wt.Steps) - 1), Created: time.Now(), Published: true, } err = ec.Insert(db, screening) ab.MaybeFail(http.StatusInternalServerError, err) images := map[string][]byte{} for i, d := range data { if d == "" { continue } dataurl, err := dataurl.DecodeString(d) if err != nil { ab.LogTrace(r).Printf("data url error: %s", dataurl) ab.Fail(http.StatusBadRequest, err) } if dataurl.ContentType() != "image/png" { ab.Fail(http.StatusBadRequest, errors.New("not a png")) } fn := screening.ScreenshotPath(uint(i)) images[fn] = dataurl.Data } if len(images) == 0 { ab.Fail(http.StatusBadRequest, errors.New("no images sent")) } for name, content := range images { if err := ioutil.WriteFile(name, content, 0644); err != nil { ab.LogUser(r).Println(err) } } ab.Render(r). SetCode(http.StatusCreated). JSON(screening) }), userLoggedInMiddleware) lock := map[string]chan struct{}{} var mtx sync.Mutex srv.Get("/api/walkthrough/:id/screening", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { wid := ab.GetParams(r).ByName("id") db := ab.GetDB(r) screening, err := LoadActualScreeningForWalkthrough(db, ec, wid) ab.MaybeFail(http.StatusInternalServerError, err) if screening == nil { ab.Fail(http.StatusNotFound, nil) } fn := screening.GIFPath() reply := func() { filelist := make([]string, int(screening.Steps)) for i := uint(0); i < screening.Steps; i++ { filelist[i] = "/" + screening.ScreenshotPath(i) } ab.Render(r).AddOffer("image/gif", func(w http.ResponseWriter) { f, err := os.Open(fn) ab.MaybeFail(http.StatusInternalServerError, err) defer f.Close() io.Copy(w, f) }).JSON(filelist) } if _, err := os.Stat(fn); err == nil { reply() return } // Short-circuits the gif generation process. // If the client wants JSON, there is no need // to go through the GIF generation, which is // an expensive process. if r.Header.Get("Accept") == "application/json" { reply() return } mtx.Lock() l, ok := lock[fn] if ok { mtx.Unlock() select { case <-l: reply() case <-time.After(5 * time.Second): w.Header().Set("Retry-After", "30") ab.Render(r).SetCode(http.StatusServiceUnavailable) } return } l = make(chan struct{}) lock[fn] = l mtx.Unlock() err = screening.createGIF(false) defer func() { mtx.Lock() delete(lock, fn) mtx.Unlock() }() if err != nil { if _, ok := err.(*os.PathError); ok { ab.Fail(http.StatusNotFound, err) } else { ab.Fail(http.StatusInternalServerError, err) } } close(l) reply() })) return nil } return res }
func Chat(session sockjs.Session) { glog.Info("Session started") sessionId := session.ID() chatSession := &ChatSession{ Id: sessionId, IsReady: false, Session: &session, } ChatSessions.Set(sessionId, chatSession) acceptedTypes := &map[string]string{ "image/jpeg": ".jpg", "image/jpg": ".jpg", "image/png": ".png", "image/gif": ".gif", } ticker := time.NewTicker(time.Second) // Not too nice, will be refactored later... online := func() { ready, chatting := ChatSessions.GetNumberOfReadyAndChatting() msg := &ChatMessage{ "event": "online", "r": ready, "c": chatting, } out, _ := json.Marshal(msg) body := string(out) session.Send(body) } go func() { for _ = range ticker.C { online() } }() online() for { if msg, err := session.Recv(); err == nil { var data ChatMessage json.Unmarshal([]byte(msg), &data) switch data["event"] { case "ready": ChatReady(sessionId, data["region"].(string)) case "typing": ChatSessions.Action(func() { chatSession.Room.BroadcastOthers(sessionId, "typing", strconv.FormatBool(data["typing"].(bool))) }) case "send": ChatSessions.Action(func() { chatSession.Room.BroadcastOthers(sessionId, "message", data["message"].(string)) }) case "exit": ChatSessions.Action(func() { glog.Info("Chat session ended") chatSession.Room.BroadcastOthers(sessionId, "exit", "") for i, _ := range chatSession.Room.Sessions { s := chatSession.Room.Sessions[i] if s != chatSession { s.Room = nil } //s.IsReady = true } chatSession.Room = nil }) case "picture": glog.Info("Picture received") ChatSessions.Action(func() { chatSession.Room.BroadcastOthers(sessionId, "picturebefore", "true") dataURL, err := dataurl.DecodeString(data["data"].(string)) if err != nil { glog.Error("Problem decoding file: ", err) } filename := helpers.GetRandomString(8) mt := dataURL.ContentType() if ext, ok := (*acceptedTypes)[mt]; ok { err = ioutil.WriteFile(MediaContent+filename+ext, dataURL.Data, 0644) if err != nil { glog.Error("Error saving file: ", err) } chatSession.Room.BroadcastOthers(sessionId, "picture", data["data"].(string)) } }) } continue } break } ticker.Stop() ChatSessions.Close(sessionId) glog.Info("Session closed") }
func UploadHandler(conn *rtgo.Conn, data []byte, msg *rtgo.Message) { schema := make(map[string]interface{}) err := json.Unmarshal(msg.Payload, &schema) if err != nil { log.Println(err) return } topic := schema["topic"].(string) now := time.Now() schema["timestamp"] = fmt.Sprintf("%d/%d/%d(%s)%d:%d:%d", now.Month(), now.Day(), now.Year(), now.Weekday().String()[:3], now.Hour(), now.Minute(), now.Second()) schema["uuid"] = uuid.NewV4().String() hash := fmt.Sprintf("%x", sha256.Sum256([]byte(fmt.Sprintf("%s%s", schema["timestamp"], schema["uuid"]))))[:9] schema["hash"] = hash if file, ok := schema["file"].(string); ok { file_path := fmt.Sprintf("./static/images/uploads/%s", schema["file_name"]) fdata, err := dataurl.DecodeString(file) if err != nil { log.Println(err) return } ioutil.WriteFile(file_path, fdata.Data, 0775) saved_file, err := os.Open(file_path) if err != nil { log.Println(err) return } var config image.Config if schema["file_mime"] == "image/jpeg" { config, err = jpeg.DecodeConfig(saved_file) } else if schema["file_mime"] == "image/png" { config, err = png.DecodeConfig(saved_file) } else if schema["file_mime"] == "image/gif" { config, err = gif.DecodeConfig(saved_file) } schema["file_dimensions"] = fmt.Sprintf("%dx%d", config.Width, config.Height) delete(schema, "file") } if schema["type"] == "thread" { if err := app.DB.InsertObj(topic, hash, schema); err != nil { return } } else if schema["type"] == "reply" { thread := schema["thread"].(string) if obj, err := app.DB.GetObj(topic, thread); err == nil { thisobj := obj.(map[string]interface{}) replies := thisobj["replies"].(map[string]interface{}) replies[hash] = schema tagging := schema["tagging"].([]interface{}) for _, tag := range tagging { if tag.(string) == thread { thisobj["taggedBy"] = append(thisobj["taggedBy"].([]interface{}), hash) } else if _, ok := replies[tag.(string)]; ok { reply := replies[tag.(string)].(map[string]interface{}) reply["taggedBy"] = append(reply["taggedBy"].([]interface{}), hash) } } if err := app.DB.InsertObj(topic, thread, thisobj); err != nil { log.Println(err) return } } else { log.Println(err) return } } payload, err := json.Marshal(&schema) if err != nil { log.Println(err) return } response := &rtgo.Message{ RoomLength: len(schema["topic"].(string)), Room: schema["topic"].(string), EventLength: len("new-" + schema["type"].(string)), Event: "new-" + schema["type"].(string), DstLength: 0, Dst: "", SrcLength: len(conn.Id), Src: conn.Id, PayloadLength: len(payload), Payload: payload, } binary_response := rtgo.MessageToBytes(response) conn.Emit(binary_response, response) conn.Send <- binary_response }
// FetchResource fetches a resource given a URL. The supported schemes are http, data, and oem. func FetchResource(l *log.Logger, u url.URL) ([]byte, error) { switch u.Scheme { case "http", "https": client := NewHttpClient(l) data, status, err := client.Get(u.String()) if err != nil { return nil, err } l.Debug("GET result: %s", http.StatusText(status)) switch status { case http.StatusOK, http.StatusNoContent: return data, nil case http.StatusNotFound: return nil, ErrNotFound default: return nil, ErrFailed } case "data": url, err := dataurl.DecodeString(u.String()) if err != nil { return nil, err } return url.Data, nil case "oem": path := filepath.Clean(u.Path) if !filepath.IsAbs(path) { l.Err("oem path is not absolute: %q", u.Path) return nil, ErrPathNotAbsolute } // check if present under oemDirPath, if so use it. absPath := filepath.Join(oemDirPath, path) data, err := ioutil.ReadFile(absPath) if os.IsNotExist(err) { l.Info("oem config not found in %q, trying %q", oemDirPath, oemMountPath) // try oemMountPath, requires mounting it. err := mountOEM(l) if err != nil { l.Err("failed to mount oem partition: %v", err) return nil, ErrFailed } absPath := filepath.Join(oemMountPath, path) data, err = ioutil.ReadFile(absPath) umountOEM(l) } else if err != nil { l.Err("failed to read oem config: %v", err) return nil, ErrFailed } return data, nil default: return nil, ErrSchemeUnsupported } }
func parseOutputOnlyFile( ctx *common.Context, data string, settings *common.ProblemSettings, ) (map[string]outputOnlyFile, error) { dataURL, err := dataurl.DecodeString(data) result := make(map[string]outputOnlyFile) if err != nil { // |data| is not a dataurl. Try just returning the data as an Entry. ctx.Log.Info("data is not a dataurl. Generating Main.out", "err", err) result["Main.out"] = outputOnlyFile{data, false} return result, nil } z, err := zip.NewReader(bytes.NewReader(dataURL.Data), int64(len(dataURL.Data))) if err != nil { ctx.Log.Warn("error reading zip", "err", err) return result, err } expectedFileNames := make(map[string]struct{}) for _, groupSettings := range settings.Cases { for _, caseSettings := range groupSettings.Cases { expectedFileNames[fmt.Sprintf("%s.out", caseSettings.Name)] = struct{}{} } } for _, f := range z.File { if !strings.HasSuffix(f.FileHeader.Name, ".out") { ctx.Log.Info( "Output-only compressed file has invalid name. Skipping", "name", f.FileHeader.Name, ) continue } // Some people just cannot follow instructions. Be a little bit more // tolerant and skip any intermediate directories. fileName := f.FileHeader.Name if idx := strings.LastIndex(fileName, "/"); idx != -1 { fileName = fileName[idx+1:] } if _, ok := expectedFileNames[fileName]; !ok { ctx.Log.Info( "Output-only compressed file not expected. Skipping", "name", f.FileHeader.Name, ) continue } if f.FileHeader.UncompressedSize64 > uint64(settings.Limits.OutputLimit) { ctx.Log.Info( "Output-only compressed file is too large. Generating empty file", "name", f.FileHeader.Name, "size", f.FileHeader.UncompressedSize64, ) result[fileName] = outputOnlyFile{"", true} continue } rc, err := f.Open() if err != nil { ctx.Log.Info( "Error opening file", "name", f.FileHeader.Name, "err", err, ) continue } defer rc.Close() var buf bytes.Buffer if _, err := io.Copy(&buf, rc); err != nil { ctx.Log.Info( "Error reading file", "name", f.FileHeader.Name, "err", err, ) continue } result[fileName] = outputOnlyFile{buf.String(), false} } return result, nil }