Пример #1
0
// 检测 cfg 的各项字段是否合法,
// 初始化相关内容。比如静态文件路由等。
func (cfg *Config) init() error {
	if len(cfg.Port) == 0 {
		if cfg.HTTPS {
			cfg.Port = httpsPort
		} else {
			cfg.Port = httpPort
		}
	}
	if cfg.Port[0] != ':' {
		cfg.Port = ":" + cfg.Port
	}

	if cfg.HTTPState < 0 || cfg.HTTPState >= httpStateSize {
		return errors.New("无效的httpState值")
	}

	if cfg.HTTPS {
		if !utils.FileExists(cfg.CertFile) {
			return errors.New("certFile 所指的文件并不存在")
		}
		if !utils.FileExists(cfg.KeyFile) {
			return errors.New("keyFile 所指的文件并不存在")
		}
	}

	return nil
}
Пример #2
0
// 用于输出配置文件到指定的位置。
// 目前包含了日志配置文件和程序本身的配置文件。
func installConfig() error {
	if !utils.FileExists(Appdir(configDir)) {
		if err := os.MkdirAll(Appdir(configDir), os.ModePerm); err != nil {
			return err
		}
		if !utils.FileExists(Appdir(configDir)) {
			return fmt.Errorf("路径[%v]不存在,且无法创建", Appdir(configDir))
		}
	}

	if err := ioutil.WriteFile(Appdir(logConfigFile), static.LogConfig, os.ModePerm); err != nil {
		return err
	}

	cfg := &Config{
		Core: &web.Config{
			HTTPS:    false,
			CertFile: "",
			KeyFile:  "",
			Port:     "8080",
			Headers: map[string]string{
				"Server": "typing",
			},
		},
		Debug: true,

		AdminURLPrefix: "/admin",
		Salt:           rands.String(6, 7, rands.Lower, rands.Upper, rands.Digit, rands.Punct),

		DBDSN:    "./output/main.db",
		DBPrefix: "typing_",
		DBDriver: "sqlite3",

		FrontAPIPrefix: "/api",
		AdminAPIPrefix: "/admin/api",

		ThemeURLPrefix: "/themes",

		UploadDirFormat: "2006/01/",
		UploadExts:      ".txt;.png;.jpg;.jpeg",
		UploadSize:      1024 * 1024 * 5,
		UploadURLPrefix: "/uploads",
	}
	data, err := json.MarshalIndent(cfg, "", "    ")
	if err != nil {
		return err
	}

	return ioutil.WriteFile(Appdir(configFile), data, os.ModePerm)
}
Пример #3
0
// Init 对 Options 作一些初始化操作。
func (o *Options) Init() *app.OptionsError {
	if len(o.Dir) == 0 {
		return &app.OptionsError{Field: "dir", Message: locale.Sprintf(locale.ErrRequired)}
	}

	if len(o.Type) == 0 {
		return &app.OptionsError{Field: "type", Message: locale.Sprintf(locale.ErrRequired)}
	}

	if !utils.FileExists(o.Dir) {
		if err := os.MkdirAll(o.Dir, os.ModePerm); err != nil {
			msg := locale.Sprintf(locale.ErrMkdirError, err)
			return &app.OptionsError{Field: "dir", Message: msg}
		}
	}

	if !isSuppertedType(o.Type) {
		return &app.OptionsError{Field: "type", Message: locale.Sprintf(locale.ErrInvalidFormat)}
	}

	// 只有 html 和 html+ 才需要判断模板文件是否存在
	if o.Type == "html" || o.Type == "html+" {
		if len(o.Template) > 0 && !utils.FileExists(o.Template) {
			msg := locale.Sprintf(locale.ErrTemplateNotExists)
			return &app.OptionsError{Field: "template", Message: msg}
		}
	}

	// 调试模式,必须得有模板和端口
	if o.Type == "html+" {
		if len(o.Template) == 0 {
			return &app.OptionsError{Field: "template", Message: locale.Sprintf(locale.ErrRequired)}
		}

		if len(o.Port) == 0 {
			return &app.OptionsError{Field: "port", Message: locale.Sprintf(locale.ErrRequired)}
		}

		if o.Port[0] != ':' {
			o.Port = ":" + o.Port
		}
	}

	return nil
}
Пример #4
0
// Init 对 Options 作一些初始化操作。
func (o *Options) Init() *app.OptionsError {
	if len(o.Dir) == 0 {
		return &app.OptionsError{Field: "dir", Message: "不能为空"}
	}

	if len(o.Type) == 0 {
		return &app.OptionsError{Field: "type", Message: "不能为空"}
	}

	if !utils.FileExists(o.Dir) {
		if err := os.MkdirAll(o.Dir, os.ModePerm); err != nil {
			msg := "不存在,且在创建时提示以下信息:" + err.Error()
			return &app.OptionsError{Field: "dir", Message: msg}
		}
	}

	if !isSuppertedType(o.Type) {
		return &app.OptionsError{Field: "type", Message: "不支持的类型"}
	}

	// 只有 html 和 html+ 才需要判断模板文件是否存在
	if o.Type == "html" || o.Type == "html+" {
		if len(o.Template) > 0 && !utils.FileExists(o.Template) {
			return &app.OptionsError{Field: "template", Message: "模板目录不存在"}
		}
	}

	// 调试模式,必须得有模板和端口
	if o.Type == "html+" {
		if len(o.Template) == 0 {
			return &app.OptionsError{Field: "template", Message: "不能为空"}
		}

		if len(o.Port) == 0 {
			return &app.OptionsError{Field: "port", Message: "不能为空"}
		}

		if o.Port[0] != ':' {
			o.Port = ":" + o.Port
		}
	}

	return nil
}
Пример #5
0
// 首页
func pageRoot(w http.ResponseWriter, r *http.Request) {
	// 首页的匹配模式为:/,可以匹配任意路径。所以此处作个判断,只有完全匹配的,才是显示首页
	if r.URL.Path == app.HomeURL() {
		pagePosts(w, r)
		return
	}

	path := cfg.RootDir + r.URL.Path
	if utils.FileExists(path) {
		http.ServeFile(w, r, path)
		return
	}

	pageHttpStatusCode(w, r, http.StatusNotFound)
}
Пример #6
0
// 输出一个特定状态码下的错误页面。若该页面模板不存在,则只输出状态码,而没有内容。
// 只对状态码大于等于400的起作用。
func pageHttpStatusCode(w http.ResponseWriter, r *http.Request, code int) {
	if code < 400 {
		return
	}
	w.Header().Set("Content-Type", "text/html")
	w.WriteHeader(code)

	path := themeDir(currentTheme) + strconv.Itoa(code) + ".html"
	if !utils.FileExists(path) { // 文件不存在,则只输出状态码,省略内容。
		return
	}

	// TODO: serveFile会自动写入一个状态码,导致多次输出状态码的提示
	http.ServeFile(w, r, path)
}
Пример #7
0
// 初始化app包。
// 除Install函数,其它函数都依赖Init()做初始化。
//
// dir 用于指定当前程序的数据存放路径。
func Init(dir string) (err error) {
	if !utils.FileExists(dir) {
		return fmt.Errorf("appdir[%v]不存在", appdir)
	}

	if !strings.HasSuffix(dir, "/") && !strings.HasSuffix(dir, string(os.PathSeparator)) {
		dir += string(os.PathSeparator)
	}
	appdir = dir

	// 初始化日志系统
	if err := logs.InitFromXMLFile(Appdir(logConfigFile)); err != nil {
		return err
	}

	// 加载app.json配置文件
	config, err = loadConfig(Appdir(configFile))
	if err != nil {
		return err
	}

	// 根据配置文件初始化数据库
	db, err = initDB()
	if err != nil {
		return err
	}

	// 加载数据库中的配置项
	options, err = loadOptions()
	if err != nil {
		return err
	}

	// 初始化系统的状态数据。
	stats, err = loadStats()
	if err != nil {
		return err
	}

	return nil
}
Пример #8
0
// Init 检测 Options 变量是否符合要求
func (opt *Options) Init() *app.OptionsError {
	if len(opt.Dir) == 0 {
		return &app.OptionsError{Field: "dir", Message: locale.Sprintf(locale.ErrRequired)}
	}

	if !utils.FileExists(opt.Dir) {
		return &app.OptionsError{Field: "dir", Message: locale.Sprintf(locale.ErrDirNotExists)}
	}

	if len(opt.Lang) == 0 {
		return &app.OptionsError{Field: "lang", Message: locale.Sprintf(locale.ErrRequired)}
	}

	if !langIsSupported(opt.Lang) {
		return &app.OptionsError{Field: "lang", Message: locale.Sprintf(locale.ErrUnsupportedInputLang, opt.Lang)}
	}

	if len(opt.Exts) > 0 {
		exts := make([]string, 0, len(opt.Exts))
		for _, ext := range opt.Exts {
			if len(ext) == 0 {
				continue
			}

			if ext[0] != '.' {
				ext = "." + ext
			}
			exts = append(exts, ext)
		}
		opt.Exts = exts
	} else {
		opt.Exts = langExts[opt.Lang]
	}

	return nil
}
Пример #9
0
// Init 检测 Options 变量是否符合要求
func (opt *Options) Init() *app.OptionsError {
	if len(opt.Dir) == 0 {
		return &app.OptionsError{Field: "dir", Message: "不能为空"}
	}

	if !utils.FileExists(opt.Dir) {
		return &app.OptionsError{Field: "dir", Message: "该目录不存在"}
	}

	if len(opt.Lang) == 0 {
		return &app.OptionsError{Field: "lang", Message: "不能为空"}
	}

	if !langIsSupported(opt.Lang) {
		return &app.OptionsError{Field: "lang", Message: "不支持该语言"}
	}

	if len(opt.Exts) > 0 {
		exts := make([]string, 0, len(opt.Exts))
		for _, ext := range opt.Exts {
			if len(ext) == 0 {
				continue
			}

			if ext[0] != '.' {
				ext = "." + ext
			}
			exts = append(exts, ext)
		}
		opt.Exts = exts
	} else {
		opt.Exts = langExts[opt.Lang]
	}

	return nil
}