zaela-Server/world/eqw_parser.cpp

349 lines
9.3 KiB
C++
Raw Permalink Normal View History

2013-05-09 10:44:08 -04:00
/* EQEMu: Everquest Server Emulator
Copyright (C) 2001-2006 EQEMu Development Team (http://eqemulator.net)
2013-02-16 16:14:39 -08:00
2013-05-09 10:44:08 -04:00
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License.
2013-05-06 13:07:41 -04:00
2013-05-09 10:44:08 -04:00
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY except by those people which sell it, which
2013-02-16 16:14:39 -08:00
are required to give you total support for your newly bought product;
without even the implied warranty of MERCHANTABILITY or FITNESS FOR
2013-05-09 10:44:08 -04:00
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
2013-05-06 13:07:41 -04:00
2013-05-09 10:44:08 -04:00
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
2013-02-16 16:14:39 -08:00
*/
//a lot of this is copied from embperl.cpp, but I didnt feel like factoring the common stuff out
#ifdef EMBPERL
#include "../common/global_define.h"
2014-08-21 23:30:09 -07:00
#include "eqw_parser.h"
#include "eqw.h"
2014-08-21 17:26:32 -07:00
#include "../common/eqdb.h"
2015-01-18 04:03:45 -06:00
2013-02-16 16:14:39 -08:00
#include "worlddb.h"
#ifndef GvCV_set
2013-05-09 10:44:08 -04:00
#define GvCV_set(gv,cv) (GvCV(gv) = (cv))
2013-02-16 16:14:39 -08:00
#endif
XS(XS_EQWIO_PRINT);
//so embedded scripts can use xs extensions (ala 'use socket;')
EXTERN_C void boot_DynaLoader(pTHX_ CV* cv);
EXTERN_C XS(boot_EQW);
EXTERN_C XS(boot_EQDB);
EXTERN_C XS(boot_EQDBRes);
EXTERN_C XS(boot_HTTPRequest);
EXTERN_C XS(boot_EQLConfig);
2013-05-06 13:07:41 -04:00
EXTERN_C void xs_init(pTHX)
2013-02-16 16:14:39 -08:00
{
char file[256];
strncpy(file, __FILE__, 256);
file[255] = '\0';
2013-05-06 13:07:41 -04:00
2013-02-16 16:14:39 -08:00
char buf[128]; //shouldent have any function names longer than this.
2013-05-06 13:07:41 -04:00
2013-02-16 16:14:39 -08:00
//add the strcpy stuff to get rid of const warnings....
2013-05-06 13:07:41 -04:00
2013-02-16 16:14:39 -08:00
newXS(strcpy(buf, "DynaLoader::boot_DynaLoader"), boot_DynaLoader, file);
newXS(strcpy(buf, "EQW::boot_EQW"), boot_EQW, file);
newXS(strcpy(buf, "EQDB::boot_EQDB"), boot_EQDB, file);
newXS(strcpy(buf, "EQDBRes::boot_EQDBRes"), boot_EQDBRes, file);
newXS(strcpy(buf, "HTTPRequest::boot_HTTPRequest"), boot_HTTPRequest, file);
newXS(strcpy(buf, "EQLConfig::boot_EQLConfig"), boot_EQLConfig, file);
newXS(strcpy(buf, "EQWIO::PRINT"), XS_EQWIO_PRINT, file);
}
EQWParser::EQWParser() {
//setup perl...
my_perl = perl_alloc();
_empty_sv = newSV(0);
if (!my_perl) {
LogInfo("Error: perl_alloc failed!");
}
else {
2013-02-16 16:14:39 -08:00
DoInit();
}
2013-02-16 16:14:39 -08:00
}
void EQWParser::DoInit() {
const char *argv_eqemu[] = { "",
"-w", "-W",
2013-05-04 18:06:58 -07:00
"-e", "0;", nullptr };
2013-02-16 16:14:39 -08:00
int argc = 5;
char **argv = (char **)argv_eqemu;
2013-05-04 18:06:58 -07:00
char **env = { nullptr };
2013-02-16 16:14:39 -08:00
PL_perl_destruct_level = 1;
perl_construct(my_perl);
PERL_SYS_INIT3(&argc, &argv, &env);
perl_parse(my_perl, xs_init, argc, argv, env);
perl_run(my_perl);
2013-05-06 13:07:41 -04:00
2013-02-16 16:14:39 -08:00
//a little routine we use a lot.
eval_pv("sub my_eval {eval $_[0];}", TRUE); //dies on error
2013-05-06 13:07:41 -04:00
2013-02-16 16:14:39 -08:00
//ruin the perl exit and command:
eval_pv("sub my_exit {}",TRUE);
eval_pv("sub my_sleep {}",TRUE);
if(gv_stashpv("CORE::GLOBAL", FALSE)) {
GV *exitgp = gv_fetchpv("CORE::GLOBAL::exit", TRUE, SVt_PVCV);
GvCV_set(exitgp, perl_get_cv("my_exit", TRUE)); //dies on error
GvIMPORTED_CV_on(exitgp);
GV *sleepgp = gv_fetchpv("CORE::GLOBAL::sleep", TRUE, SVt_PVCV);
GvCV_set(sleepgp, perl_get_cv("my_sleep", TRUE)); //dies on error
GvIMPORTED_CV_on(sleepgp);
}
2013-05-06 13:07:41 -04:00
2013-02-16 16:14:39 -08:00
//setup eval_file
eval_pv(
"our %Cache;"
"use Symbol qw(delete_package);"
"sub eval_file {"
"my($package, $filename) = @_;"
"$filename=~s/\'//g;"
"if(! -r $filename) { print \"Unable to read perl file '$filename'\\n\"; return; }"
"my $mtime = -M $filename;"
"if(defined $Cache{$package}{mtime}&&$Cache{$package}{mtime} <= $mtime && !($package eq 'plugin')){"
" return;"
"} else {"
//we 'my' $filename,$mtime,$package,$sub to prevent them from changing our state up here.
" eval(\"package $package; my(\\$filename,\\$mtime,\\$package,\\$sub); \\$isloaded = 1; require '$filename'; \");"
"}"
"}"
,FALSE);
2013-05-06 13:07:41 -04:00
2013-02-16 16:14:39 -08:00
//make a tie-able class to capture IO and get it where it needs to go
eval_pv(
"package EQWIO; "
// "&boot_EQEmuIO;"
2013-05-09 10:44:08 -04:00
"sub TIEHANDLE { my $me = bless {}, $_[0]; $me->PRINT('Creating '.$me); return($me); } "
"sub WRITE { } "
"sub PRINTF { my $me = shift; my $fmt = shift; $me->PRINT(sprintf($fmt, @_)); } "
"sub CLOSE { my $me = shift; $me->PRINT('Closing '.$me); } "
"sub DESTROY { my $me = shift; $me->PRINT('Destroying '.$me); } "
2013-02-16 16:14:39 -08:00
//this ties us for all packages
2013-05-09 10:44:08 -04:00
"package MAIN;"
" if(tied *STDOUT) { untie(*STDOUT); }"
" if(tied *STDERR) { untie(*STDERR); }"
" tie *STDOUT, 'EQWIO';"
" tie *STDERR, 'EQWIO';"
,FALSE);
2013-05-06 13:07:41 -04:00
2013-02-16 16:14:39 -08:00
eval_pv(
"package world; "
,FALSE
);
2013-05-06 13:07:41 -04:00
2013-02-16 16:14:39 -08:00
//make sure the EQW pointer is set up in this package
EQW *curc = EQW::Singleton();
SV *l = get_sv("world::EQW", true);
2013-05-04 18:06:58 -07:00
if(curc != nullptr) {
2013-02-16 16:14:39 -08:00
sv_setref_pv(l, "EQW", curc);
} else {
//clear out the value, mainly to get rid of blessedness
sv_setsv(l, _empty_sv);
}
2013-05-06 13:07:41 -04:00
2013-02-16 16:14:39 -08:00
//make sure the EQDB pointer is set up in this package
EQDB::SetMySQL(database.getMySQL());
EQDB *curc_db = EQDB::Singleton();
SV *l_db = get_sv("world::EQDB", true);
2013-05-04 18:06:58 -07:00
if(curc_db != nullptr) {
2013-02-16 16:14:39 -08:00
sv_setref_pv(l_db, "EQDB", curc_db);
} else {
//clear out the value, mainly to get rid of blessedness
sv_setsv(l_db, _empty_sv);
}
2013-05-06 13:07:41 -04:00
2013-02-16 16:14:39 -08:00
//load up EQW
eval_pv(
2013-05-09 10:44:08 -04:00
"package EQW;"
"&boot_EQW;" //load our EQW XS
"package EQDB;"
"&boot_EQDB;" //load our EQW XS
"package EQDBRes;"
"&boot_EQDBRes;" //load our EQW XS
"package HTTPRequest;"
"&boot_HTTPRequest;" //load our HTTPRequest XS
"package EQLConfig;"
"&boot_EQLConfig;" //load our EQLConfig XS
2013-02-16 16:14:39 -08:00
, FALSE );
2013-05-06 13:07:41 -04:00
2013-02-16 16:14:39 -08:00
#ifdef EMBPERL_PLUGIN
LogInfo("Loading worldui perl plugins");
std::string err;
2013-02-16 16:14:39 -08:00
if(!eval_file("world", "worldui.pl", err)) {
LogInfo("Warning - world.pl: [{}]", err.c_str());
2013-02-16 16:14:39 -08:00
}
2013-05-06 13:07:41 -04:00
2013-02-16 16:14:39 -08:00
eval_pv(
"package world; "
"if(opendir(D,'worldui')) { "
" my @d = readdir(D);"
" closedir(D);"
" foreach(@d){ "
" next unless(/\\.pl$); "
" require 'templates/'.$_;"
" }"
"}"
,FALSE);
#endif //EMBPERL_PLUGIN
}
EQWParser::~EQWParser() {
//removed to try to stop perl from exploding on reload, we'll see
/* eval_pv(
"package quest;"
" untie *STDOUT;"
" untie *STDERR;"
2013-05-09 10:44:08 -04:00
,FALSE);
2013-02-16 16:14:39 -08:00
*/
perl_free(my_perl);
}
bool EQWParser::eval_file(const char * packagename, const char * filename, std::string &error)
{
std::vector<std::string> args;
args.push_back(packagename);
args.push_back(filename);
return(dosub("eval_file", args, error));
}
bool EQWParser::dosub(const char * subname, const std::vector<std::string> &args, std::string &error, int mode) {
2013-02-16 16:14:39 -08:00
bool err = false;
2013-05-09 10:44:08 -04:00
dSP; // initialize stack pointer
ENTER; // everything created after here
SAVETMPS; // ...is a temporary variable
PUSHMARK(SP); // remember the stack pointer
if(!args.empty())
2013-02-16 16:14:39 -08:00
{
for (auto i = args.begin(); i != args.end(); ++i) { /* push the arguments onto the perl stack */
2013-05-06 13:07:41 -04:00
XPUSHs(sv_2mortal(newSVpv(i->c_str(), i->length())));
2013-02-16 16:14:39 -08:00
}
}
2013-05-09 10:44:08 -04:00
PUTBACK; // make local stack pointer global
call_pv(subname, mode); /*eval our code*/
SPAGAIN; // refresh stack pointer
2013-02-16 16:14:39 -08:00
if(SvTRUE(ERRSV)) {
err = true;
}
2013-05-09 10:44:08 -04:00
FREETMPS; // free temp values
LEAVE; // ...and the XPUSHed "mortal" args.
2013-05-06 13:07:41 -04:00
2013-02-16 16:14:39 -08:00
if(err) {
error = "Perl runtime error: ";
error += SvPVX(ERRSV);
return(false);
}
return(true);
}
bool EQWParser::eval(const char * code, std::string &error) {
2013-02-16 16:14:39 -08:00
std::vector<std::string> arg;
arg.push_back(code);
return(dosub("my_eval", arg, error, G_SCALAR|G_DISCARD|G_EVAL|G_KEEPERR));
}
void EQWParser::EQW_eval(const char *pkg, const char *code) {
char namebuf[64];
2013-05-06 13:07:41 -04:00
2013-02-16 16:14:39 -08:00
snprintf(namebuf, 64, "package %s;", pkg);
eval_pv(namebuf, FALSE);
2013-05-06 13:07:41 -04:00
2013-02-16 16:14:39 -08:00
//make sure the EQW pointer is set up
EQW *curc = EQW::Singleton();
snprintf(namebuf, 64, "EQW");
// snprintf(namebuf, 64, "%s::EQW", pkg);
SV *l = get_sv(namebuf, true);
2013-05-04 18:06:58 -07:00
if(curc != nullptr) {
2013-02-16 16:14:39 -08:00
sv_setref_pv(l, "EQW", curc);
} else {
//clear out the value, mainly to get rid of blessedness
sv_setsv(l, _empty_sv);
}
//make sure the EQDB pointer is set up
EQDB *curc_db = EQDB::Singleton();
snprintf(namebuf, 64, "EQDB");
// snprintf(namebuf, 64, "%s::EQW", pkg);
SV *l_db = get_sv(namebuf, true);
2013-05-04 18:06:58 -07:00
if(curc_db != nullptr) {
2013-02-16 16:14:39 -08:00
sv_setref_pv(l_db, "EQDB", curc_db);
} else {
//clear out the value, mainly to get rid of blessedness
sv_setsv(l_db, _empty_sv);
}
2013-05-06 13:07:41 -04:00
std::string err;
2013-02-16 16:14:39 -08:00
if(!eval(code, err)) {
EQW::Singleton()->AppendOutput(err.c_str());
}
}
void EQWParser::SetHTTPRequest(const char *pkg, HTTPRequest *it) {
char namebuf[64];
2013-05-06 13:07:41 -04:00
2013-02-16 16:14:39 -08:00
snprintf(namebuf, 64, "package %s;", pkg);
eval_pv(namebuf, FALSE);
2013-05-06 13:07:41 -04:00
2013-02-16 16:14:39 -08:00
snprintf(namebuf, 64, "request");
// snprintf(namebuf, 64, "%s::EQW", pkg);
SV *l = get_sv(namebuf, true);
2013-05-04 18:06:58 -07:00
if(it != nullptr) {
2013-02-16 16:14:39 -08:00
sv_setref_pv(l, "HTTPRequest", it);
} else {
//clear out the value, mainly to get rid of blessedness
sv_setsv(l, _empty_sv);
}
}
/*
$editors = array();
$editors["merchant"] = new MerchantEditor();
#... for other editors
if(defined($editors[$editor])) {
$edit = $editors[$editor];
$edit->dispatch($action);
}
class MerchantEditor extends BaseEditor {
MerchantEditor() {
$this->RegisterAction(0, "get_merchantlist", "merchant/merchant.tmpl.php", "no");
$this->RegisterAction(1, "get_merchantlist", "merchant/merchant.edit.tmpl.php", "no");
}
}
function dispatch() {
my $dispatcher = $this->_dispatchers[$action];
$body = new Template($dispatcher["template"]);
my $proc = $dispatcher["proc"];
$vars = $this->$proc();
if($dispatcher["guestmode"] == "no") {
check_authorization();
}
if ($vars) {
foreach ($vars as $key=>$value) {
$body->set($key, $value);
}
}
}
*/
#endif //EMBPERL
2013-05-09 10:44:08 -04:00