Ejemplo n.º 1
0
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
	}
}
Ejemplo n.º 2
0
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
}
Ejemplo n.º 3
0
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)
	}
}
Ejemplo n.º 4
0
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
}
Ejemplo n.º 5
0
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")
}
Ejemplo n.º 6
0
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
}
Ejemplo n.º 7
0
// 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
	}
}
Ejemplo n.º 8
0
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
}