local sql = require("sqlite3") local session = require("session") local tags = require("tags") local db = require("db") local queries = require("queries") local util = require("util") local cache = require("cache") local pages = require("pages") local config = require("config") local stmnt_read, stmnt_update_views, stmnt_comments local oldconfigure = configure function configure(...) stmnt_read = assert(db.conn:prepare(queries.select_post)) stmnt_update_views = assert(db.conn:prepare(queries.update_views)) stmnt_comments = assert(db.conn:prepare(queries.select_comments)) return oldconfigure(...) end --[[ Increases a story's hit counter by 1 ]] local function add_view(storyid) stmnt_update_views:bind_names{ id = storyid } local err = util.do_sql(stmnt_update_views) assert(err == sql.DONE, "Failed to update view counter:"..tostring(err)) stmnt_update_views:reset() end --[[ Populates ps with story settings, returns true if story was found, or nil if it wasn't ]] local function populate_ps_story(req,ps) --Make sure our story exists stmnt_read:bind_names{ id = ps.storyid, } local err = util.do_sql(stmnt_read) if err == sql.DONE then --We got no story stmnt_read:reset() log(LOG_DEBUG,"No story with id:" .. ps.storyid) return false end --If we've made it here, we have a story. Populate our settings --with title, text, ect. assert(err == sql.ROW) local title, storytext, tauthor, isanon, authorname, views, unlisted, hash = unpack( stmnt_read:get_values() ) ps.unlisted = unlisted == 1 if ps.unlisted and hash ~= ps.hash then log(LOG_DEBUG,"Tried to get story id:" .. ps.storyid .. " but it was unlisted and hash was incorrect.") stmnt_read:reset() return false end ps.title = title ps.text = zlib.decompress(storytext) ps.tauthor = tauthor ps.isanon = isanon == 1 ps.author = authorname ps.views = views stmnt_read:reset() --Tags ps.tags = tags.get(ps.storyid) return true end --[[ Get the comments for a story ]] local function get_comments(req,ps) stmnt_comments:bind_names{ id = ps.storyid } local comments = {} for com_author, com_isanon, com_text in util.sql_rows(stmnt_comments) do table.insert(comments,{ author = com_author, isanon = com_isanon == 1, --int to boolean text = com_text }) end return comments end local function read_get(req) --Pages settings local ps = { domain = config.domain, host = http_request_get_host(req), path = http_request_get_path(req), method = http_method_text(req), } --Get our story id assert(string.len(ps.path) > 0,"Tried to read 0-length story id") ps.idp = string.sub(ps.path,2)--remove leading "/" ps.storyid = util.decode_id(ps.idp) add_view(ps.storyid) --If we're logged in, set author and authorid local author, authorid = session.get(req) if author and authorid then ps.loggedauthor = author ps.iam = author ps.loggedauthorid = authorid end --If we need to show comments http_request_populate_qs(req) ps.show_comments = http_argument_get_string(req,"comments") if ps.show_comments then ps.comments = get_comments(req,ps) end --If this post is unlisted, get the hash local hashstr = http_argument_get_string(req,"pwd") if hashstr then ps.hash = util.decode_unlisted(hashstr) ps.hashstr = hashstr end local text --normal story display if (not ps.loggedauthor) then local params = {} if ps.show_comments then table.insert(params,"comments=1") end if ps.hash then table.insert(params,"pwd=" .. hashstr) end local cachestrparts = { ps.host, ps.path, } if #params > 0 then table.insert(cachestrparts,"?") table.insert(cachestrparts,table.concat(params,"&")) end local cachestr = table.concat(cachestrparts) text = cache.render(cachestr,function() log(LOG_DEBUG,"Cache miss, rendering story " .. cachestr) if not populate_ps_story(req,ps) then return pages.nostory(ps) end local output = pages.read(ps) assert(output,"failed to read page:" .. cachestr) return output end) else --we are logged in, don't cache if not populate_ps_story(req,ps) then text = pages.nostory(ps) else ps.owner = (ps.loggedauthorid == ps.tauthor) text = pages.read(ps) end end assert(text) http_response(req,200,text) return end return read_get