337 lines
9.2 KiB
C
337 lines
9.2 KiB
C
#include <kore/kore.h>
|
|
#include <kore/http.h>
|
|
#ifdef BUILD_PROD
|
|
#include <luajit.h>
|
|
#else
|
|
#define LUA_OK 0
|
|
#endif
|
|
#include <lauxlib.h>
|
|
#include <lua.h>
|
|
#include <lualib.h>
|
|
#include "smr.h"
|
|
#include "libkore.h"
|
|
#include "libcrypto.h"
|
|
#include <dirent.h>
|
|
#include <kore/seccomp.h>
|
|
|
|
int home(struct http_request *);
|
|
int post_story(struct http_request *);
|
|
int edit_story(struct http_request *);
|
|
int edit_bio(struct http_request *);
|
|
int read_story(struct http_request *);
|
|
int login(struct http_request *);
|
|
int logout(struct http_request *);
|
|
int claim(struct http_request *);
|
|
int download(struct http_request *);
|
|
int preview(struct http_request *);
|
|
int search(struct http_request *);
|
|
int archive(struct http_request *);
|
|
int api(struct http_request *);
|
|
int style(struct http_request *);
|
|
int miligram(struct http_request *);
|
|
int delete(struct http_request *);
|
|
int do_lua(struct http_request *req, const char *name);
|
|
int errhandeler(lua_State *);
|
|
lua_State *L;
|
|
/*
|
|
These should be defined in in kore somewhere and included here
|
|
*/
|
|
void kore_worker_configure(void);
|
|
void kore_worker_teardown(void);
|
|
/*
|
|
static / index
|
|
static / _post post
|
|
static / _edit edit
|
|
dynamic / .* read
|
|
static / _login login
|
|
static / _claim claim
|
|
*/
|
|
|
|
/*Allow seccomp things for luajit and sqlite*/
|
|
KORE_SECCOMP_FILTER("app",
|
|
KORE_SYSCALL_ALLOW(pread64),
|
|
KORE_SYSCALL_ALLOW(pwrite64),
|
|
KORE_SYSCALL_ALLOW(fdatasync),
|
|
KORE_SYSCALL_ALLOW(unlinkat),
|
|
KORE_SYSCALL_ALLOW(mremap),
|
|
KORE_SYSCALL_ALLOW(newfstatat),
|
|
KORE_SYSCALL_ALLOW(getdents64),
|
|
KORE_SYSCALL_ALLOW(gettimeofday),
|
|
KORE_SYSCALL_ALLOW(fchown)
|
|
);
|
|
|
|
int
|
|
errhandeler(lua_State *state){
|
|
printf("Error: %s\n",lua_tostring(state,1));//"error"
|
|
lua_getglobal(state,"debug");//"error",{debug}
|
|
lua_getglobal(state,"print");//"error",{debug},print()
|
|
lua_getfield(state,-2,"traceback");//"error",{debug},print(),traceback()
|
|
lua_call(state,0,1);//"error",{debug},print(),"traceback"
|
|
lua_call(state,1,0);//"error",{debug}
|
|
printf("Called print()\n");
|
|
lua_getfield(state,-1,"traceback");//"error",{debug},traceback()
|
|
printf("got traceback\n");
|
|
lua_call(state,0,1);//"error",{debug},"traceback"
|
|
lua_pushstring(state,"\n");
|
|
printf("called traceback\n");
|
|
lua_pushvalue(state,-4);//"error",{debug},"traceback","error"
|
|
printf("pushed error\n");
|
|
lua_concat(state,3);//"error",{debug},"traceback .. error"
|
|
printf("concated\n");
|
|
int ref = luaL_ref(state,LUA_REGISTRYINDEX);//"error",{debug}
|
|
lua_pop(state,2);//
|
|
lua_rawgeti(state,LUA_REGISTRYINDEX,ref);//"traceback .. error"
|
|
return 1;
|
|
}
|
|
|
|
int
|
|
do_lua(struct http_request *req, const char *name){
|
|
//printf("About to do lua %s\n",name);
|
|
lua_pushcfunction(L,errhandeler);
|
|
lua_getglobal(L,name);//err(),name()
|
|
if(!lua_isfunction(L,-1)){
|
|
printf("Could not find a method named %s\n",name);
|
|
lua_pop(L,2);//
|
|
return (KORE_RESULT_OK);
|
|
}
|
|
lua_pushlightuserdata(L,req);//err,name(),ud_req
|
|
int err = lua_pcall(L,1,0,-3);
|
|
if(err != LUA_OK){
|
|
size_t retlen;
|
|
const char *ret = lua_tolstring(L,-1,&retlen);
|
|
printf("Failed to run %s: %s\n",name,lua_tostring(L,-1));
|
|
http_response(req, 500, ret, retlen);
|
|
lua_pop(L,lua_gettop(L));
|
|
return (KORE_RESULT_OK);
|
|
}
|
|
return KORE_RESULT_OK;
|
|
}
|
|
|
|
#define route(method, lua_method) \
|
|
int\
|
|
method(struct http_request *req){\
|
|
return do_lua(req,#lua_method);\
|
|
}
|
|
|
|
/* md
|
|
@name http/_paste
|
|
Called at the endpoint <domain>/_paste.
|
|
This method doesn't need any parameters for GET requests.
|
|
This method expects the following for POST requests:
|
|
* title :: string - story title
|
|
* text :: string - text to put through markup
|
|
* markup :: string - a valid markup type
|
|
In addition to the normal assets, this page includes
|
|
suggest_tags.js, which suggests tags that have been
|
|
submitted to the site before.
|
|
@custom http_method GET POST
|
|
*/
|
|
/* md
|
|
@name lua/paste
|
|
This function is called automatically with the request submitted at
|
|
<endpoint>/_paste
|
|
@param http_request req The request to service
|
|
*/
|
|
route(post_story,"paste");
|
|
|
|
/***
|
|
Called at the endpoint <domain>/_edit.
|
|
This method requires the following for GET requests:
|
|
* story :: string - The url of the story to edit
|
|
This method requires the following for POST requests:
|
|
* title :: string - story title
|
|
* text :: string - text to put through markup
|
|
* markup :: string - a valid markup type
|
|
* story :: string - the story we're editing
|
|
In addition to normal assets, this page includes
|
|
suggest_tags.js, which suggests tags that have been
|
|
submitted to the site before.
|
|
@function _G.edit
|
|
@custom http_method GET POST
|
|
@param http_request req The request to service
|
|
***/
|
|
route(edit_story, "edit");
|
|
|
|
/***
|
|
Called at the endpoint <domain>/_bio
|
|
This method does not need any parameters for GET requests.
|
|
This method requires the following for POST requests:
|
|
* text :: string - The text to use as the author bio
|
|
* author :: string - The author to modify
|
|
If the logged in user does not match the author being
|
|
modified, the user recives a 401 Unauthorized error.
|
|
@function _G.edit_bio
|
|
@custom http_method GET POST
|
|
@param http_request req The request to service
|
|
***/
|
|
route(edit_bio, "edit_bio");
|
|
|
|
/***
|
|
Called at the endpoint <domain>/[^_]*
|
|
This method does not require any parameters for GET requests, but may include:
|
|
* load_comments :: 0 | 1 - Legacy parameter for loading comments
|
|
* pwd :: [0-9a-f]{128} - If the post is marked as "unlisted", this parameter is
|
|
needed, if it is not passed, the user receives a 401 Unauthorized error.
|
|
This method requires the following for POST requests:
|
|
* text :: string - Comment text
|
|
* postas :: string - The user to post as, if this is not "Anonymous", the
|
|
request must include a session cookie. If it does not, the user receives
|
|
a 401 Unauthorized error.
|
|
* pwd :: [0-9a-f]{128} - Currently unused, but it's intended use is to validate
|
|
the user has the password for unlisted stories.
|
|
@function _G.read
|
|
@custom http_method GET POST
|
|
@param http_request req The request to service
|
|
***/
|
|
route(read_story, "read");
|
|
|
|
/***
|
|
Called at the endpoint <domain>/_login
|
|
This method does not require any parameters for GET requests.
|
|
This method requiries the following for POST requests:
|
|
* user :: [a-z0-9]{1,30} - The username to log in as
|
|
* pass :: any - The passfile for this user
|
|
To overload login functionality in an addon, see @{api.authenticate}
|
|
@function _G.login
|
|
@custom http_method GET POST
|
|
@param http_request req The request to service.
|
|
***/
|
|
int
|
|
login(struct http_request *req){
|
|
return do_lua(req,"login");
|
|
}
|
|
|
|
int
|
|
logout(struct http_request *req){
|
|
return do_lua(req,"logout");
|
|
}
|
|
|
|
int
|
|
claim(struct http_request *req){
|
|
return do_lua(req,"claim");
|
|
}
|
|
|
|
int
|
|
download(struct http_request *req){
|
|
return do_lua(req,"download");
|
|
}
|
|
|
|
int
|
|
preview(struct http_request *req){
|
|
return do_lua(req,"preview");
|
|
}
|
|
|
|
int
|
|
search(struct http_request *req){
|
|
return do_lua(req,"search");
|
|
}
|
|
|
|
int
|
|
archive(struct http_request *req){
|
|
/*
|
|
struct kore_fileref *ref = kore_fileref_get("data/archive.zip",1);
|
|
if(ref != NULL){
|
|
http_response_fileref(ref,HTTP_STATUS_OK,ref);
|
|
kore_fileref_release(ref);
|
|
return KORE_RESULT_OK;
|
|
}else{
|
|
char msg[] = "Failed to create file ref";
|
|
http_response(req,200,msg,strlen(msg));
|
|
return KORE_RESULT_OK;
|
|
}
|
|
*/
|
|
return do_lua(req,"archive");
|
|
}
|
|
|
|
int
|
|
api(struct http_request *req){
|
|
return do_lua(req,"api");
|
|
}
|
|
|
|
int
|
|
home(struct http_request *req){
|
|
return do_lua(req,"home");
|
|
}
|
|
|
|
int
|
|
delete(struct http_request *req){
|
|
return do_lua(req,"delete");
|
|
}
|
|
|
|
void
|
|
kore_worker_configure(void){
|
|
printf("Configuring worker...\n");
|
|
int err;
|
|
/*DIR *dp;*/
|
|
/*struct dirent *ep;*/
|
|
/*dp = opendir("./");*/
|
|
/*if(dp != NULL){*/
|
|
/*while(ep = readdir(dp)){*/
|
|
/*printf("%s\n",ep->d_name);*/
|
|
/*}*/
|
|
/*closedir(dp);*/
|
|
/*}*/
|
|
L = luaL_newstate();
|
|
|
|
|
|
// Open libraries
|
|
luaL_openlibs(L);
|
|
load_kore_libs(L);
|
|
load_crypto_libs(L);
|
|
|
|
// Set package.path
|
|
lua_getglobal(L,"package"); // {package}
|
|
lua_getfield(L,-1,"path"); // {package}, "package.path"
|
|
lua_pushstring(L,";/var/smr/?.lua;/usr/local/share/lua/5.1/?.lua"); // {package}, "package.path", "/var/smr/?.lua"
|
|
lua_concat(L,2); //{package}, "package.path;/var/app_name/?.lua"
|
|
lua_setfield(L,-2,"path"); //{package}
|
|
lua_getfield(L,-1,"cpath");
|
|
lua_pushstring(L,";/usr/local/lib/lua/5.1/?.so");
|
|
lua_concat(L,2);
|
|
lua_setfield(L,-2,"cpath");
|
|
lua_pop(L,1);
|
|
|
|
// Run init
|
|
lua_pushcfunction(L,errhandeler);
|
|
printf("About to run loadfile...\n");
|
|
luaL_loadfile(L,SM_INIT);
|
|
printf("Done running loadfile...\n");
|
|
if(!lua_isfunction(L,-1)){//failed to loadfile()
|
|
printf("Failed to load %s: %s\n",SM_INIT,lua_tostring(L,-1));
|
|
lua_pop(L,1);
|
|
return;
|
|
}
|
|
printf("About to pcall\n");
|
|
err = lua_pcall(L,0,LUA_MULTRET,-2);
|
|
printf("Done pcalling\n");
|
|
//err = luaL_dofile(L,"init.lua");
|
|
if(err){
|
|
printf("Failed to run %s\n",SM_INIT);
|
|
return;
|
|
}
|
|
lua_pushcfunction(L,errhandeler);
|
|
lua_getglobal(L,"configure");
|
|
err = lua_pcall(L,0,0,-2);
|
|
if(err != LUA_OK){
|
|
printf("Failed to run configure(): %s\n",lua_tostring(L,-1));
|
|
lua_pop(L,2);
|
|
return;
|
|
}
|
|
lua_pop(L,lua_gettop(L));
|
|
printf("Finished configuring worker\n");
|
|
}
|
|
|
|
void
|
|
kore_worker_teardown(void){
|
|
int err;
|
|
lua_pushcfunction(L,errhandeler);
|
|
lua_getglobal(L,"teardown");
|
|
err = lua_pcall(L,0,0,1);
|
|
if(err != LUA_OK){
|
|
printf("Failed to run configure(): %s\n",lua_tostring(L,-1));
|
|
lua_pop(L,2);
|
|
return;
|
|
}
|
|
lua_close(L);
|
|
}
|