2024-06-01 17:40:11 +03:00
local SQL = require " luasql.mysql "
local BigGlobe = require " bigglobe "
local SQLEnv = SQL.mysql ( )
local SQLConn
local Rand = require " openssl.rand "
assert ( Rand.ready ( ) )
local SessionsKey = Rand.bytes ( 64 )
local ObjHideKey = io.open ( " objkey " , " rb " ) : read " *a "
local AES128ECB = require " openssl.cipher " . new ( " AES-128-ECB " ) -- Can be ECB without reprecussions
local Escapes = require " html "
local LFS = require " lfs "
local unistd = require " posix.unistd "
local stdio = require " posix.stdio "
local USER_PRIVS_BANNED = 0
local USER_PRIVS_UNAPPROVED = 1
local USER_PRIVS_APPROVED = 2
local USER_PRIVS_MOD = 128
local USER_PRIVS_ADMIN = 255
local function pingdb ( )
if not SQLConn or not SQLConn : ping ( ) then
SQLConn = SQLEnv : connect ( " ikibooru " , BigGlobe.cfg . sqlu , BigGlobe.cfg . sqlp , BigGlobe.cfg . sqlh )
end
return SQLConn ~= nil
end
-- UTC to store in database
local function getnow ( )
return " ' " .. SQLConn : escape ( os.date ( " !%Y-%m-%d %H:%M:%S " ) ) .. " ' "
end
local function autocomplete ( liek , over18 )
pingdb ( )
local ret = { }
local cursor = SQLConn : execute ( " SELECT * FROM tags WHERE name LIKE ' " .. SQLConn : escape ( " % " .. liek .. " % " ) .. " ' " .. ( over18 and " " or " AND adultonly = 0 " ) .. " ; " )
if not cursor then return " " end
local row = cursor : fetch ( { } )
while row do
ret [ # ret + 1 ] = table.concat ( row , " , " ) .. " \n "
row = cursor : fetch ( row )
end
cursor : close ( )
return table.concat ( ret )
end
local function searchobjs ( taglist , namefilter , offset , adultstuff )
-- Security check
for k , v in pairs ( taglist ) do
if type ( taglist [ k ] ) ~= " number " then
return nil
end
end
if not adultstuff then
adultstuff = - 1
end
pingdb ( )
offset = tonumber ( offset )
local sqlq
if # taglist > 0 and namefilter then
sqlq = string.format (
" SELECT * FROM objects WHERE %s id IN (SELECT objid FROM objtag WHERE tagid IN (%s) GROUP BY objid HAVING COUNT(tagid) >= %s) AND MATCH(name) AGAINST('%s') AND id > %s AND published = 1 ORDER BY id ASC LIMIT 50; " ,
( { [ - 1 ] = " id NOT IN (SELECT objid FROM objtag WHERE tagid IN (SELECT id FROM tags WHERE adultonly = 1)) AND " , [ 0 ] = " " , [ 1 ] = " id IN (SELECT objid FROM objtag WHERE tagid IN (SELECT id FROM tags WHERE adultonly = 1)) AND " } ) [ adultstuff ] ,
table.concat ( taglist , " , " ) ,
# taglist ,
SQLConn : escape ( namefilter ) ,
offset
)
elseif # taglist > 0 and not namefilter then
sqlq = string.format (
" SELECT * FROM objects WHERE %s id IN (SELECT objid FROM objtag WHERE tagid IN (%s) GROUP BY objid HAVING COUNT(tagid) >= %s) AND id > %s AND published = 1 ORDER BY id ASC LIMIT 50; " ,
( { [ - 1 ] = " id NOT IN (SELECT objid FROM objtag WHERE tagid IN (SELECT id FROM tags WHERE adultonly = 1)) AND " , [ 0 ] = " " , [ 1 ] = " id IN (SELECT objid FROM objtag WHERE tagid IN (SELECT id FROM tags WHERE adultonly = 1)) AND " } ) [ adultstuff ] ,
table.concat ( taglist , " , " ) ,
# taglist ,
offset
)
elseif # taglist == 0 and namefilter then
sqlq = string.format (
" SELECT * FROM objects WHERE %s MATCH(name) AGAINST('%s') AND id > %s AND published = 1 ORDER BY id ASC LIMIT 50; " ,
( { [ - 1 ] = " id NOT IN (SELECT objid FROM objtag WHERE tagid IN (SELECT id FROM tags WHERE adultonly = 1)) AND " , [ 0 ] = " " , [ 1 ] = " id IN (SELECT objid FROM objtag WHERE tagid IN (SELECT id FROM tags WHERE adultonly = 1)) AND " } ) [ adultstuff ] ,
SQLConn : escape ( namefilter ) ,
offset
)
else
sqlq = string.format (
" SELECT * FROM objects WHERE %s id > %s AND published = 1 ORDER BY id ASC LIMIT 50; " ,
( { [ - 1 ] = " id NOT IN (SELECT objid FROM objtag WHERE tagid IN (SELECT id FROM tags WHERE adultonly = 1)) AND " , [ 0 ] = " " , [ 1 ] = " id IN (SELECT objid FROM objtag WHERE tagid IN (SELECT id FROM tags WHERE adultonly = 1)) AND " } ) [ adultstuff ] ,
offset
)
end
local cursor = SQLConn : execute ( sqlq )
if not cursor then return { } end
local ret = { }
while true do
local row = cursor : fetch ( { } , " a " )
if not row then break end
table.insert ( ret , row )
end
return ret
end
local function getobj ( objid )
if type ( objid ) ~= " number " then return nil end
pingdb ( )
local cursor = SQLConn : execute ( " SELECT * FROM objects WHERE id = " .. objid .. " ; " )
if not cursor then return nil end
local ret = cursor : fetch ( { } , " a " )
if not ret then return nil end
ret.id = tonumber ( ret.id ) --for some reason..
ret.owner = tonumber ( ret.owner )
ret.published = ret.published : byte ( 1 ) ~= 0
ret.approved = ret.approved : byte ( 1 ) ~= 0
return ret
end
local hextointandinttohex = { }
for i = 0 , 255 do local s = string.format ( " %02x " , i ) ; hextointandinttohex [ s ] = i ; hextointandinttohex [ i ] = s ; end
local function b256toreadable ( src )
local r = { }
src : gsub ( " . " , function ( b ) table.insert ( r , hextointandinttohex [ b : byte ( ) ] ) end )
return table.concat ( r )
end
local function readabletob256 ( src )
if # src % 2 == 1 then error ( " gotta be even length, man " ) end
local r = { }
for i = 1 , # src , 2 do
table.insert ( r , string.char ( hextointandinttohex [ src : sub ( i , i + 1 ) ] ) )
end
return table.concat ( r )
end
local function isobjhexvalid ( objhex )
return # objhex == 32 and not objhex : find ( " [^0-9a-f] " )
end
local function objhideid ( objid )
local t = { }
for i = 1 , 16 do
table.insert ( t , objid % 256 )
objid = objid // 256
end
local c = AES128ECB : encrypt ( ObjHideKey , nil , false ) : final ( string.char ( table.unpack ( t ) ) )
return b256toreadable ( c )
end
local function objshowid ( objhex )
if not isobjhexvalid ( objhex ) then return nil end
local c = AES128ECB : decrypt ( ObjHideKey , nil , false ) : final ( readabletob256 ( objhex ) )
local r = 0
for i = 16 , 1 , - 1 do
r = r * 256 + c : byte ( i )
end
return r
end
local function testobjfilename ( fname )
if fname : match " ^%s+.*$ " or fname : match " ^%.+$ " or fname : match " .*%s+$ " or fname : match " .*%.+$ " then return false end
for k , v in pairs { " CON " , " PRN " , " AUX " , " NUL " , " COM1 " , " COM2 " , " COM3 " , " COM4 " , " COM5 " , " COM6 " , " COM7 " , " COM8 " , " COM9 " , " LPT1 " , " LPT2 " , " LPT3 " , " LPT4 " , " LPT5 " , " LPT6 " , " LPT7 " , " LPT8 " , " LPT9 " } do
if fname == v or fname : match ( " ^ " .. v .. " %..+ " ) then
return false
end
end
2024-06-11 16:40:33 +03:00
return not fname : find " [/ \\ \0 - \31 %<%>%:% \" %|%?%*%[%]%%] " and # fname <= 56
2024-06-01 17:40:11 +03:00
end
local function urltophysical ( p )
if p : sub ( 1 , 6 ) == " /objd/ " then
if isobjhexvalid ( p : sub ( 7 , 7 + 31 ) ) and testobjfilename ( p : sub ( 7 + 33 ) ) then
return " objd/ " .. p : sub ( 7 , 7 + 31 ) : gsub ( " .. " , " %0/ " ) .. p : sub ( 7 + 32 )
end
return nil
else
return p : sub ( 2 )
end
end
-- PERFORMS NO QUOTA CHECKING; THATS DONE IN obje.html.l
local function createfile ( objid , fname , fsz )
if not testobjfilename ( fname ) or fname == " .thumb.jpg " then return false end
if type ( fsz ) ~= " number " then return false end
local f = io.open ( urltophysical ( " /objd/ " .. objhideid ( objid ) .. " / " .. fname ) , " wb " )
if not f then return false end
if unistd.ftruncate ( stdio.fileno ( f ) , fsz ) ~= 0 then return false end
f : close ( )
return true
end
local function updatefile ( objid , fname , offset , data )
if not testobjfilename ( fname ) or fname == " .thumb.jpg " then return false end
local fn = urltophysical ( " /objd/ " .. objhideid ( objid ) .. " / " .. fname )
if offset + # data > lfs.attributes ( fn ) . size then
return false
end
local f = io.open ( fn , " r+b " )
if not f then
return false
end
if not f : seek ( " set " , offset ) then return false end
if not f : write ( data ) then return false end
f : close ( )
return true
end
local function remfilefromobj ( objid , fname )
if not testobjfilename ( fname ) then return false end
if not os.remove ( urltophysical ( " /objd/ " .. objhideid ( objid ) .. " / " .. fname ) ) then return false end
return true
end
local function genobjthumbnail ( objid , fname , maxsize )
if not testobjfilename ( fname ) then return false end
local objhex = objhideid ( objid )
local srcfn = urltophysical ( " /objd/ " .. objhex .. " / " .. fname )
local tempfn = " /tmp/ikibooruthumb " .. b256toreadable ( Rand.bytes ( 16 ) ) .. " .jpg "
local destfn = urltophysical ( " /objd/ " .. objhex .. " /.thumb.jpg " )
2024-06-11 16:41:16 +03:00
local ret , killa , exitcode = os.execute ( BigGlobe.cfg . magickprefix .. " convert " .. Escapes.shellescape ( srcfn ) .. " -background white -strip -interlace Plane -sampling-factor 4:2:0 -flatten -define jpeg:extent=100kb " .. Escapes.shellescape ( tempfn ) )
2024-06-01 17:40:11 +03:00
if not ret or killa ~= " exit " or exitcode ~= 0 then return false end
if LFS.attributes ( tempfn ) . size > maxsize then
os.remove ( tempfn )
return false
end
local inn = io.open ( tempfn , " rb " )
local outt = io.open ( destfn , " wb " )
if not inn or not outt then
os.remove ( tempfn )
return false
end
outt : write ( inn : read " *a " )
outt : close ( )
inn : close ( )
os.remove ( tempfn )
return true
end
local function isdisplaynamevalid ( str )
return not str : find " [ \0 - \31 ] " and # str <= 32
end
local function isemailvalid ( str )
return not str : match " ^%s*$ " and not str : find " [ \0 - \31 ] " and # str <= 64
end
local function getuserbyemail ( email )
if type ( email ) ~= " string " then return nil end
pingdb ( )
local cursor = SQLConn : execute ( " SELECT * FROM users WHERE email = ' " .. SQLConn : escape ( email ) .. " '; " )
if not cursor then return nil end
local ret = cursor : fetch ( { } , " a " )
if not ret then return nil end
ret.id = tonumber ( ret.id )
ret.privs = tonumber ( ret.privs )
return ret
end
local function getuserbyid ( userid )
userid = tonumber ( userid )
if not userid then return nil end
pingdb ( )
local cursor = SQLConn : execute ( " SELECT * FROM users WHERE id = " .. userid .. " ; " )
if not cursor then return nil end
local ret = cursor : fetch ( { } , " a " )
if not ret then return nil end
ret.id = tonumber ( ret.id )
ret.privs = tonumber ( ret.privs )
return ret
end
local function reguser ( email , displayname , privs )
if not isdisplaynamevalid ( displayname ) then return false , " displayname " end
privs = tonumber ( privs )
if not privs then return false , " privs " end
pingdb ( )
local cursor = SQLConn : execute ( " INSERT INTO users (displayname, email, createtime, privs) VALUES (' " .. SQLConn : escape ( displayname ) .. " ', ' " .. SQLConn : escape ( email ) .. " ', " .. getnow ( ) .. " , " .. privs .. " ); " )
if not cursor then return false , " db " end
return tonumber ( SQLConn : getlastautoid ( ) )
end
local function userregverify ( str )
local start , sep = str : find " ^[^%;]+; "
-- Malformity check
if not start then return nil end
local digest = str : sub ( 1 , sep - 1 )
local msg = str : sub ( sep + 1 )
local thetime = msg : match " t%=(%d+)%; "
if not thetime then return nil end
if os.difftime ( thetime , os.time ( ) ) < 0 then return false end
if b256toreadable ( require " openssl.hmac " . new ( SessionsKey , " sha256 " ) : final ( msg ) ) ~= digest then
return nil
end
if not msg : match " ^reg%; " then return nil end
return { em = readabletob256 ( msg : match " em=([^%;]*) " ) }
end
local function userregcode ( em )
local t = os.date " *t "
t.day = t.day + 7 --7 day expiry
local str = " reg;em= " .. b256toreadable ( em ) .. " ;t= " .. os.time ( t ) .. " ; "
return b256toreadable ( require " openssl.hmac " . new ( SessionsKey , " sha256 " ) : final ( str ) ) .. " ; " .. str
end
local function userauth ( user )
local t = os.date " *t "
t.day = t.day + 7 --7 day expiry
local str = " id= " .. user.id .. " ;t= " .. os.time ( t ) .. " ; "
return b256toreadable ( require " openssl.hmac " . new ( SessionsKey , " sha256 " ) : final ( str ) ) .. " ; " .. str
end
local function userverify ( str )
local start , sep = str : find " ^[^%;]+; " ;
-- Malformity check
if not start then return nil end
local digest = str : sub ( 1 , sep - 1 )
local msg = str : sub ( sep + 1 )
local thetime = msg : match ( " t%=(%d+)%; " )
-- Malformity check
if not thetime then return nil end
-- Expiry check
if os.difftime ( thetime , os.time ( ) ) < 0 then return false end
if b256toreadable ( require " openssl.hmac " . new ( SessionsKey , " sha256 " ) : final ( msg ) ) ~= digest then
return nil
end
if not msg : match " ^id%= " then return nil end
return getuserbyid ( msg : match " ^id%=(%d+) " )
end
local function tagadd ( name , category , adultonly )
category = tonumber ( category )
if not category then return false end
category = category - 1
pingdb ( )
2024-07-18 22:53:44 +03:00
local cur = SQLConn : execute ( " INSERT INTO tags (name, category, adultonly) VALUES (' " .. SQLConn : escape ( name ) .. " ', " .. category .. " , " .. ( adultonly and 1 or 0 ) .. " ); " )
if not cur then return nil end
return tonumber ( SQLConn : getlastautoid ( ) )
2024-06-01 17:40:11 +03:00
end
local function regnewobj ( ownerid , approved , published )
ownerid = tonumber ( ownerid )
if not ownerid then return nil end
if type ( approved ) ~= " boolean " then return nil end
if type ( published ) ~= " boolean " then return nil end
pingdb ( )
local cur = SQLConn : execute ( " INSERT INTO objects (name, owner, approved, published, createtime) VALUES ('', " .. ownerid .. " , " .. ( approved and 1 or 0 ) .. " , " .. ( published and 1 or 0 ) .. " , " .. getnow ( ) .. " ); " )
if not cur then return nil end
local objid = tonumber ( SQLConn : getlastautoid ( ) )
local objpath = " objd/ "
for objpathpart in objhideid ( objid ) : gmatch ( " .. " ) do
objpath = objpath .. objpathpart .. " / "
LFS.mkdir ( objpath )
end
return objid
end
local function getownedobjs ( ownerid )
ownerid = tonumber ( ownerid )
if not ownerid then return nil end
pingdb ( )
local cur = SQLConn : execute ( " SELECT * FROM objects WHERE owner = " .. ownerid .. " ORDER BY id DESC; " )
if not cur then return { } end
local ret = { }
while true do
local row = cur : fetch ( { } , " a " )
if not row then break end
row.id = tonumber ( row.id )
row.owner = tonumber ( row.owner )
table.insert ( ret , row )
end
return ret
end
local function objupdate ( objid , newname , newpublished )
if not isdisplaynamevalid ( newname ) then return false end
objid = tonumber ( objid )
if not objid then return false end
if type ( newpublished ) ~= " boolean " then return false end
pingdb ( )
if not SQLConn : execute ( " UPDATE objects SET name = ' " .. SQLConn : escape ( newname ) .. " ', published = " .. ( newpublished and 1 or 0 ) .. " WHERE id = " .. objid .. " ; " ) then return false end
return true
end
local function updatetags ( tagarr , newname , newcategory , newadultonly , del )
for k , v in pairs ( tagarr ) do
if type ( v ) ~= " number " then
return false
end
end
if # tagarr == 0 then return false end
if newcategory and type ( newcategory ) ~= " number " then
return false
end
pingdb ( )
if del then
return not not SQLConn : execute ( " DELETE FROM tags WHERE id IN ( " .. table.concat ( tagarr , " , " ) .. " ); " )
end
local cols = { " adultonly = " .. ( newadultonly and 1 or 0 ) }
if newname then
table.insert ( cols , newname and ( " name = ' " .. SQLConn : escape ( newname ) .. " ' " ) or " " )
end
if newcategory then
newcategory = newcategory - 1
table.insert ( cols , newcategory and ( " category = " .. newcategory ) or " " )
end
return not not SQLConn : execute ( " UPDATE tags SET " .. table.concat ( cols , " , " ) .. " WHERE id IN ( " .. table.concat ( tagarr , " , " ) .. " ); " )
end
local function csrf ( userid )
local str = table.concat ( { os.time ( ) , tonumber ( userid ) } , " ; " )
return b256toreadable ( require " openssl.hmac " . new ( SessionsKey , " sha256 " ) : final ( str ) ) .. " ; " .. str
end
local function csrfverify ( userid , booboo )
if not booboo : find " ; " then return false end
local digest = booboo : sub ( 1 , booboo : find " ; " - 1 )
local msg = booboo : sub ( booboo : find " ; " + 1 )
if b256toreadable ( require " openssl.hmac " . new ( SessionsKey , " sha256 " ) : final ( msg ) ) ~= digest then
return false
end
return tonumber ( msg : match " ;(%d+)$ " ) == userid
end
local function nexttoapproveobj ( )
pingdb ( )
local cur = SQLConn : execute ( " SELECT id FROM objects WHERE published = 1 AND approved = 0 ORDER BY id ASC LIMIT 1; " )
if not cur then return nil end
return tonumber ( cur : fetch ( ) )
end
local function banuser ( uid )
if type ( uid ) ~= " number " then
return false
end
pingdb ( )
return not not SQLConn : execute ( " UPDATE users SET privs = " .. USER_PRIVS_BANNED .. " WHERE id = " .. uid .. " ; " )
end
local function approveuser ( uid )
if type ( uid ) ~= " number " then
return false
end
pingdb ( )
return not not SQLConn : execute ( " UPDATE users SET privs = " .. USER_PRIVS_APPROVED .. " WHERE id = " .. uid .. " AND privs = " .. USER_PRIVS_UNAPPROVED .. " ; " )
end
local function delobj ( oid , delfiles )
if type ( oid ) ~= " number " then
return false
end
pingdb ( )
if not SQLConn : execute ( " DELETE FROM objects WHERE id = " .. oid .. " ; " ) then
return false
end
if delfiles then
local d = urltophysical ( " /objd/ " .. objhideid ( oid ) )
for f in LFS.dir ( d ) do
if f ~= " . " and f ~= " .. " then
os.remove ( d .. f )
end
end
end
return true
end
local function approveobj ( oid )
if type ( oid ) ~= " number " then
return false
end
pingdb ( )
return not not SQLConn : execute ( " UPDATE objects SET approved = 1 WHERE id = " .. oid .. " ; " )
end
local function userinfoupdate ( userid , displayname )
if type ( userid ) ~= " number " then return false end
if not isdisplaynamevalid ( displayname ) then return false end
pingdb ( )
return not not SQLConn : execute ( " UPDATE users SET displayname = ' " .. SQLConn : escape ( displayname ) .. " ' WHERE id = " .. userid .. " ; " )
end
local function getobjtags ( objid )
if type ( objid ) ~= " number " then return nil end
pingdb ( )
local cur = SQLConn : execute ( " SELECT * FROM tags WHERE id IN (SELECT tagid FROM objtag WHERE objid = " .. objid .. " ); " )
if not cur then return nil end
local ret = { }
local n = 0
while true do
local t = cur : fetch ( { } , " *a " )
if not t then break end
t.id = tonumber ( t.id )
t.category = tonumber ( t.category )
ret [ t.id ] = t
n = n + 1
end
return ret , n
end
local function addtagstoobj ( objid , taglist )
if type ( objid ) ~= " number " then return false end
local temp = { }
for k , v in pairs ( taglist ) do
if type ( v ) ~= " number " then return false end
table.insert ( temp , " ( " .. objid .. " , " .. v .. " ) " )
end
pingdb ( )
return not not SQLConn : execute ( " INSERT INTO objtag (objid, tagid) VALUES " .. table.concat ( temp , " , " ) .. " ; " )
end
local function remtagsfromobj ( objid , taglist )
if type ( objid ) ~= " number " then return false end
local temp = { }
for k , v in pairs ( taglist ) do
if type ( v ) ~= " number " then return false end
table.insert ( temp , " tagid = " .. v )
end
pingdb ( )
return not not SQLConn : execute ( " DELETE FROM objtag WHERE objid = " .. objid .. " AND ( " .. table.concat ( temp , " OR " ) .. " ); " )
end
local function getmoderators ( )
pingdb ( )
local cur = SQLConn : execute ( " SELECT * from users WHERE privs = " .. USER_PRIVS_MOD .. " ; " )
if not cur then return { } end
local ret = { }
while true do
local t = cur : fetch ( { } , " a " )
if not t then break end
t.id = tonumber ( t.id )
t.privs = tonumber ( t.privs )
table.insert ( ret , t )
end
return ret
end
local function setmodsviaemails ( emails )
pingdb ( )
if not SQLConn : execute ( " UPDATE users SET privs = " .. USER_PRIVS_APPROVED .. " WHERE privs = " .. USER_PRIVS_MOD .. " ; " ) then
return false
end
for k , v in pairs ( emails ) do
emails [ k ] = " ' " .. SQLConn : escape ( v ) .. " ' "
end
return not not SQLConn : execute ( " UPDATE users SET privs = " .. USER_PRIVS_MOD .. " WHERE privs < " .. USER_PRIVS_MOD .. " AND email IN ( " .. table.concat ( emails , " , " ) .. " ); " )
end
local function getcomments ( objid )
if type ( objid ) ~= " number " then return nil end
pingdb ( )
local cur = SQLConn : execute ( " SELECT comment.id AS id, comment.content AS content, comment.authorid AS authorid, user.displayname AS authordisplayname, comment.createtime AS createtime FROM comments comment INNER JOIN users user ON comment.authorid = user.id WHERE comment.objid = " .. objid .. " ORDER BY id DESC; " )
if not cur then return { } end
local ret = { }
while true do
local t = cur : fetch ( { } , " a " )
if not t then break end
t.id = tonumber ( t.id )
t.authorid = tonumber ( t.authorid )
table.insert ( ret , t )
end
return ret
end
local function postcomment ( objid , userid , content )
if # content > BigGlobe.MAX_COMMENT_SIZE then
return false
end
pingdb ( )
return not not SQLConn : execute ( " INSERT INTO comments (objid, authorid, content, createtime) VALUES ( " .. objid .. " , " .. userid .. " , ' " .. SQLConn : escape ( content ) .. " ', " .. getnow ( ) .. " ) " )
end
local function addreport ( reporterid , reporteeid , content )
if type ( reporterid ) ~= " number " then return false end
if type ( reporteeid ) ~= " number " then return false end
pingdb ( )
return not not SQLConn : execute ( " INSERT INTO reports (reporter, reportee, content, createtime, status) VALUES ( " .. reporterid .. " , " .. reporteeid .. " , ' " .. SQLConn : escape ( content ) .. " ', " .. getnow ( ) .. " , " .. BigGlobe.REPORT_STATUS_OPEN .. " ) " )
end
local function getreportcount ( )
pingdb ( )
local cur = SQLConn : execute ( " SELECT COUNT(*) FROM reports WHERE status = 0; " )
if not cur then return nil end
return cur : fetch ( )
end
local function getreports ( status , offset )
if type ( status ) ~= " number " then return nil end
if type ( offset ) ~= " number " then offset = 0 end
pingdb ( )
local cur = SQLConn : execute ( " SELECT * FROM reports WHERE status = " .. status .. " AND id > " .. offset .. " ORDER BY id ASC LIMIT 50; " )
if not cur then return { } end
local ret = { }
while true do
local t = cur : fetch ( { } , " a " )
if not t then break end
t.id = tonumber ( t.id )
t.reporter = tonumber ( t.reporter )
t.reportee = tonumber ( t.reportee )
t.status = tonumber ( t.status )
table.insert ( ret , t )
end
return ret
end
local function setreportstatus ( rid , newstatus )
if type ( rid ) ~= " number " then return false end
if type ( newstatus ) ~= " number " then return false end
pingdb ( )
return not not SQLConn : execute ( " UPDATE reports SET status = " .. newstatus .. " WHERE id = " .. rid .. " ; " )
end
local function getobjcount ( )
pingdb ( )
local cur = SQLConn : execute ( " SELECT COUNT(*) FROM objects; " )
if not cur then return nil end
return cur : fetch ( )
end
local function gettagcount ( )
pingdb ( )
local cur = SQLConn : execute ( " SELECT COUNT(*) FROM tags; " )
if not cur then return nil end
return cur : fetch ( )
end
return {
USER_PRIVS_BANNED = USER_PRIVS_BANNED ,
USER_PRIVS_UNAPPROVED = USER_PRIVS_UNAPPROVED ,
USER_PRIVS_APPROVED = USER_PRIVS_APPROVED ,
USER_PRIVS_MOD = USER_PRIVS_MOD ,
USER_PRIVS_ADMIN = USER_PRIVS_ADMIN ,
autocomplete = autocomplete ,
searchobjs = searchobjs ,
getobj = getobj ,
objhideid = objhideid ,
objshowid = objshowid ,
isobjhexvalid = isobjhexvalid ,
urltophysical = urltophysical ,
createfile = createfile ,
updatefile = updatefile ,
remfilefromobj = remfilefromobj ,
genobjthumbnail = genobjthumbnail ,
isdisplaynamevalid = isdisplaynamevalid ,
isemailvalid = isemailvalid ,
getuserbyemail = getuserbyemail ,
getuserbyid = getuserbyid ,
userauth = userauth ,
userverify = userverify ,
userregcode = userregcode ,
userregverify = userregverify ,
reguser = reguser ,
tagadd = tagadd ,
regnewobj = regnewobj ,
getownedobjs = getownedobjs ,
objupdate = objupdate ,
updatetags = updatetags ,
b256toreadable = b256toreadable ,
readabletob256 = readabletob256 ,
csrf = csrf ,
csrfverify = csrfverify ,
nexttoapproveobj = nexttoapproveobj ,
banuser = banuser ,
approveuser = approveuser ,
delobj = delobj ,
approveobj = approveobj ,
userinfoupdate = userinfoupdate ,
getobjtags = getobjtags ,
addtagstoobj = addtagstoobj ,
remtagsfromobj = remtagsfromobj ,
getmoderators = getmoderators ,
setmodsviaemails = setmodsviaemails ,
getcomments = getcomments ,
postcomment = postcomment ,
addreport = addreport ,
getreportcount = getreportcount ,
getreports = getreports ,
setreportstatus = setreportstatus ,
getobjcount = getobjcount ,
gettagcount = gettagcount ,
}