| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138 |
- package main
- import (
- "net/http"
- "path/filepath"
- "net/url"
- "log"
- "strings"
- "errors"
- fs "imuslab.com/arozos/mod/filesystem"
- )
- /*
- Media Server
- This function serve large file objects like video and audio file via asynchronize go routine :)
- Example usage:
- /media/?file=user:/Desktop/test/02.Orchestra- エミール (Addendum version).mp3
- /media/?file=user:/Desktop/test/02.Orchestra- エミール (Addendum version).mp3&download=true
- This will serve / download the file located at files/users/{username}/Desktop/test/02.Orchestra- エミール (Addendum version).mp3
- >>> PLEASE ALWAYS USE URLENCODE IN THE LINK PASSED INTO THE /media ENDPOINT <<<
- */
- func mediaServer_init(){
- http.HandleFunc("/media/", serverMedia);
- http.HandleFunc("/media/getMime/", serveMediaMime);
- }
- //This function validate the incoming media request and return the real path for the targed file
- func media_server_validateSourceFile(w http.ResponseWriter, r *http.Request) (string, error){
- username, err := authAgent.GetUserName(w,r);
- if (err != nil){
- return "", errors.New("User not logged in");
- }
- userinfo, _ := userHandler.GetUserInfoFromUsername(username);
- //Validate url valid
- if (strings.Count(r.URL.String(), "?") > 1){
- return "", errors.New("Invalid paramters. Multiple ? found")
- }
-
- targetfile, _ := mv(r,"file",false)
- targetfile, _ = url.QueryUnescape(targetfile)
- if (targetfile == ""){
- return "", errors.New("Missing paramter 'file'");
- }
- //Translate the virtual directory to realpath
- realFilepath, err := userinfo.VirtualPathToRealPath(targetfile);
- if (fileExists(realFilepath) && IsDir(realFilepath)){
- return "", errors.New("Given path is not a file.")
- }
- if (err != nil){
- return "", errors.New("Unable to translate the given filepath")
- }
- if (!fileExists(realFilepath)){
- //Sometime if url is not URL encoded, this error might be shown as well
- //Try to use manual segmentation
- originalURL := r.URL.String();
- //Must be pre-processed with system special URI Decode function to handle edge cases
- originalURL = fs.DecodeURI(originalURL);
- if (strings.Contains(originalURL, "&download=true")){
- originalURL = strings.ReplaceAll(originalURL, "&download=true", "")
- }else if (strings.Contains(originalURL, "download=true")){
- originalURL = strings.ReplaceAll(originalURL, "download=true", "")
- }
- if (strings.Contains(originalURL, "&file=")){
- originalURL = strings.ReplaceAll(originalURL, "&file=", "file=")
- }
- urlInfo := strings.Split(originalURL, "file=")
- possibleVirtualFilePath := urlInfo[len(urlInfo) - 1]
- possibleRealpath, err := userinfo.VirtualPathToRealPath(possibleVirtualFilePath);
- if (err != nil){
- log.Println("Error when trying to serve file in compatibility mode", err.Error());
- return "", errors.New("Error when trying to serve file in compatibility mode");
- }
- if (fileExists(possibleRealpath)){
- realFilepath = possibleRealpath;
- log.Println("[Media Server] Serving file " + filepath.Base(possibleRealpath) + " in compatibility mode. Do not to use '&' or '+' sign in filename! ")
- return realFilepath, nil
- }else{
- return "", errors.New("File not exists")
- }
- }
-
- return realFilepath, nil
- }
- func serveMediaMime(w http.ResponseWriter, r *http.Request){
- realFilepath, err := media_server_validateSourceFile(w,r)
- if (err != nil){
- sendErrorResponse(w, err.Error())
- return
- }
- mime := "text/directory"
- if !IsDir(realFilepath){
- m, _, err := fs.GetMime(realFilepath)
- if (err != nil){
- mime = ""
- }
- mime = m
- }
- sendTextResponse(w, mime);
- }
- func serverMedia(w http.ResponseWriter, r *http.Request) {
- //Serve normal media files
- realFilepath, err := media_server_validateSourceFile(w,r)
- if (err != nil){
- sendErrorResponse(w, err.Error())
- return
- }
- //Check if downloadMode
- downloadMode := false
- dw, _ := mv(r, "download",false)
- if (dw == "true"){
- downloadMode = true;
- }
- //Serve the file
- if (downloadMode){
- //Fixing the header issue on Golang url encode lib problems
- w.Header().Set("Content-Disposition", "attachment; filename*=UTF-8''" + strings.ReplaceAll(url.QueryEscape(filepath.Base(realFilepath)),"+","%20"))
- w.Header().Set("Content-Type", r.Header.Get("Content-Type"))
- }
- http.ServeFile(w, r, realFilepath)
- }
|