member center, blog redesign
This commit is contained in:
1 parent
5f186f4455
commit
274782b89e
428 files changed
+23054
-480
No files matched your search
+107
-15
@@ -1,10 +1,11 @@
|
||||
package lea
|
||||
|
||||
import (
|
||||
"strings"
|
||||
"path/filepath"
|
||||
"os"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// 分离文件名与扩展名(包含.)
|
||||
@@ -14,14 +15,14 @@ func SplitFilename(filename string) (baseName, ext string) {
|
||||
ext = SubstringByte(filename, strings.LastIndex(filename, "."))
|
||||
baseName = strings.TrimRight(filename, ext)
|
||||
ext = strings.ToLower(ext)
|
||||
return;
|
||||
return
|
||||
}
|
||||
|
||||
// 转换文件的格式
|
||||
// toExt包含.
|
||||
func TransferExt(path string, toExt string) string {
|
||||
dir := filepath.Dir(path) + "/" // 文件路径
|
||||
name := filepath.Base(path) // 文件名 a.jpg
|
||||
dir := filepath.Dir(path) + "/" // 文件路径
|
||||
name := filepath.Base(path) // 文件名 a.jpg
|
||||
// 获取文件名与路径
|
||||
baseName, _ := SplitFilename(name)
|
||||
return dir + baseName + toExt
|
||||
@@ -38,7 +39,7 @@ func GetFilesize(path string) int64 {
|
||||
if err == nil {
|
||||
return fileinfo.Size()
|
||||
}
|
||||
return 0;
|
||||
return 0
|
||||
}
|
||||
|
||||
// 清空dir下所有的文件和文件夹
|
||||
@@ -79,12 +80,103 @@ func CopyFile(srcName, dstName string) (written int64, err error) {
|
||||
return io.Copy(dst, src)
|
||||
}
|
||||
|
||||
func CopyDir(source string, dest string) (err error) {
|
||||
// get properties of source dir
|
||||
sourceinfo, err := os.Stat(source)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// create dest dir
|
||||
|
||||
err = os.MkdirAll(dest, sourceinfo.Mode())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
directory, _ := os.Open(source)
|
||||
|
||||
objects, err := directory.Readdir(-1)
|
||||
|
||||
for _, obj := range objects {
|
||||
|
||||
sourcefilepointer := source + "/" + obj.Name()
|
||||
|
||||
destinationfilepointer := dest + "/" + obj.Name()
|
||||
|
||||
if obj.IsDir() {
|
||||
// create sub-directories - recursively
|
||||
err = CopyDir(sourcefilepointer, destinationfilepointer)
|
||||
if err != nil {
|
||||
// fmt.Println(err)
|
||||
}
|
||||
} else {
|
||||
// perform copy
|
||||
_, err = CopyFile(sourcefilepointer, destinationfilepointer)
|
||||
if err != nil {
|
||||
// fmt.Println(err)
|
||||
}
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func DeleteFile(path string) bool {
|
||||
err := os.Remove(path)
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
func IsDirExists(path string) bool {
|
||||
fi, err := os.Stat(path)
|
||||
if err != nil {
|
||||
return os.IsExist(err)
|
||||
}else{
|
||||
return fi.IsDir()
|
||||
}
|
||||
return false
|
||||
}
|
||||
fi, err := os.Stat(path)
|
||||
if err != nil {
|
||||
return os.IsExist(err)
|
||||
} else {
|
||||
return fi.IsDir()
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// 获得文件str内容
|
||||
func GetFileStrContent(path string) string {
|
||||
fileBytes, err := ioutil.ReadFile(path)
|
||||
if err != nil {
|
||||
return ""
|
||||
}
|
||||
return string(fileBytes)
|
||||
}
|
||||
|
||||
func IsFileExist(filename string) bool {
|
||||
var exist = true
|
||||
if _, err := os.Stat(filename); os.IsNotExist(err) {
|
||||
exist = false
|
||||
}
|
||||
return exist
|
||||
}
|
||||
|
||||
// 写入string内容
|
||||
func PutFileStrContent(path, content string) bool {
|
||||
var f *os.File
|
||||
var err1 error
|
||||
defer (func() {
|
||||
if f != nil {
|
||||
f.Close()
|
||||
}
|
||||
})()
|
||||
f, err1 = os.OpenFile(path, os.O_RDWR|os.O_TRUNC|os.O_CREATE, 0666) //打开文件
|
||||
// Log(err1)
|
||||
// var n int
|
||||
_, err1 = io.WriteString(f, content) //写入文件(字符串)
|
||||
// Log(content)
|
||||
// Log(err1)
|
||||
// Log(n)
|
||||
// Log(path)
|
||||
|
||||
if err1 != nil {
|
||||
Log(err1)
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
@@ -27,6 +27,12 @@ var rulesStr = `{
|
||||
],
|
||||
"domain": [
|
||||
{"rule": "domain", "msg": "errorDomain"}
|
||||
],
|
||||
"perPageSize": [
|
||||
{"rule": "min", "data": "1", "msg": "errorPerPageSize"}
|
||||
],
|
||||
"sortField": [
|
||||
{"rule": "sortField", "msg": "errorSortField"}
|
||||
]
|
||||
}
|
||||
`
|
||||
@@ -49,6 +55,25 @@ var rules = map[string]func(string, map[string]string)(bool, string) {
|
||||
ok = len(value) >= dataI
|
||||
return
|
||||
},
|
||||
"min": func(value string, rule map[string]string)(ok bool, msg string) {
|
||||
if value == "" {
|
||||
return
|
||||
}
|
||||
data := rule["data"]
|
||||
dataI, _ := strconv.Atoi(data)
|
||||
vI, _ := strconv.Atoi(value)
|
||||
ok = vI >= dataI
|
||||
return
|
||||
},
|
||||
|
||||
"sortField": func(value string, rule map[string]string)(ok bool, msg string) {
|
||||
if value == "" {
|
||||
return
|
||||
}
|
||||
sortFields := []string{"PublicTime", "CreatedTime", "UpdatedTime", "Title"}
|
||||
ok = InArray(sortFields, value)
|
||||
return
|
||||
},
|
||||
|
||||
"password": func(value string, rule map[string]string)(ok bool, msg string) {
|
||||
if value == "" {
|
||||
|
||||
@@ -0,0 +1,230 @@
|
||||
package archive
|
||||
|
||||
import (
|
||||
"archive/tar"
|
||||
"compress/gzip"
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
"path"
|
||||
)
|
||||
|
||||
// main functions shows how to TarGz a directory/file and
|
||||
// UnTarGz a file
|
||||
// Gzip and tar from source directory or file to destination file
|
||||
// you need check file exist before you call this function
|
||||
|
||||
func main() {
|
||||
/*
|
||||
os.Mkdir("/home/ty4z2008/tar", 0777)
|
||||
w, err := CopyFile("/home/ty4z2008/tar/1.pdf", "/home/ty4z2008/src/1.pdf")
|
||||
//targetfile,sourcefile
|
||||
if err != nil {
|
||||
fmt.Println(err.Error())
|
||||
}
|
||||
fmt.Println(w)
|
||||
|
||||
TarGz("/home/ty4z2008/tar/1.pdf", "/home/ty4z2008/test.tar.gz") //压缩
|
||||
//UnTarGz("/home/ty4z2008/1.tar.gz", "/home/ty4z2008") //解压
|
||||
os.RemoveAll("/home/ty4z2008/tar")
|
||||
*/
|
||||
// TaZip("/Users/life/Desktop/j", "/Users/life/Desktop/aaa.tar.gz")
|
||||
Zip("/Users/life/Desktop/j", "/Users/life/Desktop/aaa.zip")
|
||||
fmt.Println("ok")
|
||||
}
|
||||
|
||||
func TarGz(srcDirPath string, destFilePath string) (ok bool) {
|
||||
defer func() { //必须要先声明defer,否则不能捕获到panic异常
|
||||
if err := recover(); err != nil {
|
||||
ok = false
|
||||
}
|
||||
|
||||
}()
|
||||
|
||||
fw, err := os.Create(destFilePath)
|
||||
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
defer fw.Close()
|
||||
|
||||
// Gzip writer
|
||||
gw := gzip.NewWriter(fw)
|
||||
defer gw.Close()
|
||||
|
||||
// Tar writer
|
||||
tw := tar.NewWriter(gw)
|
||||
defer tw.Close()
|
||||
|
||||
// Check if it's a file or a directory
|
||||
f, err := os.Open(srcDirPath)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
fi, err := f.Stat()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
if fi.IsDir() {
|
||||
// handle source directory
|
||||
// fmt.Println("Cerating tar.gz from directory...")
|
||||
tarGzDir(srcDirPath, path.Base(srcDirPath), tw)
|
||||
} else {
|
||||
// handle file directly
|
||||
// fmt.Println("Cerating tar.gz from " + fi.Name() + "...")
|
||||
tarGzFile(srcDirPath, fi.Name(), tw, fi)
|
||||
}
|
||||
ok = true
|
||||
return
|
||||
}
|
||||
|
||||
// Deal with directories
|
||||
// if find files, handle them with tarGzFile
|
||||
// Every recurrence append the base path to the recPath
|
||||
// recPath is the path inside of tar.gz
|
||||
func tarGzDir(srcDirPath string, recPath string, tw *tar.Writer) {
|
||||
// Open source diretory
|
||||
dir, err := os.Open(srcDirPath)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
defer dir.Close()
|
||||
|
||||
// Get file info slice
|
||||
fis, err := dir.Readdir(0)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
for _, fi := range fis {
|
||||
// Append path
|
||||
curPath := srcDirPath + "/" + fi.Name()
|
||||
// Check it is directory or file
|
||||
if fi.IsDir() {
|
||||
// Directory
|
||||
// (Directory won't add unitl all subfiles are added)
|
||||
// fmt.Printf("Adding path...%s\n", curPath)
|
||||
tarGzDir(curPath, recPath+"/"+fi.Name(), tw)
|
||||
} else {
|
||||
// File
|
||||
// fmt.Printf("Adding file...%s\n", curPath)
|
||||
}
|
||||
|
||||
tarGzFile(curPath, recPath+"/"+fi.Name(), tw, fi)
|
||||
}
|
||||
}
|
||||
|
||||
// Deal with files
|
||||
func tarGzFile(srcFile string, recPath string, tw *tar.Writer, fi os.FileInfo) {
|
||||
if fi.IsDir() {
|
||||
// fmt.Println("??")
|
||||
// Create tar header
|
||||
hdr := new(tar.Header)
|
||||
// if last character of header name is '/' it also can be directory
|
||||
// but if you don't set Typeflag, error will occur when you untargz
|
||||
hdr.Name = recPath // + "/"
|
||||
// fmt.Println(hdr.Name)
|
||||
hdr.Typeflag = tar.TypeDir
|
||||
// hdr.Size = 0
|
||||
//hdr.Mode = 0755 | c_ISDIR
|
||||
// hdr.Mode = int64(fi.Mode()) // 加这个会有错误!!!
|
||||
// hdr.ModTime = fi.ModTime() // 加这个会有错误!!
|
||||
|
||||
// Write hander
|
||||
err := tw.WriteHeader(hdr)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
} else {
|
||||
// File reader
|
||||
fr, err := os.Open(srcFile)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
defer fr.Close()
|
||||
|
||||
// Create tar header
|
||||
hdr := new(tar.Header)
|
||||
hdr.Name = recPath
|
||||
// fmt.Println(hdr.Name)
|
||||
hdr.Size = fi.Size()
|
||||
hdr.Mode = int64(fi.Mode())
|
||||
hdr.ModTime = fi.ModTime()
|
||||
|
||||
// Write hander
|
||||
err = tw.WriteHeader(hdr)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
// Write file data
|
||||
_, err = io.Copy(tw, fr)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Ungzip and untar from source file to destination directory
|
||||
// you need check file exist before you call this function
|
||||
func UnTarGz(srcFilePath string, destDirPath string) {
|
||||
// fmt.Println("UnTarGzing " + srcFilePath + "...")
|
||||
// Create destination directory
|
||||
os.Mkdir(destDirPath, os.ModePerm)
|
||||
|
||||
fr, err := os.Open(srcFilePath)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
defer fr.Close()
|
||||
|
||||
// Gzip reader
|
||||
gr, err := gzip.NewReader(fr)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
defer gr.Close()
|
||||
|
||||
// Tar reader
|
||||
tr := tar.NewReader(gr)
|
||||
|
||||
for {
|
||||
hdr, err := tr.Next()
|
||||
if err == io.EOF {
|
||||
// End of tar archive
|
||||
break
|
||||
}
|
||||
//handleError(err)
|
||||
// fmt.Println("UnTarGzing file..." + hdr.Name)
|
||||
// Check if it is diretory or file
|
||||
if hdr.Typeflag != tar.TypeDir {
|
||||
// Get files from archive
|
||||
// Create diretory before create file
|
||||
os.MkdirAll(destDirPath+"/"+path.Dir(hdr.Name), os.ModePerm)
|
||||
// Write data to file
|
||||
fw, _ := os.Create(destDirPath + "/" + hdr.Name)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
_, err = io.Copy(fw, tr)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
}
|
||||
// fmt.Println("Well done!")
|
||||
}
|
||||
|
||||
// Copyfile
|
||||
func CopyFile(dstName, srcName string) (written int64, err error) {
|
||||
src, err := os.Open(srcName)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
defer src.Close()
|
||||
dst, err := os.OpenFile(dstName, os.O_WRONLY|os.O_CREATE, 0644)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
defer dst.Close()
|
||||
return io.Copy(dst, src)
|
||||
}
|
||||
@@ -0,0 +1,192 @@
|
||||
package archive
|
||||
|
||||
import (
|
||||
"archive/zip"
|
||||
"fmt"
|
||||
"strings"
|
||||
"io"
|
||||
"os"
|
||||
"path"
|
||||
)
|
||||
|
||||
// main functions shows how to TarGz a directory/file and
|
||||
// UnTarGz a file
|
||||
// Gzip and tar from source directory or file to destination file
|
||||
// you need check file exist before you call this function
|
||||
|
||||
func Zip(srcDirPath string, destFilePath string) (ok bool) {
|
||||
defer func() { //必须要先声明defer,否则不能捕获到panic异常
|
||||
if err := recover(); err != nil {
|
||||
ok = false
|
||||
}
|
||||
}()
|
||||
|
||||
fw, err := os.Create(destFilePath)
|
||||
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
defer fw.Close()
|
||||
|
||||
// Tar writer
|
||||
tw := zip.NewWriter(fw)
|
||||
defer tw.Close()
|
||||
|
||||
// Check if it's a file or a directory
|
||||
f, err := os.Open(srcDirPath)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
fi, err := f.Stat()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
if fi.IsDir() {
|
||||
// handle source directory
|
||||
// fmt.Println("Cerating tar.gz from directory...")
|
||||
zipDir(srcDirPath, path.Base(srcDirPath), tw)
|
||||
} else {
|
||||
// handle file directly
|
||||
// fmt.Println("Cerating tar.gz from " + fi.Name() + "...")
|
||||
zipFile(srcDirPath, fi.Name(), tw, fi)
|
||||
}
|
||||
ok = true
|
||||
return
|
||||
}
|
||||
|
||||
// Deal with directories
|
||||
// if find files, handle them with zipFile
|
||||
// Every recurrence append the base path to the recPath
|
||||
// recPath is the path inside of tar.gz
|
||||
func zipDir(srcDirPath string, recPath string, tw *zip.Writer) {
|
||||
// Open source diretory
|
||||
dir, err := os.Open(srcDirPath)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
defer dir.Close()
|
||||
|
||||
// Get file info slice
|
||||
fis, err := dir.Readdir(0)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
for _, fi := range fis {
|
||||
// Append path
|
||||
curPath := srcDirPath + "/" + fi.Name()
|
||||
// Check it is directory or file
|
||||
if fi.IsDir() {
|
||||
// Directory
|
||||
// (Directory won't add unitl all subfiles are added)
|
||||
// fmt.Printf("Adding path...%s\n", curPath)
|
||||
zipDir(curPath, recPath+"/"+fi.Name(), tw)
|
||||
} else {
|
||||
// File
|
||||
// fmt.Printf("Adding file...%s\n", curPath)
|
||||
}
|
||||
|
||||
zipFile(curPath, recPath+"/"+fi.Name(), tw, fi)
|
||||
}
|
||||
}
|
||||
|
||||
// Deal with files
|
||||
func zipFile(srcFile string, recPath string, tw *zip.Writer, fi os.FileInfo) {
|
||||
if fi.IsDir() {
|
||||
// fmt.Println("??")
|
||||
// Create tar header
|
||||
/*
|
||||
fh, err := zip.FileInfoHeader(fi)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
fh.Name = recPath // + "/"
|
||||
err = tw.WriteHeader(hdr)
|
||||
tw.Create(recPath)
|
||||
*/
|
||||
} else {
|
||||
// File reader
|
||||
fr, err := os.Open(srcFile)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
defer fr.Close()
|
||||
|
||||
// Write hander
|
||||
w, err2 := tw.Create(recPath)
|
||||
if err2 != nil {
|
||||
panic(err)
|
||||
}
|
||||
// Write file data
|
||||
_, err = io.Copy(w, fr)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Ungzip and untar from source file to destination directory
|
||||
// you need check file exist before you call this function
|
||||
func Unzip(srcFilePath string, destDirPath string) (ok bool, msg string) {
|
||||
ok = false
|
||||
msg = ""
|
||||
|
||||
defer func() { //必须要先声明defer,否则不能捕获到panic异常
|
||||
if err := recover(); err != nil {
|
||||
msg = fmt.Sprintf("%v", err)
|
||||
ok = false
|
||||
}
|
||||
}()
|
||||
|
||||
os.Mkdir(destDirPath, os.ModePerm)
|
||||
r, err := zip.OpenReader(srcFilePath);
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
defer r.Close();
|
||||
for _, f := range r.File {
|
||||
// fmt.Println("FileName : ", f.Name); // j/aaa.zip
|
||||
rc, err := f.Open();
|
||||
if err!=nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
// 把首文件夹去掉, 即j去掉, 分离出文件夹和文件名
|
||||
paths := strings.Split(f.Name, "/")
|
||||
prePath := ""
|
||||
filename := ""
|
||||
l := len(paths)
|
||||
// fmt.Println(l)
|
||||
if l > 1 {
|
||||
// 去掉第1个文件夹
|
||||
if l == 2 {
|
||||
filename = paths[1]
|
||||
} else {
|
||||
filename = paths[l-1]
|
||||
prePath = strings.Join(paths[1:l-1], "/")
|
||||
}
|
||||
} else {
|
||||
filename = f.Name
|
||||
}
|
||||
// fmt.Println(prePath)
|
||||
|
||||
// 相对于目标文件件下的路径
|
||||
destPath := destDirPath + "/" + filename
|
||||
if prePath != "" {
|
||||
os.MkdirAll(destDirPath + "/" + prePath, os.ModePerm)
|
||||
destPath = destDirPath + "/" + prePath + "/" + filename
|
||||
}
|
||||
// Write data to file
|
||||
// fmt.Println(destPath)
|
||||
fw, _ := os.Create(destPath)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
_, err = io.Copy(fw, rc)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
|
||||
ok = true
|
||||
return
|
||||
}
|
||||
@@ -0,0 +1,302 @@
|
||||
package blog
|
||||
|
||||
import (
|
||||
. "github.com/leanote/leanote/app/lea"
|
||||
"github.com/revel/revel"
|
||||
"html/template"
|
||||
"io/ioutil"
|
||||
// "os"
|
||||
"fmt"
|
||||
"bytes"
|
||||
"io"
|
||||
"net/http"
|
||||
"regexp"
|
||||
"strconv"
|
||||
"strings"
|
||||
)
|
||||
|
||||
//--------------------
|
||||
// leanote 自定义主题
|
||||
// 不使用revel的模板机制
|
||||
// By life
|
||||
//--------------------
|
||||
|
||||
var ts = []string{"header.html", "footer.html", "highlight.html", "comment.html", "view.html", "404.html"}
|
||||
var selfTs = []string{"header.html", "footer.html", "index.html", "about_me.html"} // 用户自定义的文件列表
|
||||
|
||||
type BlogTpl struct {
|
||||
Template *template.Template
|
||||
PathContent map[string]string // path => content
|
||||
}
|
||||
|
||||
func (this *BlogTpl) Content(name string) string {
|
||||
return this.PathContent[name]
|
||||
}
|
||||
|
||||
var BlogTplObject *BlogTpl
|
||||
var CloneTemplate *template.Template
|
||||
|
||||
type RenderTemplateResult struct {
|
||||
Template *template.Template
|
||||
PathContent map[string]string
|
||||
RenderArgs map[string]interface{}
|
||||
|
||||
IsPreview bool // 是否是预览
|
||||
CurBlogTpl *BlogTpl
|
||||
}
|
||||
|
||||
func parseTemplateError(err error) (templateName string, line int, description string) {
|
||||
description = err.Error()
|
||||
i := regexp.MustCompile(`:\d+:`).FindStringIndex(description)
|
||||
if i != nil {
|
||||
line, err = strconv.Atoi(description[i[0]+1 : i[1]-1])
|
||||
if err != nil {
|
||||
}
|
||||
templateName = description[:i[0]]
|
||||
if colon := strings.Index(templateName, ":"); colon != -1 {
|
||||
templateName = templateName[colon+1:]
|
||||
}
|
||||
templateName = strings.TrimSpace(templateName)
|
||||
description = description[i[1]+1:]
|
||||
}
|
||||
return templateName, line, description
|
||||
}
|
||||
func (r *RenderTemplateResult) render(req *revel.Request, resp *revel.Response, wr io.Writer) {
|
||||
err := r.Template.Execute(wr, r.RenderArgs)
|
||||
if err == nil {
|
||||
return
|
||||
}
|
||||
|
||||
var templateContent []string
|
||||
templateName, line, description := parseTemplateError(err)
|
||||
var content = ""
|
||||
if templateName == "" {
|
||||
templateName = r.Template.Name()
|
||||
content = r.PathContent[templateName]
|
||||
} else {
|
||||
content = r.PathContent[templateName]
|
||||
}
|
||||
if content != "" {
|
||||
templateContent = strings.Split(content, "\n")
|
||||
}
|
||||
|
||||
compileError := &revel.Error{
|
||||
Title: "Template Execution Error",
|
||||
Path: templateName,
|
||||
Description: description,
|
||||
Line: line,
|
||||
SourceLines: templateContent,
|
||||
}
|
||||
|
||||
// 这里, 错误!!
|
||||
// 这里应该导向到本主题的错误页面
|
||||
resp.Status = 500
|
||||
ErrorResult{r.RenderArgs, compileError, r.IsPreview, r.CurBlogTpl}.Apply(req, resp)
|
||||
}
|
||||
|
||||
func (r *RenderTemplateResult) Apply(req *revel.Request, resp *revel.Response) {
|
||||
// Handle panics when rendering templates.
|
||||
defer func() {
|
||||
if err := recover(); err != nil {
|
||||
}
|
||||
}()
|
||||
|
||||
chunked := revel.Config.BoolDefault("results.chunked", false)
|
||||
|
||||
// If it's a HEAD request, throw away the bytes.
|
||||
out := io.Writer(resp.Out)
|
||||
if req.Method == "HEAD" {
|
||||
out = ioutil.Discard
|
||||
}
|
||||
|
||||
// In a prod mode, write the status, render, and hope for the best.
|
||||
// (In a dev mode, always render to a temporary buffer first to avoid having
|
||||
// error pages distorted by HTML already written)
|
||||
if chunked && !revel.DevMode {
|
||||
resp.WriteHeader(http.StatusOK, "text/html; charset=utf-8")
|
||||
r.render(req, resp, out) // 这里!!!
|
||||
return
|
||||
}
|
||||
|
||||
// Render the template into a temporary buffer, to see if there was an error
|
||||
// rendering the template. If not, then copy it into the response buffer.
|
||||
// Otherwise, template render errors may result in unpredictable HTML (and
|
||||
// would carry a 200 status code)
|
||||
var b bytes.Buffer
|
||||
r.render(req, resp, &b)
|
||||
if !chunked {
|
||||
resp.Out.Header().Set("Content-Length", strconv.Itoa(b.Len()))
|
||||
}
|
||||
resp.WriteHeader(http.StatusOK, "text/html; charset=utf-8")
|
||||
b.WriteTo(out)
|
||||
}
|
||||
|
||||
// 博客模板
|
||||
func Init() {
|
||||
BlogTplObject = &BlogTpl{PathContent: map[string]string{}}
|
||||
BlogTplObject.Template = template.New("blog").Funcs(revel.TemplateFuncs)
|
||||
for _, path := range ts {
|
||||
fileBytes, _ := ioutil.ReadFile(revel.ViewsPath + "/Blog/" + path)
|
||||
fileStr := string(fileBytes)
|
||||
path := "blog/" + path
|
||||
// path := path
|
||||
BlogTplObject.PathContent[path] = fileStr
|
||||
BlogTplObject.Template.New(path).Parse(fileStr) // 以blog为根
|
||||
}
|
||||
// 复制一份
|
||||
CloneTemplate, _ = BlogTplObject.Template.Clone()
|
||||
}
|
||||
|
||||
// name = index.html, search.html, cate.html, page.html
|
||||
// basePath 表未用户主题的基路径, 如/xxx/public/upload/32323232/themes/theme1, 如果没有, 则表示用自带的
|
||||
// isPreview 如果是, 错误提示则显示系统的 500 错误详情信息, 供debug
|
||||
//
|
||||
func RenderTemplate(name string, args map[string]interface{}, basePath string, isPreview bool) revel.Result {
|
||||
var r *RenderTemplateResult
|
||||
// 传来的主题路径为空, 则用系统的
|
||||
// 都不会为空的
|
||||
if basePath == "" {
|
||||
path := "blog/" + name
|
||||
// path := name
|
||||
t := BlogTplObject.Template.Lookup(path)
|
||||
r = &RenderTemplateResult{
|
||||
Template: t,
|
||||
PathContent: BlogTplObject.PathContent, // 为了显示错误
|
||||
RenderArgs: args, // 把args给它
|
||||
}
|
||||
} else {
|
||||
// 复制一份
|
||||
newBlogTplObject := &BlogTpl{}
|
||||
var err error
|
||||
newBlogTplObject.Template, err = CloneTemplate.Clone() // 复制一份, 为防止多用户出现问题, 因为newBlogTplObject是全局的
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
newBlogTplObject.PathContent = map[string]string{}
|
||||
for k, v := range BlogTplObject.PathContent {
|
||||
newBlogTplObject.PathContent[k] = v
|
||||
}
|
||||
|
||||
// 将该basePath下的所有文件提出
|
||||
files := ListDir(basePath)
|
||||
Log(basePath)
|
||||
LogJ(files);
|
||||
for _, t := range files {
|
||||
if !strings.Contains(t, ".html") {
|
||||
continue;
|
||||
}
|
||||
fileBytes, err := ioutil.ReadFile(basePath + "/" + t)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
fileStr := string(fileBytes)
|
||||
newBlogTplObject.PathContent[t] = fileStr
|
||||
newBlogTplObject.Template.New(t).Parse(fileStr)
|
||||
}
|
||||
|
||||
// 如果本主题下没有, 则用系统的
|
||||
t := newBlogTplObject.Template.Lookup(name)
|
||||
|
||||
if t == nil {
|
||||
path := "blog/" + name
|
||||
t = BlogTplObject.Template.Lookup(path)
|
||||
}
|
||||
r = &RenderTemplateResult{
|
||||
Template: t,
|
||||
PathContent: newBlogTplObject.PathContent, // 为了显示错误
|
||||
RenderArgs: args,
|
||||
CurBlogTpl: newBlogTplObject,
|
||||
IsPreview: isPreview,
|
||||
}
|
||||
}
|
||||
|
||||
return r
|
||||
}
|
||||
|
||||
|
||||
////////////////////
|
||||
// 错误显示
|
||||
|
||||
type ErrorResult struct {
|
||||
RenderArgs map[string]interface{}
|
||||
Error error
|
||||
IsPreview bool
|
||||
CurBlogTpl *BlogTpl
|
||||
}
|
||||
|
||||
// 错误显示出
|
||||
func (r ErrorResult) Apply(req *revel.Request, resp *revel.Response) {
|
||||
format := req.Format
|
||||
status := resp.Status
|
||||
if status == 0 {
|
||||
status = http.StatusInternalServerError
|
||||
}
|
||||
|
||||
contentType := revel.ContentTypeByFilename("xxx." + format)
|
||||
if contentType == revel.DefaultFileContentType {
|
||||
contentType = "text/plain"
|
||||
}
|
||||
|
||||
// Get the error template.
|
||||
var err error
|
||||
templatePath := fmt.Sprintf("errors/%d.%s", status, format)
|
||||
err = nil
|
||||
// tmpl, err := revel.MainTemplateLoader.Template("index.html") // 这里找到错误页面主题
|
||||
|
||||
// This func shows a plaintext error message, in case the template rendering
|
||||
// doesn't work.
|
||||
showPlaintext := func(err error) {
|
||||
revel.PlaintextErrorResult{fmt.Errorf("Server Error:\n%s\n\n"+
|
||||
"Additionally, an error occurred when rendering the error page:\n%s",
|
||||
r.Error, err)}.Apply(req, resp)
|
||||
}
|
||||
|
||||
// 根据是否是preview来得到404模板
|
||||
// 是, 则显示系统的错误信息, blog-500.html
|
||||
var tmpl *template.Template
|
||||
if r.IsPreview {
|
||||
tmpl = r.CurBlogTpl.Template.Lookup("blog/404.html")
|
||||
} else {
|
||||
tmpl = r.CurBlogTpl.Template.Lookup("404.html")
|
||||
}
|
||||
if tmpl == nil {
|
||||
if err == nil {
|
||||
err = fmt.Errorf("Couldn't find template %s", templatePath)
|
||||
}
|
||||
showPlaintext(err)
|
||||
return
|
||||
}
|
||||
|
||||
// If it's not a revel error, wrap it in one.
|
||||
var revelError *revel.Error
|
||||
switch e := r.Error.(type) {
|
||||
case *revel.Error:
|
||||
revelError = e
|
||||
case error:
|
||||
revelError = &revel.Error{
|
||||
Title: "Server Error",
|
||||
Description: e.Error(),
|
||||
}
|
||||
}
|
||||
|
||||
if revelError == nil {
|
||||
panic("no error provided")
|
||||
}
|
||||
|
||||
if r.RenderArgs == nil {
|
||||
r.RenderArgs = make(map[string]interface{})
|
||||
}
|
||||
r.RenderArgs["Error"] = revelError
|
||||
r.RenderArgs["Router"] = revel.MainRouter
|
||||
|
||||
// 不是preview就不要显示错误了
|
||||
LogJ(revelError)
|
||||
// if r.IsPreview {
|
||||
var b bytes.Buffer
|
||||
out := io.Writer(resp.Out)
|
||||
// out = ioutil.Discard
|
||||
err = tmpl.Execute(&b, r.RenderArgs)
|
||||
resp.WriteHeader(http.StatusOK, "text/html; charset=utf-8")
|
||||
b.WriteTo(out)
|
||||
// }
|
||||
}
|
||||
@@ -3,6 +3,7 @@ import (
|
||||
"strings"
|
||||
"os"
|
||||
// "path/filepath"
|
||||
"net"
|
||||
"net/http"
|
||||
"io/ioutil"
|
||||
. "github.com/leanote/leanote/app/lea"
|
||||
@@ -89,4 +90,13 @@ func trimQueryParams(url string) string {
|
||||
url = Substr(url, 0, pos);
|
||||
}
|
||||
return url;
|
||||
}
|
||||
|
||||
// 通过domain得到ip
|
||||
func GetIpFromDomain(domain string) string {
|
||||
ip, _ := net.LookupIP(domain)
|
||||
if ip != nil && len(ip) > 0 {
|
||||
return ip[0].String()
|
||||
}
|
||||
return ""
|
||||
}
|
||||
@@ -44,8 +44,12 @@ func RouterFilter(c *revel.Controller, fc []revel.Filter) {
|
||||
if route.ControllerName != "Static" {
|
||||
// api设置
|
||||
// leanote.com/api/user/get => ApiUser::Get
|
||||
if strings.HasPrefix(path, "/api/") || strings.HasPrefix(path, "api/") {
|
||||
//* /api/login ApiAuth.Login, 这里的设置, 其实已经转成了ApiAuth了
|
||||
if strings.HasPrefix(path, "/api") && !strings.HasPrefix(route.ControllerName, "Api"){
|
||||
route.ControllerName = "Api" + route.ControllerName
|
||||
} else if strings.HasPrefix(path, "/member") && !strings.HasPrefix(route.ControllerName, "Member") {
|
||||
// member设置
|
||||
route.ControllerName = "Member" + route.ControllerName
|
||||
}
|
||||
// end
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user