| 
									
										
										
										
											2017-04-03 10:00:38 -04:00
										 |  |  | package srnd | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | import ( | 
					
						
							|  |  |  | 	"encoding/json" | 
					
						
							|  |  |  | 	"io/ioutil" | 
					
						
							|  |  |  | 	"net/http" | 
					
						
							|  |  |  | 	"path/filepath" | 
					
						
							|  |  |  | 	"strconv" | 
					
						
							|  |  |  | 	"strings" | 
					
						
							|  |  |  | ) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | type NullCache struct { | 
					
						
							|  |  |  | 	regenThreadChan chan ArticleEntry | 
					
						
							|  |  |  | 	regenGroupChan  chan groupRegenRequest | 
					
						
							|  |  |  | 	handler         *nullHandler | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | type nullHandler struct { | 
					
						
							|  |  |  | 	database       Database | 
					
						
							|  |  |  | 	attachments    bool | 
					
						
							|  |  |  | 	requireCaptcha bool | 
					
						
							|  |  |  | 	name           string | 
					
						
							|  |  |  | 	prefix         string | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (self *nullHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { | 
					
						
							|  |  |  | 	path := r.URL.Path | 
					
						
							|  |  |  | 	_, file := filepath.Split(path) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	isjson := strings.HasSuffix(path, "/json") || strings.HasSuffix(path, "/json/") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if strings.HasPrefix(path, "/t/") { | 
					
						
							|  |  |  | 		// thread handler | 
					
						
							|  |  |  | 		parts := strings.Split(path[3:], "/") | 
					
						
							|  |  |  | 		hash := parts[0] | 
					
						
							|  |  |  | 		msg, err := self.database.GetMessageIDByHash(hash) | 
					
						
							|  |  |  | 		if err == nil { | 
					
						
							| 
									
										
										
										
											2017-08-03 12:09:11 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  | 			if !db.HasArticleLocal(msg.MessageID()) { | 
					
						
							|  |  |  | 				goto notfound | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-04-03 10:00:38 -04:00
										 |  |  | 			template.genThread(self.attachments, self.requireCaptcha, msg, self.prefix, self.name, w, self.database, isjson) | 
					
						
							|  |  |  | 			return | 
					
						
							|  |  |  | 		} else { | 
					
						
							|  |  |  | 			goto notfound | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	if strings.Trim(path, "/") == "overboard" { | 
					
						
							|  |  |  | 		// generate ukko aka overboard | 
					
						
							|  |  |  | 		template.genUkko(self.prefix, self.name, w, self.database, isjson) | 
					
						
							|  |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if strings.HasPrefix(path, "/b/") { | 
					
						
							|  |  |  | 		// board handler | 
					
						
							|  |  |  | 		parts := strings.Split(path[3:], "/") | 
					
						
							|  |  |  | 		page := 0 | 
					
						
							|  |  |  | 		group := parts[0] | 
					
						
							|  |  |  | 		if len(parts) > 1 && parts[1] != "" && parts[1] != "json" { | 
					
						
							|  |  |  | 			var err error | 
					
						
							|  |  |  | 			page, err = strconv.Atoi(parts[1]) | 
					
						
							|  |  |  | 			if err != nil { | 
					
						
							|  |  |  | 				goto notfound | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		hasgroup := self.database.HasNewsgroup(group) | 
					
						
							|  |  |  | 		if !hasgroup { | 
					
						
							|  |  |  | 			goto notfound | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		pages := self.database.GetGroupPageCount(group) | 
					
						
							|  |  |  | 		if page >= int(pages) { | 
					
						
							|  |  |  | 			goto notfound | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		template.genBoardPage(self.attachments, self.requireCaptcha, self.prefix, self.name, group, page, w, self.database, isjson) | 
					
						
							|  |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if strings.HasPrefix(path, "/o/") { | 
					
						
							|  |  |  | 		page := 0 | 
					
						
							|  |  |  | 		parts := strings.Split(path[3:], "/") | 
					
						
							|  |  |  | 		if parts[0] != "json" && parts[0] != "" { | 
					
						
							|  |  |  | 			var err error | 
					
						
							|  |  |  | 			page, err = strconv.Atoi(parts[0]) | 
					
						
							|  |  |  | 			if err != nil { | 
					
						
							|  |  |  | 				goto notfound | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		template.genUkkoPaginated(self.prefix, self.name, w, self.database, page, isjson) | 
					
						
							|  |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if len(file) == 0 || file == "index.html" { | 
					
						
							|  |  |  | 		template.genFrontPage(10, self.prefix, self.name, w, ioutil.Discard, self.database) | 
					
						
							|  |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if file == "index.json" { | 
					
						
							|  |  |  | 		// TODO: index.json | 
					
						
							|  |  |  | 		goto notfound | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	if strings.HasPrefix(file, "history.html") { | 
					
						
							|  |  |  | 		template.genGraphs(self.prefix, w, self.database) | 
					
						
							|  |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	if strings.HasPrefix(file, "boards.html") { | 
					
						
							| 
									
										
										
										
											2017-04-03 21:35:09 -04:00
										 |  |  | 		template.genBoardList(self.prefix, self.name, w, self.database) | 
					
						
							| 
									
										
										
										
											2017-04-03 10:00:38 -04:00
										 |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if strings.HasPrefix(file, "boards.json") { | 
					
						
							|  |  |  | 		b := self.database.GetAllNewsgroups() | 
					
						
							|  |  |  | 		json.NewEncoder(w).Encode(b) | 
					
						
							|  |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if strings.HasPrefix(file, "ukko.html") { | 
					
						
							|  |  |  | 		template.genUkko(self.prefix, self.name, w, self.database, false) | 
					
						
							|  |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	if strings.HasPrefix(file, "ukko.json") { | 
					
						
							|  |  |  | 		template.genUkko(self.prefix, self.name, w, self.database, true) | 
					
						
							|  |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if strings.HasPrefix(file, "ukko-") { | 
					
						
							|  |  |  | 		page := getUkkoPage(file) | 
					
						
							|  |  |  | 		template.genUkkoPaginated(self.prefix, self.name, w, self.database, page, isjson) | 
					
						
							|  |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	if strings.HasPrefix(file, "thread-") { | 
					
						
							|  |  |  | 		hash := getThreadHash(file) | 
					
						
							|  |  |  | 		if len(hash) == 0 { | 
					
						
							|  |  |  | 			goto notfound | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2017-08-03 12:07:12 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-04-03 10:00:38 -04:00
										 |  |  | 		msg, err := self.database.GetMessageIDByHash(hash) | 
					
						
							|  |  |  | 		if err != nil { | 
					
						
							|  |  |  | 			goto notfound | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2017-08-03 12:07:12 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		if !self.database.HasArticleLocal(msg.MessageID()) { | 
					
						
							|  |  |  | 			goto notfound | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-04-03 10:00:38 -04:00
										 |  |  | 		template.genThread(self.attachments, self.requireCaptcha, msg, self.prefix, self.name, w, self.database, isjson) | 
					
						
							|  |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	if strings.HasPrefix(file, "catalog-") { | 
					
						
							|  |  |  | 		group := getGroupForCatalog(file) | 
					
						
							|  |  |  | 		if len(group) == 0 { | 
					
						
							|  |  |  | 			goto notfound | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		hasgroup := self.database.HasNewsgroup(group) | 
					
						
							|  |  |  | 		if !hasgroup { | 
					
						
							|  |  |  | 			goto notfound | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		template.genCatalog(self.prefix, self.name, group, w, self.database) | 
					
						
							|  |  |  | 		return | 
					
						
							|  |  |  | 	} else { | 
					
						
							|  |  |  | 		group, page := getGroupAndPage(file) | 
					
						
							|  |  |  | 		if len(group) == 0 || page < 0 { | 
					
						
							|  |  |  | 			goto notfound | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		hasgroup := self.database.HasNewsgroup(group) | 
					
						
							|  |  |  | 		if !hasgroup { | 
					
						
							|  |  |  | 			goto notfound | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		pages := self.database.GetGroupPageCount(group) | 
					
						
							|  |  |  | 		if page >= int(pages) { | 
					
						
							|  |  |  | 			goto notfound | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		template.genBoardPage(self.attachments, self.requireCaptcha, self.prefix, self.name, group, page, w, self.database, isjson) | 
					
						
							|  |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | notfound: | 
					
						
							|  |  |  | 	template.renderNotFound(w, r, self.prefix, self.name) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (self *NullCache) DeleteBoardMarkup(group string) { | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // try to delete root post's page | 
					
						
							|  |  |  | func (self *NullCache) DeleteThreadMarkup(root_post_id string) { | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // regen every newsgroup | 
					
						
							|  |  |  | func (self *NullCache) RegenAll() { | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (self *NullCache) RegenFrontPage() { | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (self *NullCache) SetRequireCaptcha(required bool) { | 
					
						
							|  |  |  | 	self.handler.requireCaptcha = required | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (self *NullCache) pollRegen() { | 
					
						
							|  |  |  | 	for { | 
					
						
							|  |  |  | 		select { | 
					
						
							|  |  |  | 		// consume regen requests | 
					
						
							|  |  |  | 		case _ = <-self.regenGroupChan: | 
					
						
							|  |  |  | 			{ | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		case _ = <-self.regenThreadChan: | 
					
						
							|  |  |  | 			{ | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // regen every page of the board | 
					
						
							|  |  |  | func (self *NullCache) RegenerateBoard(group string) { | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // regenerate pages after a mod event | 
					
						
							|  |  |  | func (self *NullCache) RegenOnModEvent(newsgroup, msgid, root string, page int) { | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (self *NullCache) Start() { | 
					
						
							|  |  |  | 	go self.pollRegen() | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (self *NullCache) Regen(msg ArticleEntry) { | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (self *NullCache) GetThreadChan() chan ArticleEntry { | 
					
						
							|  |  |  | 	return self.regenThreadChan | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (self *NullCache) GetGroupChan() chan groupRegenRequest { | 
					
						
							|  |  |  | 	return self.regenGroupChan | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (self *NullCache) GetHandler() http.Handler { | 
					
						
							|  |  |  | 	return self.handler | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (self *NullCache) Close() { | 
					
						
							|  |  |  | 	//nothig to do | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func NewNullCache(prefix, webroot, name string, attachments bool, db Database, store ArticleStore) CacheInterface { | 
					
						
							|  |  |  | 	cache := new(NullCache) | 
					
						
							|  |  |  | 	cache.regenThreadChan = make(chan ArticleEntry, 16) | 
					
						
							|  |  |  | 	cache.regenGroupChan = make(chan groupRegenRequest, 8) | 
					
						
							|  |  |  | 	cache.handler = &nullHandler{ | 
					
						
							|  |  |  | 		prefix:         prefix, | 
					
						
							|  |  |  | 		name:           name, | 
					
						
							|  |  |  | 		attachments:    attachments, | 
					
						
							|  |  |  | 		requireCaptcha: true, | 
					
						
							|  |  |  | 		database:       db, | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return cache | 
					
						
							|  |  |  | } |