Finished WWWGen
This commit is contained in:
parent
6dd5e3a7b7
commit
386d8d30bd
|
@ -0,0 +1,9 @@
|
|||
a.out
|
||||
boot.dol
|
||||
boot.elf
|
||||
todos.json
|
||||
WWWGen.hpp
|
||||
bin/
|
||||
build/
|
||||
.vscode/
|
||||
src/sqlite.o
|
|
@ -0,0 +1,17 @@
|
|||
all: bin/tws bin/twss bin/wwwgen bin/wwwgentest
|
||||
|
||||
bin/wwwgentest: wwwgentest.cpp wwwroot bin/wwwgen
|
||||
./bin/wwwgen
|
||||
$(CXX) -g -std=gnu++23 -Isrc -o bin/wwwgentest wwwgentest.cpp src/sqlite.o -lm -lpthread -ljansson -lmbedtls -lmbedx509 -lmbedcrypto `pkg-config --libs --cflags libcurl`
|
||||
|
||||
bin/wwwgen: wwwgen.cpp
|
||||
$(CXX) -o bin/wwwgen wwwgen.cpp -std=gnu++23
|
||||
|
||||
bin/tws: src/sqlite.o src/tesseswebserver.cpp src/tesseswebserver.hpp src/tesseswebserverfeatures.hpp src/tessesscriptengine.hpp
|
||||
mkdir -p bin
|
||||
$(CXX) -g -std=gnu++23 -o bin/tws src/tesseswebserver.cpp src/sqlite.o -lm -lpthread -ljansson -lmbedtls -lmbedx509 -lmbedcrypto `pkg-config --libs --cflags libcurl`
|
||||
bin/twss: src/sqlite.o
|
||||
mkdir -p bin
|
||||
$(CXX) -O2 -std=gnu++23 -o bin/twss scriptengine.cpp -lm -lpthread -ljansson `pkg-config --libs --cflags libcurl`
|
||||
src/sqlite.o: src/sqlite3.c
|
||||
$(CC) -O2 -c -o src/sqlite.o src/sqlite3.c
|
|
@ -0,0 +1,138 @@
|
|||
#---------------------------------------------------------------------------------
|
||||
# Clear the implicit built in rules
|
||||
#---------------------------------------------------------------------------------
|
||||
.SUFFIXES:
|
||||
#---------------------------------------------------------------------------------
|
||||
ifeq ($(strip $(DEVKITPPC)),)
|
||||
$(error "Please set DEVKITPPC in your environment. export DEVKITPPC=<path to>devkitPPC")
|
||||
endif
|
||||
|
||||
include $(DEVKITPPC)/wii_rules
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
# TARGET is the name of the output
|
||||
# BUILD is the directory where object files & intermediate files will be placed
|
||||
# SOURCES is a list of directories containing source code
|
||||
# INCLUDES is a list of directories containing extra header files
|
||||
#---------------------------------------------------------------------------------
|
||||
TARGET := boot
|
||||
BUILD := build
|
||||
SOURCES := src
|
||||
DATA := data
|
||||
INCLUDES :=
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
# options for code generation
|
||||
#---------------------------------------------------------------------------------
|
||||
|
||||
CFLAGS = -O2 -Wall -DUSE_SCRIPT_ENGINE -DUSE_MBEDTLS -DUSE_CURL -DUSE_SQLITE3 -DUSE_JANSSON -DSQLITE_OMIT_LOAD_EXTENSION -DSQLITE_OMIT_WAL -DSQLITE_THREADSAFE=0 -DUSE_WIISOCKETS $(MACHDEP) $(INCLUDE)
|
||||
CXXFLAGS = $(CFLAGS) -std=gnu++23
|
||||
|
||||
LDFLAGS = -g $(MACHDEP) -Wl,-Map,$(notdir $@).map
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
# any extra libraries we wish to link with the project
|
||||
#---------------------------------------------------------------------------------
|
||||
LIBS := -lfat -lcurl -lmbedtls -lmbedx509 -lmbedcrypto -ljansson -lwiiuse -lbte -logc -lm -lwiisocket
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
# list of directories containing libraries, this must be the top level containing
|
||||
# include and lib
|
||||
#---------------------------------------------------------------------------------
|
||||
LIBDIRS := $(PORTLIBS)
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
# no real need to edit anything past this point unless you need to add additional
|
||||
# rules for different file extensions
|
||||
#---------------------------------------------------------------------------------
|
||||
ifneq ($(BUILD),$(notdir $(CURDIR)))
|
||||
#---------------------------------------------------------------------------------
|
||||
|
||||
export OUTPUT := $(CURDIR)/$(TARGET)
|
||||
|
||||
export VPATH := $(foreach dir,$(SOURCES),$(CURDIR)/$(dir)) \
|
||||
$(foreach dir,$(DATA),$(CURDIR)/$(dir))
|
||||
|
||||
export DEPSDIR := $(CURDIR)/$(BUILD)
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
# automatically build a list of object files for our project
|
||||
#---------------------------------------------------------------------------------
|
||||
CFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.c)))
|
||||
CPPFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.cpp)))
|
||||
sFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.s)))
|
||||
SFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.S)))
|
||||
BINFILES := $(foreach dir,$(DATA),$(notdir $(wildcard $(dir)/*.*)))
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
# use CXX for linking C++ projects, CC for standard C
|
||||
#---------------------------------------------------------------------------------
|
||||
ifeq ($(strip $(CPPFILES)),)
|
||||
export LD := $(CC)
|
||||
else
|
||||
export LD := $(CXX)
|
||||
endif
|
||||
|
||||
export OFILES_BIN := $(addsuffix .o,$(BINFILES))
|
||||
export OFILES_SOURCES := $(CPPFILES:.cpp=.o) $(CFILES:.c=.o) $(sFILES:.s=.o) $(SFILES:.S=.o)
|
||||
export OFILES := $(OFILES_BIN) $(OFILES_SOURCES)
|
||||
|
||||
export HFILES := $(addsuffix .h,$(subst .,_,$(BINFILES)))
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
# build a list of include paths
|
||||
#---------------------------------------------------------------------------------
|
||||
export INCLUDE := $(foreach dir,$(INCLUDES), -iquote $(CURDIR)/$(dir)) \
|
||||
$(foreach dir,$(LIBDIRS),-I$(dir)/include) \
|
||||
-I$(CURDIR)/$(BUILD) \
|
||||
-I$(LIBOGC_INC)
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
# build a list of library paths
|
||||
#---------------------------------------------------------------------------------
|
||||
export LIBPATHS := -L$(LIBOGC_LIB) $(foreach dir,$(LIBDIRS),-L$(dir)/lib)
|
||||
|
||||
export OUTPUT := $(CURDIR)/$(TARGET)
|
||||
.PHONY: $(BUILD) clean
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
$(BUILD):
|
||||
@[ -d $@ ] || mkdir -p $@
|
||||
@$(MAKE) --no-print-directory -C $(BUILD) -f $(CURDIR)/Makefile.wii
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
clean:
|
||||
@echo clean ...
|
||||
@rm -fr $(BUILD) $(OUTPUT).elf $(OUTPUT).dol
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
run:
|
||||
wiiload $(TARGET).dol
|
||||
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
else
|
||||
|
||||
DEPENDS := $(OFILES:.o=.d)
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
# main targets
|
||||
#---------------------------------------------------------------------------------
|
||||
$(OUTPUT).dol: $(OUTPUT).elf
|
||||
$(OUTPUT).elf: $(OFILES)
|
||||
|
||||
$(OFILES_SOURCES) : $(HFILES)
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
# This rule links in binary data with the .jpg extension
|
||||
#---------------------------------------------------------------------------------
|
||||
%.jpg.o %_jpg.h : %.jpg
|
||||
#---------------------------------------------------------------------------------
|
||||
@echo $(notdir $<)
|
||||
$(bin2o)
|
||||
|
||||
-include $(DEPENDS)
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
endif
|
||||
#---------------------------------------------------------------------------------
|
|
@ -0,0 +1,116 @@
|
|||
operator+ add operator
|
||||
operator- subtract operator
|
||||
operator* times operator
|
||||
operator/ divide operator
|
||||
operator% mod operator
|
||||
operator| bitwise or operator
|
||||
operator& bitwise and operator
|
||||
operator^ xor operator
|
||||
operator! logical not operator
|
||||
operator~ bitwise not operator
|
||||
operator, negative operator (because - is already used)
|
||||
operator<< left shift operator
|
||||
operator>> right shift operator
|
||||
operator< less than operator
|
||||
operator> greater than operator
|
||||
operator<= less than equals operator
|
||||
operator>= greater than equals operator
|
||||
operator== equals operator
|
||||
getNAME property getter with NAME
|
||||
setNAME property setter with NAME
|
||||
iget array subscript get
|
||||
iset array subscript set
|
||||
|
||||
|
||||
//myDict has to be declared by using myDict = dictionary();
|
||||
|
||||
|
||||
for + - * / % | & ^ << >> < > <= >= ==
|
||||
the signature is
|
||||
func myAddOp(this, right) {
|
||||
//do anything you want with this and right and the return value will be used as result of expression
|
||||
//this param is optional but recomended
|
||||
//but if you want myDict as a param it must be called this
|
||||
//this is available on all methods on dictionary
|
||||
//this language does not support closures
|
||||
return "Some Result\n";
|
||||
}
|
||||
and then
|
||||
myDict.operator+ = myAddOp;
|
||||
//now you can use it
|
||||
myV = myDict + 5; //right will be 5
|
||||
|
||||
for ! ~ ,
|
||||
the signature is
|
||||
func myNotEquals(this)
|
||||
{
|
||||
//do anything you want with this and the return value will be used as result of expression
|
||||
//this param is optional but recomended
|
||||
//but if you want myDict as a param it must be called this
|
||||
//this is available on all methods on dictionary
|
||||
//this language does not support closures
|
||||
return true;
|
||||
}
|
||||
myDict.operator! = myNotEquals;
|
||||
//now you can use it
|
||||
if(!myDict) //do something
|
||||
|
||||
for getNAME
|
||||
the signature is
|
||||
func myGetNAMEImpl(this)
|
||||
{
|
||||
//do anything you want with this and the return value will be used as result of expression
|
||||
//this param is optional but recomended
|
||||
//but if you want myDict as a param it must be called this
|
||||
//this is available on all methods on dictionary
|
||||
//this language does not support closures
|
||||
return "Some Result\n";
|
||||
}
|
||||
myDict.getNAME = myGetNAMEImpl;
|
||||
//now you can use it
|
||||
print myDict.NAME;
|
||||
|
||||
for setNAME
|
||||
the signature is
|
||||
func mySetNAMEImpl(this,value)
|
||||
{
|
||||
//do anything you want with this and value and the return value will be used as result of expression
|
||||
//this param is optional but recomended
|
||||
//but if you want myDict as a param it must be called this
|
||||
//this is available on all methods on dictionary
|
||||
//this language does not support closures
|
||||
return 42; //only for things like this "res = myDict.NAME = 53;" res would be whatever return value would be
|
||||
}
|
||||
myDict.setNAME = mySetNAMEImpl;
|
||||
//now you can use it
|
||||
myDict.NAME = 42; //value will be 42
|
||||
|
||||
for iget
|
||||
the signature is
|
||||
func myigetImpl(this,index)
|
||||
{
|
||||
//do anything you want with this and index and the return value will be used as result of expression
|
||||
//this param is optional but recomended
|
||||
//but if you want myDict as a param it must be called this
|
||||
//this is available on all methods on dictionary
|
||||
//this language does not support closures
|
||||
}
|
||||
myDict.iset = myisetImpl;
|
||||
//now you can use it
|
||||
print myDict[true]; //index will be true (I used true here rather than a string or a number to show it could be anything, even a dict or something)
|
||||
|
||||
|
||||
for iset
|
||||
the signature is
|
||||
func myisetImpl(this,index,value)
|
||||
{
|
||||
//do anything you want with this, index and value and the return value will be used as result of expression
|
||||
//this param is optional but recomended
|
||||
//but if you want myDict as a param it must be called this
|
||||
//this is available on all methods on dictionary
|
||||
//this language does not support closures
|
||||
return 42; //only for things like this "res = myDict.NAME = 53;" res would be whatever return value would be
|
||||
}
|
||||
myDict.iset = myisetImpl;
|
||||
//now you can use it
|
||||
myDict["Apple"] = 42; //index will be "Apple" and value will be 42
|
|
@ -0,0 +1,65 @@
|
|||
#include "src/tesseswebserver.hpp"
|
||||
TESSESWEBSERVER_STATIC_DECLARATION
|
||||
using namespace Tesses::WebServer;
|
||||
using namespace Tesses::WebServer::ScriptEngine;
|
||||
|
||||
|
||||
|
||||
int main(int argc,char** argv)
|
||||
{
|
||||
RootEnvironment* rEnv = new RootEnvironment();
|
||||
rEnv->print = [](ScriptType arg)-> void {
|
||||
|
||||
std::cout << ConvertToString(arg);
|
||||
};
|
||||
|
||||
if(argc == 1)
|
||||
{
|
||||
printf("USAGE: %s myscript.twss <ARGS>\n",argv[0]);
|
||||
return 1;
|
||||
}
|
||||
|
||||
List* ls = new List();
|
||||
rEnv->SetValue("args",ObjectType(ls));
|
||||
|
||||
if(argc > 1)
|
||||
{
|
||||
for(int i = 1;i<argc;i++)
|
||||
{
|
||||
ls->items.push_back(std::string(argv[i]));
|
||||
}
|
||||
}
|
||||
|
||||
BytecodeCompiler bcc(ScriptParser::Parse(argv[1]));
|
||||
|
||||
bcc.Compile();
|
||||
auto rf = bcc.file->rootFunction;
|
||||
rf->env = rEnv;
|
||||
rf->isRoot=true;
|
||||
for(auto f : bcc.file->functions)
|
||||
{
|
||||
auto rf2 = f.second;
|
||||
rf2->env = rEnv;
|
||||
rf2->isRoot=false;
|
||||
|
||||
|
||||
|
||||
|
||||
rEnv->SetValue(f.first,ObjectType(f.second));
|
||||
}
|
||||
|
||||
auto res=rf->Execute(rEnv,{});
|
||||
|
||||
|
||||
delete ls;
|
||||
delete rEnv;
|
||||
delete bcc.file;
|
||||
|
||||
|
||||
if(std::holds_alternative<int64_t>(res))
|
||||
{
|
||||
return (int)std::get<int64_t>(res);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,719 @@
|
|||
/*
|
||||
** 2006 June 7
|
||||
**
|
||||
** The author disclaims copyright to this source code. In place of
|
||||
** a legal notice, here is a blessing:
|
||||
**
|
||||
** May you do good and not evil.
|
||||
** May you find forgiveness for yourself and forgive others.
|
||||
** May you share freely, never taking more than you give.
|
||||
**
|
||||
*************************************************************************
|
||||
** This header file defines the SQLite interface for use by
|
||||
** shared libraries that want to be imported as extensions into
|
||||
** an SQLite instance. Shared libraries that intend to be loaded
|
||||
** as extensions by SQLite should #include this file instead of
|
||||
** sqlite3.h.
|
||||
*/
|
||||
#ifndef SQLITE3EXT_H
|
||||
#define SQLITE3EXT_H
|
||||
#include "sqlite3.h"
|
||||
|
||||
/*
|
||||
** The following structure holds pointers to all of the SQLite API
|
||||
** routines.
|
||||
**
|
||||
** WARNING: In order to maintain backwards compatibility, add new
|
||||
** interfaces to the end of this structure only. If you insert new
|
||||
** interfaces in the middle of this structure, then older different
|
||||
** versions of SQLite will not be able to load each other's shared
|
||||
** libraries!
|
||||
*/
|
||||
struct sqlite3_api_routines {
|
||||
void * (*aggregate_context)(sqlite3_context*,int nBytes);
|
||||
int (*aggregate_count)(sqlite3_context*);
|
||||
int (*bind_blob)(sqlite3_stmt*,int,const void*,int n,void(*)(void*));
|
||||
int (*bind_double)(sqlite3_stmt*,int,double);
|
||||
int (*bind_int)(sqlite3_stmt*,int,int);
|
||||
int (*bind_int64)(sqlite3_stmt*,int,sqlite_int64);
|
||||
int (*bind_null)(sqlite3_stmt*,int);
|
||||
int (*bind_parameter_count)(sqlite3_stmt*);
|
||||
int (*bind_parameter_index)(sqlite3_stmt*,const char*zName);
|
||||
const char * (*bind_parameter_name)(sqlite3_stmt*,int);
|
||||
int (*bind_text)(sqlite3_stmt*,int,const char*,int n,void(*)(void*));
|
||||
int (*bind_text16)(sqlite3_stmt*,int,const void*,int,void(*)(void*));
|
||||
int (*bind_value)(sqlite3_stmt*,int,const sqlite3_value*);
|
||||
int (*busy_handler)(sqlite3*,int(*)(void*,int),void*);
|
||||
int (*busy_timeout)(sqlite3*,int ms);
|
||||
int (*changes)(sqlite3*);
|
||||
int (*close)(sqlite3*);
|
||||
int (*collation_needed)(sqlite3*,void*,void(*)(void*,sqlite3*,
|
||||
int eTextRep,const char*));
|
||||
int (*collation_needed16)(sqlite3*,void*,void(*)(void*,sqlite3*,
|
||||
int eTextRep,const void*));
|
||||
const void * (*column_blob)(sqlite3_stmt*,int iCol);
|
||||
int (*column_bytes)(sqlite3_stmt*,int iCol);
|
||||
int (*column_bytes16)(sqlite3_stmt*,int iCol);
|
||||
int (*column_count)(sqlite3_stmt*pStmt);
|
||||
const char * (*column_database_name)(sqlite3_stmt*,int);
|
||||
const void * (*column_database_name16)(sqlite3_stmt*,int);
|
||||
const char * (*column_decltype)(sqlite3_stmt*,int i);
|
||||
const void * (*column_decltype16)(sqlite3_stmt*,int);
|
||||
double (*column_double)(sqlite3_stmt*,int iCol);
|
||||
int (*column_int)(sqlite3_stmt*,int iCol);
|
||||
sqlite_int64 (*column_int64)(sqlite3_stmt*,int iCol);
|
||||
const char * (*column_name)(sqlite3_stmt*,int);
|
||||
const void * (*column_name16)(sqlite3_stmt*,int);
|
||||
const char * (*column_origin_name)(sqlite3_stmt*,int);
|
||||
const void * (*column_origin_name16)(sqlite3_stmt*,int);
|
||||
const char * (*column_table_name)(sqlite3_stmt*,int);
|
||||
const void * (*column_table_name16)(sqlite3_stmt*,int);
|
||||
const unsigned char * (*column_text)(sqlite3_stmt*,int iCol);
|
||||
const void * (*column_text16)(sqlite3_stmt*,int iCol);
|
||||
int (*column_type)(sqlite3_stmt*,int iCol);
|
||||
sqlite3_value* (*column_value)(sqlite3_stmt*,int iCol);
|
||||
void * (*commit_hook)(sqlite3*,int(*)(void*),void*);
|
||||
int (*complete)(const char*sql);
|
||||
int (*complete16)(const void*sql);
|
||||
int (*create_collation)(sqlite3*,const char*,int,void*,
|
||||
int(*)(void*,int,const void*,int,const void*));
|
||||
int (*create_collation16)(sqlite3*,const void*,int,void*,
|
||||
int(*)(void*,int,const void*,int,const void*));
|
||||
int (*create_function)(sqlite3*,const char*,int,int,void*,
|
||||
void (*xFunc)(sqlite3_context*,int,sqlite3_value**),
|
||||
void (*xStep)(sqlite3_context*,int,sqlite3_value**),
|
||||
void (*xFinal)(sqlite3_context*));
|
||||
int (*create_function16)(sqlite3*,const void*,int,int,void*,
|
||||
void (*xFunc)(sqlite3_context*,int,sqlite3_value**),
|
||||
void (*xStep)(sqlite3_context*,int,sqlite3_value**),
|
||||
void (*xFinal)(sqlite3_context*));
|
||||
int (*create_module)(sqlite3*,const char*,const sqlite3_module*,void*);
|
||||
int (*data_count)(sqlite3_stmt*pStmt);
|
||||
sqlite3 * (*db_handle)(sqlite3_stmt*);
|
||||
int (*declare_vtab)(sqlite3*,const char*);
|
||||
int (*enable_shared_cache)(int);
|
||||
int (*errcode)(sqlite3*db);
|
||||
const char * (*errmsg)(sqlite3*);
|
||||
const void * (*errmsg16)(sqlite3*);
|
||||
int (*exec)(sqlite3*,const char*,sqlite3_callback,void*,char**);
|
||||
int (*expired)(sqlite3_stmt*);
|
||||
int (*finalize)(sqlite3_stmt*pStmt);
|
||||
void (*free)(void*);
|
||||
void (*free_table)(char**result);
|
||||
int (*get_autocommit)(sqlite3*);
|
||||
void * (*get_auxdata)(sqlite3_context*,int);
|
||||
int (*get_table)(sqlite3*,const char*,char***,int*,int*,char**);
|
||||
int (*global_recover)(void);
|
||||
void (*interruptx)(sqlite3*);
|
||||
sqlite_int64 (*last_insert_rowid)(sqlite3*);
|
||||
const char * (*libversion)(void);
|
||||
int (*libversion_number)(void);
|
||||
void *(*malloc)(int);
|
||||
char * (*mprintf)(const char*,...);
|
||||
int (*open)(const char*,sqlite3**);
|
||||
int (*open16)(const void*,sqlite3**);
|
||||
int (*prepare)(sqlite3*,const char*,int,sqlite3_stmt**,const char**);
|
||||
int (*prepare16)(sqlite3*,const void*,int,sqlite3_stmt**,const void**);
|
||||
void * (*profile)(sqlite3*,void(*)(void*,const char*,sqlite_uint64),void*);
|
||||
void (*progress_handler)(sqlite3*,int,int(*)(void*),void*);
|
||||
void *(*realloc)(void*,int);
|
||||
int (*reset)(sqlite3_stmt*pStmt);
|
||||
void (*result_blob)(sqlite3_context*,const void*,int,void(*)(void*));
|
||||
void (*result_double)(sqlite3_context*,double);
|
||||
void (*result_error)(sqlite3_context*,const char*,int);
|
||||
void (*result_error16)(sqlite3_context*,const void*,int);
|
||||
void (*result_int)(sqlite3_context*,int);
|
||||
void (*result_int64)(sqlite3_context*,sqlite_int64);
|
||||
void (*result_null)(sqlite3_context*);
|
||||
void (*result_text)(sqlite3_context*,const char*,int,void(*)(void*));
|
||||
void (*result_text16)(sqlite3_context*,const void*,int,void(*)(void*));
|
||||
void (*result_text16be)(sqlite3_context*,const void*,int,void(*)(void*));
|
||||
void (*result_text16le)(sqlite3_context*,const void*,int,void(*)(void*));
|
||||
void (*result_value)(sqlite3_context*,sqlite3_value*);
|
||||
void * (*rollback_hook)(sqlite3*,void(*)(void*),void*);
|
||||
int (*set_authorizer)(sqlite3*,int(*)(void*,int,const char*,const char*,
|
||||
const char*,const char*),void*);
|
||||
void (*set_auxdata)(sqlite3_context*,int,void*,void (*)(void*));
|
||||
char * (*xsnprintf)(int,char*,const char*,...);
|
||||
int (*step)(sqlite3_stmt*);
|
||||
int (*table_column_metadata)(sqlite3*,const char*,const char*,const char*,
|
||||
char const**,char const**,int*,int*,int*);
|
||||
void (*thread_cleanup)(void);
|
||||
int (*total_changes)(sqlite3*);
|
||||
void * (*trace)(sqlite3*,void(*xTrace)(void*,const char*),void*);
|
||||
int (*transfer_bindings)(sqlite3_stmt*,sqlite3_stmt*);
|
||||
void * (*update_hook)(sqlite3*,void(*)(void*,int ,char const*,char const*,
|
||||
sqlite_int64),void*);
|
||||
void * (*user_data)(sqlite3_context*);
|
||||
const void * (*value_blob)(sqlite3_value*);
|
||||
int (*value_bytes)(sqlite3_value*);
|
||||
int (*value_bytes16)(sqlite3_value*);
|
||||
double (*value_double)(sqlite3_value*);
|
||||
int (*value_int)(sqlite3_value*);
|
||||
sqlite_int64 (*value_int64)(sqlite3_value*);
|
||||
int (*value_numeric_type)(sqlite3_value*);
|
||||
const unsigned char * (*value_text)(sqlite3_value*);
|
||||
const void * (*value_text16)(sqlite3_value*);
|
||||
const void * (*value_text16be)(sqlite3_value*);
|
||||
const void * (*value_text16le)(sqlite3_value*);
|
||||
int (*value_type)(sqlite3_value*);
|
||||
char *(*vmprintf)(const char*,va_list);
|
||||
/* Added ??? */
|
||||
int (*overload_function)(sqlite3*, const char *zFuncName, int nArg);
|
||||
/* Added by 3.3.13 */
|
||||
int (*prepare_v2)(sqlite3*,const char*,int,sqlite3_stmt**,const char**);
|
||||
int (*prepare16_v2)(sqlite3*,const void*,int,sqlite3_stmt**,const void**);
|
||||
int (*clear_bindings)(sqlite3_stmt*);
|
||||
/* Added by 3.4.1 */
|
||||
int (*create_module_v2)(sqlite3*,const char*,const sqlite3_module*,void*,
|
||||
void (*xDestroy)(void *));
|
||||
/* Added by 3.5.0 */
|
||||
int (*bind_zeroblob)(sqlite3_stmt*,int,int);
|
||||
int (*blob_bytes)(sqlite3_blob*);
|
||||
int (*blob_close)(sqlite3_blob*);
|
||||
int (*blob_open)(sqlite3*,const char*,const char*,const char*,sqlite3_int64,
|
||||
int,sqlite3_blob**);
|
||||
int (*blob_read)(sqlite3_blob*,void*,int,int);
|
||||
int (*blob_write)(sqlite3_blob*,const void*,int,int);
|
||||
int (*create_collation_v2)(sqlite3*,const char*,int,void*,
|
||||
int(*)(void*,int,const void*,int,const void*),
|
||||
void(*)(void*));
|
||||
int (*file_control)(sqlite3*,const char*,int,void*);
|
||||
sqlite3_int64 (*memory_highwater)(int);
|
||||
sqlite3_int64 (*memory_used)(void);
|
||||
sqlite3_mutex *(*mutex_alloc)(int);
|
||||
void (*mutex_enter)(sqlite3_mutex*);
|
||||
void (*mutex_free)(sqlite3_mutex*);
|
||||
void (*mutex_leave)(sqlite3_mutex*);
|
||||
int (*mutex_try)(sqlite3_mutex*);
|
||||
int (*open_v2)(const char*,sqlite3**,int,const char*);
|
||||
int (*release_memory)(int);
|
||||
void (*result_error_nomem)(sqlite3_context*);
|
||||
void (*result_error_toobig)(sqlite3_context*);
|
||||
int (*sleep)(int);
|
||||
void (*soft_heap_limit)(int);
|
||||
sqlite3_vfs *(*vfs_find)(const char*);
|
||||
int (*vfs_register)(sqlite3_vfs*,int);
|
||||
int (*vfs_unregister)(sqlite3_vfs*);
|
||||
int (*xthreadsafe)(void);
|
||||
void (*result_zeroblob)(sqlite3_context*,int);
|
||||
void (*result_error_code)(sqlite3_context*,int);
|
||||
int (*test_control)(int, ...);
|
||||
void (*randomness)(int,void*);
|
||||
sqlite3 *(*context_db_handle)(sqlite3_context*);
|
||||
int (*extended_result_codes)(sqlite3*,int);
|
||||
int (*limit)(sqlite3*,int,int);
|
||||
sqlite3_stmt *(*next_stmt)(sqlite3*,sqlite3_stmt*);
|
||||
const char *(*sql)(sqlite3_stmt*);
|
||||
int (*status)(int,int*,int*,int);
|
||||
int (*backup_finish)(sqlite3_backup*);
|
||||
sqlite3_backup *(*backup_init)(sqlite3*,const char*,sqlite3*,const char*);
|
||||
int (*backup_pagecount)(sqlite3_backup*);
|
||||
int (*backup_remaining)(sqlite3_backup*);
|
||||
int (*backup_step)(sqlite3_backup*,int);
|
||||
const char *(*compileoption_get)(int);
|
||||
int (*compileoption_used)(const char*);
|
||||
int (*create_function_v2)(sqlite3*,const char*,int,int,void*,
|
||||
void (*xFunc)(sqlite3_context*,int,sqlite3_value**),
|
||||
void (*xStep)(sqlite3_context*,int,sqlite3_value**),
|
||||
void (*xFinal)(sqlite3_context*),
|
||||
void(*xDestroy)(void*));
|
||||
int (*db_config)(sqlite3*,int,...);
|
||||
sqlite3_mutex *(*db_mutex)(sqlite3*);
|
||||
int (*db_status)(sqlite3*,int,int*,int*,int);
|
||||
int (*extended_errcode)(sqlite3*);
|
||||
void (*log)(int,const char*,...);
|
||||
sqlite3_int64 (*soft_heap_limit64)(sqlite3_int64);
|
||||
const char *(*sourceid)(void);
|
||||
int (*stmt_status)(sqlite3_stmt*,int,int);
|
||||
int (*strnicmp)(const char*,const char*,int);
|
||||
int (*unlock_notify)(sqlite3*,void(*)(void**,int),void*);
|
||||
int (*wal_autocheckpoint)(sqlite3*,int);
|
||||
int (*wal_checkpoint)(sqlite3*,const char*);
|
||||
void *(*wal_hook)(sqlite3*,int(*)(void*,sqlite3*,const char*,int),void*);
|
||||
int (*blob_reopen)(sqlite3_blob*,sqlite3_int64);
|
||||
int (*vtab_config)(sqlite3*,int op,...);
|
||||
int (*vtab_on_conflict)(sqlite3*);
|
||||
/* Version 3.7.16 and later */
|
||||
int (*close_v2)(sqlite3*);
|
||||
const char *(*db_filename)(sqlite3*,const char*);
|
||||
int (*db_readonly)(sqlite3*,const char*);
|
||||
int (*db_release_memory)(sqlite3*);
|
||||
const char *(*errstr)(int);
|
||||
int (*stmt_busy)(sqlite3_stmt*);
|
||||
int (*stmt_readonly)(sqlite3_stmt*);
|
||||
int (*stricmp)(const char*,const char*);
|
||||
int (*uri_boolean)(const char*,const char*,int);
|
||||
sqlite3_int64 (*uri_int64)(const char*,const char*,sqlite3_int64);
|
||||
const char *(*uri_parameter)(const char*,const char*);
|
||||
char *(*xvsnprintf)(int,char*,const char*,va_list);
|
||||
int (*wal_checkpoint_v2)(sqlite3*,const char*,int,int*,int*);
|
||||
/* Version 3.8.7 and later */
|
||||
int (*auto_extension)(void(*)(void));
|
||||
int (*bind_blob64)(sqlite3_stmt*,int,const void*,sqlite3_uint64,
|
||||
void(*)(void*));
|
||||
int (*bind_text64)(sqlite3_stmt*,int,const char*,sqlite3_uint64,
|
||||
void(*)(void*),unsigned char);
|
||||
int (*cancel_auto_extension)(void(*)(void));
|
||||
int (*load_extension)(sqlite3*,const char*,const char*,char**);
|
||||
void *(*malloc64)(sqlite3_uint64);
|
||||
sqlite3_uint64 (*msize)(void*);
|
||||
void *(*realloc64)(void*,sqlite3_uint64);
|
||||
void (*reset_auto_extension)(void);
|
||||
void (*result_blob64)(sqlite3_context*,const void*,sqlite3_uint64,
|
||||
void(*)(void*));
|
||||
void (*result_text64)(sqlite3_context*,const char*,sqlite3_uint64,
|
||||
void(*)(void*), unsigned char);
|
||||
int (*strglob)(const char*,const char*);
|
||||
/* Version 3.8.11 and later */
|
||||
sqlite3_value *(*value_dup)(const sqlite3_value*);
|
||||
void (*value_free)(sqlite3_value*);
|
||||
int (*result_zeroblob64)(sqlite3_context*,sqlite3_uint64);
|
||||
int (*bind_zeroblob64)(sqlite3_stmt*, int, sqlite3_uint64);
|
||||
/* Version 3.9.0 and later */
|
||||
unsigned int (*value_subtype)(sqlite3_value*);
|
||||
void (*result_subtype)(sqlite3_context*,unsigned int);
|
||||
/* Version 3.10.0 and later */
|
||||
int (*status64)(int,sqlite3_int64*,sqlite3_int64*,int);
|
||||
int (*strlike)(const char*,const char*,unsigned int);
|
||||
int (*db_cacheflush)(sqlite3*);
|
||||
/* Version 3.12.0 and later */
|
||||
int (*system_errno)(sqlite3*);
|
||||
/* Version 3.14.0 and later */
|
||||
int (*trace_v2)(sqlite3*,unsigned,int(*)(unsigned,void*,void*,void*),void*);
|
||||
char *(*expanded_sql)(sqlite3_stmt*);
|
||||
/* Version 3.18.0 and later */
|
||||
void (*set_last_insert_rowid)(sqlite3*,sqlite3_int64);
|
||||
/* Version 3.20.0 and later */
|
||||
int (*prepare_v3)(sqlite3*,const char*,int,unsigned int,
|
||||
sqlite3_stmt**,const char**);
|
||||
int (*prepare16_v3)(sqlite3*,const void*,int,unsigned int,
|
||||
sqlite3_stmt**,const void**);
|
||||
int (*bind_pointer)(sqlite3_stmt*,int,void*,const char*,void(*)(void*));
|
||||
void (*result_pointer)(sqlite3_context*,void*,const char*,void(*)(void*));
|
||||
void *(*value_pointer)(sqlite3_value*,const char*);
|
||||
int (*vtab_nochange)(sqlite3_context*);
|
||||
int (*value_nochange)(sqlite3_value*);
|
||||
const char *(*vtab_collation)(sqlite3_index_info*,int);
|
||||
/* Version 3.24.0 and later */
|
||||
int (*keyword_count)(void);
|
||||
int (*keyword_name)(int,const char**,int*);
|
||||
int (*keyword_check)(const char*,int);
|
||||
sqlite3_str *(*str_new)(sqlite3*);
|
||||
char *(*str_finish)(sqlite3_str*);
|
||||
void (*str_appendf)(sqlite3_str*, const char *zFormat, ...);
|
||||
void (*str_vappendf)(sqlite3_str*, const char *zFormat, va_list);
|
||||
void (*str_append)(sqlite3_str*, const char *zIn, int N);
|
||||
void (*str_appendall)(sqlite3_str*, const char *zIn);
|
||||
void (*str_appendchar)(sqlite3_str*, int N, char C);
|
||||
void (*str_reset)(sqlite3_str*);
|
||||
int (*str_errcode)(sqlite3_str*);
|
||||
int (*str_length)(sqlite3_str*);
|
||||
char *(*str_value)(sqlite3_str*);
|
||||
/* Version 3.25.0 and later */
|
||||
int (*create_window_function)(sqlite3*,const char*,int,int,void*,
|
||||
void (*xStep)(sqlite3_context*,int,sqlite3_value**),
|
||||
void (*xFinal)(sqlite3_context*),
|
||||
void (*xValue)(sqlite3_context*),
|
||||
void (*xInv)(sqlite3_context*,int,sqlite3_value**),
|
||||
void(*xDestroy)(void*));
|
||||
/* Version 3.26.0 and later */
|
||||
const char *(*normalized_sql)(sqlite3_stmt*);
|
||||
/* Version 3.28.0 and later */
|
||||
int (*stmt_isexplain)(sqlite3_stmt*);
|
||||
int (*value_frombind)(sqlite3_value*);
|
||||
/* Version 3.30.0 and later */
|
||||
int (*drop_modules)(sqlite3*,const char**);
|
||||
/* Version 3.31.0 and later */
|
||||
sqlite3_int64 (*hard_heap_limit64)(sqlite3_int64);
|
||||
const char *(*uri_key)(const char*,int);
|
||||
const char *(*filename_database)(const char*);
|
||||
const char *(*filename_journal)(const char*);
|
||||
const char *(*filename_wal)(const char*);
|
||||
/* Version 3.32.0 and later */
|
||||
const char *(*create_filename)(const char*,const char*,const char*,
|
||||
int,const char**);
|
||||
void (*free_filename)(const char*);
|
||||
sqlite3_file *(*database_file_object)(const char*);
|
||||
/* Version 3.34.0 and later */
|
||||
int (*txn_state)(sqlite3*,const char*);
|
||||
/* Version 3.36.1 and later */
|
||||
sqlite3_int64 (*changes64)(sqlite3*);
|
||||
sqlite3_int64 (*total_changes64)(sqlite3*);
|
||||
/* Version 3.37.0 and later */
|
||||
int (*autovacuum_pages)(sqlite3*,
|
||||
unsigned int(*)(void*,const char*,unsigned int,unsigned int,unsigned int),
|
||||
void*, void(*)(void*));
|
||||
/* Version 3.38.0 and later */
|
||||
int (*error_offset)(sqlite3*);
|
||||
int (*vtab_rhs_value)(sqlite3_index_info*,int,sqlite3_value**);
|
||||
int (*vtab_distinct)(sqlite3_index_info*);
|
||||
int (*vtab_in)(sqlite3_index_info*,int,int);
|
||||
int (*vtab_in_first)(sqlite3_value*,sqlite3_value**);
|
||||
int (*vtab_in_next)(sqlite3_value*,sqlite3_value**);
|
||||
/* Version 3.39.0 and later */
|
||||
int (*deserialize)(sqlite3*,const char*,unsigned char*,
|
||||
sqlite3_int64,sqlite3_int64,unsigned);
|
||||
unsigned char *(*serialize)(sqlite3*,const char *,sqlite3_int64*,
|
||||
unsigned int);
|
||||
const char *(*db_name)(sqlite3*,int);
|
||||
/* Version 3.40.0 and later */
|
||||
int (*value_encoding)(sqlite3_value*);
|
||||
/* Version 3.41.0 and later */
|
||||
int (*is_interrupted)(sqlite3*);
|
||||
/* Version 3.43.0 and later */
|
||||
int (*stmt_explain)(sqlite3_stmt*,int);
|
||||
/* Version 3.44.0 and later */
|
||||
void *(*get_clientdata)(sqlite3*,const char*);
|
||||
int (*set_clientdata)(sqlite3*, const char*, void*, void(*)(void*));
|
||||
};
|
||||
|
||||
/*
|
||||
** This is the function signature used for all extension entry points. It
|
||||
** is also defined in the file "loadext.c".
|
||||
*/
|
||||
typedef int (*sqlite3_loadext_entry)(
|
||||
sqlite3 *db, /* Handle to the database. */
|
||||
char **pzErrMsg, /* Used to set error string on failure. */
|
||||
const sqlite3_api_routines *pThunk /* Extension API function pointers. */
|
||||
);
|
||||
|
||||
/*
|
||||
** The following macros redefine the API routines so that they are
|
||||
** redirected through the global sqlite3_api structure.
|
||||
**
|
||||
** This header file is also used by the loadext.c source file
|
||||
** (part of the main SQLite library - not an extension) so that
|
||||
** it can get access to the sqlite3_api_routines structure
|
||||
** definition. But the main library does not want to redefine
|
||||
** the API. So the redefinition macros are only valid if the
|
||||
** SQLITE_CORE macros is undefined.
|
||||
*/
|
||||
#if !defined(SQLITE_CORE) && !defined(SQLITE_OMIT_LOAD_EXTENSION)
|
||||
#define sqlite3_aggregate_context sqlite3_api->aggregate_context
|
||||
#ifndef SQLITE_OMIT_DEPRECATED
|
||||
#define sqlite3_aggregate_count sqlite3_api->aggregate_count
|
||||
#endif
|
||||
#define sqlite3_bind_blob sqlite3_api->bind_blob
|
||||
#define sqlite3_bind_double sqlite3_api->bind_double
|
||||
#define sqlite3_bind_int sqlite3_api->bind_int
|
||||
#define sqlite3_bind_int64 sqlite3_api->bind_int64
|
||||
#define sqlite3_bind_null sqlite3_api->bind_null
|
||||
#define sqlite3_bind_parameter_count sqlite3_api->bind_parameter_count
|
||||
#define sqlite3_bind_parameter_index sqlite3_api->bind_parameter_index
|
||||
#define sqlite3_bind_parameter_name sqlite3_api->bind_parameter_name
|
||||
#define sqlite3_bind_text sqlite3_api->bind_text
|
||||
#define sqlite3_bind_text16 sqlite3_api->bind_text16
|
||||
#define sqlite3_bind_value sqlite3_api->bind_value
|
||||
#define sqlite3_busy_handler sqlite3_api->busy_handler
|
||||
#define sqlite3_busy_timeout sqlite3_api->busy_timeout
|
||||
#define sqlite3_changes sqlite3_api->changes
|
||||
#define sqlite3_close sqlite3_api->close
|
||||
#define sqlite3_collation_needed sqlite3_api->collation_needed
|
||||
#define sqlite3_collation_needed16 sqlite3_api->collation_needed16
|
||||
#define sqlite3_column_blob sqlite3_api->column_blob
|
||||
#define sqlite3_column_bytes sqlite3_api->column_bytes
|
||||
#define sqlite3_column_bytes16 sqlite3_api->column_bytes16
|
||||
#define sqlite3_column_count sqlite3_api->column_count
|
||||
#define sqlite3_column_database_name sqlite3_api->column_database_name
|
||||
#define sqlite3_column_database_name16 sqlite3_api->column_database_name16
|
||||
#define sqlite3_column_decltype sqlite3_api->column_decltype
|
||||
#define sqlite3_column_decltype16 sqlite3_api->column_decltype16
|
||||
#define sqlite3_column_double sqlite3_api->column_double
|
||||
#define sqlite3_column_int sqlite3_api->column_int
|
||||
#define sqlite3_column_int64 sqlite3_api->column_int64
|
||||
#define sqlite3_column_name sqlite3_api->column_name
|
||||
#define sqlite3_column_name16 sqlite3_api->column_name16
|
||||
#define sqlite3_column_origin_name sqlite3_api->column_origin_name
|
||||
#define sqlite3_column_origin_name16 sqlite3_api->column_origin_name16
|
||||
#define sqlite3_column_table_name sqlite3_api->column_table_name
|
||||
#define sqlite3_column_table_name16 sqlite3_api->column_table_name16
|
||||
#define sqlite3_column_text sqlite3_api->column_text
|
||||
#define sqlite3_column_text16 sqlite3_api->column_text16
|
||||
#define sqlite3_column_type sqlite3_api->column_type
|
||||
#define sqlite3_column_value sqlite3_api->column_value
|
||||
#define sqlite3_commit_hook sqlite3_api->commit_hook
|
||||
#define sqlite3_complete sqlite3_api->complete
|
||||
#define sqlite3_complete16 sqlite3_api->complete16
|
||||
#define sqlite3_create_collation sqlite3_api->create_collation
|
||||
#define sqlite3_create_collation16 sqlite3_api->create_collation16
|
||||
#define sqlite3_create_function sqlite3_api->create_function
|
||||
#define sqlite3_create_function16 sqlite3_api->create_function16
|
||||
#define sqlite3_create_module sqlite3_api->create_module
|
||||
#define sqlite3_create_module_v2 sqlite3_api->create_module_v2
|
||||
#define sqlite3_data_count sqlite3_api->data_count
|
||||
#define sqlite3_db_handle sqlite3_api->db_handle
|
||||
#define sqlite3_declare_vtab sqlite3_api->declare_vtab
|
||||
#define sqlite3_enable_shared_cache sqlite3_api->enable_shared_cache
|
||||
#define sqlite3_errcode sqlite3_api->errcode
|
||||
#define sqlite3_errmsg sqlite3_api->errmsg
|
||||
#define sqlite3_errmsg16 sqlite3_api->errmsg16
|
||||
#define sqlite3_exec sqlite3_api->exec
|
||||
#ifndef SQLITE_OMIT_DEPRECATED
|
||||
#define sqlite3_expired sqlite3_api->expired
|
||||
#endif
|
||||
#define sqlite3_finalize sqlite3_api->finalize
|
||||
#define sqlite3_free sqlite3_api->free
|
||||
#define sqlite3_free_table sqlite3_api->free_table
|
||||
#define sqlite3_get_autocommit sqlite3_api->get_autocommit
|
||||
#define sqlite3_get_auxdata sqlite3_api->get_auxdata
|
||||
#define sqlite3_get_table sqlite3_api->get_table
|
||||
#ifndef SQLITE_OMIT_DEPRECATED
|
||||
#define sqlite3_global_recover sqlite3_api->global_recover
|
||||
#endif
|
||||
#define sqlite3_interrupt sqlite3_api->interruptx
|
||||
#define sqlite3_last_insert_rowid sqlite3_api->last_insert_rowid
|
||||
#define sqlite3_libversion sqlite3_api->libversion
|
||||
#define sqlite3_libversion_number sqlite3_api->libversion_number
|
||||
#define sqlite3_malloc sqlite3_api->malloc
|
||||
#define sqlite3_mprintf sqlite3_api->mprintf
|
||||
#define sqlite3_open sqlite3_api->open
|
||||
#define sqlite3_open16 sqlite3_api->open16
|
||||
#define sqlite3_prepare sqlite3_api->prepare
|
||||
#define sqlite3_prepare16 sqlite3_api->prepare16
|
||||
#define sqlite3_prepare_v2 sqlite3_api->prepare_v2
|
||||
#define sqlite3_prepare16_v2 sqlite3_api->prepare16_v2
|
||||
#define sqlite3_profile sqlite3_api->profile
|
||||
#define sqlite3_progress_handler sqlite3_api->progress_handler
|
||||
#define sqlite3_realloc sqlite3_api->realloc
|
||||
#define sqlite3_reset sqlite3_api->reset
|
||||
#define sqlite3_result_blob sqlite3_api->result_blob
|
||||
#define sqlite3_result_double sqlite3_api->result_double
|
||||
#define sqlite3_result_error sqlite3_api->result_error
|
||||
#define sqlite3_result_error16 sqlite3_api->result_error16
|
||||
#define sqlite3_result_int sqlite3_api->result_int
|
||||
#define sqlite3_result_int64 sqlite3_api->result_int64
|
||||
#define sqlite3_result_null sqlite3_api->result_null
|
||||
#define sqlite3_result_text sqlite3_api->result_text
|
||||
#define sqlite3_result_text16 sqlite3_api->result_text16
|
||||
#define sqlite3_result_text16be sqlite3_api->result_text16be
|
||||
#define sqlite3_result_text16le sqlite3_api->result_text16le
|
||||
#define sqlite3_result_value sqlite3_api->result_value
|
||||
#define sqlite3_rollback_hook sqlite3_api->rollback_hook
|
||||
#define sqlite3_set_authorizer sqlite3_api->set_authorizer
|
||||
#define sqlite3_set_auxdata sqlite3_api->set_auxdata
|
||||
#define sqlite3_snprintf sqlite3_api->xsnprintf
|
||||
#define sqlite3_step sqlite3_api->step
|
||||
#define sqlite3_table_column_metadata sqlite3_api->table_column_metadata
|
||||
#define sqlite3_thread_cleanup sqlite3_api->thread_cleanup
|
||||
#define sqlite3_total_changes sqlite3_api->total_changes
|
||||
#define sqlite3_trace sqlite3_api->trace
|
||||
#ifndef SQLITE_OMIT_DEPRECATED
|
||||
#define sqlite3_transfer_bindings sqlite3_api->transfer_bindings
|
||||
#endif
|
||||
#define sqlite3_update_hook sqlite3_api->update_hook
|
||||
#define sqlite3_user_data sqlite3_api->user_data
|
||||
#define sqlite3_value_blob sqlite3_api->value_blob
|
||||
#define sqlite3_value_bytes sqlite3_api->value_bytes
|
||||
#define sqlite3_value_bytes16 sqlite3_api->value_bytes16
|
||||
#define sqlite3_value_double sqlite3_api->value_double
|
||||
#define sqlite3_value_int sqlite3_api->value_int
|
||||
#define sqlite3_value_int64 sqlite3_api->value_int64
|
||||
#define sqlite3_value_numeric_type sqlite3_api->value_numeric_type
|
||||
#define sqlite3_value_text sqlite3_api->value_text
|
||||
#define sqlite3_value_text16 sqlite3_api->value_text16
|
||||
#define sqlite3_value_text16be sqlite3_api->value_text16be
|
||||
#define sqlite3_value_text16le sqlite3_api->value_text16le
|
||||
#define sqlite3_value_type sqlite3_api->value_type
|
||||
#define sqlite3_vmprintf sqlite3_api->vmprintf
|
||||
#define sqlite3_vsnprintf sqlite3_api->xvsnprintf
|
||||
#define sqlite3_overload_function sqlite3_api->overload_function
|
||||
#define sqlite3_prepare_v2 sqlite3_api->prepare_v2
|
||||
#define sqlite3_prepare16_v2 sqlite3_api->prepare16_v2
|
||||
#define sqlite3_clear_bindings sqlite3_api->clear_bindings
|
||||
#define sqlite3_bind_zeroblob sqlite3_api->bind_zeroblob
|
||||
#define sqlite3_blob_bytes sqlite3_api->blob_bytes
|
||||
#define sqlite3_blob_close sqlite3_api->blob_close
|
||||
#define sqlite3_blob_open sqlite3_api->blob_open
|
||||
#define sqlite3_blob_read sqlite3_api->blob_read
|
||||
#define sqlite3_blob_write sqlite3_api->blob_write
|
||||
#define sqlite3_create_collation_v2 sqlite3_api->create_collation_v2
|
||||
#define sqlite3_file_control sqlite3_api->file_control
|
||||
#define sqlite3_memory_highwater sqlite3_api->memory_highwater
|
||||
#define sqlite3_memory_used sqlite3_api->memory_used
|
||||
#define sqlite3_mutex_alloc sqlite3_api->mutex_alloc
|
||||
#define sqlite3_mutex_enter sqlite3_api->mutex_enter
|
||||
#define sqlite3_mutex_free sqlite3_api->mutex_free
|
||||
#define sqlite3_mutex_leave sqlite3_api->mutex_leave
|
||||
#define sqlite3_mutex_try sqlite3_api->mutex_try
|
||||
#define sqlite3_open_v2 sqlite3_api->open_v2
|
||||
#define sqlite3_release_memory sqlite3_api->release_memory
|
||||
#define sqlite3_result_error_nomem sqlite3_api->result_error_nomem
|
||||
#define sqlite3_result_error_toobig sqlite3_api->result_error_toobig
|
||||
#define sqlite3_sleep sqlite3_api->sleep
|
||||
#define sqlite3_soft_heap_limit sqlite3_api->soft_heap_limit
|
||||
#define sqlite3_vfs_find sqlite3_api->vfs_find
|
||||
#define sqlite3_vfs_register sqlite3_api->vfs_register
|
||||
#define sqlite3_vfs_unregister sqlite3_api->vfs_unregister
|
||||
#define sqlite3_threadsafe sqlite3_api->xthreadsafe
|
||||
#define sqlite3_result_zeroblob sqlite3_api->result_zeroblob
|
||||
#define sqlite3_result_error_code sqlite3_api->result_error_code
|
||||
#define sqlite3_test_control sqlite3_api->test_control
|
||||
#define sqlite3_randomness sqlite3_api->randomness
|
||||
#define sqlite3_context_db_handle sqlite3_api->context_db_handle
|
||||
#define sqlite3_extended_result_codes sqlite3_api->extended_result_codes
|
||||
#define sqlite3_limit sqlite3_api->limit
|
||||
#define sqlite3_next_stmt sqlite3_api->next_stmt
|
||||
#define sqlite3_sql sqlite3_api->sql
|
||||
#define sqlite3_status sqlite3_api->status
|
||||
#define sqlite3_backup_finish sqlite3_api->backup_finish
|
||||
#define sqlite3_backup_init sqlite3_api->backup_init
|
||||
#define sqlite3_backup_pagecount sqlite3_api->backup_pagecount
|
||||
#define sqlite3_backup_remaining sqlite3_api->backup_remaining
|
||||
#define sqlite3_backup_step sqlite3_api->backup_step
|
||||
#define sqlite3_compileoption_get sqlite3_api->compileoption_get
|
||||
#define sqlite3_compileoption_used sqlite3_api->compileoption_used
|
||||
#define sqlite3_create_function_v2 sqlite3_api->create_function_v2
|
||||
#define sqlite3_db_config sqlite3_api->db_config
|
||||
#define sqlite3_db_mutex sqlite3_api->db_mutex
|
||||
#define sqlite3_db_status sqlite3_api->db_status
|
||||
#define sqlite3_extended_errcode sqlite3_api->extended_errcode
|
||||
#define sqlite3_log sqlite3_api->log
|
||||
#define sqlite3_soft_heap_limit64 sqlite3_api->soft_heap_limit64
|
||||
#define sqlite3_sourceid sqlite3_api->sourceid
|
||||
#define sqlite3_stmt_status sqlite3_api->stmt_status
|
||||
#define sqlite3_strnicmp sqlite3_api->strnicmp
|
||||
#define sqlite3_unlock_notify sqlite3_api->unlock_notify
|
||||
#define sqlite3_wal_autocheckpoint sqlite3_api->wal_autocheckpoint
|
||||
#define sqlite3_wal_checkpoint sqlite3_api->wal_checkpoint
|
||||
#define sqlite3_wal_hook sqlite3_api->wal_hook
|
||||
#define sqlite3_blob_reopen sqlite3_api->blob_reopen
|
||||
#define sqlite3_vtab_config sqlite3_api->vtab_config
|
||||
#define sqlite3_vtab_on_conflict sqlite3_api->vtab_on_conflict
|
||||
/* Version 3.7.16 and later */
|
||||
#define sqlite3_close_v2 sqlite3_api->close_v2
|
||||
#define sqlite3_db_filename sqlite3_api->db_filename
|
||||
#define sqlite3_db_readonly sqlite3_api->db_readonly
|
||||
#define sqlite3_db_release_memory sqlite3_api->db_release_memory
|
||||
#define sqlite3_errstr sqlite3_api->errstr
|
||||
#define sqlite3_stmt_busy sqlite3_api->stmt_busy
|
||||
#define sqlite3_stmt_readonly sqlite3_api->stmt_readonly
|
||||
#define sqlite3_stricmp sqlite3_api->stricmp
|
||||
#define sqlite3_uri_boolean sqlite3_api->uri_boolean
|
||||
#define sqlite3_uri_int64 sqlite3_api->uri_int64
|
||||
#define sqlite3_uri_parameter sqlite3_api->uri_parameter
|
||||
#define sqlite3_uri_vsnprintf sqlite3_api->xvsnprintf
|
||||
#define sqlite3_wal_checkpoint_v2 sqlite3_api->wal_checkpoint_v2
|
||||
/* Version 3.8.7 and later */
|
||||
#define sqlite3_auto_extension sqlite3_api->auto_extension
|
||||
#define sqlite3_bind_blob64 sqlite3_api->bind_blob64
|
||||
#define sqlite3_bind_text64 sqlite3_api->bind_text64
|
||||
#define sqlite3_cancel_auto_extension sqlite3_api->cancel_auto_extension
|
||||
#define sqlite3_load_extension sqlite3_api->load_extension
|
||||
#define sqlite3_malloc64 sqlite3_api->malloc64
|
||||
#define sqlite3_msize sqlite3_api->msize
|
||||
#define sqlite3_realloc64 sqlite3_api->realloc64
|
||||
#define sqlite3_reset_auto_extension sqlite3_api->reset_auto_extension
|
||||
#define sqlite3_result_blob64 sqlite3_api->result_blob64
|
||||
#define sqlite3_result_text64 sqlite3_api->result_text64
|
||||
#define sqlite3_strglob sqlite3_api->strglob
|
||||
/* Version 3.8.11 and later */
|
||||
#define sqlite3_value_dup sqlite3_api->value_dup
|
||||
#define sqlite3_value_free sqlite3_api->value_free
|
||||
#define sqlite3_result_zeroblob64 sqlite3_api->result_zeroblob64
|
||||
#define sqlite3_bind_zeroblob64 sqlite3_api->bind_zeroblob64
|
||||
/* Version 3.9.0 and later */
|
||||
#define sqlite3_value_subtype sqlite3_api->value_subtype
|
||||
#define sqlite3_result_subtype sqlite3_api->result_subtype
|
||||
/* Version 3.10.0 and later */
|
||||
#define sqlite3_status64 sqlite3_api->status64
|
||||
#define sqlite3_strlike sqlite3_api->strlike
|
||||
#define sqlite3_db_cacheflush sqlite3_api->db_cacheflush
|
||||
/* Version 3.12.0 and later */
|
||||
#define sqlite3_system_errno sqlite3_api->system_errno
|
||||
/* Version 3.14.0 and later */
|
||||
#define sqlite3_trace_v2 sqlite3_api->trace_v2
|
||||
#define sqlite3_expanded_sql sqlite3_api->expanded_sql
|
||||
/* Version 3.18.0 and later */
|
||||
#define sqlite3_set_last_insert_rowid sqlite3_api->set_last_insert_rowid
|
||||
/* Version 3.20.0 and later */
|
||||
#define sqlite3_prepare_v3 sqlite3_api->prepare_v3
|
||||
#define sqlite3_prepare16_v3 sqlite3_api->prepare16_v3
|
||||
#define sqlite3_bind_pointer sqlite3_api->bind_pointer
|
||||
#define sqlite3_result_pointer sqlite3_api->result_pointer
|
||||
#define sqlite3_value_pointer sqlite3_api->value_pointer
|
||||
/* Version 3.22.0 and later */
|
||||
#define sqlite3_vtab_nochange sqlite3_api->vtab_nochange
|
||||
#define sqlite3_value_nochange sqlite3_api->value_nochange
|
||||
#define sqlite3_vtab_collation sqlite3_api->vtab_collation
|
||||
/* Version 3.24.0 and later */
|
||||
#define sqlite3_keyword_count sqlite3_api->keyword_count
|
||||
#define sqlite3_keyword_name sqlite3_api->keyword_name
|
||||
#define sqlite3_keyword_check sqlite3_api->keyword_check
|
||||
#define sqlite3_str_new sqlite3_api->str_new
|
||||
#define sqlite3_str_finish sqlite3_api->str_finish
|
||||
#define sqlite3_str_appendf sqlite3_api->str_appendf
|
||||
#define sqlite3_str_vappendf sqlite3_api->str_vappendf
|
||||
#define sqlite3_str_append sqlite3_api->str_append
|
||||
#define sqlite3_str_appendall sqlite3_api->str_appendall
|
||||
#define sqlite3_str_appendchar sqlite3_api->str_appendchar
|
||||
#define sqlite3_str_reset sqlite3_api->str_reset
|
||||
#define sqlite3_str_errcode sqlite3_api->str_errcode
|
||||
#define sqlite3_str_length sqlite3_api->str_length
|
||||
#define sqlite3_str_value sqlite3_api->str_value
|
||||
/* Version 3.25.0 and later */
|
||||
#define sqlite3_create_window_function sqlite3_api->create_window_function
|
||||
/* Version 3.26.0 and later */
|
||||
#define sqlite3_normalized_sql sqlite3_api->normalized_sql
|
||||
/* Version 3.28.0 and later */
|
||||
#define sqlite3_stmt_isexplain sqlite3_api->stmt_isexplain
|
||||
#define sqlite3_value_frombind sqlite3_api->value_frombind
|
||||
/* Version 3.30.0 and later */
|
||||
#define sqlite3_drop_modules sqlite3_api->drop_modules
|
||||
/* Version 3.31.0 and later */
|
||||
#define sqlite3_hard_heap_limit64 sqlite3_api->hard_heap_limit64
|
||||
#define sqlite3_uri_key sqlite3_api->uri_key
|
||||
#define sqlite3_filename_database sqlite3_api->filename_database
|
||||
#define sqlite3_filename_journal sqlite3_api->filename_journal
|
||||
#define sqlite3_filename_wal sqlite3_api->filename_wal
|
||||
/* Version 3.32.0 and later */
|
||||
#define sqlite3_create_filename sqlite3_api->create_filename
|
||||
#define sqlite3_free_filename sqlite3_api->free_filename
|
||||
#define sqlite3_database_file_object sqlite3_api->database_file_object
|
||||
/* Version 3.34.0 and later */
|
||||
#define sqlite3_txn_state sqlite3_api->txn_state
|
||||
/* Version 3.36.1 and later */
|
||||
#define sqlite3_changes64 sqlite3_api->changes64
|
||||
#define sqlite3_total_changes64 sqlite3_api->total_changes64
|
||||
/* Version 3.37.0 and later */
|
||||
#define sqlite3_autovacuum_pages sqlite3_api->autovacuum_pages
|
||||
/* Version 3.38.0 and later */
|
||||
#define sqlite3_error_offset sqlite3_api->error_offset
|
||||
#define sqlite3_vtab_rhs_value sqlite3_api->vtab_rhs_value
|
||||
#define sqlite3_vtab_distinct sqlite3_api->vtab_distinct
|
||||
#define sqlite3_vtab_in sqlite3_api->vtab_in
|
||||
#define sqlite3_vtab_in_first sqlite3_api->vtab_in_first
|
||||
#define sqlite3_vtab_in_next sqlite3_api->vtab_in_next
|
||||
/* Version 3.39.0 and later */
|
||||
#ifndef SQLITE_OMIT_DESERIALIZE
|
||||
#define sqlite3_deserialize sqlite3_api->deserialize
|
||||
#define sqlite3_serialize sqlite3_api->serialize
|
||||
#endif
|
||||
#define sqlite3_db_name sqlite3_api->db_name
|
||||
/* Version 3.40.0 and later */
|
||||
#define sqlite3_value_encoding sqlite3_api->value_encoding
|
||||
/* Version 3.41.0 and later */
|
||||
#define sqlite3_is_interrupted sqlite3_api->is_interrupted
|
||||
/* Version 3.43.0 and later */
|
||||
#define sqlite3_stmt_explain sqlite3_api->stmt_explain
|
||||
/* Version 3.44.0 and later */
|
||||
#define sqlite3_get_clientdata sqlite3_api->get_clientdata
|
||||
#define sqlite3_set_clientdata sqlite3_api->set_clientdata
|
||||
#endif /* !defined(SQLITE_CORE) && !defined(SQLITE_OMIT_LOAD_EXTENSION) */
|
||||
|
||||
#if !defined(SQLITE_CORE) && !defined(SQLITE_OMIT_LOAD_EXTENSION)
|
||||
/* This case when the file really is being compiled as a loadable
|
||||
** extension */
|
||||
# define SQLITE_EXTENSION_INIT1 const sqlite3_api_routines *sqlite3_api=0;
|
||||
# define SQLITE_EXTENSION_INIT2(v) sqlite3_api=v;
|
||||
# define SQLITE_EXTENSION_INIT3 \
|
||||
extern const sqlite3_api_routines *sqlite3_api;
|
||||
#else
|
||||
/* This case when the file is being statically linked into the
|
||||
** application */
|
||||
# define SQLITE_EXTENSION_INIT1 /*no-op*/
|
||||
# define SQLITE_EXTENSION_INIT2(v) (void)v; /* unused parameter */
|
||||
# define SQLITE_EXTENSION_INIT3 /*no-op*/
|
||||
#endif
|
||||
|
||||
#endif /* SQLITE3EXT_H */
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,102 @@
|
|||
#include "tesseswebserver.hpp"
|
||||
#if defined(GEKKO)
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <gccore.h>
|
||||
#include <fat.h>
|
||||
static void *xfb = NULL;
|
||||
static GXRModeObj *rmode = NULL;
|
||||
#endif
|
||||
TESSESWEBSERVER_STATIC_DECLARATION
|
||||
using namespace Tesses::WebServer;
|
||||
using namespace Tesses::WebServer::ScriptEngine;
|
||||
|
||||
class DummyServer : public IServer
|
||||
{
|
||||
public:
|
||||
bool Handle(ServerContext* ctx)
|
||||
{
|
||||
std::string resp = {};
|
||||
|
||||
for(auto param : ctx->queryParams.GetAll())
|
||||
{
|
||||
resp.append(param.first);
|
||||
resp.append(": ");
|
||||
resp.append(param.second);
|
||||
resp.append("\r\n");
|
||||
}
|
||||
|
||||
ctx->SetContentType("text/plain")->SendText(resp);
|
||||
return true;
|
||||
}
|
||||
};
|
||||
#if defined(GEKKO)
|
||||
void resetWii(u32 irq, void* ctx)
|
||||
{
|
||||
HttpServerListener::S();
|
||||
}
|
||||
#endif
|
||||
int main(int argc,char** argv)
|
||||
{
|
||||
|
||||
#if defined(GEKKO)
|
||||
fatInitDefault();
|
||||
// Initialise the video system
|
||||
VIDEO_Init();
|
||||
|
||||
// This function initialises the attached controllers
|
||||
|
||||
// Obtain the preferred video mode from the system
|
||||
// This will correspond to the settings in the Wii menu
|
||||
rmode = VIDEO_GetPreferredMode(NULL);
|
||||
|
||||
// Allocate memory for the display in the uncached region
|
||||
xfb = MEM_K0_TO_K1(SYS_AllocateFramebuffer(rmode));
|
||||
|
||||
// Initialise the console, required for printf
|
||||
console_init(xfb,20,20,rmode->fbWidth,rmode->xfbHeight,rmode->fbWidth*VI_DISPLAY_PIX_SZ);
|
||||
|
||||
// Set up the video registers with the chosen mode
|
||||
VIDEO_Configure(rmode);
|
||||
|
||||
// Tell the video hardware where our display memory is
|
||||
VIDEO_SetNextFramebuffer(xfb);
|
||||
|
||||
// Make the display visible
|
||||
VIDEO_SetBlack(false);
|
||||
|
||||
// Flush the video register changes to the hardware
|
||||
VIDEO_Flush();
|
||||
|
||||
// Wait for Video setup to complete
|
||||
VIDEO_WaitVSync();
|
||||
if(rmode->viTVMode&VI_NON_INTERLACE) VIDEO_WaitVSync();
|
||||
|
||||
|
||||
// The console understands VT terminal escape codes
|
||||
// This positions the cursor on row 2, column 0
|
||||
// we can use variables for this with format codes too
|
||||
// e.g. printf ("\x1b[%d;%dH", row, column );
|
||||
printf("\x1b[2;0H");
|
||||
|
||||
SYS_SetResetCallback(resetWii);
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
HttpServerListener::Init();
|
||||
|
||||
IServer* myServer = new StaticServer("wwwroot",true,true);
|
||||
|
||||
HttpServerListener::Listen(myServer,2003/*new SSLCerts("/etc/letsencrypt/live2")*/);
|
||||
|
||||
HttpServerListener::WaitTillInterrupted();
|
||||
|
||||
delete myServer;
|
||||
|
||||
|
||||
|
||||
HttpServerListener::FreeServer();
|
||||
return 0;
|
||||
}
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,7 @@
|
|||
#pragma once
|
||||
|
||||
#define USE_SCRIPT_ENGINE
|
||||
#define USE_MBEDTLS
|
||||
#define USE_CURL
|
||||
#define USE_SQLITE3
|
||||
#define USE_JANSSON
|
|
@ -0,0 +1,497 @@
|
|||
#pragma once
|
||||
|
||||
typedef enum StatusCode {
|
||||
Continue=100,
|
||||
SwitchingProtocols=101,
|
||||
Processing=102,
|
||||
EarlyHints=103,
|
||||
OK=200,
|
||||
Created=201,
|
||||
Accepted=202,
|
||||
NonAuthoritativeInformation=203,
|
||||
NoContent=204,
|
||||
ResetContent=205,
|
||||
PartialContent=206,
|
||||
MultiStatus=207,
|
||||
AlreadyReported=208,
|
||||
IMUsed=226,
|
||||
MultipleChoices=300,
|
||||
MovedPermanently=301,
|
||||
Found=302,
|
||||
SeeOther=303,
|
||||
NotModified=304,
|
||||
UseProxy=305,
|
||||
TemporaryRedirect=307,
|
||||
PermanentRedirect=308,
|
||||
BadRequest=400,
|
||||
Unauthorized=401,
|
||||
PaymentRequired=402,
|
||||
Forbidden=403,
|
||||
NotFound=404,
|
||||
MethodNotAllowed=405,
|
||||
NotAcceptable=406,
|
||||
ProxyAuthenticationRequired=407,
|
||||
RequestTimeout=408,
|
||||
Conflict=409,
|
||||
Gone=410,
|
||||
LengthRequired=411,
|
||||
PreconditionFailed=412,
|
||||
PayloadTooLarge=413,
|
||||
URITooLong=414,
|
||||
UnsupportedMediaType=415,
|
||||
RangeNotSatisfiable=416,
|
||||
ExpectationFailed=417,
|
||||
ImATeapot=418,
|
||||
MisdirectedRequest=421,
|
||||
UnprocessableContent=422,
|
||||
Locked=423,
|
||||
FailedDependency=424,
|
||||
TooEarly=425,
|
||||
UpgradeRequired=426,
|
||||
PreconditionRequired=428,
|
||||
TooManyRequests=429,
|
||||
RequestHeaderFieldsTooLarge=431,
|
||||
UnavailableForLegalReasons=451,
|
||||
InternalServerError=500,
|
||||
NotImplemented=501,
|
||||
BadGateway=502,
|
||||
ServiceUnavailable=503,
|
||||
GatewayTimeout=504,
|
||||
HTTPVersionNotSupported=505,
|
||||
VariantAlsoNegotiates=506,
|
||||
InsufficientStorage=507,
|
||||
LoopDetected=508,
|
||||
NotExtended=510,
|
||||
NetworkAuthenticationRequired=511
|
||||
} StatusCode;
|
||||
|
||||
|
||||
class HttpUtils {
|
||||
|
||||
|
||||
public:
|
||||
static std::string MimeType(std::filesystem::path p)
|
||||
{
|
||||
std::string ext = p.extension().string();
|
||||
if(ext == ".html" || ext == ".htm")
|
||||
{
|
||||
return "text/html";
|
||||
}
|
||||
if(ext == ".js")
|
||||
{
|
||||
return "text/javascript";
|
||||
}
|
||||
if(ext == ".json")
|
||||
{
|
||||
return "application/json";
|
||||
}
|
||||
if(ext == ".wasm")
|
||||
{
|
||||
return "application/wasm";
|
||||
}
|
||||
if(ext == ".png")
|
||||
{
|
||||
return "image/png";
|
||||
}
|
||||
if(ext == ".jpg" || ext == ".jpeg")
|
||||
{
|
||||
return "image/jpeg";
|
||||
}
|
||||
if(ext == ".css")
|
||||
{
|
||||
return "text/css";
|
||||
}
|
||||
if(ext == ".gif")
|
||||
{
|
||||
return "image/gif";
|
||||
}
|
||||
if(ext == ".mp4")
|
||||
{
|
||||
return "video/mp4";
|
||||
}
|
||||
if(ext == ".webm")
|
||||
{
|
||||
return "video/webm";
|
||||
}
|
||||
if(ext == ".webmanifest")
|
||||
{
|
||||
return "application/manifest+json";
|
||||
}
|
||||
|
||||
return "application/octet-stream";
|
||||
}
|
||||
static bool Invalid(char c)
|
||||
{
|
||||
//just do windows because it is the strictist when it comes to windows, mac and linux
|
||||
if(c >= 0 && c < 32) return true;
|
||||
if(c == 127) return true;
|
||||
if(c == '\\') return true;
|
||||
if(c == '*') return true;
|
||||
if(c == '/') return true;
|
||||
if(c == '|') return true;
|
||||
if(c == ':') return true;
|
||||
if(c == '<') return true;
|
||||
if(c == '>') return true;
|
||||
if(c == '\"') return true;
|
||||
if(c == '?') return true;
|
||||
return false;
|
||||
}
|
||||
static std::string Sanitise(std::string text)
|
||||
{
|
||||
std::string myStr={};
|
||||
for(auto item : text)
|
||||
{
|
||||
if(Invalid(item)) continue;
|
||||
myStr.push_back(item);
|
||||
}
|
||||
return myStr;
|
||||
}
|
||||
static char nibble_to_hex_char(uint8_t number)
|
||||
{
|
||||
if(number >= 0 && number <= 9)
|
||||
{
|
||||
return '0'+number;
|
||||
}
|
||||
if(number >= 0xA && number <= 0xF)
|
||||
{
|
||||
return (char)(55+number);
|
||||
}
|
||||
return '0';
|
||||
}
|
||||
static uint8_t hex_char_to_nibble(char c)
|
||||
{
|
||||
if(c >= '0' && c <= '9')
|
||||
return c - '0';
|
||||
|
||||
if(c >= 'A' && c <= 'F')
|
||||
return (c-'A')+0xA;
|
||||
|
||||
if(c >= 'a' && c <= 'f')
|
||||
return (c-'a')+0xA;
|
||||
return 0;
|
||||
}
|
||||
static std::vector<std::pair<std::string,std::string>> QueryParamsDecode(std::string query)
|
||||
{
|
||||
std::vector<std::pair<std::string,std::string>> strs;
|
||||
for(auto item : SplitString(query,"&"))
|
||||
{
|
||||
std::vector<std::string> ss=SplitString(item,"=",2);
|
||||
if(ss.size() >= 1)
|
||||
{
|
||||
std::string value = {};
|
||||
if(ss.size() == 2)
|
||||
{
|
||||
value = UrlDecode(ss[1]);
|
||||
}
|
||||
strs.push_back(std::pair<std::string,std::string>(UrlDecode(ss[0]),value));
|
||||
}
|
||||
}
|
||||
return strs;
|
||||
}
|
||||
|
||||
static std::string QueryParamsEncode(std::vector<std::pair<std::string,std::string>> query)
|
||||
{
|
||||
std::string s={};
|
||||
bool first = true;
|
||||
for(auto item : query)
|
||||
{
|
||||
if(!first)
|
||||
{
|
||||
s.push_back('&');
|
||||
}
|
||||
s.insert(s.size(),UrlEncode(item.first));
|
||||
s.push_back('=');
|
||||
s.insert(s.size(),UrlEncode(item.second));
|
||||
first=false;
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
static std::string UrlDecode(std::string v)
|
||||
{
|
||||
std::string s = {};
|
||||
|
||||
for(size_t i = 0;i<v.size();i++)
|
||||
{
|
||||
if(v[i] == '+')
|
||||
s.push_back(' ');
|
||||
else if(v[i] == '%')
|
||||
{
|
||||
i++;
|
||||
uint8_t n = hex_char_to_nibble(v[i])<<4;
|
||||
i++;
|
||||
n |= hex_char_to_nibble(v[i]);
|
||||
s.push_back((char)n);
|
||||
}
|
||||
else
|
||||
s.push_back(v[i]);
|
||||
|
||||
}
|
||||
return s;
|
||||
}
|
||||
static std::string UrlPathEncode(std::string v)
|
||||
{
|
||||
std::string s = {};
|
||||
|
||||
for(auto item : v)
|
||||
{
|
||||
if(item >= 'A' && item <= 'Z')
|
||||
s.push_back(item);
|
||||
else if(item >= 'a' && item <= 'z')
|
||||
s.push_back(item);
|
||||
else if(item >= '0' && item <= '9')
|
||||
s.push_back(item);
|
||||
else if(item == '-' || item == '_' || item == '.' || item == '~')
|
||||
s.push_back(item);
|
||||
else
|
||||
{
|
||||
s.push_back('%');
|
||||
s.push_back(nibble_to_hex_char((item >> 4) & 0xF));
|
||||
s.push_back(nibble_to_hex_char((item) & 0xF));
|
||||
}
|
||||
}
|
||||
return s;
|
||||
}
|
||||
static std::string UrlPathDecode(std::string v)
|
||||
{
|
||||
std::string s = {};
|
||||
|
||||
for(size_t i = 0;i<v.size();i++)
|
||||
{
|
||||
if(v[i] == '%')
|
||||
{
|
||||
i++;
|
||||
uint8_t n = hex_char_to_nibble(v[i])<<4;
|
||||
i++;
|
||||
n |= hex_char_to_nibble(v[i]);
|
||||
s.push_back((char)n);
|
||||
}
|
||||
else
|
||||
s.push_back(v[i]);
|
||||
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
static std::string UrlEncode(std::string v)
|
||||
{
|
||||
std::string s = {};
|
||||
|
||||
for(auto item : v)
|
||||
{
|
||||
if(item == ' ')
|
||||
s.push_back('+');
|
||||
else if(item >= 'A' && item <= 'Z')
|
||||
s.push_back(item);
|
||||
else if(item >= 'a' && item <= 'z')
|
||||
s.push_back(item);
|
||||
else if(item >= '0' && item <= '9')
|
||||
s.push_back(item);
|
||||
else if(item == '-' || item == '_' || item == '.' || item == '~')
|
||||
s.push_back(item);
|
||||
else
|
||||
{
|
||||
s.push_back('%');
|
||||
s.push_back(nibble_to_hex_char((item >> 4) & 0xF));
|
||||
s.push_back(nibble_to_hex_char((item) & 0xF));
|
||||
}
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
static std::vector<std::string> SplitString(std::string text, std::string delimiter,std::size_t maxCnt = std::string::npos)
|
||||
{
|
||||
std::vector<std::string> strs;
|
||||
std::size_t i = 1;
|
||||
while(text.length() > 0)
|
||||
{
|
||||
if(i == maxCnt)
|
||||
{
|
||||
strs.push_back(text);
|
||||
break;
|
||||
}
|
||||
std::size_t index= text.find_first_of(delimiter);
|
||||
|
||||
|
||||
|
||||
if(index == std::string::npos)
|
||||
{
|
||||
strs.push_back(text);
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
std::string left = text.substr(0,index);
|
||||
|
||||
text = text.substr(index+delimiter.size());
|
||||
|
||||
strs.push_back(left);
|
||||
|
||||
}
|
||||
i++;
|
||||
}
|
||||
return strs;
|
||||
}
|
||||
static std::string HtmlEncode(std::string html)
|
||||
{
|
||||
std::string myHtml = {};
|
||||
for(auto item : html)
|
||||
{
|
||||
if(item == '\"')
|
||||
{
|
||||
myHtml.append(""");
|
||||
}
|
||||
else if(item == '\'')
|
||||
{
|
||||
myHtml.append("'");
|
||||
}
|
||||
else if(item == '&')
|
||||
{
|
||||
myHtml.append("&");
|
||||
}
|
||||
else if(item == '<')
|
||||
{
|
||||
myHtml.append("<");
|
||||
}
|
||||
else if(item == '>')
|
||||
{
|
||||
myHtml.append(">");
|
||||
}
|
||||
else
|
||||
{
|
||||
myHtml.push_back(item);
|
||||
}
|
||||
}
|
||||
return myHtml;
|
||||
}
|
||||
static std::string StatusCodeString(StatusCode code)
|
||||
{
|
||||
switch(code)
|
||||
{
|
||||
case StatusCode::Continue:
|
||||
return "Continue";
|
||||
case StatusCode::SwitchingProtocols:
|
||||
return "Switching Protocols";
|
||||
case StatusCode::Processing:
|
||||
return "Processing";
|
||||
case StatusCode::EarlyHints:
|
||||
return "Early Hints";
|
||||
case StatusCode::OK:
|
||||
return "OK";
|
||||
case StatusCode::Created:
|
||||
return "Created";
|
||||
case StatusCode::Accepted:
|
||||
return "Accepted";
|
||||
case StatusCode::NonAuthoritativeInformation:
|
||||
return "Non-Authoritative Information";
|
||||
case StatusCode::NoContent:
|
||||
return "No Content";
|
||||
case StatusCode::ResetContent:
|
||||
return "Reset Content";
|
||||
case StatusCode::PartialContent:
|
||||
return "PartialContent";
|
||||
case StatusCode::MultiStatus:
|
||||
return "Multi-Status";
|
||||
case StatusCode::AlreadyReported:
|
||||
return "Already Reported";
|
||||
case StatusCode::IMUsed:
|
||||
return "IM Used";
|
||||
case StatusCode::MultipleChoices:
|
||||
return "Multiple Choices";
|
||||
case StatusCode::MovedPermanently:
|
||||
return "Moved Permanently";
|
||||
case StatusCode::Found:
|
||||
return "Found";
|
||||
case StatusCode::SeeOther:
|
||||
return "See Other";
|
||||
case StatusCode::NotModified:
|
||||
return "Not Modified";
|
||||
case StatusCode::UseProxy:
|
||||
return "Use Proxy";
|
||||
case StatusCode::TemporaryRedirect:
|
||||
return "Temporary Redirect";
|
||||
case StatusCode::PermanentRedirect:
|
||||
return "Permanent Redirect";
|
||||
case StatusCode::BadRequest:
|
||||
return "Bad Request";
|
||||
case StatusCode::Unauthorized:
|
||||
return "Unauthorized";
|
||||
case StatusCode::PaymentRequired:
|
||||
return "Payment Required";
|
||||
case StatusCode::Forbidden:
|
||||
return "Forbidden";
|
||||
case StatusCode::NotFound:
|
||||
return "Not Found";
|
||||
case StatusCode::MethodNotAllowed:
|
||||
return "Method Not Allowed";
|
||||
case StatusCode::NotAcceptable:
|
||||
return "Not Acceptable";
|
||||
case StatusCode::ProxyAuthenticationRequired:
|
||||
return "Proxy Authentication Required";
|
||||
case StatusCode::RequestTimeout:
|
||||
return "Request Timeout";
|
||||
case StatusCode::Conflict:
|
||||
return "Conflict";
|
||||
case StatusCode::Gone:
|
||||
return "Gone";
|
||||
case StatusCode::LengthRequired:
|
||||
return "Length Required";
|
||||
case StatusCode::PreconditionFailed:
|
||||
return "Precondition Failed";
|
||||
case StatusCode::PayloadTooLarge:
|
||||
return "Payload Too Large";
|
||||
case StatusCode::URITooLong:
|
||||
return "URI Too Long";
|
||||
case StatusCode::UnsupportedMediaType:
|
||||
return "Unsupported Media Type";
|
||||
case StatusCode::RangeNotSatisfiable:
|
||||
return "Range Not Satisfiable";
|
||||
case StatusCode::ExpectationFailed:
|
||||
return "Expectation Failed";
|
||||
case StatusCode::ImATeapot:
|
||||
return "I'm a teapot";
|
||||
case StatusCode::MisdirectedRequest:
|
||||
return "Misdirected Request";
|
||||
case StatusCode::UnprocessableContent:
|
||||
return "Unprocessable Content";
|
||||
case StatusCode::Locked:
|
||||
return "Locked";
|
||||
case StatusCode::FailedDependency:
|
||||
return "Failed Dependency";
|
||||
case StatusCode::TooEarly:
|
||||
return "Too Early";
|
||||
case StatusCode::UpgradeRequired:
|
||||
return "Upgrade Required";
|
||||
case StatusCode::PreconditionRequired:
|
||||
return "Precondition Required";
|
||||
case StatusCode::TooManyRequests:
|
||||
return "Too Many Requests";
|
||||
case StatusCode::RequestHeaderFieldsTooLarge:
|
||||
return "Request Header Fields Too Large";
|
||||
case StatusCode::UnavailableForLegalReasons:
|
||||
return "Unavailable For Legal Reasons";
|
||||
case StatusCode::InternalServerError:
|
||||
return "Internal Server Error";
|
||||
case StatusCode::NotImplemented:
|
||||
return "Not Implemented";
|
||||
case StatusCode::ServiceUnavailable:
|
||||
return "Service Unavailable";
|
||||
case StatusCode::GatewayTimeout:
|
||||
return "Gateway Timeout";
|
||||
case StatusCode::HTTPVersionNotSupported:
|
||||
return "HTTP Version Not Supported";
|
||||
case StatusCode::VariantAlsoNegotiates:
|
||||
return "Variant Also Negotiates";
|
||||
case StatusCode::InsufficientStorage:
|
||||
return "Insufficient Storage";
|
||||
case StatusCode::LoopDetected:
|
||||
return "Loop Detected";
|
||||
case StatusCode::NotExtended:
|
||||
return "Not Extended";
|
||||
case StatusCode::NetworkAuthenticationRequired:
|
||||
return "Network Authentication Required";
|
||||
default:
|
||||
return "";
|
||||
}
|
||||
}
|
||||
};
|
|
@ -0,0 +1,655 @@
|
|||
/*
|
||||
** 2010 April 7
|
||||
**
|
||||
** The author disclaims copyright to this source code. In place of
|
||||
** a legal notice, here is a blessing:
|
||||
**
|
||||
** May you do good and not evil.
|
||||
** May you find forgiveness for yourself and forgive others.
|
||||
** May you share freely, never taking more than you give.
|
||||
**
|
||||
*************************************************************************
|
||||
**
|
||||
** This file implements an example of a simple VFS implementation that
|
||||
** omits complex features often not required or not possible on embedded
|
||||
** platforms. Code is included to buffer writes to the journal file,
|
||||
** which can be a significant performance improvement on some embedded
|
||||
** platforms.
|
||||
**
|
||||
** OVERVIEW
|
||||
**
|
||||
** The code in this file implements a minimal SQLite VFS that can be
|
||||
** used on Linux and other posix-like operating systems. The following
|
||||
** system calls are used:
|
||||
**
|
||||
** File-system: access(), unlink(), getcwd()
|
||||
** File IO: open(), read(), write(), fsync(), close(), fstat()
|
||||
** Other: sleep(), usleep(), time()
|
||||
**
|
||||
** The following VFS features are omitted:
|
||||
**
|
||||
** 1. File locking. The user must ensure that there is at most one
|
||||
** connection to each database when using this VFS. Multiple
|
||||
** connections to a single shared-cache count as a single connection
|
||||
** for the purposes of the previous statement.
|
||||
**
|
||||
** 2. The loading of dynamic extensions (shared libraries).
|
||||
**
|
||||
** 3. Temporary files. The user must configure SQLite to use in-memory
|
||||
** temp files when using this VFS. The easiest way to do this is to
|
||||
** compile with:
|
||||
**
|
||||
** -DSQLITE_TEMP_STORE=3
|
||||
**
|
||||
** 4. File truncation. As of version 3.6.24, SQLite may run without
|
||||
** a working xTruncate() call, providing the user does not configure
|
||||
** SQLite to use "journal_mode=truncate", or use both
|
||||
** "journal_mode=persist" and ATTACHed databases.
|
||||
**
|
||||
** It is assumed that the system uses UNIX-like path-names. Specifically,
|
||||
** that '/' characters are used to separate path components and that
|
||||
** a path-name is a relative path unless it begins with a '/'. And that
|
||||
** no UTF-8 encoded paths are greater than 512 bytes in length.
|
||||
**
|
||||
** JOURNAL WRITE-BUFFERING
|
||||
**
|
||||
** To commit a transaction to the database, SQLite first writes rollback
|
||||
** information into the journal file. This usually consists of 4 steps:
|
||||
**
|
||||
** 1. The rollback information is sequentially written into the journal
|
||||
** file, starting at the start of the file.
|
||||
** 2. The journal file is synced to disk.
|
||||
** 3. A modification is made to the first few bytes of the journal file.
|
||||
** 4. The journal file is synced to disk again.
|
||||
**
|
||||
** Most of the data is written in step 1 using a series of calls to the
|
||||
** VFS xWrite() method. The buffers passed to the xWrite() calls are of
|
||||
** various sizes. For example, as of version 3.6.24, when committing a
|
||||
** transaction that modifies 3 pages of a database file that uses 4096
|
||||
** byte pages residing on a media with 512 byte sectors, SQLite makes
|
||||
** eleven calls to the xWrite() method to create the rollback journal,
|
||||
** as follows:
|
||||
**
|
||||
** Write offset | Bytes written
|
||||
** ----------------------------
|
||||
** 0 512
|
||||
** 512 4
|
||||
** 516 4096
|
||||
** 4612 4
|
||||
** 4616 4
|
||||
** 4620 4096
|
||||
** 8716 4
|
||||
** 8720 4
|
||||
** 8724 4096
|
||||
** 12820 4
|
||||
** ++++++++++++SYNC+++++++++++
|
||||
** 0 12
|
||||
** ++++++++++++SYNC+++++++++++
|
||||
**
|
||||
** On many operating systems, this is an efficient way to write to a file.
|
||||
** However, on some embedded systems that do not cache writes in OS
|
||||
** buffers it is much more efficient to write data in blocks that are
|
||||
** an integer multiple of the sector-size in size and aligned at the
|
||||
** start of a sector.
|
||||
**
|
||||
** To work around this, the code in this file allocates a fixed size
|
||||
** buffer of SQLITE_DEMOVFS_BUFFERSZ using sqlite3_malloc() whenever a
|
||||
** journal file is opened. It uses the buffer to coalesce sequential
|
||||
** writes into aligned SQLITE_DEMOVFS_BUFFERSZ blocks. When SQLite
|
||||
** invokes the xSync() method to sync the contents of the file to disk,
|
||||
** all accumulated data is written out, even if it does not constitute
|
||||
** a complete block. This means the actual IO to create the rollback
|
||||
** journal for the example transaction above is this:
|
||||
**
|
||||
** Write offset | Bytes written
|
||||
** ----------------------------
|
||||
** 0 8192
|
||||
** 8192 4632
|
||||
** ++++++++++++SYNC+++++++++++
|
||||
** 0 12
|
||||
** ++++++++++++SYNC+++++++++++
|
||||
**
|
||||
** Much more efficient if the underlying OS is not caching write
|
||||
** operations.
|
||||
*/
|
||||
|
||||
/*removed tests from https://www.sqlite.org/src/doc/trunk/src/test_demovfs.c*/
|
||||
|
||||
#if defined(GEKKO)
|
||||
|
||||
#include "sqlite3.h"
|
||||
|
||||
#include <assert.h>
|
||||
#include <string.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/file.h>
|
||||
#include <sys/param.h>
|
||||
#include <unistd.h>
|
||||
#include <time.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
/*
|
||||
** Size of the write buffer used by journal files in bytes.
|
||||
*/
|
||||
#ifndef SQLITE_DEMOVFS_BUFFERSZ
|
||||
# define SQLITE_DEMOVFS_BUFFERSZ 8192
|
||||
#endif
|
||||
|
||||
/*
|
||||
** The maximum pathname length supported by this VFS.
|
||||
*/
|
||||
#define MAXPATHNAME 512
|
||||
|
||||
/*
|
||||
** When using this VFS, the sqlite3_file* handles that SQLite uses are
|
||||
** actually pointers to instances of type DemoFile.
|
||||
*/
|
||||
typedef struct DemoFile DemoFile;
|
||||
struct DemoFile {
|
||||
sqlite3_file base; /* Base class. Must be first. */
|
||||
int fd; /* File descriptor */
|
||||
|
||||
char *aBuffer; /* Pointer to malloc'd buffer */
|
||||
int nBuffer; /* Valid bytes of data in zBuffer */
|
||||
sqlite3_int64 iBufferOfst; /* Offset in file of zBuffer[0] */
|
||||
};
|
||||
|
||||
/*
|
||||
** Write directly to the file passed as the first argument. Even if the
|
||||
** file has a write-buffer (DemoFile.aBuffer), ignore it.
|
||||
*/
|
||||
static int demoDirectWrite(
|
||||
DemoFile *p, /* File handle */
|
||||
const void *zBuf, /* Buffer containing data to write */
|
||||
int iAmt, /* Size of data to write in bytes */
|
||||
sqlite_int64 iOfst /* File offset to write to */
|
||||
){
|
||||
off_t ofst; /* Return value from lseek() */
|
||||
size_t nWrite; /* Return value from write() */
|
||||
|
||||
ofst = lseek(p->fd, iOfst, SEEK_SET);
|
||||
if( ofst!=iOfst ){
|
||||
return SQLITE_IOERR_WRITE;
|
||||
}
|
||||
|
||||
nWrite = write(p->fd, zBuf, iAmt);
|
||||
if( nWrite!=iAmt ){
|
||||
return SQLITE_IOERR_WRITE;
|
||||
}
|
||||
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
** Flush the contents of the DemoFile.aBuffer buffer to disk. This is a
|
||||
** no-op if this particular file does not have a buffer (i.e. it is not
|
||||
** a journal file) or if the buffer is currently empty.
|
||||
*/
|
||||
static int demoFlushBuffer(DemoFile *p){
|
||||
int rc = SQLITE_OK;
|
||||
if( p->nBuffer ){
|
||||
rc = demoDirectWrite(p, p->aBuffer, p->nBuffer, p->iBufferOfst);
|
||||
p->nBuffer = 0;
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*
|
||||
** Close a file.
|
||||
*/
|
||||
static int demoClose(sqlite3_file *pFile){
|
||||
int rc;
|
||||
DemoFile *p = (DemoFile*)pFile;
|
||||
rc = demoFlushBuffer(p);
|
||||
sqlite3_free(p->aBuffer);
|
||||
close(p->fd);
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*
|
||||
** Read data from a file.
|
||||
*/
|
||||
static int demoRead(
|
||||
sqlite3_file *pFile,
|
||||
void *zBuf,
|
||||
int iAmt,
|
||||
sqlite_int64 iOfst
|
||||
){
|
||||
DemoFile *p = (DemoFile*)pFile;
|
||||
off_t ofst; /* Return value from lseek() */
|
||||
int nRead; /* Return value from read() */
|
||||
int rc; /* Return code from demoFlushBuffer() */
|
||||
|
||||
/* Flush any data in the write buffer to disk in case this operation
|
||||
** is trying to read data the file-region currently cached in the buffer.
|
||||
** It would be possible to detect this case and possibly save an
|
||||
** unnecessary write here, but in practice SQLite will rarely read from
|
||||
** a journal file when there is data cached in the write-buffer.
|
||||
*/
|
||||
rc = demoFlushBuffer(p);
|
||||
if( rc!=SQLITE_OK ){
|
||||
return rc;
|
||||
}
|
||||
|
||||
ofst = lseek(p->fd, iOfst, SEEK_SET);
|
||||
if( ofst!=iOfst ){
|
||||
return SQLITE_IOERR_READ;
|
||||
}
|
||||
nRead = read(p->fd, zBuf, iAmt);
|
||||
|
||||
if( nRead==iAmt ){
|
||||
return SQLITE_OK;
|
||||
}else if( nRead>=0 ){
|
||||
if( nRead<iAmt ){
|
||||
memset(&((char*)zBuf)[nRead], 0, iAmt-nRead);
|
||||
}
|
||||
return SQLITE_IOERR_SHORT_READ;
|
||||
}
|
||||
|
||||
return SQLITE_IOERR_READ;
|
||||
}
|
||||
|
||||
/*
|
||||
** Write data to a crash-file.
|
||||
*/
|
||||
static int demoWrite(
|
||||
sqlite3_file *pFile,
|
||||
const void *zBuf,
|
||||
int iAmt,
|
||||
sqlite_int64 iOfst
|
||||
){
|
||||
DemoFile *p = (DemoFile*)pFile;
|
||||
|
||||
if( p->aBuffer ){
|
||||
char *z = (char *)zBuf; /* Pointer to remaining data to write */
|
||||
int n = iAmt; /* Number of bytes at z */
|
||||
sqlite3_int64 i = iOfst; /* File offset to write to */
|
||||
|
||||
while( n>0 ){
|
||||
int nCopy; /* Number of bytes to copy into buffer */
|
||||
|
||||
/* If the buffer is full, or if this data is not being written directly
|
||||
** following the data already buffered, flush the buffer. Flushing
|
||||
** the buffer is a no-op if it is empty.
|
||||
*/
|
||||
if( p->nBuffer==SQLITE_DEMOVFS_BUFFERSZ || p->iBufferOfst+p->nBuffer!=i ){
|
||||
int rc = demoFlushBuffer(p);
|
||||
if( rc!=SQLITE_OK ){
|
||||
return rc;
|
||||
}
|
||||
}
|
||||
assert( p->nBuffer==0 || p->iBufferOfst+p->nBuffer==i );
|
||||
p->iBufferOfst = i - p->nBuffer;
|
||||
|
||||
/* Copy as much data as possible into the buffer. */
|
||||
nCopy = SQLITE_DEMOVFS_BUFFERSZ - p->nBuffer;
|
||||
if( nCopy>n ){
|
||||
nCopy = n;
|
||||
}
|
||||
memcpy(&p->aBuffer[p->nBuffer], z, nCopy);
|
||||
p->nBuffer += nCopy;
|
||||
|
||||
n -= nCopy;
|
||||
i += nCopy;
|
||||
z += nCopy;
|
||||
}
|
||||
}else{
|
||||
return demoDirectWrite(p, zBuf, iAmt, iOfst);
|
||||
}
|
||||
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
** Truncate a file. This is a no-op for this VFS (see header comments at
|
||||
** the top of the file).
|
||||
*/
|
||||
static int demoTruncate(sqlite3_file *pFile, sqlite_int64 size){
|
||||
#if 0
|
||||
if( ftruncate(((DemoFile *)pFile)->fd, size) ) return SQLITE_IOERR_TRUNCATE;
|
||||
#endif
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
** Sync the contents of the file to the persistent media.
|
||||
*/
|
||||
static int demoSync(sqlite3_file *pFile, int flags){
|
||||
DemoFile *p = (DemoFile*)pFile;
|
||||
int rc;
|
||||
|
||||
rc = demoFlushBuffer(p);
|
||||
if( rc!=SQLITE_OK ){
|
||||
return rc;
|
||||
}
|
||||
|
||||
rc = fsync(p->fd);
|
||||
return (rc==0 ? SQLITE_OK : SQLITE_IOERR_FSYNC);
|
||||
}
|
||||
|
||||
/*
|
||||
** Write the size of the file in bytes to *pSize.
|
||||
*/
|
||||
static int demoFileSize(sqlite3_file *pFile, sqlite_int64 *pSize){
|
||||
DemoFile *p = (DemoFile*)pFile;
|
||||
int rc; /* Return code from fstat() call */
|
||||
struct stat sStat; /* Output of fstat() call */
|
||||
|
||||
/* Flush the contents of the buffer to disk. As with the flush in the
|
||||
** demoRead() method, it would be possible to avoid this and save a write
|
||||
** here and there. But in practice this comes up so infrequently it is
|
||||
** not worth the trouble.
|
||||
*/
|
||||
rc = demoFlushBuffer(p);
|
||||
if( rc!=SQLITE_OK ){
|
||||
return rc;
|
||||
}
|
||||
|
||||
rc = fstat(p->fd, &sStat);
|
||||
if( rc!=0 ) return SQLITE_IOERR_FSTAT;
|
||||
*pSize = sStat.st_size;
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
** Locking functions. The xLock() and xUnlock() methods are both no-ops.
|
||||
** The xCheckReservedLock() always indicates that no other process holds
|
||||
** a reserved lock on the database file. This ensures that if a hot-journal
|
||||
** file is found in the file-system it is rolled back.
|
||||
*/
|
||||
static int demoLock(sqlite3_file *pFile, int eLock){
|
||||
return SQLITE_OK;
|
||||
}
|
||||
static int demoUnlock(sqlite3_file *pFile, int eLock){
|
||||
return SQLITE_OK;
|
||||
}
|
||||
static int demoCheckReservedLock(sqlite3_file *pFile, int *pResOut){
|
||||
*pResOut = 0;
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
** No xFileControl() verbs are implemented by this VFS.
|
||||
*/
|
||||
static int demoFileControl(sqlite3_file *pFile, int op, void *pArg){
|
||||
return SQLITE_NOTFOUND;
|
||||
}
|
||||
|
||||
/*
|
||||
** The xSectorSize() and xDeviceCharacteristics() methods. These two
|
||||
** may return special values allowing SQLite to optimize file-system
|
||||
** access to some extent. But it is also safe to simply return 0.
|
||||
*/
|
||||
static int demoSectorSize(sqlite3_file *pFile){
|
||||
return 0;
|
||||
}
|
||||
static int demoDeviceCharacteristics(sqlite3_file *pFile){
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
** Open a file handle.
|
||||
*/
|
||||
static int demoOpen(
|
||||
sqlite3_vfs *pVfs, /* VFS */
|
||||
const char *zName, /* File to open, or 0 for a temp file */
|
||||
sqlite3_file *pFile, /* Pointer to DemoFile struct to populate */
|
||||
int flags, /* Input SQLITE_OPEN_XXX flags */
|
||||
int *pOutFlags /* Output SQLITE_OPEN_XXX flags (or NULL) */
|
||||
){
|
||||
static const sqlite3_io_methods demoio = {
|
||||
1, /* iVersion */
|
||||
demoClose, /* xClose */
|
||||
demoRead, /* xRead */
|
||||
demoWrite, /* xWrite */
|
||||
demoTruncate, /* xTruncate */
|
||||
demoSync, /* xSync */
|
||||
demoFileSize, /* xFileSize */
|
||||
demoLock, /* xLock */
|
||||
demoUnlock, /* xUnlock */
|
||||
demoCheckReservedLock, /* xCheckReservedLock */
|
||||
demoFileControl, /* xFileControl */
|
||||
demoSectorSize, /* xSectorSize */
|
||||
demoDeviceCharacteristics /* xDeviceCharacteristics */
|
||||
};
|
||||
|
||||
DemoFile *p = (DemoFile*)pFile; /* Populate this structure */
|
||||
int oflags = 0; /* flags to pass to open() call */
|
||||
char *aBuf = 0;
|
||||
|
||||
if( zName==0 ){
|
||||
return SQLITE_IOERR;
|
||||
}
|
||||
|
||||
if( flags&SQLITE_OPEN_MAIN_JOURNAL ){
|
||||
aBuf = (char *)sqlite3_malloc(SQLITE_DEMOVFS_BUFFERSZ);
|
||||
if( !aBuf ){
|
||||
return SQLITE_NOMEM;
|
||||
}
|
||||
}
|
||||
|
||||
if( flags&SQLITE_OPEN_EXCLUSIVE ) oflags |= O_EXCL;
|
||||
if( flags&SQLITE_OPEN_CREATE ) oflags |= O_CREAT;
|
||||
if( flags&SQLITE_OPEN_READONLY ) oflags |= O_RDONLY;
|
||||
if( flags&SQLITE_OPEN_READWRITE ) oflags |= O_RDWR;
|
||||
|
||||
memset(p, 0, sizeof(DemoFile));
|
||||
p->fd = open(zName, oflags);
|
||||
if( p->fd<0 ){
|
||||
sqlite3_free(aBuf);
|
||||
return SQLITE_CANTOPEN;
|
||||
}
|
||||
p->aBuffer = aBuf;
|
||||
|
||||
if( pOutFlags ){
|
||||
*pOutFlags = flags;
|
||||
}
|
||||
p->base.pMethods = &demoio;
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
** Delete the file identified by argument zPath. If the dirSync parameter
|
||||
** is non-zero, then ensure the file-system modification to delete the
|
||||
** file has been synced to disk before returning.
|
||||
*/
|
||||
static int demoDelete(sqlite3_vfs *pVfs, const char *zPath, int dirSync){
|
||||
int rc; /* Return code */
|
||||
|
||||
rc = unlink(zPath);
|
||||
if( rc!=0 && errno==ENOENT ) return SQLITE_OK;
|
||||
|
||||
if( rc==0 && dirSync ){
|
||||
int dfd; /* File descriptor open on directory */
|
||||
char *zSlash;
|
||||
char zDir[MAXPATHNAME+1]; /* Name of directory containing file zPath */
|
||||
|
||||
/* Figure out the directory name from the path of the file deleted. */
|
||||
sqlite3_snprintf(MAXPATHNAME, zDir, "%s", zPath);
|
||||
zDir[MAXPATHNAME] = '\0';
|
||||
zSlash = strrchr(zDir,'/');
|
||||
if( zSlash ){
|
||||
/* Open a file-descriptor on the directory. Sync. Close. */
|
||||
zSlash[0] = 0;
|
||||
dfd = open(zDir, O_RDONLY, 0);
|
||||
if( dfd<0 ){
|
||||
rc = -1;
|
||||
}else{
|
||||
rc = fsync(dfd);
|
||||
close(dfd);
|
||||
}
|
||||
}
|
||||
}
|
||||
return (rc==0 ? SQLITE_OK : SQLITE_IOERR_DELETE);
|
||||
}
|
||||
|
||||
#ifndef F_OK
|
||||
# define F_OK 0
|
||||
#endif
|
||||
#ifndef R_OK
|
||||
# define R_OK 4
|
||||
#endif
|
||||
#ifndef W_OK
|
||||
# define W_OK 2
|
||||
#endif
|
||||
|
||||
/*
|
||||
** Query the file-system to see if the named file exists, is readable or
|
||||
** is both readable and writable.
|
||||
*/
|
||||
static int demoAccess(
|
||||
sqlite3_vfs *pVfs,
|
||||
const char *zPath,
|
||||
int flags,
|
||||
int *pResOut
|
||||
){
|
||||
int rc; /* access() return code */
|
||||
int eAccess = F_OK; /* Second argument to access() */
|
||||
|
||||
assert( flags==SQLITE_ACCESS_EXISTS /* access(zPath, F_OK) */
|
||||
|| flags==SQLITE_ACCESS_READ /* access(zPath, R_OK) */
|
||||
|| flags==SQLITE_ACCESS_READWRITE /* access(zPath, R_OK|W_OK) */
|
||||
);
|
||||
|
||||
if( flags==SQLITE_ACCESS_READWRITE ) eAccess = R_OK|W_OK;
|
||||
if( flags==SQLITE_ACCESS_READ ) eAccess = R_OK;
|
||||
|
||||
rc = access(zPath, eAccess);
|
||||
*pResOut = (rc==0);
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
** Argument zPath points to a nul-terminated string containing a file path.
|
||||
** If zPath is an absolute path, then it is copied as is into the output
|
||||
** buffer. Otherwise, if it is a relative path, then the equivalent full
|
||||
** path is written to the output buffer.
|
||||
**
|
||||
** This function assumes that paths are UNIX style. Specifically, that:
|
||||
**
|
||||
** 1. Path components are separated by a '/'. and
|
||||
** 2. Full paths begin with a '/' character.
|
||||
*/
|
||||
static int demoFullPathname(
|
||||
sqlite3_vfs *pVfs, /* VFS */
|
||||
const char *zPath, /* Input path (possibly a relative path) */
|
||||
int nPathOut, /* Size of output buffer in bytes */
|
||||
char *zPathOut /* Pointer to output buffer */
|
||||
){
|
||||
char zDir[MAXPATHNAME+1];
|
||||
if( zPath[0]=='/' ){
|
||||
zDir[0] = '\0';
|
||||
}else{
|
||||
if( getcwd(zDir, sizeof(zDir))==0 ) return SQLITE_IOERR;
|
||||
}
|
||||
zDir[MAXPATHNAME] = '\0';
|
||||
|
||||
sqlite3_snprintf(nPathOut, zPathOut, "%s/%s", zDir, zPath);
|
||||
zPathOut[nPathOut-1] = '\0';
|
||||
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
** The following four VFS methods:
|
||||
**
|
||||
** xDlOpen
|
||||
** xDlError
|
||||
** xDlSym
|
||||
** xDlClose
|
||||
**
|
||||
** are supposed to implement the functionality needed by SQLite to load
|
||||
** extensions compiled as shared objects. This simple VFS does not support
|
||||
** this functionality, so the following functions are no-ops.
|
||||
*/
|
||||
static void *demoDlOpen(sqlite3_vfs *pVfs, const char *zPath){
|
||||
return 0;
|
||||
}
|
||||
static void demoDlError(sqlite3_vfs *pVfs, int nByte, char *zErrMsg){
|
||||
sqlite3_snprintf(nByte, zErrMsg, "Loadable extensions are not supported");
|
||||
zErrMsg[nByte-1] = '\0';
|
||||
}
|
||||
static void (*demoDlSym(sqlite3_vfs *pVfs, void *pH, const char *z))(void){
|
||||
return 0;
|
||||
}
|
||||
static void demoDlClose(sqlite3_vfs *pVfs, void *pHandle){
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
** Parameter zByte points to a buffer nByte bytes in size. Populate this
|
||||
** buffer with pseudo-random data.
|
||||
*/
|
||||
static int demoRandomness(sqlite3_vfs *pVfs, int nByte, char *zByte){
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
** Sleep for at least nMicro microseconds. Return the (approximate) number
|
||||
** of microseconds slept for.
|
||||
*/
|
||||
static int demoSleep(sqlite3_vfs *pVfs, int nMicro){
|
||||
sleep(nMicro / 1000000);
|
||||
usleep(nMicro % 1000000);
|
||||
return nMicro;
|
||||
}
|
||||
|
||||
/*
|
||||
** Set *pTime to the current UTC time expressed as a Julian day. Return
|
||||
** SQLITE_OK if successful, or an error code otherwise.
|
||||
**
|
||||
** http://en.wikipedia.org/wiki/Julian_day
|
||||
**
|
||||
** This implementation is not very good. The current time is rounded to
|
||||
** an integer number of seconds. Also, assuming time_t is a signed 32-bit
|
||||
** value, it will stop working some time in the year 2038 AD (the so-called
|
||||
** "year 2038" problem that afflicts systems that store time this way).
|
||||
*/
|
||||
static int demoCurrentTime(sqlite3_vfs *pVfs, double *pTime){
|
||||
time_t t = time(0);
|
||||
*pTime = t/86400.0 + 2440587.5;
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
** This function returns a pointer to the VFS implemented in this file.
|
||||
** To make the VFS available to SQLite:
|
||||
**
|
||||
** sqlite3_vfs_register(sqlite3_demovfs(), 0);
|
||||
*/
|
||||
uid_t geteuid(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int fchown(int fildes, uid_t owner, gid_t group)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
sqlite3_vfs *sqlite3_demovfs(void){
|
||||
static sqlite3_vfs demovfs = {
|
||||
1, /* iVersion */
|
||||
sizeof(DemoFile), /* szOsFile */
|
||||
MAXPATHNAME, /* mxPathname */
|
||||
0, /* pNext */
|
||||
"demo", /* zName */
|
||||
0, /* pAppData */
|
||||
demoOpen, /* xOpen */
|
||||
demoDelete, /* xDelete */
|
||||
demoAccess, /* xAccess */
|
||||
demoFullPathname, /* xFullPathname */
|
||||
demoDlOpen, /* xDlOpen */
|
||||
demoDlError, /* xDlError */
|
||||
demoDlSym, /* xDlSym */
|
||||
demoDlClose, /* xDlClose */
|
||||
demoRandomness, /* xRandomness */
|
||||
demoSleep, /* xSleep */
|
||||
demoCurrentTime, /* xCurrentTime */
|
||||
};
|
||||
return &demovfs;
|
||||
}
|
||||
|
||||
#endif
|
|
@ -0,0 +1,500 @@
|
|||
#include <fstream>
|
||||
#include <iostream>
|
||||
#include <cstring>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <filesystem>
|
||||
#include "src/tesseswebserverhttputils.hpp"
|
||||
|
||||
void byte_array_f(std::string& s,FILE* f)
|
||||
{
|
||||
s.push_back('{');
|
||||
uint8_t buffer[1024];
|
||||
size_t read = 0;
|
||||
bool first=true;
|
||||
do {
|
||||
read=fread(buffer,1,1024,f);
|
||||
for(size_t i = 0;i<read;i++)
|
||||
{
|
||||
if(!first) s.push_back(',');
|
||||
s.append("0x");
|
||||
uint8_t high = (uint8_t)((buffer[i] >> 4) & 0x0F);
|
||||
uint8_t low = (uint8_t)(buffer[i] & 0x0F);
|
||||
|
||||
s.push_back(HttpUtils::nibble_to_hex_char(high));
|
||||
s.push_back(HttpUtils::nibble_to_hex_char(low));
|
||||
first=false;
|
||||
}
|
||||
|
||||
} while(read > 0);
|
||||
|
||||
|
||||
s.push_back('}');
|
||||
|
||||
}
|
||||
|
||||
void byte_array_a(std::string& s,uint8_t* buffer,size_t read)
|
||||
{
|
||||
s.push_back('{');
|
||||
bool first=true;
|
||||
for(size_t i = 0;i<read;i++)
|
||||
{
|
||||
if(!first) s.push_back(',');
|
||||
s.append("0x");
|
||||
uint8_t high = (uint8_t)((buffer[i] >> 4) & 0x0F);
|
||||
uint8_t low = (uint8_t)(buffer[i] & 0x0F);
|
||||
|
||||
s.push_back(HttpUtils::nibble_to_hex_char(high));
|
||||
s.push_back(HttpUtils::nibble_to_hex_char(low));
|
||||
first=false;
|
||||
}
|
||||
|
||||
|
||||
|
||||
s.push_back('}');
|
||||
|
||||
}
|
||||
|
||||
class Resource {
|
||||
public:
|
||||
std::string mime;
|
||||
std::string data;
|
||||
std::string path;
|
||||
bool twss;
|
||||
};
|
||||
|
||||
void follow_symlink(std::filesystem::path& p)
|
||||
{
|
||||
while(std::filesystem::is_symlink(p))
|
||||
{
|
||||
p = std::filesystem::read_symlink(p);
|
||||
}
|
||||
}
|
||||
|
||||
void get_files(std::vector<Resource>& resources, std::vector<std::string>& indexes, bool enableListing, std::filesystem::path srcDir, std::string httpDir)
|
||||
{
|
||||
std::filesystem::path index;
|
||||
bool useIndexFile=false;
|
||||
for(auto item : indexes)
|
||||
{
|
||||
std::filesystem::path myIndex = srcDir / item;
|
||||
follow_symlink(myIndex);
|
||||
|
||||
if(std::filesystem::is_regular_file(myIndex))
|
||||
{
|
||||
index = myIndex;
|
||||
useIndexFile=true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
bool mustList=false;
|
||||
std::vector<std::pair<std::string,bool>> paths;
|
||||
|
||||
|
||||
if(useIndexFile)
|
||||
{
|
||||
Resource res;
|
||||
res.path = httpDir;
|
||||
res.twss = index.extension() == ".twss";
|
||||
FILE* f = fopen(index.c_str(),"rb");
|
||||
byte_array_f(res.data,f);
|
||||
fclose(f);
|
||||
res.mime = HttpUtils::MimeType(index);
|
||||
resources.push_back(res);
|
||||
if(!httpDir.ends_with('/'))
|
||||
{
|
||||
res.path = httpDir + "/";
|
||||
resources.push_back(res);
|
||||
}
|
||||
}
|
||||
else if(enableListing)
|
||||
{
|
||||
mustList=true;
|
||||
}
|
||||
|
||||
for(auto item : std::filesystem::directory_iterator(srcDir))
|
||||
{
|
||||
auto ent = item.path();
|
||||
follow_symlink(ent);
|
||||
|
||||
|
||||
if(std::filesystem::is_directory(ent))
|
||||
{
|
||||
get_files(resources, indexes, enableListing,ent,httpDir.ends_with('/') ? (httpDir + item.path().filename().string()) : (httpDir + "/" + item.path().filename().string()));
|
||||
if(mustList)
|
||||
paths.push_back(std::pair<std::string,bool>(item.path().filename().string(),true));
|
||||
}
|
||||
|
||||
if(std::filesystem::is_regular_file(ent))
|
||||
{
|
||||
Resource res;
|
||||
res.path = httpDir.ends_with('/') ? (httpDir + item.path().filename().string()) : (httpDir + "/" + item.path().filename().string());
|
||||
res.twss = item.path().extension() == ".twss";
|
||||
FILE* f = fopen(ent.c_str(),"rb");
|
||||
byte_array_f(res.data,f);
|
||||
fclose(f);
|
||||
res.mime = HttpUtils::MimeType(ent);
|
||||
resources.push_back(res);
|
||||
if(mustList)
|
||||
paths.push_back(std::pair<std::string,bool>(item.path().filename().string(),false));
|
||||
}
|
||||
}
|
||||
|
||||
if(mustList)
|
||||
{
|
||||
|
||||
std::string html = "<html><head><title>Index of ";
|
||||
html.append(HttpUtils::HtmlEncode(httpDir.ends_with('/') ? httpDir : (httpDir + "/")));
|
||||
html.append("</title></head><body><h1>Index of ");
|
||||
html.append(HttpUtils::HtmlEncode(httpDir.ends_with('/') ? httpDir : (httpDir + "/")));
|
||||
html.append("</h1><pre><hr><a href=\"../\">../</a>\r\n");
|
||||
|
||||
for(auto item : paths)
|
||||
{
|
||||
html.append("<a href=\"");
|
||||
html.append(HttpUtils::UrlPathEncode(item.first));
|
||||
if(item.second)
|
||||
html.append("/\">");
|
||||
else
|
||||
html.append("\">");
|
||||
html.append(HttpUtils::HtmlEncode(item.first));
|
||||
if(item.second)
|
||||
html.append("/</a>\r\n");
|
||||
else
|
||||
html.append("</a>\r\n");
|
||||
}
|
||||
html.append("</pre><hr></body></html>");
|
||||
|
||||
Resource res;
|
||||
res.path = httpDir;
|
||||
res.twss = false;
|
||||
byte_array_a(res.data,(uint8_t*)&html[0],html.size());
|
||||
res.mime = "text/html";
|
||||
resources.push_back(res);
|
||||
if(!httpDir.ends_with('/'))
|
||||
{
|
||||
res.path = httpDir + "/";
|
||||
resources.push_back(res);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool file_exists(const char* dir, const char* path)
|
||||
{
|
||||
std::filesystem::path p0(dir);
|
||||
std::filesystem::path p1(path);
|
||||
std::filesystem::path p2 = p0 / p1;
|
||||
follow_symlink(p2);
|
||||
return std::filesystem::is_regular_file(p2);
|
||||
}
|
||||
|
||||
std::string escape_string(std::string path)
|
||||
{
|
||||
std::string s={};
|
||||
s.push_back('\"');
|
||||
for(auto item : path)
|
||||
{
|
||||
switch(item)
|
||||
{
|
||||
case '\\':
|
||||
case '\"':
|
||||
case '\'':
|
||||
s.push_back('\\');
|
||||
s.push_back(item);
|
||||
break;
|
||||
case '\0':
|
||||
s.push_back('\\');
|
||||
s.push_back('0');
|
||||
break;
|
||||
case '\t':
|
||||
s.push_back('\\');
|
||||
s.push_back('t');
|
||||
break;
|
||||
case '\n':
|
||||
s.push_back('\\');
|
||||
s.push_back('n');
|
||||
break;
|
||||
case '\r':
|
||||
s.push_back('\\');
|
||||
s.push_back('r');
|
||||
break;
|
||||
case '\v':
|
||||
s.push_back('\\');
|
||||
s.push_back('v');
|
||||
break;
|
||||
case '\f':
|
||||
s.push_back('\\');
|
||||
s.push_back('f');
|
||||
break;
|
||||
case '\b':
|
||||
s.push_back('\\');
|
||||
s.push_back('b');
|
||||
break;
|
||||
case '\a':
|
||||
s.push_back('\\');
|
||||
s.push_back('a');
|
||||
break;
|
||||
case '\?':
|
||||
s.push_back('\\');
|
||||
s.push_back('?');
|
||||
break;
|
||||
default:
|
||||
{
|
||||
if(item >= ' ' && item <= '~')
|
||||
s.push_back(item);
|
||||
else
|
||||
{
|
||||
s.push_back('\\');
|
||||
s.push_back('x');
|
||||
s.push_back(HttpUtils::nibble_to_hex_char((uint8_t)((item >> 4) & 0x0F)));
|
||||
s.push_back(HttpUtils::nibble_to_hex_char((uint8_t)(item & 0x0F)));
|
||||
}
|
||||
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
s.push_back('\"');
|
||||
return s;
|
||||
}
|
||||
|
||||
int main(int argc,char** argv)
|
||||
{
|
||||
const char* error = NULL;
|
||||
const char* output = "WWWGen.hpp";
|
||||
const char* source = "wwwroot";
|
||||
bool enableScripts=true;
|
||||
bool enableListing=true;
|
||||
bool enableDefaultIndexes=true;
|
||||
bool help=false;
|
||||
|
||||
std::vector<std::string> indexes;
|
||||
|
||||
for(int i = 1;i<argc;i++)
|
||||
{
|
||||
if(strcmp(argv[i],"--help") == 0 || strcmp(argv[i],"-h") == 0)
|
||||
{
|
||||
help = true;
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
|
||||
if(strcmp(argv[i],"--disable-script") == 0)
|
||||
{
|
||||
enableScripts = false;
|
||||
}
|
||||
if(strcmp(argv[i],"--disable-listing") == 0)
|
||||
{
|
||||
enableListing = false;
|
||||
}
|
||||
if(strcmp(argv[i],"--disable-default-indexes") == 0)
|
||||
{
|
||||
enableDefaultIndexes = false;
|
||||
}
|
||||
|
||||
if(strcmp(argv[i],"-o") == 0 || strcmp(argv[i],"--output") == 0)
|
||||
{
|
||||
if(i+1<argc)
|
||||
{
|
||||
output = argv[i+1];
|
||||
i++;
|
||||
}
|
||||
else
|
||||
{
|
||||
error = "Ran out of arguments";
|
||||
help = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(strcmp(argv[i],"-s") == 0 || strcmp(argv[i],"--source") == 0)
|
||||
{
|
||||
if(i+1<argc)
|
||||
{
|
||||
source = argv[i+1];
|
||||
i++;
|
||||
}
|
||||
else
|
||||
{
|
||||
error = "Ran out of arguments";
|
||||
help = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(strcmp(argv[i],"-i") == 0 || strcmp(argv[i],"--index") == 0)
|
||||
{
|
||||
if(i+1<argc)
|
||||
{
|
||||
indexes.push_back(argv[i+1]);
|
||||
i++;
|
||||
}
|
||||
else
|
||||
{
|
||||
error = "Ran out of arguments";
|
||||
help = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if(help)
|
||||
{
|
||||
if(error != NULL)
|
||||
{
|
||||
printf("ERROR: %s\n", error);
|
||||
}
|
||||
printf("USAGE: %s [options]\n\n",argv[0]);
|
||||
printf("FLAGS:\n");
|
||||
printf("-h, --help\tShow this help screen\n");
|
||||
printf("--disable-script\tDisable .twss scripts from being ran\n");
|
||||
printf("--disable-listing\tDisable directory listing on server\n");
|
||||
printf("--disable-default-indexes\tDisable default index files \"index.html\", \"default.html\", \"index.htm\", \"default.htm\", \"index.twss\", \"default.twss\"\n");
|
||||
printf("\n");
|
||||
printf("OPTIONS:\n");
|
||||
printf("-o [header file], --output [header file]\t(defaults to \"WWWGen.hpp\") Specify the output header filename with extension, be aware this is also the class name (without extension of course so no spaces)\n");
|
||||
printf("-s [source dir], --source [source dir]\t(defaults to \"wwwroot\") Specify the source directory to convert\n");
|
||||
printf("-i [index file], --index [index file]\tSpecify custom index file such as index.html where going to / on server will resolve /index.html or /page will become /page/index.html, to use multiple files use this option again followed by filename\n");
|
||||
printf("\nIf you run this program without any arguments the directory \"wwwroot\" and output file \"WWWGen.hpp\" will be used and scripts WILL be able to run, users WILL be able to list directories without index files and these index filenames will be used \"index.html\", \"default.html\", \"index.htm\", \"default.htm\", \"index.twss\", \"default.twss\"\n");
|
||||
return 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
if(enableDefaultIndexes)
|
||||
{
|
||||
indexes.push_back("index.html");
|
||||
indexes.push_back("default.html");
|
||||
indexes.push_back("index.htm");
|
||||
indexes.push_back("default.htm");
|
||||
if(enableScripts)
|
||||
{
|
||||
indexes.push_back("index.twss");
|
||||
indexes.push_back("default.twss");
|
||||
}
|
||||
}
|
||||
|
||||
std::filesystem::path p(output);
|
||||
std::string name = p.filename().replace_extension("").string();
|
||||
|
||||
std::vector<Resource> resources;
|
||||
get_files(resources, indexes, enableListing,source,"/");
|
||||
|
||||
std::string cls = "#pragma once\n/* Generated via wwwgen */\n#include <string>\n#include <vector>\n#include <initializer_list>\n#include <filesystem>\n#include <tesseswebserver.hpp>\nclass " + name + "Resource {public: std::vector<uint8_t> data; std::string mime; std::string path; bool isScript; " + name + "Resource(std::string path, std::string mime,bool isScript, std::initializer_list<uint8_t> data) {this->path = path; this->mime = mime; this->isScript=isScript; this->data = data;} };\nclass " + name + " : public Tesses::WebServer::IServer {\n";
|
||||
|
||||
if(enableScripts)
|
||||
{
|
||||
cls.append("#if defined(USE_SCRIPT_ENGINE)\nTesses::WebServer::ScriptEngine::RootEnvironment* env;\nTesses::WebServer::ScriptEngine::BytecodeFile* initFile;\n#endif\n");
|
||||
cls.append("\nstd::vector<uint8_t>* get_script_file(std::filesystem::path p){ int i = get_file(p); if(i > -1) return &(resources[i].data); return nullptr; }\n");
|
||||
}
|
||||
cls.append("int get_file(std::filesystem::path p){ int index = 0; for(auto item : resources) { if(p.string() == item.path) return index; index++; } return -1; }");
|
||||
cls.append("std::filesystem::path sanitise(std::string name){std::filesystem::path p=\"/\"; auto path_parts = Tesses::WebServer::HttpUtils::SplitString(name.substr(1),\"/\");for(auto item : path_parts){auto decoded = Tesses::WebServer::HttpUtils::Sanitise(Tesses::WebServer::HttpUtils::UrlPathDecode(item));if(decoded == \"..\" || decoded == \".\") continue; p /= decoded;} return p;}\n");
|
||||
cls.append("std::vector<");
|
||||
cls.append(name);
|
||||
cls.append("Resource> resources;\n");
|
||||
cls.append("public:\n");
|
||||
cls.append(name);
|
||||
cls.append("(){\n");
|
||||
|
||||
for(auto item : resources)
|
||||
{
|
||||
cls.append("resources.push_back(");
|
||||
cls.append(name);
|
||||
cls.append("Resource(");
|
||||
cls.append(escape_string(item.path));
|
||||
cls.push_back(',');
|
||||
cls.append(escape_string(item.mime));
|
||||
cls.append(item.twss ? ",true," : ",false,");
|
||||
cls.append(item.data);
|
||||
cls.append("));\n");
|
||||
}
|
||||
|
||||
if(enableScripts)
|
||||
{
|
||||
cls.append("\n#if defined(USE_SCRIPT_ENGINE)\n");
|
||||
cls.append("env = new Tesses::WebServer::ScriptEngine::RootEnvironment();");
|
||||
cls.append("env->print = [](Tesses::WebServer::ScriptEngine::ScriptType t)->void {");
|
||||
cls.append("std::cout << \"[Script]: \" << Tesses::WebServer::ScriptEngine::ConvertToString(t) << std::endl;");
|
||||
cls.append("};");
|
||||
|
||||
if(file_exists(source,"init.twss"))
|
||||
{
|
||||
cls.append("Tesses::WebServer::ScriptEngine::ConstBufferReadFile readFile([this](std::filesystem::path p) -> std::vector<uint8_t>* { return get_script_file(p);});");
|
||||
cls.append("Tesses::WebServer::ScriptEngine::BytecodeCompiler bcc(Tesses::WebServer::ScriptEngine::ScriptParser::Parse(&readFile,\"/init.twss\"));");
|
||||
cls.append("bcc.Compile();");
|
||||
cls.append("this->initFile = bcc.file;auto rf = bcc.file->rootFunction;rf->env = env;rf->isRoot=true;for(auto f : bcc.file->functions){auto rf2 = f.second;rf2->env = env;rf2->isRoot=false;env->SetValue(f.first,Tesses::WebServer::ScriptEngine::ObjectType(f.second));}rf->Execute(env,{});");
|
||||
|
||||
}
|
||||
|
||||
cls.append("\n#endif\n");
|
||||
}
|
||||
cls.append("}");
|
||||
|
||||
cls.append("bool Handle(Tesses::WebServer::ServerContext* ctx){auto path=sanitise(ctx->path); int index = get_file(path); if(index == -1) return false;");
|
||||
|
||||
if(enableScripts)
|
||||
{
|
||||
cls.append("\n#if defined(USE_SCRIPT_ENGINE)\n");
|
||||
cls.append("if(resources[index].isScript) {");
|
||||
cls.append("auto myEnv = new Tesses::WebServer::ScriptEngine::RootEnvironment();");
|
||||
cls.append("myEnv->global = this->env;");
|
||||
cls.append("std::string str={};");
|
||||
cls.append("myEnv->print = [&str](Tesses::WebServer::ScriptEngine::ScriptType typ) -> void {");
|
||||
cls.append("str.append(Tesses::WebServer::ScriptEngine::ConvertToString(typ));");
|
||||
cls.append("};");
|
||||
cls.append("Tesses::WebServer::ScriptEngine::ConstBufferReadFile readFile([this](std::filesystem::path p) -> std::vector<uint8_t>* { return get_script_file(p);});");
|
||||
cls.append("Tesses::WebServer::ScriptEngine::BytecodeCompiler bcc(Tesses::WebServer::ScriptEngine::ScriptParser::Parse(&readFile,resources[index].path));");
|
||||
cls.append("bcc.Compile();");
|
||||
cls.append("auto rf = bcc.file->rootFunction;");
|
||||
cls.append("rf->env = myEnv;");
|
||||
cls.append("rf->isRoot=true;");
|
||||
cls.append("for(auto f : bcc.file->functions)");
|
||||
cls.append("{");
|
||||
cls.append("auto rf2 = f.second;");
|
||||
cls.append("rf2->env = myEnv;");
|
||||
cls.append("rf2->isRoot=false;");
|
||||
cls.append("env->SetValue(f.first,Tesses::WebServer::ScriptEngine::ObjectType(f.second));");
|
||||
cls.append("}");
|
||||
cls.append("myEnv->RegisterHttpFuncs(ctx);");
|
||||
cls.append("rf->Execute(myEnv,{});");
|
||||
cls.append("delete bcc.file;");
|
||||
cls.append("delete myEnv;");
|
||||
cls.append("ctx->SetContentType(\"text/html\")->SendText(str);");
|
||||
|
||||
cls.append("}else{\n#endif\n");
|
||||
}
|
||||
|
||||
cls.append("ctx->SetContentType(resources[index].mime)->SendBytes(resources[index].data.data(),resources[index].data.size());");
|
||||
|
||||
if(enableScripts)
|
||||
{
|
||||
cls.append("\n#if defined(USE_SCRIPT_ENGINE)\n}\n#endif\n");
|
||||
}
|
||||
|
||||
cls.append("return true;}");
|
||||
|
||||
if(enableScripts){
|
||||
cls.append("~");
|
||||
cls.append(name);
|
||||
cls.append("(){\n#if defined(USE_SCRIPT_ENGINE)\n");
|
||||
|
||||
if(file_exists(source,"deinit.twss"))
|
||||
{
|
||||
cls.append("Tesses::WebServer::ScriptEngine::ConstBufferReadFile readFile([this](std::filesystem::path p) -> std::vector<uint8_t>* { return get_script_file(p);});");
|
||||
cls.append("Tesses::WebServer::ScriptEngine::BytecodeCompiler bcc(Tesses::WebServer::ScriptEngine::ScriptParser::Parse(&readFile,\"/deinit.twss\"));");
|
||||
cls.append("bcc.Compile();");
|
||||
cls.append("auto rf = bcc.file->rootFunction;rf->env = env;rf->isRoot=true;for(auto f : bcc.file->functions){auto rf2 = f.second;rf2->env = env;rf2->isRoot=false;env->SetValue(f.first,Tesses::WebServer::ScriptEngine::ObjectType(f.second));}rf->Execute(env,{});");
|
||||
cls.append("delete bcc.file;");
|
||||
}
|
||||
cls.append("delete initFile;");
|
||||
cls.append("delete env;");
|
||||
cls.append("\n#endif\n}");
|
||||
}
|
||||
|
||||
cls.append("};");
|
||||
|
||||
|
||||
std::ofstream strm(output,std::ofstream::binary);
|
||||
|
||||
strm << cls << "\n";
|
||||
}
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,103 @@
|
|||
#include "WWWGen.hpp"
|
||||
|
||||
#if defined(GEKKO)
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <gccore.h>
|
||||
#include <fat.h>
|
||||
static void *xfb = NULL;
|
||||
static GXRModeObj *rmode = NULL;
|
||||
#endif
|
||||
TESSESWEBSERVER_STATIC_DECLARATION
|
||||
using namespace Tesses::WebServer;
|
||||
using namespace Tesses::WebServer::ScriptEngine;
|
||||
|
||||
class DummyServer : public IServer
|
||||
{
|
||||
public:
|
||||
bool Handle(ServerContext* ctx)
|
||||
{
|
||||
std::string resp = {};
|
||||
|
||||
for(auto param : ctx->queryParams.GetAll())
|
||||
{
|
||||
resp.append(param.first);
|
||||
resp.append(": ");
|
||||
resp.append(param.second);
|
||||
resp.append("\r\n");
|
||||
}
|
||||
|
||||
ctx->SetContentType("text/plain")->SendText(resp);
|
||||
return true;
|
||||
}
|
||||
};
|
||||
#if defined(GEKKO)
|
||||
void resetWii(u32 irq, void* ctx)
|
||||
{
|
||||
HttpServerListener::StopViaInterrupt(0);
|
||||
}
|
||||
#endif
|
||||
int main(int argc,char** argv)
|
||||
{
|
||||
|
||||
#if defined(GEKKO)
|
||||
fatInitDefault();
|
||||
// Initialise the video system
|
||||
VIDEO_Init();
|
||||
|
||||
// This function initialises the attached controllers
|
||||
|
||||
// Obtain the preferred video mode from the system
|
||||
// This will correspond to the settings in the Wii menu
|
||||
rmode = VIDEO_GetPreferredMode(NULL);
|
||||
|
||||
// Allocate memory for the display in the uncached region
|
||||
xfb = MEM_K0_TO_K1(SYS_AllocateFramebuffer(rmode));
|
||||
|
||||
// Initialise the console, required for printf
|
||||
console_init(xfb,20,20,rmode->fbWidth,rmode->xfbHeight,rmode->fbWidth*VI_DISPLAY_PIX_SZ);
|
||||
|
||||
// Set up the video registers with the chosen mode
|
||||
VIDEO_Configure(rmode);
|
||||
|
||||
// Tell the video hardware where our display memory is
|
||||
VIDEO_SetNextFramebuffer(xfb);
|
||||
|
||||
// Make the display visible
|
||||
VIDEO_SetBlack(false);
|
||||
|
||||
// Flush the video register changes to the hardware
|
||||
VIDEO_Flush();
|
||||
|
||||
// Wait for Video setup to complete
|
||||
VIDEO_WaitVSync();
|
||||
if(rmode->viTVMode&VI_NON_INTERLACE) VIDEO_WaitVSync();
|
||||
|
||||
|
||||
// The console understands VT terminal escape codes
|
||||
// This positions the cursor on row 2, column 0
|
||||
// we can use variables for this with format codes too
|
||||
// e.g. printf ("\x1b[%d;%dH", row, column );
|
||||
printf("\x1b[2;0H");
|
||||
|
||||
SYS_SetResetCallback(resetWii);
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
HttpServerListener::Init();
|
||||
|
||||
WWWGen* myServer = new WWWGen();
|
||||
|
||||
HttpServerListener::Listen(myServer,2003/*new SSLCerts("/etc/letsencrypt/live2")*/);
|
||||
|
||||
HttpServerListener::WaitTillInterrupted();
|
||||
|
||||
delete myServer;
|
||||
|
||||
|
||||
|
||||
HttpServerListener::FreeServer();
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,15 @@
|
|||
<!--tws
|
||||
id = query_first("id");
|
||||
if(id)
|
||||
{
|
||||
var name = "";
|
||||
index = id.toLong();
|
||||
if(index >= 0 && index < (global todos).count)
|
||||
{
|
||||
(global todos).removeat(index);
|
||||
global save();
|
||||
}
|
||||
|
||||
}
|
||||
redirect("/");
|
||||
-->
|
|
@ -0,0 +1,39 @@
|
|||
<!--tws
|
||||
id = query_first("id");
|
||||
if(id)
|
||||
{
|
||||
var name = "";
|
||||
index = id.toLong();
|
||||
if(index >= 0 && index < (global todos).count)
|
||||
{
|
||||
name = htmlencode((global todos)[index]);
|
||||
}
|
||||
|
||||
--><!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Delete <!--tws print name;
|
||||
-->?</title>
|
||||
</head>
|
||||
<body>
|
||||
<h1>Delete <!--tws print name;-->?</h1>
|
||||
<a href="./delete-confirm.twss?id=<!--tws print id; -->">Yes</a> | <a href="../">No</a>
|
||||
</body>
|
||||
</html>
|
||||
<!--tws}else{-->
|
||||
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>No Id</title>
|
||||
</head>
|
||||
<body>
|
||||
<h1>No Id</h1>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
<!--tws}-->
|
Loading…
Reference in New Issue