Example #1
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})
	}
}
Example #2
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)
}
Example #3
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)
	}
}
Example #4
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)
}
Example #5
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)
}