Organize lua endpoints
Move all endpoints under the src/lua/endpoints folder, and delete the previous location.
This commit is contained in:
parent
a640096bdd
commit
a45d0787a2
1
Makefile
1
Makefile
|
@ -34,6 +34,7 @@ $(chroot_dir): apk-tools-static-$(version).apk
|
||||||
mkdir -p $(chroot_dir)/pages
|
mkdir -p $(chroot_dir)/pages
|
||||||
mkdir -p $(chroot_dir)/sql
|
mkdir -p $(chroot_dir)/sql
|
||||||
mkdir -p $(chroot_dir)/data
|
mkdir -p $(chroot_dir)/data
|
||||||
|
mkdir -p $(chroot_dir)/endpoints
|
||||||
#cd $(chroot_dir) && tar -xvzf ../apk-tools-static-*.apk
|
#cd $(chroot_dir) && tar -xvzf ../apk-tools-static-*.apk
|
||||||
#cd $(chroot_dir) && sudo ./sbin/apk.static -X $(mirror)latest-stable/main -U --allow-untrusted --root $(chroot_dir) --no-cache --initdb add alpine-base
|
#cd $(chroot_dir) && sudo ./sbin/apk.static -X $(mirror)latest-stable/main -U --allow-untrusted --root $(chroot_dir) --no-cache --initdb add alpine-base
|
||||||
#ln -s /dev/urandom $(chroot_dir)/dev/random #Prevent an attacker with access to the chroot from exhausting our entropy pool and causing a dos
|
#ln -s /dev/urandom $(chroot_dir)/dev/random #Prevent an attacker with access to the chroot from exhausting our entropy pool and causing a dos
|
||||||
|
|
|
@ -1,16 +0,0 @@
|
||||||
local cache = require("cache")
|
|
||||||
local config = require("config")
|
|
||||||
local pages = require("pages")
|
|
||||||
|
|
||||||
|
|
||||||
local function claim_get(req)
|
|
||||||
--Get the page to claim a name
|
|
||||||
local cachestr = string.format("%s/_claim",config.domain)
|
|
||||||
local text = cache.render(cachestr,function()
|
|
||||||
print("cache miss, rendering claim page")
|
|
||||||
return pages.claim{err=""}
|
|
||||||
end)
|
|
||||||
http_response(req,200,text)
|
|
||||||
end
|
|
||||||
|
|
||||||
return claim_get
|
|
|
@ -1,74 +0,0 @@
|
||||||
local sql = require("lsqlite3")
|
|
||||||
|
|
||||||
local pages = require("pages")
|
|
||||||
local db = require("db")
|
|
||||||
local queries = require("queries")
|
|
||||||
local util = require("util")
|
|
||||||
local sessionlib = require("session")
|
|
||||||
local config = require("config")
|
|
||||||
|
|
||||||
local stmnt_author_create
|
|
||||||
|
|
||||||
local oldconfigure = configure
|
|
||||||
function configure(...)
|
|
||||||
|
|
||||||
stmnt_author_create = util.sqlassert(db.conn:prepare(queries.insert_author))
|
|
||||||
return oldconfigure(...)
|
|
||||||
end
|
|
||||||
|
|
||||||
local function claim_post(req)
|
|
||||||
--Actually claim a name
|
|
||||||
http_request_populate_post(req)
|
|
||||||
local name = assert(http_argument_get_string(req,"user"))
|
|
||||||
local text
|
|
||||||
--What in the world, Kore should be rejecting names that
|
|
||||||
--are not lower case & no symbols, but some still get through somehow.
|
|
||||||
if not name:match("^[a-z0-9]*$") then
|
|
||||||
print("Bad username:",name)
|
|
||||||
text = pages.claim{
|
|
||||||
err = "Usernames must match ^[a-z0-9]{1,30}$"
|
|
||||||
}
|
|
||||||
http_response(req,200,text)
|
|
||||||
return
|
|
||||||
end
|
|
||||||
local rngf = assert(io.open("/dev/urandom","rb"))
|
|
||||||
local passlength = string.byte(rngf:read(1)) + 64
|
|
||||||
local salt = rngf:read(64)
|
|
||||||
local password = rngf:read(passlength)
|
|
||||||
rngf:close()
|
|
||||||
local hash = sha3(salt .. password)
|
|
||||||
stmnt_author_create:bind_names{
|
|
||||||
name = name,
|
|
||||||
}
|
|
||||||
stmnt_author_create:bind_blob(2,salt)
|
|
||||||
stmnt_author_create:bind_blob(3,hash)
|
|
||||||
local err = util.do_sql(stmnt_author_create)
|
|
||||||
if err == sql.DONE then
|
|
||||||
print("success")
|
|
||||||
--We sucessfully made the new author
|
|
||||||
local id = stmnt_author_create:last_insert_rowid()
|
|
||||||
stmnt_author_create:reset()
|
|
||||||
--Give them a file back
|
|
||||||
http_response_header(req,"Content-Type","application/octet-stream")
|
|
||||||
http_response_header(req,"Content-Disposition","attachment; filename=\"" .. name .. "." .. config.domain .. ".passfile\"")
|
|
||||||
local session = sessionlib.start(id)
|
|
||||||
text = password
|
|
||||||
print("session started, about to send password:",text)
|
|
||||||
http_response(req,200,text)
|
|
||||||
return
|
|
||||||
elseif err == sql.CONSTRAINT then
|
|
||||||
--If the creation failed, they probably just tried
|
|
||||||
--to use a name that was already taken
|
|
||||||
text = pages.claim {
|
|
||||||
err = "Failed to claim. That name may already be taken."
|
|
||||||
}
|
|
||||||
elseif err == sql.ERROR or err == sql.MISUSE then
|
|
||||||
--This is bad though
|
|
||||||
text = pages.claim {
|
|
||||||
err = "Failed to claim"
|
|
||||||
}
|
|
||||||
end
|
|
||||||
stmnt_author_create:reset()
|
|
||||||
http_response(req,200,text)
|
|
||||||
end
|
|
||||||
return claim_post
|
|
|
@ -1,45 +0,0 @@
|
||||||
local sql = require("lsqlite3")
|
|
||||||
local zlib = require("zlib")
|
|
||||||
|
|
||||||
local db = require("db")
|
|
||||||
local queries = require("queries")
|
|
||||||
local util = require("util")
|
|
||||||
local pages = require("pages")
|
|
||||||
|
|
||||||
local stmnt_download
|
|
||||||
local oldconfigure = configure
|
|
||||||
function configure(...)
|
|
||||||
stmnt_download = assert(db.conn:prepare(queries.select_download))
|
|
||||||
return oldconfigure(...)
|
|
||||||
end
|
|
||||||
|
|
||||||
local function download_get(req)
|
|
||||||
local host = http_request_get_host(req)
|
|
||||||
local path = http_request_get_path(req)
|
|
||||||
print("host:",host,"path:",path)
|
|
||||||
http_request_populate_qs(req)
|
|
||||||
local story = assert(http_argument_get_string(req,"story"))
|
|
||||||
local story_id = util.decode_id(story)
|
|
||||||
print("Downloading", story_id)
|
|
||||||
stmnt_download:bind_names{
|
|
||||||
postid = story_id
|
|
||||||
}
|
|
||||||
local err = util.do_sql(stmnt_download)
|
|
||||||
if err == sql.DONE then
|
|
||||||
--No rows, story not found
|
|
||||||
http_responose(req,404,pages.nostory{path=story})
|
|
||||||
stmnt_download:reset()
|
|
||||||
return
|
|
||||||
end
|
|
||||||
assert(err == sql.ROW, "after doing download sql, result was not a row, was:" .. tostring(err))
|
|
||||||
local txt_compressed, title = unpack(stmnt_download:get_values())
|
|
||||||
local text = zlib.decompress(txt_compressed)
|
|
||||||
stmnt_download:reset()
|
|
||||||
http_response_header(req,"Content-Type","application/octet-stream")
|
|
||||||
local nicetitle = title:gsub("%W","_")
|
|
||||||
http_response_header(req,"Content-Disposition","attachment; filename=\"" .. nicetitle .. ".txt\"")
|
|
||||||
http_response(req,200,text)
|
|
||||||
|
|
||||||
end
|
|
||||||
|
|
||||||
return download_get
|
|
|
@ -1,68 +0,0 @@
|
||||||
local zlib = require("zlib")
|
|
||||||
local sql = require("lsqlite3")
|
|
||||||
|
|
||||||
local db = require("db")
|
|
||||||
local queries = require("queries")
|
|
||||||
local util = require("util")
|
|
||||||
local pages = require("pages")
|
|
||||||
local tags = require("tags")
|
|
||||||
local session = require("session")
|
|
||||||
local config = require("config")
|
|
||||||
|
|
||||||
local stmnt_edit
|
|
||||||
local oldconfigure = configure
|
|
||||||
function configure(...)
|
|
||||||
stmnt_edit = assert(db.conn:prepare(queries.select_edit))
|
|
||||||
return oldconfigure(...)
|
|
||||||
end
|
|
||||||
|
|
||||||
local function edit_get(req)
|
|
||||||
local host = http_request_get_host(req)
|
|
||||||
local path = http_request_get_path(req)
|
|
||||||
local author, authorid = session.get(req)
|
|
||||||
|
|
||||||
http_request_populate_qs(req)
|
|
||||||
local story = assert(http_argument_get_string(req,"story"))
|
|
||||||
local story_id = util.decode_id(story)
|
|
||||||
local ret
|
|
||||||
|
|
||||||
print("we want to edit story:",story)
|
|
||||||
--Check that the logged in user is the owner of the story
|
|
||||||
--sql-side. If we're not the owner, we'll get 0 rows back.
|
|
||||||
stmnt_edit:bind_names{
|
|
||||||
postid = story_id,
|
|
||||||
authorid = authorid
|
|
||||||
}
|
|
||||||
local err = util.do_sql(stmnt_edit)
|
|
||||||
if err == sql.DONE then
|
|
||||||
--No rows, we're probably not the owner (it might
|
|
||||||
--also be because there's no such story)
|
|
||||||
ret = pages.cantedit{
|
|
||||||
path = story,
|
|
||||||
}
|
|
||||||
stmnt_edit:reset()
|
|
||||||
http_response(req,200,ret)
|
|
||||||
return
|
|
||||||
end
|
|
||||||
assert(err == sql.ROW)
|
|
||||||
local data = stmnt_edit:get_values()
|
|
||||||
local txt_compressed, markup, isanon, title = unpack(data)
|
|
||||||
local text = zlib.decompress(txt_compressed)
|
|
||||||
local tags = tags.get(story_id)
|
|
||||||
local tags_txt = table.concat(tags,";")
|
|
||||||
stmnt_edit:reset()
|
|
||||||
ret = pages.edit{
|
|
||||||
title = title,
|
|
||||||
text = text,
|
|
||||||
markup = markup,
|
|
||||||
user = author,
|
|
||||||
isanon = isanon == 1,
|
|
||||||
domain = config.domain,
|
|
||||||
story = story_id,
|
|
||||||
err = "",
|
|
||||||
tags = tags_txt
|
|
||||||
}
|
|
||||||
http_response(req,200,ret)
|
|
||||||
end
|
|
||||||
|
|
||||||
return edit_get
|
|
|
@ -1,89 +0,0 @@
|
||||||
local sql = require("lsqlite3")
|
|
||||||
local zlib = require("zlib")
|
|
||||||
|
|
||||||
local db = require("db")
|
|
||||||
local queries = require("queries")
|
|
||||||
local pages = require("pages")
|
|
||||||
local parsers = require("parsers")
|
|
||||||
local util = require("util")
|
|
||||||
local tagslib = require("tags")
|
|
||||||
local cache = require("cache")
|
|
||||||
local config = require("config")
|
|
||||||
local session = require("session")
|
|
||||||
|
|
||||||
local stmnt_author_of, stmnt_update_raw, stmnt_update
|
|
||||||
|
|
||||||
local oldconfigure = configure
|
|
||||||
function configure(...)
|
|
||||||
stmnt_author_of = assert(db.conn:prepare(queries.select_author_of_post))
|
|
||||||
stmnt_update_raw = assert(db.conn:prepare(queries.update_raw))
|
|
||||||
stmnt_update = assert(db.conn:prepare(queries.update_post))
|
|
||||||
return oldconfigure(...)
|
|
||||||
end
|
|
||||||
|
|
||||||
local function edit_post(req)
|
|
||||||
local host = http_request_get_host(req)
|
|
||||||
local path = http_request_get_path(req)
|
|
||||||
local author, author_id = session.get(req)
|
|
||||||
|
|
||||||
http_request_populate_post(req)
|
|
||||||
local storyid = tonumber(assert(http_argument_get_string(req,"story")))
|
|
||||||
local title = assert(http_argument_get_string(req,"title"))
|
|
||||||
local text = assert(http_argument_get_string(req,"text"))
|
|
||||||
local pasteas = assert(http_argument_get_string(req,"pasteas"))
|
|
||||||
local markup = assert(http_argument_get_string(req,"markup"))
|
|
||||||
local tags_str = http_argument_get_string(req,"tags")
|
|
||||||
stmnt_author_of:bind_names{
|
|
||||||
id = storyid
|
|
||||||
}
|
|
||||||
local err = util.do_sql(stmnt_author_of)
|
|
||||||
if err ~= sql.ROW then
|
|
||||||
stmnt_author_of:reset()
|
|
||||||
error("No author found for story:" .. storyid)
|
|
||||||
end
|
|
||||||
local data = stmnt_author_of:get_values()
|
|
||||||
stmnt_author_of:reset()
|
|
||||||
local realauthor = data[1]
|
|
||||||
assert(realauthor == author_id) --Make sure the author of the story is the currently logged in user
|
|
||||||
local parsed = parsers[markup](text)
|
|
||||||
local compr_raw = zlib.compress(text)
|
|
||||||
local compr = zlib.compress(parsed)
|
|
||||||
local tags = {}
|
|
||||||
if tags_str then
|
|
||||||
tags = util.parse_tags(tags_str)
|
|
||||||
end
|
|
||||||
assert(stmnt_update_raw:bind_blob(1,compr_raw) == sql.OK)
|
|
||||||
assert(stmnt_update_raw:bind(2,markup) == sql.OK)
|
|
||||||
assert(stmnt_update_raw:bind(3,storyid) == sql.OK)
|
|
||||||
assert(util.do_sql(stmnt_update_raw) == sql.DONE, "Failed to update raw")
|
|
||||||
stmnt_update_raw:reset()
|
|
||||||
assert(stmnt_update:bind(1,title) == sql.OK)
|
|
||||||
assert(stmnt_update:bind_blob(2,compr) == sql.OK)
|
|
||||||
assert(stmnt_update:bind(3,pasteas == "anonymous" and 1 or 0) == sql.OK)
|
|
||||||
assert(stmnt_update:bind(4,storyid) == sql.OK)
|
|
||||||
assert(util.do_sql(stmnt_update) == sql.DONE, "Failed to update text")
|
|
||||||
stmnt_update:reset()
|
|
||||||
tagslib.set(storyid,tags)
|
|
||||||
--[[
|
|
||||||
assert(stmnt_drop_tags:bind_names{postid = storyid} == sql.OK)
|
|
||||||
do_sql(stmnt_drop_tags)
|
|
||||||
stmnt_drop_tags:reset()
|
|
||||||
for _,tag in pairs(tags) do
|
|
||||||
print("Looking at tag",tag)
|
|
||||||
assert(stmnt_ins_tag:bind(1,storyid) == sql.OK)
|
|
||||||
assert(stmnt_ins_tag:bind(2,tag) == sql.OK)
|
|
||||||
err = do_sql(stmnt_ins_tag)
|
|
||||||
stmnt_ins_tag:reset()
|
|
||||||
end
|
|
||||||
]]
|
|
||||||
local id_enc = util.encode_id(storyid)
|
|
||||||
local loc = string.format("https://%s/%s",config.domain,id_enc)
|
|
||||||
cache.dirty(string.format("%s/%s",config.domain,id_enc)) -- This place to read this post
|
|
||||||
cache.dirty(string.format("%s",config.domain)) -- The site index (ex, if the author changed the paste from their's to "Anonymous", the cache should reflect that).
|
|
||||||
cache.dirty(string.format("%s.%s",author,config.domain)) -- The author's index, same reasoning as above.
|
|
||||||
http_response_header(req,"Location",loc)
|
|
||||||
http_response(req,303,"")
|
|
||||||
return
|
|
||||||
end
|
|
||||||
|
|
||||||
return edit_post
|
|
|
@ -45,8 +45,8 @@ local function populate_ps_story(req,ps)
|
||||||
if err == sql.DONE then
|
if err == sql.DONE then
|
||||||
--We got no story
|
--We got no story
|
||||||
stmnt_read:reset()
|
stmnt_read:reset()
|
||||||
error("No story by this name",ps.storyid)
|
print("No story by this name",ps.storyid)
|
||||||
return
|
return false
|
||||||
end
|
end
|
||||||
--If we've made it here, we have a story. Populate our settings
|
--If we've made it here, we have a story. Populate our settings
|
||||||
--with title, text, ect.
|
--with title, text, ect.
|
||||||
|
@ -149,14 +149,18 @@ local function read_get(req)
|
||||||
ps.show_comments and "?comments=1" or ""
|
ps.show_comments and "?comments=1" or ""
|
||||||
)
|
)
|
||||||
text = cache.render(cachestr,function()
|
text = cache.render(cachestr,function()
|
||||||
populate_ps_story(req,ps)
|
if not populate_ps_story(req,ps) then
|
||||||
|
return pages.nostory(ps)
|
||||||
|
end
|
||||||
local output = pages.read(ps)
|
local output = pages.read(ps)
|
||||||
assert(output,"failed to read page:" .. cachestr)
|
assert(output,"failed to read page:" .. cachestr)
|
||||||
return output
|
return output
|
||||||
end)
|
end)
|
||||||
else --we are logged in, don't cache
|
else --we are logged in, don't cache
|
||||||
print("is author")
|
print("is author")
|
||||||
populate_ps_story(req,ps)
|
if not populate_ps_story(req,ps) then
|
||||||
|
return pages.nostory(ps)
|
||||||
|
end
|
||||||
print("tauthor was", ps.tauthor, "while author was:",ps.author)
|
print("tauthor was", ps.tauthor, "while author was:",ps.author)
|
||||||
ps.owner = (ps.loggedauthorid == ps.tauthor)
|
ps.owner = (ps.loggedauthorid == ps.tauthor)
|
||||||
text = pages.read(ps)
|
text = pages.read(ps)
|
||||||
|
|
|
@ -1,115 +0,0 @@
|
||||||
local sql = require("lsqlite3")
|
|
||||||
|
|
||||||
local cache = require("cache")
|
|
||||||
local queries = require("queries")
|
|
||||||
local db = require("db")
|
|
||||||
local util = require("util")
|
|
||||||
local config = require("config")
|
|
||||||
local pages = require("pages")
|
|
||||||
local libtags = require("tags")
|
|
||||||
|
|
||||||
local stmnt_index, stmnt_author, stmnt_author_bio
|
|
||||||
|
|
||||||
local oldconfigure = configure
|
|
||||||
function configure(...)
|
|
||||||
stmnt_index = assert(db.conn:prepare(queries.select_site_index))
|
|
||||||
--TODO: actually let authors edit their bio
|
|
||||||
stmnt_author_bio = assert(db.conn:prepare([[
|
|
||||||
SELECT authors.biography FROM authors WHERE authors.name = :author;
|
|
||||||
]]))
|
|
||||||
stmnt_author = assert(db.conn:prepare(queries.select_author_index))
|
|
||||||
return oldconfigure(...)
|
|
||||||
end
|
|
||||||
|
|
||||||
local function get_site_home(req)
|
|
||||||
print("Cache miss, rendering index")
|
|
||||||
stmnt_index:bind_names{}
|
|
||||||
local err = util.do_sql(stmnt_index)
|
|
||||||
local latest = {}
|
|
||||||
--err may be sql.ROW or sql.DONE if we don't have any stories yet
|
|
||||||
while err == sql.ROW do
|
|
||||||
local data = stmnt_index:get_values()
|
|
||||||
local storytags = libtags.get(data[1])
|
|
||||||
table.insert(latest,{
|
|
||||||
url = util.encode_id(data[1]),
|
|
||||||
title = data[2],
|
|
||||||
isanon = data[3] == 1,
|
|
||||||
posted = os.date("%B %d %Y",tonumber(data[4])),
|
|
||||||
author = data[5],
|
|
||||||
tags = storytags,
|
|
||||||
})
|
|
||||||
err = stmnt_index:step()
|
|
||||||
end
|
|
||||||
stmnt_index:reset()
|
|
||||||
return pages.index{
|
|
||||||
domain = config.domain,
|
|
||||||
stories = latest
|
|
||||||
}
|
|
||||||
end
|
|
||||||
local function get_author_home(req)
|
|
||||||
local host = http_request_get_host(req)
|
|
||||||
local subdomain = host:match("([^\\.]+)")
|
|
||||||
stmnt_author_bio:bind_names{author=subdomain}
|
|
||||||
local err = util.do_sql(stmnt_author_bio)
|
|
||||||
if err == sql.DONE then
|
|
||||||
print("No such author")
|
|
||||||
stmnt_author_bio:reset()
|
|
||||||
return pages.noauthor{
|
|
||||||
author = subdomain
|
|
||||||
}
|
|
||||||
end
|
|
||||||
print("err:",err)
|
|
||||||
assert(err == sql.ROW,"failed to get author:" .. subdomain .. " error:" .. tostring(err))
|
|
||||||
local data = stmnt_author_bio:get_values()
|
|
||||||
local bio = data[1]
|
|
||||||
stmnt_author_bio:reset()
|
|
||||||
print("Getting author's stories")
|
|
||||||
stmnt_author:bind_names{author=subdomain}
|
|
||||||
err = util.do_sql(stmnt_author)
|
|
||||||
print("err:",err)
|
|
||||||
local stories = {}
|
|
||||||
while err == sql.ROW do
|
|
||||||
local data = stmnt_author:get_values()
|
|
||||||
local id, title, time = unpack(data)
|
|
||||||
local tags = libtags.get(id)
|
|
||||||
table.insert(stories,{
|
|
||||||
url = util.encode_id(id),
|
|
||||||
title = title,
|
|
||||||
posted = os.date("%B %d %Y",tonumber(time)),
|
|
||||||
tags = tags,
|
|
||||||
})
|
|
||||||
err = stmnt_author:step()
|
|
||||||
end
|
|
||||||
stmnt_author:reset()
|
|
||||||
return pages.author_index{
|
|
||||||
domain=config.domain,
|
|
||||||
author=subdomain,
|
|
||||||
stories=stories,
|
|
||||||
bio=bio
|
|
||||||
}
|
|
||||||
|
|
||||||
end
|
|
||||||
|
|
||||||
local function index_get(req)
|
|
||||||
local method = http_method_text(req)
|
|
||||||
local host = http_request_get_host(req)
|
|
||||||
local path = http_request_get_path(req)
|
|
||||||
--Default home page
|
|
||||||
local subdomain = host:match("([^\\.]+)")
|
|
||||||
local text
|
|
||||||
if host == config.domain then
|
|
||||||
local cachepath = string.format("%s",config.domain)
|
|
||||||
text = cache.render(cachepath, function()
|
|
||||||
return get_site_home(req)
|
|
||||||
end)
|
|
||||||
else --author home page
|
|
||||||
local cachepath = string.format("%s.%s",subdomain,config.domain)
|
|
||||||
text = cache.render(cachepath, function()
|
|
||||||
return get_author_home(req)
|
|
||||||
end)
|
|
||||||
end
|
|
||||||
assert(text)
|
|
||||||
http_response(req,200,text)
|
|
||||||
end
|
|
||||||
|
|
||||||
return index_get
|
|
1207
src/lua/init.lua
1207
src/lua/init.lua
File diff suppressed because it is too large
Load Diff
|
@ -1,17 +0,0 @@
|
||||||
local config = require("config")
|
|
||||||
local cache = require("cache")
|
|
||||||
local config = require("config")
|
|
||||||
local pages = require("pages")
|
|
||||||
|
|
||||||
|
|
||||||
local function login_get(req)
|
|
||||||
--Just give them the login page
|
|
||||||
local ret = cache.render(string.format("%s/_login",config.domain),function()
|
|
||||||
return pages.login{
|
|
||||||
err = "",
|
|
||||||
}
|
|
||||||
end)
|
|
||||||
http_response(req,200,ret)
|
|
||||||
end
|
|
||||||
|
|
||||||
return login_get
|
|
|
@ -1,61 +0,0 @@
|
||||||
local sql = require("lsqlite3")
|
|
||||||
|
|
||||||
local db = require("db")
|
|
||||||
local util = require("util")
|
|
||||||
local session = require("session")
|
|
||||||
local config = require("config")
|
|
||||||
local pages = require("pages")
|
|
||||||
|
|
||||||
local stmnt_author_acct
|
|
||||||
|
|
||||||
local oldconfigure = configure
|
|
||||||
function configure(...)
|
|
||||||
--Get the data we need to check if someone can log in
|
|
||||||
stmnt_author_acct = assert(db.conn:prepare([[
|
|
||||||
SELECT id, salt, passhash FROM authors WHERE name = :name;
|
|
||||||
]]))
|
|
||||||
|
|
||||||
return oldconfigure(...)
|
|
||||||
end
|
|
||||||
|
|
||||||
local function login_post(req)
|
|
||||||
--Try to log in
|
|
||||||
http_populate_multipart_form(req)
|
|
||||||
local name = assert(http_argument_get_string(req,"user"))
|
|
||||||
local pass = assert(http_file_get(req,"pass"))
|
|
||||||
stmnt_author_acct:bind_names{
|
|
||||||
name = name
|
|
||||||
}
|
|
||||||
local text
|
|
||||||
local err = util.do_sql(stmnt_author_acct)
|
|
||||||
if err == sql.ROW then
|
|
||||||
local id, salt, passhash = unpack(stmnt_author_acct:get_values())
|
|
||||||
stmnt_author_acct:reset()
|
|
||||||
local todigest = salt .. pass
|
|
||||||
local hash = sha3(todigest)
|
|
||||||
if hash == passhash then
|
|
||||||
local mysession = session.start(id)
|
|
||||||
http_response_cookie(req,"session",mysession,"/",0,0)
|
|
||||||
local loc = string.format("https://%s.%s",name,config.domain)
|
|
||||||
http_response_header(req,"Location",loc)
|
|
||||||
http_response(req,303,"")
|
|
||||||
return
|
|
||||||
else
|
|
||||||
text = pages.login{
|
|
||||||
err = "Incorrect username or password"
|
|
||||||
}
|
|
||||||
end
|
|
||||||
elseif err == sql.DONE then --Allows user enumeration, do we want this?
|
|
||||||
--Probably not a problem since all passwords are forced to be "good"
|
|
||||||
stmnt_author_acct:reset()
|
|
||||||
text = pages.login{
|
|
||||||
err = "Failed to find user:" .. name
|
|
||||||
}
|
|
||||||
else
|
|
||||||
stmnt_author_acct:reset()
|
|
||||||
error("Other sql error during login")
|
|
||||||
end
|
|
||||||
http_response(req,200,text)
|
|
||||||
end
|
|
||||||
|
|
||||||
return login_post
|
|
|
@ -0,0 +1,8 @@
|
||||||
|
|
||||||
|
--Grammar
|
||||||
|
local function parser(str)
|
||||||
|
str:gsub("
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
return parser
|
|
@ -1,96 +0,0 @@
|
||||||
local config = require("config")
|
|
||||||
local session = require("session")
|
|
||||||
local pages = require("pages")
|
|
||||||
local cache = require("cache")
|
|
||||||
|
|
||||||
local function paste_get(req)
|
|
||||||
--Get the paste page
|
|
||||||
local host = http_request_get_host(req)
|
|
||||||
local text
|
|
||||||
local author,_ = session.get(req)
|
|
||||||
if host == config.domain and author then
|
|
||||||
http_response_header(req,"Location",string.format("https://%s.%s/_paste",author,config.domain))
|
|
||||||
http_response(req,303,"")
|
|
||||||
return
|
|
||||||
elseif host == config.domain and author == nil then
|
|
||||||
text = cache.render(string.format("%s/_paste",host),function()
|
|
||||||
print("Cache missing, rendering post page")
|
|
||||||
return pages.paste{
|
|
||||||
domain = config.domain,
|
|
||||||
err = "",
|
|
||||||
}
|
|
||||||
end)
|
|
||||||
http_response(req,200,text)
|
|
||||||
elseif host ~= config.domain and author then
|
|
||||||
text = pages.author_paste{
|
|
||||||
domain = config.domain,
|
|
||||||
user = author,
|
|
||||||
err = "",
|
|
||||||
text="",
|
|
||||||
}
|
|
||||||
elseif host ~= config.domain and author == nil then
|
|
||||||
http_response_header(req,"Location",string.format("https://%s/_paste",config.domain))
|
|
||||||
http_response(req,303,"")
|
|
||||||
else
|
|
||||||
error(string.format(
|
|
||||||
"Unable to find a good case for paste:%s,%s,%s",
|
|
||||||
host,
|
|
||||||
config.domain,
|
|
||||||
author
|
|
||||||
))
|
|
||||||
end
|
|
||||||
assert(text)
|
|
||||||
http_response(req,200,text)
|
|
||||||
--[=[
|
|
||||||
if host == config.domain then
|
|
||||||
local author,_ = get_session(req)
|
|
||||||
if author then
|
|
||||||
http_response_header(req,"Location",string.format("https://%s.%s/_paste",author,domain))
|
|
||||||
http_response(req,303,"")
|
|
||||||
return
|
|
||||||
else
|
|
||||||
--For an anonymous user
|
|
||||||
ret = cache.render(string.format("%s/_paste",host),function()
|
|
||||||
print("Cache missing, rendering post page")
|
|
||||||
return pages.paste{
|
|
||||||
domain = domain,
|
|
||||||
err = "",
|
|
||||||
}
|
|
||||||
end)
|
|
||||||
end
|
|
||||||
|
|
||||||
else
|
|
||||||
--Or for someone that's logged in
|
|
||||||
print("Looks like a logged in user wants to paste!")
|
|
||||||
local subdomain = host:match("([^%.]+)")
|
|
||||||
local author,_ = session.get(req)
|
|
||||||
print("subdomain:",subdomain,"author:",author)
|
|
||||||
--If they try to paste as an author, but are on the
|
|
||||||
--wrong subdomain, or or not logged in, redirect them
|
|
||||||
--to the right place. Their own subdomain for authors
|
|
||||||
--or the anonymous paste page for not logged in users.
|
|
||||||
if author == nil then
|
|
||||||
http_response_header(req,"Location","https://"..domain.."/_paste")
|
|
||||||
http_response(req,303,"")
|
|
||||||
return
|
|
||||||
end
|
|
||||||
if author ~= subdomain then
|
|
||||||
http_response_header(req,"Location",string.format("https://%s.%s/_paste",author,domain))
|
|
||||||
http_response(req,303,"")
|
|
||||||
return
|
|
||||||
end
|
|
||||||
assert(author == subdomain,"someone wants to paste as someone else")
|
|
||||||
--We're where we want to be, serve up this users's
|
|
||||||
--paste page. No cache, because how often is a user
|
|
||||||
--going to paste?
|
|
||||||
ret = pages.author_paste{
|
|
||||||
domain = domain,
|
|
||||||
user = author,
|
|
||||||
text = "",
|
|
||||||
err = "",
|
|
||||||
}
|
|
||||||
end
|
|
||||||
]=]
|
|
||||||
end
|
|
||||||
|
|
||||||
return paste_get
|
|
|
@ -1,194 +0,0 @@
|
||||||
local sql = require("lsqlite3")
|
|
||||||
local zlib = require("zlib")
|
|
||||||
|
|
||||||
local util = require("util")
|
|
||||||
local parsers = require("parsers")
|
|
||||||
local config = require("config")
|
|
||||||
local queries = require("queries")
|
|
||||||
local db = require("db")
|
|
||||||
local cache = require("cache")
|
|
||||||
local tags = require("tags")
|
|
||||||
local session = require("session")
|
|
||||||
|
|
||||||
local stmnt_raw,stmnt_paste
|
|
||||||
|
|
||||||
local oldconfigure = configure
|
|
||||||
function configure(...)
|
|
||||||
stmnt_paste = assert(db.conn:prepare(queries.insert_post))
|
|
||||||
stmnt_raw = assert(db.conn:prepare(queries.insert_raw))
|
|
||||||
return oldconfigure(...)
|
|
||||||
end
|
|
||||||
|
|
||||||
local function anon_paste(req,ps)
|
|
||||||
--Public paste
|
|
||||||
--[[
|
|
||||||
This doesn't actually do much for IPv4 addresses,
|
|
||||||
since there are only 32 bits of address. Someone who
|
|
||||||
got a copy of the database could
|
|
||||||
just generate all 2^32 hashes and look up who posted
|
|
||||||
what. Use IPv6, Tor or I2P where possible. (but then I
|
|
||||||
guess it's harder to ban spammers... hmm..)
|
|
||||||
]]
|
|
||||||
--local ip = http_request_get_ip(req)
|
|
||||||
--local iphash = sha3(ip)
|
|
||||||
--Don't store this information for now, until I come up
|
|
||||||
--with a more elegent solution.
|
|
||||||
|
|
||||||
util.sqlbind(stmnt_paste,"bind_blob",1,ps.text)
|
|
||||||
--assert(stmnt_paste:bind_blob(1,text) == sql.OK)
|
|
||||||
util.sqlbind(stmnt_paste,"bind",2,ps.title)
|
|
||||||
--assert(stmnt_paste:bind(2,esctitle) == sql.OK)
|
|
||||||
util.sqlbind(stmnt_paste,"bind",3,-1)
|
|
||||||
--assert(stmnt_paste:bind(3,-1) == sql.OK)
|
|
||||||
util.sqlbind(stmnt_paste,"bind",4,true)
|
|
||||||
--assert(stmnt_paste:bind(4,true) == sql.OK)
|
|
||||||
util.sqlbind(stmnt_paste,"bind_blob",5,"")
|
|
||||||
--assert(stmnt_paste:bind_blob(5,"") == sql.OK)
|
|
||||||
err = util.do_sql(stmnt_paste)
|
|
||||||
stmnt_paste:reset()
|
|
||||||
if err == sql.DONE then
|
|
||||||
local rowid = stmnt_paste:last_insert_rowid()
|
|
||||||
assert(stmnt_raw:bind(1,rowid) == sql.OK)
|
|
||||||
assert(stmnt_raw:bind_blob(2,ps.raw) == sql.OK)
|
|
||||||
assert(stmnt_raw:bind(3,ps.markup) == sql.OK)
|
|
||||||
err = util.do_sql(stmnt_raw)
|
|
||||||
stmnt_raw:reset()
|
|
||||||
if err ~= sql.DONE then
|
|
||||||
print("Failed to save raw text, but paste still went though")
|
|
||||||
end
|
|
||||||
tags.set(rowid,ps.tags)
|
|
||||||
--[[
|
|
||||||
for _,tag in pairs(ps.tags) do
|
|
||||||
print("tag 1:",stmnt_ins_tag:bind(1,rowid))
|
|
||||||
print("Looking at tag",tag)
|
|
||||||
print("tag 2:",stmnt_ins_tag:bind(2,tag))
|
|
||||||
err = util.do_sql(stmnt_ins_tag)
|
|
||||||
stmnt_ins_tag:reset()
|
|
||||||
end
|
|
||||||
]]
|
|
||||||
local url = util.encode_id(rowid)
|
|
||||||
local loc = string.format("https://%s/%s",config.domain,url)
|
|
||||||
http_response_header(req,"Location",loc)
|
|
||||||
http_response(req,303,"")
|
|
||||||
cache.dirty(string.format("%s/%s",config.domain,url))
|
|
||||||
cache.dirty(string.format("%s",config.domain))
|
|
||||||
return
|
|
||||||
elseif err == sql.ERROR or err == sql.MISUSE then
|
|
||||||
ret = "Failed to paste: " .. tostring(err)
|
|
||||||
else
|
|
||||||
error("Error pasting:" .. tostring(err))
|
|
||||||
end
|
|
||||||
stmnt_paste:reset()
|
|
||||||
end
|
|
||||||
local function author_paste(req,ps)
|
|
||||||
--Author paste
|
|
||||||
local author, authorid = session.get(req)
|
|
||||||
if author == nil then
|
|
||||||
ret = pages.author_paste{
|
|
||||||
domain = domain,
|
|
||||||
author = subdomain,
|
|
||||||
err = "You are not logged in, you must be logged in to post as " .. subdomain .. ".",
|
|
||||||
text = text
|
|
||||||
}
|
|
||||||
end
|
|
||||||
local asanon = assert(http_argument_get_string(req,"pasteas"))
|
|
||||||
--No need to check if the author is posting to the
|
|
||||||
--"right" sudomain, just post it to the one they have
|
|
||||||
--the session key for.
|
|
||||||
assert(stmnt_paste:bind_blob(1,ps.text) == sql.OK)
|
|
||||||
assert(stmnt_paste:bind(2,ps.title) == sql.OK)
|
|
||||||
assert(stmnt_paste:bind(3,authorid) == sql.OK)
|
|
||||||
if asanon == "anonymous" then
|
|
||||||
assert(stmnt_paste:bind(4,true) == sql.OK)
|
|
||||||
else
|
|
||||||
assert(stmnt_paste:bind(4,false) == sql.OK)
|
|
||||||
end
|
|
||||||
assert(stmnt_paste:bind_blob(5,"") == sql.OK)
|
|
||||||
err = util.do_sql(stmnt_paste)
|
|
||||||
stmnt_paste:reset()
|
|
||||||
if err == sql.DONE then
|
|
||||||
local rowid = stmnt_paste:last_insert_rowid()
|
|
||||||
assert(stmnt_raw:bind(1,rowid) == sql.OK)
|
|
||||||
assert(stmnt_raw:bind_blob(2,ps.raw) == sql.OK)
|
|
||||||
assert(stmnt_raw:bind(3,ps.markup) == sql.OK)
|
|
||||||
err = util.do_sql(stmnt_raw)
|
|
||||||
stmnt_raw:reset()
|
|
||||||
if err ~= sql.DONE then
|
|
||||||
print("Failed to save raw text, but paste still went through")
|
|
||||||
end
|
|
||||||
tags.set(rowid,ps.tags)
|
|
||||||
--[[
|
|
||||||
for _,tag in pairs(ps.tags) do
|
|
||||||
print("tag 1:",stmnt_ins_tag:bind(1,rowid))
|
|
||||||
print("Looking at tag",tag)
|
|
||||||
print("tag 2:",stmnt_ins_tag:bind(2,tag))
|
|
||||||
err = do_sql(stmnt_ins_tag)
|
|
||||||
stmnt_ins_tag:reset()
|
|
||||||
end
|
|
||||||
]]
|
|
||||||
local url = util.encode_id(rowid)
|
|
||||||
local loc
|
|
||||||
if asanon == "anonymous" then
|
|
||||||
loc = string.format("https://%s/%s",config.domain,url)
|
|
||||||
else
|
|
||||||
loc = string.format("https://%s.%s/%s",author,config.domain,url)
|
|
||||||
end
|
|
||||||
http_response_header(req,"Location",loc)
|
|
||||||
http_response(req,303,"")
|
|
||||||
cache.dirty(string.format("%s.%s",author,config.domain))
|
|
||||||
cache.dirty(string.format("%s/%s",config.domain,url))
|
|
||||||
cache.dirty(string.format("%s",config.domain))
|
|
||||||
return
|
|
||||||
elseif err == sql.ERROR or err == sql.MISUSE then
|
|
||||||
ret = "Failed to paste: " .. tostring(err)
|
|
||||||
else
|
|
||||||
error("Error pasting:",err)
|
|
||||||
end
|
|
||||||
stmnt_paste:reset()
|
|
||||||
|
|
||||||
end
|
|
||||||
local function decodeentities(capture)
|
|
||||||
local n = tonumber(capture,16)
|
|
||||||
local c = string.char(n)
|
|
||||||
if escapes[c] then
|
|
||||||
return escapes[c]
|
|
||||||
else
|
|
||||||
return c
|
|
||||||
end
|
|
||||||
end
|
|
||||||
local function paste_post(req)
|
|
||||||
local host = http_request_get_host(req)
|
|
||||||
local path = http_request_get_path(req)
|
|
||||||
|
|
||||||
local ps = {}
|
|
||||||
--We're creatinga new paste
|
|
||||||
http_request_populate_post(req)
|
|
||||||
local title = assert(http_argument_get_string(req,"title"))
|
|
||||||
local text = assert(http_argument_get_string(req,"text"))
|
|
||||||
ps.markup = assert(http_argument_get_string(req,"markup"))
|
|
||||||
local tag_str = http_argument_get_string(req,"tags")
|
|
||||||
ps.tags = {}
|
|
||||||
if tag_str then
|
|
||||||
ps.tags = util.parse_tags(tag_str)
|
|
||||||
end
|
|
||||||
local pasteas
|
|
||||||
ps.raw = zlib.compress(text)
|
|
||||||
text = string.gsub(text,"%%(%x%x)",decodeentities)
|
|
||||||
text = parsers[ps.markup](text)
|
|
||||||
assert(text,"Failed to parse text")
|
|
||||||
text = zlib.compress(text)
|
|
||||||
assert(text,"Failed to compress text")
|
|
||||||
ps.text = text
|
|
||||||
local esctitle = string.gsub(title,"%%(%x%x)",decodeentities)
|
|
||||||
--Always sanatize the title with the plain parser. no markup
|
|
||||||
--in the title.
|
|
||||||
ps.title = parsers.plain(title)
|
|
||||||
if host == config.domain then
|
|
||||||
anon_paste(req,ps)
|
|
||||||
else
|
|
||||||
author_paste(req,ps)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
--assert(ret)
|
|
||||||
--http_response(req,200,ret)
|
|
||||||
return paste_post
|
|
|
@ -1,33 +0,0 @@
|
||||||
local parsers = require("parsers")
|
|
||||||
local tags = require("tags")
|
|
||||||
local util = require("util")
|
|
||||||
local pages = require("pages")
|
|
||||||
local config = require("config")
|
|
||||||
|
|
||||||
local function preview_post(req)
|
|
||||||
print("We want to preview a paste!")
|
|
||||||
local host = http_request_get_host(req)
|
|
||||||
local path = http_request_get_path(req)
|
|
||||||
http_request_populate_post(req)
|
|
||||||
local title = assert(http_argument_get_string(req,"title"))
|
|
||||||
local text = assert(http_argument_get_string(req,"text"))
|
|
||||||
local markup = assert(http_argument_get_string(req,"markup"))
|
|
||||||
local tag_str = http_argument_get_string(req,"tags")
|
|
||||||
local tags = {}
|
|
||||||
if tag_str then
|
|
||||||
tags = util.parse_tags(tag_str)
|
|
||||||
end
|
|
||||||
print("title:",title,"text:",text,"markup:",markup)
|
|
||||||
local parsed = parsers[markup](text)
|
|
||||||
local ret = pages.read{
|
|
||||||
domain = config.domain,
|
|
||||||
title = title,
|
|
||||||
author = "preview",
|
|
||||||
idp = "preview",
|
|
||||||
text = parsed,
|
|
||||||
tags = tags,
|
|
||||||
}
|
|
||||||
http_response(req,200,ret)
|
|
||||||
end
|
|
||||||
|
|
||||||
return preview_post
|
|
|
@ -1,169 +0,0 @@
|
||||||
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()
|
|
||||||
error("No story by this name",ps.storyid)
|
|
||||||
return
|
|
||||||
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 = unpack(
|
|
||||||
stmnt_read:get_values()
|
|
||||||
)
|
|
||||||
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
|
|
||||||
}
|
|
||||||
err = util.do_sql(stmnt_comments)
|
|
||||||
local comments = {}
|
|
||||||
while err ~= sql.DONE do
|
|
||||||
local com_author, com_isanon, com_text = unpack(stmnt_comments:get_values())
|
|
||||||
table.insert(comments,{
|
|
||||||
author = com_author,
|
|
||||||
isanon = com_isanon == 1, --int to boolean
|
|
||||||
text = com_text
|
|
||||||
})
|
|
||||||
err = stmnt_comments:step()
|
|
||||||
end
|
|
||||||
stmnt_comments:reset()
|
|
||||||
return comments
|
|
||||||
end
|
|
||||||
|
|
||||||
--[[
|
|
||||||
The author is viewing their own story, give them an edit button
|
|
||||||
]]
|
|
||||||
local function read_get_author(req,storyid,author,authorid,comments)
|
|
||||||
|
|
||||||
end
|
|
||||||
|
|
||||||
--[[
|
|
||||||
An author is viewing a story, allow them to post comments as themselves
|
|
||||||
]]
|
|
||||||
local function read_get_loggedin(req,ps)
|
|
||||||
if ps.tauthor == ps.authorid then
|
|
||||||
--The story exists and we're logged in as the
|
|
||||||
--owner, display the edit button
|
|
||||||
return read_get_author(req,ps)
|
|
||||||
end
|
|
||||||
return pages.read(ps)
|
|
||||||
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),
|
|
||||||
}
|
|
||||||
print("reading", ps.path)
|
|
||||||
|
|
||||||
--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
|
|
||||||
|
|
||||||
local text
|
|
||||||
--normal story display
|
|
||||||
if (not ps.loggedauthor) then
|
|
||||||
print("not author")
|
|
||||||
local cachestr = string.format("%s%s%s",
|
|
||||||
ps.host,
|
|
||||||
ps.path,
|
|
||||||
ps.show_comments and "?comments=1" or ""
|
|
||||||
)
|
|
||||||
text = cache.render(cachestr,function()
|
|
||||||
populate_ps_story(req,ps)
|
|
||||||
local output = pages.read(ps)
|
|
||||||
assert(output,"failed to read page:" .. cachestr)
|
|
||||||
return output
|
|
||||||
end)
|
|
||||||
else --we are logged in, don't cache
|
|
||||||
print("is author")
|
|
||||||
populate_ps_story(req,ps)
|
|
||||||
print("tauthor was", ps.tauthor, "while author was:",ps.author)
|
|
||||||
ps.owner = (ps.loggedauthorid == ps.tauthor)
|
|
||||||
text = pages.read(ps)
|
|
||||||
end
|
|
||||||
assert(text)
|
|
||||||
http_response(req,200,text)
|
|
||||||
return
|
|
||||||
end
|
|
||||||
|
|
||||||
return read_get
|
|
|
@ -1,53 +0,0 @@
|
||||||
local sql = require("sqlite3")
|
|
||||||
|
|
||||||
local cache = require("cache")
|
|
||||||
local session = require("session")
|
|
||||||
local util = require("util")
|
|
||||||
local db = require("db")
|
|
||||||
local queries = require("queries")
|
|
||||||
local config = require("config")
|
|
||||||
|
|
||||||
local stmnt_comment_insert
|
|
||||||
|
|
||||||
local oldconfigure = configure
|
|
||||||
function configure(...)
|
|
||||||
stmnt_comment_insert = assert(db.conn:prepare(queries.insert_comment))
|
|
||||||
return oldconfigure(...)
|
|
||||||
end
|
|
||||||
|
|
||||||
local function read_post(req)
|
|
||||||
local host = http_request_get_host(req)
|
|
||||||
local path = http_request_get_path(req)
|
|
||||||
--We're posting a comment
|
|
||||||
http_request_populate_post(req)
|
|
||||||
http_populate_cookies(req)
|
|
||||||
local author, authorid = session.get(req)
|
|
||||||
local comment_text = assert(http_argument_get_string(req,"text"))
|
|
||||||
local pasteas = assert(http_argument_get_string(req,"postas"))
|
|
||||||
local idp = string.sub(path,2)--remove leading "/"
|
|
||||||
local id = util.decode_id(idp)
|
|
||||||
local isanon = 1
|
|
||||||
--Even if an author is logged in, they may post their comment anonymously
|
|
||||||
if author and pasteas ~= "Anonymous" then
|
|
||||||
isanon = 0
|
|
||||||
end
|
|
||||||
stmnt_comment_insert:bind_names{
|
|
||||||
postid=id,
|
|
||||||
authorid = author and authorid or -1,
|
|
||||||
isanon = isanon,
|
|
||||||
comment_text = comment_text,
|
|
||||||
}
|
|
||||||
local err = util.do_sql(stmnt_comment_insert)
|
|
||||||
stmnt_comment_insert:reset()
|
|
||||||
if err ~= sql.DONE then
|
|
||||||
http_response(req,500,"Internal error, failed to post comment. Go back and try again.")
|
|
||||||
else
|
|
||||||
--When we post a comment, we need to dirty the cache for the "comments displayed" page.
|
|
||||||
cache.dirty(string.format("%s%s?comments=1",host,path))
|
|
||||||
local redir = string.format("https://%s%s?comments=1", config.domain, path)
|
|
||||||
http_response_header(req,"Location",redir)
|
|
||||||
http_response(req,303,"")
|
|
||||||
end
|
|
||||||
|
|
||||||
end
|
|
||||||
return read_post
|
|
|
@ -1,2 +0,0 @@
|
||||||
|
|
||||||
|
|
|
@ -1,59 +0,0 @@
|
||||||
local sql = require("lsqlite3")
|
|
||||||
|
|
||||||
local db = require("db")
|
|
||||||
local queries = require("queries")
|
|
||||||
local util = require("util")
|
|
||||||
local libtags = require("tags")
|
|
||||||
local pages = require("pages")
|
|
||||||
local config = require("config")
|
|
||||||
|
|
||||||
local stmnt_search
|
|
||||||
local oldconfigure = configure
|
|
||||||
function configure(...)
|
|
||||||
stmnt_search = assert(db.conn:prepare(queries.select_post_tags))
|
|
||||||
return oldconfigure(...)
|
|
||||||
end
|
|
||||||
|
|
||||||
local function search_get(req)
|
|
||||||
local host = http_request_get_host(req)
|
|
||||||
local path = http_request_get_path(req)
|
|
||||||
http_request_populate_qs(req)
|
|
||||||
local tag = http_argument_get_string(req,"tag")
|
|
||||||
if tag then
|
|
||||||
stmnt_search:bind_names{
|
|
||||||
tag = tag
|
|
||||||
}
|
|
||||||
local results = {}
|
|
||||||
local err
|
|
||||||
repeat
|
|
||||||
err = stmnt_search:step()
|
|
||||||
if err == sql.BUSY then
|
|
||||||
coroutine.yield()
|
|
||||||
elseif err == sql.ROW then
|
|
||||||
local id, title, anon, time, author = unpack(stmnt_search:get_values())
|
|
||||||
local idp = util.encode_id(id)
|
|
||||||
local tags = libtags.get(id)
|
|
||||||
table.insert(results,{
|
|
||||||
id = idp,
|
|
||||||
title = title,
|
|
||||||
anon = anon,
|
|
||||||
time = os.date("%B %d %Y",tonumber(time)),
|
|
||||||
author = author,
|
|
||||||
tags = tags
|
|
||||||
})
|
|
||||||
elseif err == sql.DONE then
|
|
||||||
stmnt_search:reset()
|
|
||||||
else
|
|
||||||
error("Failed to search, sql error:" .. tostring(err))
|
|
||||||
end
|
|
||||||
until err == sql.DONE
|
|
||||||
local ret = pages.search{
|
|
||||||
domain = config.domain,
|
|
||||||
results = results,
|
|
||||||
tag = tag,
|
|
||||||
}
|
|
||||||
http_response(req,200,ret)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
return search_get
|
|
|
@ -45,6 +45,9 @@
|
||||||
<% for i = 1,math.min(#v.tags, 5) do %>
|
<% for i = 1,math.min(#v.tags, 5) do %>
|
||||||
<li><a class="tag button button-outline" href="https://<%= domain %>/_search?tag=<%= v.tags[i] %>"><%= v.tags[i] %></a></li>
|
<li><a class="tag button button-outline" href="https://<%= domain %>/_search?tag=<%= v.tags[i] %>"><%= v.tags[i] %></a></li>
|
||||||
<% end %>
|
<% end %>
|
||||||
|
<% if #v.tags > 5 then %>
|
||||||
|
<li>+<%= #v.tags - 5 %></li>
|
||||||
|
<% end %>
|
||||||
</ul>
|
</ul>
|
||||||
</td><td>
|
</td><td>
|
||||||
<%= v.posted %>
|
<%= v.posted %>
|
||||||
|
|
|
@ -32,7 +32,7 @@
|
||||||
</article>
|
</article>
|
||||||
<hr/>
|
<hr/>
|
||||||
<p><%= views %> Hits</p>
|
<p><%= views %> Hits</p>
|
||||||
<ul class="row tag-list">
|
<ul class="tag-list">
|
||||||
<% for _,tag in pairs(tags) do -%>
|
<% for _,tag in pairs(tags) do -%>
|
||||||
<li><a class="tag button button-outline" href="https://<%= domain %>/_search?tag=<%= tag %>"><%= tag %></a></li>
|
<li><a class="tag button button-outline" href="https://<%= domain %>/_search?tag=<%= tag %>"><%= tag %></a></li>
|
||||||
<% end -%>
|
<% end -%>
|
||||||
|
|
Loading…
Reference in New Issue