コード例 #1
0
ファイル: callhandler.go プロジェクト: BrentNoorda/slfsrv
func (fe *fileExistsIn) goServe(lc *longCall, wsData *webserverData) {
	var err error
	var exists, isdir bool

	if exists, err = ssutil.FileOrDirExists(fe.File); err == nil {
		isdir, err = ssutil.IsDir(fe.File)
	}
	if err != nil {
		lc.Response <- jsonResponseError("error: " + err.Error())
	} else {
		lc.Response <- jsonResponse{"state": "done", "exists": exists && !isdir}
	}
}
コード例 #2
0
ファイル: callhandler.go プロジェクト: BrentNoorda/slfsrv
func (fr *fileRemoveIn) goServe(lc *longCall, wsData *webserverData) {
	var isdir bool
	var err error

	if isdir, err = ssutil.IsDir(fr.File); err != nil {
		lc.Response <- jsonResponseError("error: " + err.Error())
	}

	if isdir {
		lc.Response <- jsonResponseError("error: file.remove() cannot remove a directory")
	} else {
		err = os.Remove(fr.File)
		if err != nil {
			lc.Response <- jsonResponseError("error: " + err.Error())
		} else {
			lc.Response <- jsonResponse{"state": "done"}
		}
	}
}
コード例 #3
0
ファイル: compiler.go プロジェクト: BrentNoorda/slfsrv
func mustBeARawSelfServingSourceFile(filespec string) (exeFileData []byte, err error) {

	var fileOrDirExists, isDir bool
	if fileOrDirExists, err = ssutil.FileOrDirExists(filespec); err != nil {
		return exeFileData, err
	}
	if isDir, err = ssutil.IsDir(filespec); err != nil {
		return exeFileData, err
	}
	if !fileOrDirExists || isDir {
		return exeFileData, errors.New("compile-from file \"" + filespec + "\" does not look valid")
	}

	// read binary file - if amIAlreadyCompiled is not in there this this isn't right
	if exeFileData, err = ioutil.ReadFile(filespec); err != nil {
		return exeFileData, err
	}
	if !bytes.Contains(exeFileData, []byte(secret_offset_of_appended_data)) {
		return exeFileData, errors.New("compile-from file \"" + filespec + "\" is not valid slfsrv executable")
	}

	return
}
コード例 #4
0
ファイル: slfsrv.go プロジェクト: kissthink/slfsrv
func main() {

	var precompiled int = compiler.OffsetOfAppendedData()
	var err error = nil
	var bundleOut, compile, compileFrom, patharg, fullpatharg, initPathUrl, initQuery, storeFilespec, configFile string
	var helpWanted, compileReplaceOK, verbose, isdir bool
	var port int
	var cwd string
	var args []string
	var zipReader *zip.Reader

	rand.Seed(time.Now().Unix())

	var myselfExecutable string
	myselfExecutable, err = osext.Executable()
	if err != nil {
		fmt.Fprintf(os.Stderr, "could not determine location of self-server executable\n")
		return
	}

	if precompiled != 0 {
		helpWanted = false
		bundleOut = ""
		compile = ""
		compileFrom = ""
		configFile = ""
		fullpatharg = ""
		patharg = ""
		compileReplaceOK = false
		isdir = false
		args = []string{}

		port, verbose, err = parse_compiled_command_line()
		if err != nil {
			fmt.Fprintf(os.Stderr, "%s\n", err)
			return
		}

		zipReader, initPathUrl, err = bundle.Reader(myselfExecutable, precompiled)
		if err != nil {
			fmt.Fprintf(os.Stderr, "%s\n", err)
			return
		}

		storeFilespec = myselfExecutable + ".slfsrv-data"

	} else {

		// parse command-line inputs
		helpWanted, bundleOut, compile, compileFrom, compileReplaceOK, port, verbose, configFile, args, err = parse_command_line()
		if err != nil {
			fmt.Fprintf(os.Stderr, "%s\n", err)
			helpWanted = true
		}
		if helpWanted {
			usage()
			return
		}

		// figure out the initial path and root file to serve from
		if cwd, err = os.Getwd(); err != nil {
			fmt.Fprintf(os.Stderr, "%s\n", err)
			os.Exit(1)
		}
		cwd = filepath.ToSlash(cwd)

		config.ParseConfigFile(configFile)
		settings := config.GetSettings()
		fmt.Printf("config: %+v\n", *settings)

		if settings.Port != 0 {
			port = settings.Port
		}

		if len(args) < 2 {
			initPathUrl = ""
		} else {
			initPathUrl = args[1]
		}
		if len(args) == 0 {
			patharg = cwd
		} else {
			patharg = filepath.ToSlash(path.Clean(args[0]))
		}

		var queryIdx int = strings.Index(initPathUrl, "?")
		if queryIdx == -1 {
			initQuery = ""
		} else {
			initQuery = initPathUrl[queryIdx+1:]
			initPathUrl = initPathUrl[:queryIdx]
		}

		if initPathUrl == "" {
			// figure out if path arg is just a path (in which case add index.htm or index.html) or a full file
			if isdir, err = ssutil.IsDir(patharg); err != nil {
				fmt.Fprintf(os.Stderr, "%s\n", err)
				os.Exit(1)
			}
			if !isdir {
				patharg, initPathUrl = path.Split(patharg)
			}
		}
		fullpatharg = path.Clean(patharg)

		// if patharg is a subfolder of cwd then skip the cwd part so it is prettier
		patharg = ssutil.CleanPathRelativeToCwd(fullpatharg, cwd)

		// if initPathUrl not specified then guess at "index.htm" or "index.html"
		if initPathUrl == "" {
			var exists bool
			initPathUrl = "index.htm"
			if exists, _ = ssutil.FileOrDirExists(filepath.FromSlash(fullpatharg + "/" + initPathUrl)); !exists {
				initPathUrl = "index.html"
			}
		}
		storeFilespec = filepath.FromSlash(path.Join(fullpatharg, initPathUrl+".slfsrv-data"))

	}

	if bundleOut != "" {
		// BUNDLE into a standalone zip file
		if verbose {
			fmt.Printf("create compiled version from %s\n", filepath.FromSlash(patharg))
		}
		bundleOut = ssutil.CleanPathRelativeToCwd(bundleOut, cwd)
		err = bundle.Bundle(bundleOut, compileReplaceOK, patharg, initPathUrl, verbose)
		if err == nil {
			if verbose {
				fmt.Println("bundle SUCCESS! Created:", bundleOut)
			}
		}
		if err != nil {
			fmt.Fprintf(os.Stderr, "ERROR: %s\n", err)
		}

	} else if compile != "" {
		// COMPILE
		if compileFrom == "" {
			compileFrom = myselfExecutable
		}
		compileFrom = ssutil.CleanPathRelativeToCwd(compileFrom, cwd)
		if verbose {
			fmt.Printf("create compiled version from %s executable\n", compileFrom)
			fmt.Printf("with source files from %s/%s\n", filepath.FromSlash(patharg), initPathUrl)
		}

		compile = ssutil.CleanPathRelativeToCwd(compile, cwd)
		err = compiler.Compile(compile, compileReplaceOK, compileFrom, patharg, initPathUrl, verbose)
		if err == nil {
			if verbose {
				fmt.Println("compilation SUCCESS! Created:", compile)
			}
		}
		if err != nil {
			fmt.Fprintf(os.Stderr, "ERROR: %s\n", err)
		}
	} else {
		// SERVE
		exitChan := make(chan int)

		// we may be reading from a pre-bundled file, determine now if that is the case
		if (precompiled == 0) && !isdir {
			var zip_initPathUrl string
			zipReader, zip_initPathUrl, err = bundle.Reader(path.Join(patharg, initPathUrl), 0)

			if err == nil {
				storeFilespec = filepath.FromSlash(path.Join(fullpatharg, initPathUrl) + ".slfsrv-data")
				initPathUrl = zip_initPathUrl
			} else {
				zipReader = nil
			}
		}

		var secretKey string
		var keepAliveSeconds int64
		settings := config.GetSettings()

		if settings.SecretKey != "" {
			secretKey = settings.SecretKey
		} else {
			secretKey = generate_secret_key()
		}

		if settings.KeepAliveSeconds != 0 {
			keepAliveSeconds = settings.KeepAliveSeconds
		} else {
			keepAliveSeconds = 2
		}

		port = webserver.ListenAndServe(port, secretKey, keepAliveSeconds, zipReader, patharg, fullpatharg, initPathUrl,
			verbose, exitChan, myselfExecutable, storeFilespec)

		browser.LaunchDefaultBrowser(port, secretKey, initPathUrl, initQuery, verbose)

		<-exitChan

		tempdir.Cleanup(verbose)
	}
}
コード例 #5
0
ファイル: tempdir.go プロジェクト: BrentNoorda/slfsrv
func Tempdir(prefix string, zipReader *zip.Reader, /*null if reading from raw files*/
	rootPath string /*used if zipRead is nul*/, verbose bool) (tempdir string, err error) {

	tempdirMutex.Lock()
	defer tempdirMutex.Unlock()

	var foundInMap bool

	if tempdir, foundInMap = tempdirs[prefix]; foundInMap {
		// this prefix is already mapped, so nothing to do but return the existing mapping
		return
	}

	if tempdir, err = ioutil.TempDir("", "slfsrv-tmp-"+prefix); err != nil {
		return
	}
	if verbose {
		fmt.Println("Tempdir \"" + tempdir + "\" created for prefix \"" + prefix + "\"")
	}
	tempdirs[prefix] = tempdir

	if len(prefix) != 0 {
		// copy all the local files in our prefix directory to the temp dir
		if zipReader != nil {
			// read from the zip file

			var startsWith string = prefix + "/" // if if windows we store this slash type
			var startsWithLength int = len(startsWith)

			var f *zip.File
			for _, f = range zipReader.File {

				if strings.HasPrefix(f.Name, startsWith) {
					var rc io.ReadCloser

					if rc, err = f.Open(); err != nil {
						return
					}
					err = writeToTempDir(rc, tempdir, filepath.FromSlash(f.Name[startsWithLength:]), 0777 /*f.Mode()*/)
					if err != nil {
						rc.Close()
					} else {
						err = rc.Close()
					}
				}
			}

		} else {
			// read from the raw file system

			var isDir bool
			var copyFromDir string = filepath.Join(rootPath, prefix)

			if isDir, err = ssutil.IsDir(copyFromDir); (err == nil) && isDir {
				// prefix is a directory, so copy everything from it to tempdir

				var skipLen int = len(copyFromDir) + 1
				walkFunc := func(path string, info os.FileInfo, err error) error {
					if err == nil {
						if !info.IsDir() {
							var relativePath string = path[skipLen:]

							var f *os.File

							if f, err = os.Open(path); err == nil {
								err = writeToTempDir(f, tempdir, relativePath, info.Mode())
								if err != nil {
									f.Close()
								} else {
									err = f.Close()
								}
							}

						}
					}
					return err
				}
				if err = filepath.Walk(copyFromDir, walkFunc); err != nil {
					return
				}
			}
		}
	}

	return
}
コード例 #6
0
ファイル: compiler.go プロジェクト: BrentNoorda/slfsrv
func Compile(exeOutPath string, replaceOK bool, exeInPath string, rootPath string, initialUrl string, verbose bool) (err error) {

	var exeFileData []byte

	// verify that exeInPath exists and is a file
	if _, err = mustBeARawSelfServingSourceFile(exeInPath); err != nil {
		return err
	}

	// output must be file name, not a directory
	var isDir bool
	if isDir, err = ssutil.IsDir(exeOutPath); err != nil {
		return err
	}
	if isDir {
		return errors.New("compile file \"" + exeOutPath + "\" must not be a directory")
	}

	// verify that there is not already an output file, or it's OK to create that file
	if !replaceOK {
		var fileOrDirExists bool
		if fileOrDirExists, err = ssutil.FileOrDirExists(exeOutPath); err != nil {
			return err
		}
		if fileOrDirExists {
			return errors.New("compile file \"" + exeOutPath + "\" already exists; cannot overwrite without -replace flag")
		}
	}

	// copy source file to destination (to make sure we get all attribute)
	switch runtime.GOOS {
	case "darwin", "linux":
		var cmd *exec.Cmd = exec.Command("cp", exeInPath, exeOutPath)
		if err = cmd.Run(); err != nil {
			return err
		}
	case "windows":
		var cmd *exec.Cmd = exec.Command("cmd.exe", "/C", "copy", exeInPath, exeOutPath)
		if err = cmd.Run(); err != nil {
			return err
		}
	default:
		return errors.New("Sorry, don't know how to copy file for OS " + runtime.GOOS)
	}
	// verify that exeInPath exists and is a file
	if exeFileData, err = mustBeARawSelfServingSourceFile(exeInPath); err != nil {
		return errors.New("error copying file \"" + exeInPath + "\" to " + "\"" + exeOutPath + "\"")
	}

	exeFileData = hardcode_startup_data_into_output_file(exeFileData)

	// zip all file data
	var zipContents *bytes.Buffer
	if zipContents, err = bundle.BundleDirectory(rootPath, initialUrl); err != nil {
		return err
	}

	// append zipContents to buffer
	var exeFileBuf *bytes.Buffer = bytes.NewBuffer(exeFileData)
	if _, err = exeFileBuf.Write(zipContents.Bytes()); err != nil {
		return err
	}

	err = saveAlteredOutputFile(exeOutPath, exeFileBuf.Bytes())

	return
}