Exemple #1
0
func handleCls(c *Context, w http.ResponseWriter) error {
	vars := mux.Vars(c.R)
	bid, err := strconv.Atoi(vars["bid"])
	if err != nil {
		return err
	}

	children, err := ptt.GetBoardChildren(bid)
	if err != nil {
		return err
	}

	boards := make([]pttbbs.Board, 0, 16)
	for _, bid := range children {
		if brd, err := ptt.GetBoard(bid); err == nil {
			if pttbbs.IsValidBrdName(brd.BrdName) && !brd.Over18 && !brd.Hidden {
				boards = append(boards, brd)
			}
		}
	}

	return page.ExecutePage(w, &page.Classlist{
		Boards: boards,
	})
}
Exemple #2
0
func internalError(w http.ResponseWriter, err error) {
	log.Println(err)
	w.WriteHeader(http.StatusInternalServerError)
	page.ExecutePage(w, &page.Error{
		Title:       `500 - Internal Server Error`,
		ContentHtml: `500 - Internal Server Error / Server Too Busy.`,
	})
}
Exemple #3
0
func handleManIndex(c *Context, w http.ResponseWriter, brd *pttbbs.Board, path string) error {
	res, err := mand.List(context.TODO(), &bbspb.ListRequest{
		BoardName: brd.BrdName,
		Path:      path,
	}, grpc.FailFast(true))
	if err != nil {
		return translateMandError(err)
	}
	return page.ExecutePage(w, &page.ManIndex{
		Board:   *brd,
		Path:    path,
		Entries: res.Entries,
	})
}
Exemple #4
0
func errorWrapperHandler(f func(*Context, http.ResponseWriter) error) func(http.ResponseWriter, *http.Request) {
	return func(w http.ResponseWriter, r *http.Request) {
		setCommonResponseHeaders(w)

		if err := clarifyRemoteError(handleRequest(w, r, f)); err != nil {
			if pg, ok := err.(page.Page); ok {
				if err = page.ExecutePage(w, pg); err != nil {
					log.Println("Failed to emit error page:", err)
				}
				return
			}
			internalError(w, err)
		}
	}
}
Exemple #5
0
func handleManArticle(c *Context, w http.ResponseWriter, brd *pttbbs.Board, path string) error {
	obj, err := cacheMgr.Get(&ArticleRequest{
		Namespace: "man",
		Brd:       *brd,
		Filename:  path,
		Select: func(m pttbbs.SelectMethod, offset, maxlen int) (*pttbbs.ArticlePart, error) {
			res, err := mand.Article(context.TODO(), &bbspb.ArticleRequest{
				BoardName:  brd.BrdName,
				Path:       path,
				SelectType: manSelectType(m),
				Offset:     int64(offset),
				MaxLength:  int64(maxlen),
			}, grpc.FailFast(true))
			if err != nil {
				return nil, translateMandError(err)
			}
			return &pttbbs.ArticlePart{
				CacheKey: res.CacheKey,
				FileSize: int(res.FileSize),
				Offset:   int(res.SelectedOffset),
				Length:   int(res.SelectedSize),
				Content:  res.Content,
			}, nil
		},
	}, ZeroArticle, ArticleCacheTimeout, generateArticle)
	if err != nil {
		return err
	}
	ar := obj.(*Article)

	if !ar.IsValid {
		return NewNotFoundError(nil)
	}

	if len(ar.ContentHtml) > TruncateSize {
		log.Println("Large rendered article:", brd.BrdName, path, len(ar.ContentHtml))
	}

	return page.ExecutePage(w, &page.ManArticle{
		Title:            ar.ParsedTitle,
		Description:      ar.PreviewContent,
		Board:            brd,
		Path:             path,
		ContentHtml:      string(ar.ContentHtml),
		ContentTailHtml:  string(ar.ContentTailHtml),
		ContentTruncated: ar.IsTruncated,
	})
}
Exemple #6
0
func handleArticleCommon(c *Context, w http.ResponseWriter, brdname, filename string) error {
	var err error

	brd, err := getBoardByName(c, brdname)
	if err != nil {
		return err
	}

	// Render content
	obj, err := cacheMgr.Get(&ArticleRequest{
		Namespace: "bbs",
		Brd:       *brd,
		Filename:  filename,
		Select: func(m pttbbs.SelectMethod, offset, maxlen int) (*pttbbs.ArticlePart, error) {
			return ptt.GetArticleSelect(brd.Bid, m, filename, "", offset, maxlen)
		},
	}, ZeroArticle, ArticleCacheTimeout, generateArticle)
	// Try older filename when not found.
	if err == pttbbs.ErrNotFound {
		if name, ok := oldFilename(filename); ok {
			if handleArticleCommon(c, w, brdname, name) == nil {
				return nil
			}
		}
	}
	if err != nil {
		return err
	}
	ar := obj.(*Article)

	if !ar.IsValid {
		return NewNotFoundError(nil)
	}

	if len(ar.ContentHtml) > TruncateSize {
		log.Println("Large rendered article:", brd.BrdName, filename, len(ar.ContentHtml))
	}

	return page.ExecutePage(w, &page.BbsArticle{
		Title:            ar.ParsedTitle,
		Description:      ar.PreviewContent,
		Board:            brd,
		FileName:         filename,
		ContentHtml:      string(ar.ContentHtml),
		ContentTailHtml:  string(ar.ContentTailHtml),
		ContentTruncated: ar.IsTruncated,
	})
}
Exemple #7
0
func handleAskOver18(c *Context, w http.ResponseWriter) error {
	from := c.R.FormValue("from")
	if from == "" || !isSafeRedirectURI(from) {
		from = "/"
	}

	if c.R.Method == "POST" {
		if c.R.PostFormValue("yes") != "" {
			setOver18Cookie(w)
			w.Header().Set("Location", from)
		} else {
			w.Header().Set("Location", "/")
		}
		w.WriteHeader(http.StatusFound)
		return nil
	} else {
		return page.ExecutePage(w, &page.AskOver18{
			From: from,
		})
	}
}
Exemple #8
0
func handleClsWithBid(c *Context, w http.ResponseWriter, bid int) error {
	if bid < 1 {
		return NewNotFoundError(fmt.Errorf("invalid bid: %v", bid))
	}

	children, err := ptt.GetBoardChildren(bid)
	if err != nil {
		return err
	}

	boards := make([]pttbbs.Board, 0, 16)
	for _, bid := range children {
		if brd, err := ptt.GetBoard(bid); err == nil {
			if pttbbs.IsValidBrdName(brd.BrdName) && !brd.Over18 && !brd.Hidden {
				boards = append(boards, brd)
			}
		}
	}

	return page.ExecutePage(w, &page.Classlist{
		Boards: boards,
	})
}
Exemple #9
0
func handleBbs(c *Context, w http.ResponseWriter) error {
	vars := mux.Vars(c.R)
	brdname := vars["brdname"]

	// Note: TODO move timeout into the generating function.
	// We don't know if it is the last page without entry count.
	pageNo := 0
	timeout := BbsIndexLastPageCacheTimeout

	if pg, err := strconv.Atoi(vars["page"]); err == nil {
		pageNo = pg
		timeout = BbsIndexCacheTimeout
	}

	var err error

	brd, err := getBoardByName(c, brdname)
	if err != nil {
		return err
	}

	obj, err := cacheMgr.Get(&BbsIndexRequest{
		Brd:  *brd,
		Page: pageNo,
	}, ZeroBbsIndex, timeout, generateBbsIndex)
	if err != nil {
		return err
	}
	bbsindex := obj.(*BbsIndex)

	if !bbsindex.IsValid {
		return NewNotFoundError(fmt.Errorf("not a valid cache.BbsIndex: %v/%v", brd.BrdName, pageNo))
	}

	return page.ExecutePage(w, (*page.BbsIndex)(bbsindex))
}
Exemple #10
0
func handleArticleCommon(c *Context, w http.ResponseWriter, brdname, filename string) error {
	var err error

	brd, err := getBoardByName(c, brdname)
	if err != nil {
		return err
	}

	// Render content
	obj, err := cacheMgr.Get(&ArticleRequest{
		Brd:      *brd,
		Filename: filename,
	}, ZeroArticle, ArticleCacheTimeout, generateArticle)
	if err != nil {
		return err
	}
	ar := obj.(*Article)

	if !ar.IsValid {
		return NewNotFoundError(nil)
	}

	if len(ar.ContentHtml) > TruncateSize {
		log.Println("Large rendered article:", brd.BrdName, filename, len(ar.ContentHtml))
	}

	return page.ExecutePage(w, &page.BbsArticle{
		Title:            ar.ParsedTitle,
		Description:      ar.PreviewContent,
		Board:            brd,
		FileName:         filename,
		ContentHtml:      string(ar.ContentHtml),
		ContentTailHtml:  string(ar.ContentTailHtml),
		ContentTruncated: ar.IsTruncated,
	})
}