Exemple #1
0
// Subscribe the given UID to the notification list.
func subscribe(u config.User) bool {
	if isSubscribed(u) {
		log.Debugf("[Posts] %[1]s attempted to subscribe to the notification list, but was already subscribed", u.Name)
		return false
	}
	log.Debugf("[Posts] %[1]s successfully subscribed to the notifcation list", u.Name)
	u.SetSetting(subSetting, "true")
	config.ASave()
	return true
}
Exemple #2
0
// Unsubscribe the given UID from the notification list.
func unsubscribe(u config.User) bool {
	if !isSubscribed(u) {
		log.Debugf("[Posts] %[1]s attempted to unsubscribe from the notification list, but was not subscribed", u.Name)
		return false
	}
	log.Debugf("[Posts] %[1]s successfully unsubscribed from the notifcation list", u.Name)
	u.RemoveSetting(subSetting)
	config.ASave()
	return true
}
Exemple #3
0
func get(w http.ResponseWriter, r *http.Request) {
	if r.Method != "GET" {
		w.Header().Add("Allow", "GET")
		w.WriteHeader(http.StatusMethodNotAllowed)
		return
	}
	// Cut out the prefix slash
	path := r.URL.Path[1:]

	log.Debugf("%[1]s requested long url of %[2]s", getIP(r), path)
	url, redirect, err := data.Query(path)

	if err != nil {
		// No short url found
		log.Warnf("Failed to find redirect from short url %[2]s: %[1]s", err, path)
		writeError(w, http.StatusNotFound, "notfound", "404: %[1]s is not a valid short url", path)
		return
	}

	if redirect == "http" {
		// Short URL with HTTP redirect found.
		w.Header().Add("Location", url)
		w.WriteHeader(http.StatusFound)
	} else if redirect == "html" {
		// Short URL with HTML redirect found.
		w.WriteHeader(http.StatusOK)
		templRedirect.Execute(w, struct{ URL interface{} }{url})
	}
}
Exemple #4
0
func listen(bot *telebot.Bot) {
	reader := bufio.NewReader(os.Stdin)
	for {
		text, _ := reader.ReadString('\n')
		text = text[:len(text)-1]

		log.Debugf("[Syscmds] Received %s", text)

		args := strings.Split(text, " ")

		onCommand(bot, strings.ToLower(args[0]), args[1:])
	}
}
Exemple #5
0
// Delete handles delete requests
func Delete(w http.ResponseWriter, r *http.Request) {
	var ip = getIP(r)
	if r.Method != "POST" {
		w.Header().Add("Allow", "POST")
		w.WriteHeader(http.StatusMethodNotAllowed)
		return
	}

	// Create a json decoder for the payload.
	decoder := json.NewDecoder(r.Body)
	var dfr DeleteForm
	// Decode the payload.
	err := decoder.Decode(&dfr)
	// Check if there was an error decoding.
	if err != nil || len(dfr.ImageName) == 0 || len(dfr.Username) == 0 || len(dfr.AuthToken) == 0 {
		log.Debugf("%[1]s sent an invalid delete request.", ip)
		w.WriteHeader(http.StatusBadRequest)
		return
	}

	err = auth.CheckAuthToken(dfr.Username, []byte(dfr.AuthToken))
	// Check if the auth token was correct
	if err != nil {
		log.Debugf("%[1]s tried to authenticate as %[2]s with the wrong token.", ip, dfr.Username)
		output(w, GenericResponse{
			Success:        false,
			Status:         "invalid-authtoken",
			StatusReadable: "The authentication token was incorrect. Please try logging in again.",
		}, http.StatusUnauthorized)
		return
	}

	data, err := database.Query(dfr.ImageName)
	if err != nil {
		log.Debugf("%[1]s@%[2]s attempted to delete an image that doesn't exist.", dfr.Username, ip, data.Adder)
		output(w, GenericResponse{Success: false, Status: "not-found", StatusReadable: "The image you requested to be deleted does not exist."}, http.StatusNotFound)
		return
	}
	if data.Adder != dfr.Username {
		log.Debugf("%[1]s@%[2]s attempted to delete an image uploaded by %[3]s.", dfr.Username, ip, data.Adder)
		output(w, GenericResponse{Success: false, Status: "no-permissions",
			StatusReadable: "The image you requested to be deleted was not uploaded by you."}, http.StatusForbidden)
		return
	}

	err = database.Remove(dfr.ImageName)
	if err != nil {
		log.Warnf("Error deleting %[4]s from the database (requested by %[1]s@%[2]s): %[3]s", dfr.Username, ip, err, dfr.ImageName)
		w.WriteHeader(http.StatusInternalServerError)
		return
	}
	err = os.Remove(config.ImageLocation + "/" + dfr.ImageName + "." + data.Format)
	if err != nil {
		// If the file just didn't exist, warn about the error. If the error was something else, cancel.
		if strings.HasSuffix(err.Error(), "no such file or directory") {
			log.Warnf("Error deleting %[3]s from the filesystem (requested by %[1]s@%[2]s): File not found", dfr.Username, ip, dfr.ImageName)
		} else {
			log.Errorf("Error deleting %[4]s from the filesystem (requested by %[1]s@%[2]s): %[3]s", dfr.Username, ip, err, dfr.ImageName)
			w.WriteHeader(http.StatusInternalServerError)
			return
		}
	}
	log.Debugf("%[1]s@%[2]s successfully deleted the image with the name %[3]s.", dfr.Username, ip, dfr.ImageName)
	output(w, GenericResponse{
		Success:        true,
		Status:         "deleted",
		StatusReadable: "The image " + dfr.ImageName + " was successfully deleted.",
	}, http.StatusAccepted)
}
Exemple #6
0
// Insert handles insert requests
func Insert(w http.ResponseWriter, r *http.Request) {
	var ip = getIP(r)
	if r.Method != "POST" {
		w.Header().Add("Allow", "POST")
		w.WriteHeader(http.StatusMethodNotAllowed)
		return
	}
	// Create a json decoder for the payload.
	decoder := json.NewDecoder(r.Body)
	var ifr InsertForm
	// Decode the payload.
	err := decoder.Decode(&ifr)
	// Check if there was an error decoding.
	if err != nil || len(ifr.Image) == 0 {
		log.Debugf("%[1]s sent an invalid insert request.", ip)
		w.WriteHeader(http.StatusBadRequest)
		return
	}

	// Fill out all non-necessary unfilled values.
	if len(ifr.ImageName) == 0 {
		ifr.ImageName = ImageName(5)
	}
	if len(ifr.ImageFormat) == 0 {
		ifr.ImageFormat = "png"
	}
	if len(ifr.Client) == 0 {
		ifr.Client = "Unknown Client"
	}

	if len(ifr.Username) == 0 || len(ifr.AuthToken) == 0 {
		// Username or authentication token not supplied.
		if config.RequireAuth {
			// The user is not logged in, but the config is set to require authentication, send error.
			log.Debugf("%[1]s tried to upload an image without authentication, even though authentication is required.", ip)
			output(w, GenericResponse{
				Success:        false,
				Status:         "not-logged-in",
				StatusReadable: "This MIS server requires authentication. Please log in or register.",
			}, http.StatusUnauthorized)
			return
		}
		// The user is not logged in, but login is not required, set username to "anonymous"
		ifr.Username = "******"
	} else {
		// Username and authentication token supplied, check them.
		err = auth.CheckAuthToken(ifr.Username, []byte(ifr.AuthToken))
		if err != nil {
			log.Debugf("%[1]s tried to authenticate as %[2]s with the wrong token.", ip, ifr.Username)
			output(w, GenericResponse{
				Success:        false,
				Status:         "invalid-authtoken",
				StatusReadable: "Your authentication token was incorrect. Please try logging in again.",
			}, http.StatusUnauthorized)
			return
		}
	}

	// If the image already exists, make sure that the uploader is the owner of the image.
	var replace = false
	owner := database.GetOwner(ifr.ImageName)
	if len(owner) > 0 {
		if owner != ifr.Username || ifr.Username == "anonymous" {
			output(w, GenericResponse{
				Success:        false,
				Status:         "already-exists",
				StatusReadable: "The requested image name is already in use by another user",
			}, http.StatusForbidden)
			log.Debugf("%[1]s@%[2]s attempted to override an image uploaded by %[3]s.", ifr.Username, ip, owner)
			return
		}
		replace = true
	}

	// Decode the base64 image from the JSON request.
	image, err := base64.StdEncoding.DecodeString(ifr.Image)
	if err != nil {
		output(w, GenericResponse{Success: false, Status: "invalid-image-encoding",
			StatusReadable: "The given image is not properly encoded in base64."}, http.StatusUnsupportedMediaType)
		log.Errorf("Error while decoding image from %[1]s@%[2]s: %[3]s", ifr.Username, ip, err)
		return
	}

	mimeType := http.DetectContentType(image)

	if !strings.HasPrefix(mimeType, "image/") {
		log.Debugf("%[1]s@%[2]s attempted to upload an image with an incorrect MIME type.", ifr.Username, ip, owner)
		output(w, GenericResponse{
			Success:        false,
			Status:         "invalid-mime",
			StatusReadable: "The uploaded data is of an incorrect MIME type.",
		}, http.StatusUnsupportedMediaType)
		return
	}
	mimeType = mimeType[len("image/"):]

	// Write the image to disk.
	err = ioutil.WriteFile(config.ImageLocation+"/"+ifr.ImageName+"."+ifr.ImageFormat, image, 0644)
	if err != nil {
		log.Errorf("Error while saving image from %[1]s@%[2]s: %[3]s", ifr.Username, ip, err)
		w.WriteHeader(http.StatusInternalServerError)
		return
	}

	if !replace {
		// The image name has not been used. Insert it into the database.
		err = database.Insert(ifr.ImageName, ifr.ImageFormat, mimeType, ifr.Username, ip, ifr.Client, ifr.Hidden)
		if err != nil {
			log.Errorf("Error while inserting image from %[1]s@%[2]s into the database: %[3]s", ifr.Username, ip, err)
			output(w, GenericResponse{
				Success:        false,
				Status:         "database-error",
				StatusReadable: "An internal server error occurred while attempting to save image information to the database.",
			}, http.StatusInternalServerError)
			w.WriteHeader(http.StatusInternalServerError)
			return
		}
		log.Debugf("%[1]s@%[2]s successfully uploaded an image with the name %[3]s (new).", ifr.Username, ip, ifr.ImageName)
		output(w, GenericResponse{
			Success:        true,
			Status:         "created",
			StatusReadable: "The image was successfully saved with the name " + ifr.ImageName,
			ImageName:      ifr.ImageName,
		}, http.StatusCreated)
	} else {
		// The image name was in use. Update the data in the database.
		err = database.Update(ifr.ImageName, ifr.ImageFormat, mimeType, ip, ifr.Client, ifr.Hidden)
		if err != nil {
			log.Errorf("Error while updating data of image from %[1]s@%[2]s into the database: %[3]s", ifr.Username, ip, err)
			output(w, GenericResponse{
				Success:        false,
				Status:         "database-error",
				StatusReadable: "An internal server error occurred while attempting to save image information to the database.",
			}, http.StatusInternalServerError)
			return
		}
		log.Debugf("%[1]s@%[2]s successfully uploaded an image with the name %[3]s (replaced).", ifr.Username, ip, ifr.ImageName)
		output(w, GenericResponse{
			Success: true,
			Status:  "replaced",
			StatusReadable: "The image was successfully saved with the name " + ifr.ImageName +
				", replacing your previous image with the same name",
			ImageName: ifr.ImageName,
		}, http.StatusAccepted)
	}
}
Exemple #7
0
func query(w http.ResponseWriter, r *http.Request) {
	if r.Method != "POST" {
		w.Header().Add("Allow", "POST")
		w.WriteHeader(http.StatusMethodNotAllowed)
		return
	}
	ip := getIP(r)

	decoder := json.NewDecoder(r.Body)
	var req Request
	// Decode the payload.
	err := decoder.Decode(&req)

	if err != nil || len(req.Action) == 0 || len(req.URL) == 0 {
		log.Debugf("%[1]s sent an invalid insert request.", ip)
		w.WriteHeader(http.StatusBadRequest)
		return
	}

	if req.Action == "unshorten" {
		if !strings.HasPrefix(req.URL, config.URL) {
			log.Warnf("%[1]s attempted to unshorten an invalid URL.", ip)
			writeError(w, http.StatusBadRequest, "notshortened", "The URL you entered is not a mau\\Lu short URL.")
			return
		}
		shortID := req.URL[len(config.URL):]
		if len(shortID) > 20 {
			log.Warnf("%[1]s attempted to unshorten an impossibly long short URL", ip)
			writeError(w, http.StatusBadRequest, "toolong", "The URL you entered is too long.")
			return
		}
		longURL, _, err := data.Query(shortID)
		if err != nil {
			log.Warnf("%[1]s queried the target of the non-existent short URL %[2]s", ip, req.URL)
			writeError(w, http.StatusNotFound, "notfound", "The short url id %[1]s doesn't exist!", req.URL)
			return
		}
		log.Debugf("%[1]s queried the target of %[2]s.", ip, req.URL)
		writeSuccess(w, longURL)
	} else if req.Action == "shorten" || req.Action == "google" || req.Action == "duckduckgo" {
		if len(req.RequestShort) == 0 {
			req.RequestShort = randomShortURL()
		}

		if req.RedirectType == "js" {
			req.RedirectType = "html"
		} else if len(req.RedirectType) == 0 || (req.RedirectType != "http" && req.RedirectType != "html") {
			req.RedirectType = "http"
		}

		if !validShortURL(req.RequestShort) {
			log.Warnf("%[1]s attempted to use invalid characters in a short URL", ip)
			writeError(w, http.StatusBadRequest, "illegalchars", "The short URL contains illegal characters.")
			return
		}

		if strings.HasPrefix(req.URL, config.URL) {
			log.Warnf("%[1]s attempted to shorten the mau\\Lu url %[2]s", ip, req.URL)
			writeError(w, http.StatusBadRequest, "alreadyshortened", "The given URL is already a mau\\Lu URL")
			return
		}

		if req.Action == "google" {
			req.URL = "http://lmgtfy.com/?q=" + url.QueryEscape(req.URL)
		} else if req.Action == "duckduckgo" {
			req.URL = "http://lmddgtfy.net/?q=" + strings.Replace(url.QueryEscape(req.URL), "+", " ", -1)
		} else if !strings.HasPrefix(req.URL, "https://") && !strings.HasPrefix(req.URL, "http://") {
			log.Warnf("%[1]s attempted to shorten an URL with an unidentified protocol", ip)
			writeError(w, http.StatusBadRequest, "invalidprotocol", "Protocol couldn't be identified.")
			return
		}

		if len(req.URL) > 255 {
			log.Warnf("%[1]s attempted to shorten a very long URL", ip)
			writeError(w, http.StatusBadRequest, "toolong", "The URL you entered is too long.")
			return
		}

		str, _, err := data.Query(req.RequestShort)
		if (err == nil || len(str) != 0) && str != req.URL {
			log.Warnf("%[1]s attempted to insert %[3]s into the short url %[2]s, but it is already in use.", ip, req.RequestShort, req.URL)
			writeError(w, http.StatusConflict, "alreadyinuse", "The short url %[1]s is already in use.", req.RequestShort)
			return
		}

		resultURL := config.URL + data.Insert(req.URL, req.RequestShort, req.RedirectType)
		log.Debugf("%[1]s shortened %[3]s into %[2]s", ip, req.URL, resultURL)
		writeSuccess(w, resultURL)
	} else {
		log.Warnf("%[1]s attempted to use an unidentified action: %[2]s", ip, req.Action)
		writeError(w, http.StatusNotFound, "action", "Invalid action \"%[1]s\"", req.Action)
	}
}
Exemple #8
0
// Hide handles hide/unhide requests
func Hide(w http.ResponseWriter, r *http.Request) {
	var ip = getIP(r)
	if r.Method != "POST" {
		w.Header().Add("Allow", "POST")
		w.WriteHeader(http.StatusMethodNotAllowed)
		return
	}

	// Create a json decoder for the payload.
	decoder := json.NewDecoder(r.Body)
	var hfr HideForm
	// Decode the payload.
	err := decoder.Decode(&hfr)
	// Check if there was an error decoding.
	if err != nil || len(hfr.ImageName) == 0 || len(hfr.Username) == 0 || len(hfr.AuthToken) == 0 {
		log.Debugf("%[1]s sent an invalid hide request.", ip)
		w.WriteHeader(http.StatusBadRequest)
		return
	}

	err = auth.CheckAuthToken(hfr.Username, []byte(hfr.AuthToken))
	// Check if the auth token was correct
	if err != nil {
		log.Debugf("%[1]s tried to authenticate as %[2]s with the wrong token.", ip, hfr.Username)
		output(w, GenericResponse{
			Success:        false,
			Status:         "invalid-authtoken",
			StatusReadable: "The authentication token was incorrect. Please try logging in again.",
		}, http.StatusUnauthorized)
		return
	}

	owner := database.GetOwner(hfr.ImageName)
	if len(owner) > 0 {
		if owner != hfr.Username {
			log.Debugf("%[1]s@%[2]s attempted to hide an image uploaded by %[3]s.", hfr.Username, ip, owner)
			output(w, GenericResponse{
				Success:        false,
				Status:         "no-permissions",
				StatusReadable: "The image you requested to be deleted was not uploaded by you.",
			}, http.StatusForbidden)
			return
		}
	} else {
		log.Debugf("%[1]s@%[2]s attempted to hide an image that doesn't exist.", hfr.Username, ip, owner)
		output(w, GenericResponse{Success: false, Status: "not-found", StatusReadable: "The image you requested to be deleted does not exist."}, http.StatusNotFound)
		return
	}

	err = database.SetHidden(hfr.ImageName, hfr.Hidden)
	if err != nil {
		log.Warnf("Error changing hide status of %[4]s (requested by %[1]s@%[2]s): %[3]s", hfr.Username, ip, err, hfr.ImageName)
		w.WriteHeader(http.StatusInternalServerError)
		return
	}

	var hid string
	if hfr.Hidden {
		hid = "hidden"
	} else {
		hid = "unhidden"
	}

	log.Debugf("%[1]s@%[2]s successfully changed hidden status to %[4]t of the image with the name %[3]s.", hfr.Username, ip, hfr.ImageName, hfr.Hidden)
	output(w, GenericResponse{
		Success:        true,
		Status:         hid,
		StatusReadable: "The image " + hfr.ImageName + " was successfully " + hid + ".",
	}, http.StatusAccepted)
}
Exemple #9
0
// Search handles search requests
func Search(w http.ResponseWriter, r *http.Request) {
	var ip = getIP(r)
	if r.Method != "POST" {
		w.Header().Add("Allow", "POST")
		w.WriteHeader(http.StatusMethodNotAllowed)
		return
	}
	if !config.AllowSearch {
		log.Warnf("%[1]s attempted to execute a search, even though it's not allowed", ip)
		w.WriteHeader(http.StatusForbidden)
		return
	}
	// Create a json decoder for the payload.
	decoder := json.NewDecoder(r.Body)
	var sf SearchForm
	// Decode the payload.
	err := decoder.Decode(&sf)
	// Check if there was an error decoding.
	if err != nil || (len(sf.Format) == 0 && len(sf.Adder) == 0 && len(sf.Client) == 0 && sf.MinTime <= 0 && sf.MaxTime <= 0) {
		log.Debugf("%[1]s sent an invalid search request.", ip)
		w.WriteHeader(http.StatusBadRequest)
		return
	}

	if sf.MinTime <= 0 && sf.MaxTime > 0 {
		sf.MinTime = 1
	} else if sf.MinTime > 0 && sf.MaxTime <= 0 {
		sf.MaxTime = time.Now().Unix()
	}

	var authenticated = false
	if len(sf.AuthToken) != 0 {
		err = auth.CheckAuthToken(sf.Adder, []byte(sf.AuthToken))
		if err != nil {
			log.Debugf("%[1]s tried to authenticate as %[2]s with the wrong token.", ip, sf.Adder)
			output(w, SearchResponse{
				Success:        false,
				Status:         "invalid-authtoken",
				StatusReadable: "The authentication token was incorrect. Please try logging in again.",
			}, http.StatusUnauthorized)
			return
		}
		authenticated = true
	}

	results, err := database.Search(sf.Format, sf.Adder, sf.Client, sf.MinTime, sf.MaxTime, authenticated)
	if err != nil {
		log.Errorf("Failed to execute search %[2]s by %[1]s: %[3]s", ip, sf.String(), err)
		w.WriteHeader(http.StatusInternalServerError)
		return
	}

	if authenticated {
		log.Debugf("%[3]s@%[1]s executed a search: %[2]s", ip, sf.String(), sf.Adder)
	} else {
		log.Debugf("%[1]s executed a search: %[2]s", ip, sf.String())
	}
	output(w, SearchResponse{
		Success:        true,
		Status:         "success",
		StatusReadable: fmt.Sprintf("Search completed with %d results", len(results)),
		Results:        results,
	}, http.StatusOK)
}