2012-02-10 14:53:55 +00:00
|
|
|
/**
|
|
|
|
* javascript.cpp
|
|
|
|
* This file is part of the YATE Project http://YATE.null.ro
|
|
|
|
*
|
2012-02-17 16:19:17 +00:00
|
|
|
* Javascript channel support based on libyscript
|
2012-02-10 14:53:55 +00:00
|
|
|
*
|
|
|
|
* Yet Another Telephony Engine - a fully featured software PBX and IVR
|
2014-02-05 11:42:17 +00:00
|
|
|
* Copyright (C) 2011-2014 Null Team
|
2012-02-10 14:53:55 +00:00
|
|
|
*
|
2013-08-06 13:38:10 +00:00
|
|
|
* This software is distributed under multiple licenses;
|
|
|
|
* see the COPYING file in the main directory for licensing
|
|
|
|
* information for this specific distribution.
|
|
|
|
*
|
|
|
|
* This use of this software may be subject to additional restrictions.
|
|
|
|
* See the LEGAL file in the main directory for details.
|
2012-02-10 14:53:55 +00:00
|
|
|
*
|
|
|
|
* This program is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
2013-08-06 13:38:10 +00:00
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
2012-02-10 14:53:55 +00:00
|
|
|
*/
|
|
|
|
|
2012-02-17 16:19:17 +00:00
|
|
|
#include <yatepbx.h>
|
2012-02-10 14:53:55 +00:00
|
|
|
#include <yatescript.h>
|
2012-12-21 10:21:16 +00:00
|
|
|
#include <yatexml.h>
|
2012-02-10 14:53:55 +00:00
|
|
|
|
2013-04-12 12:46:21 +00:00
|
|
|
#define NATIVE_TITLE "[native code]"
|
|
|
|
|
2013-04-12 14:00:39 +00:00
|
|
|
#define MIN_CALLBACK_INTERVAL Thread::idleMsec()
|
|
|
|
|
2020-02-21 14:41:19 +00:00
|
|
|
#define CALL_NATIVE_METH_STR(obj,meth) \
|
|
|
|
if (YSTRING(#meth) == oper.name()) { \
|
|
|
|
ExpEvaluator::pushOne(stack,new ExpOperation((obj).meth())); \
|
|
|
|
return true; \
|
|
|
|
}
|
|
|
|
#define CALL_NATIVE_METH_INT(obj,meth) \
|
|
|
|
if (YSTRING(#meth) == oper.name()) { \
|
|
|
|
ExpEvaluator::pushOne(stack,new ExpOperation((int64_t)(obj).meth())); \
|
|
|
|
return true; \
|
|
|
|
}
|
|
|
|
|
2012-02-10 14:53:55 +00:00
|
|
|
using namespace TelEngine;
|
|
|
|
namespace { // anonymous
|
|
|
|
|
2022-01-11 09:02:56 +00:00
|
|
|
static inline void pushStackResNull(ObjList& stack, ExpOperation* oper)
|
|
|
|
{
|
|
|
|
if (oper)
|
|
|
|
ExpEvaluator::pushOne(stack,oper);
|
|
|
|
else
|
|
|
|
ExpEvaluator::pushOne(stack,JsParser::nullClone());
|
|
|
|
}
|
|
|
|
|
2021-10-27 10:22:53 +00:00
|
|
|
// Temporary class used to store an object from received parameter or build a new one to be used
|
|
|
|
// Safely release created object
|
|
|
|
template <class Obj> class ExpOpTmpObj
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
inline ExpOpTmpObj(Obj* obj, ExpOperation& op)
|
|
|
|
: m_obj(obj), m_del(!m_obj)
|
|
|
|
{ if (m_del) m_obj = new Obj(op); }
|
|
|
|
inline ~ExpOpTmpObj()
|
|
|
|
{ if (m_del) TelEngine::destruct(m_obj); }
|
|
|
|
inline Obj* operator->() const
|
|
|
|
{ return m_obj; }
|
|
|
|
inline Obj& operator*() const
|
|
|
|
{ return *m_obj; }
|
|
|
|
private:
|
|
|
|
inline ExpOpTmpObj() : m_obj(0), m_del(false) {}
|
|
|
|
Obj* m_obj;
|
|
|
|
bool m_del;
|
|
|
|
};
|
|
|
|
|
2022-01-11 09:02:56 +00:00
|
|
|
#define JS_EXP_OP_TMP_OBJ(T) \
|
|
|
|
class T##TmpParam : public ExpOpTmpObj<T> \
|
|
|
|
{ public: inline T##TmpParam(ExpOperation& op) : ExpOpTmpObj(YOBJECT(T,&op),op) {} }
|
|
|
|
|
|
|
|
JS_EXP_OP_TMP_OBJ(JPath);
|
|
|
|
JS_EXP_OP_TMP_OBJ(XPath);
|
|
|
|
|
|
|
|
#undef JS_EXP_OP_TMP_OBJ
|
2021-10-27 10:22:53 +00:00
|
|
|
|
2020-04-01 11:47:55 +00:00
|
|
|
static inline void dumpTraceToMsg(Message* msg, ObjList* lst)
|
|
|
|
{
|
|
|
|
if (!(msg && lst))
|
|
|
|
return;
|
|
|
|
unsigned int count = msg->getIntValue(YSTRING("trace_msg_count"),0);
|
|
|
|
static String s_tracePref = "trace_msg_";
|
|
|
|
for (ObjList* o = lst->skipNull(); o; o = o->skipNext()) {
|
|
|
|
String* s = static_cast<String*>(o->get());
|
|
|
|
if (TelEngine::null(s))
|
|
|
|
continue;
|
|
|
|
msg->setParam(s_tracePref + String(count++),*s);
|
|
|
|
}
|
|
|
|
msg->setParam(YSTRING("trace_msg_count"),String(count));
|
|
|
|
}
|
|
|
|
|
2013-04-12 14:00:39 +00:00
|
|
|
class JsEngineWorker;
|
|
|
|
class JsEngine;
|
|
|
|
|
2012-02-17 16:19:17 +00:00
|
|
|
class JsModule : public ChanAssistList
|
2012-02-10 14:53:55 +00:00
|
|
|
{
|
|
|
|
public:
|
2012-02-17 16:19:17 +00:00
|
|
|
enum {
|
2016-01-04 12:49:52 +00:00
|
|
|
Preroute = AssistPrivate,
|
|
|
|
EngStart,
|
2012-02-17 16:19:17 +00:00
|
|
|
};
|
|
|
|
JsModule();
|
|
|
|
virtual ~JsModule();
|
2012-02-10 14:53:55 +00:00
|
|
|
virtual void initialize();
|
2012-02-17 16:19:17 +00:00
|
|
|
virtual void init(int priority);
|
|
|
|
virtual ChanAssist* create(Message& msg, const String& id);
|
2012-02-10 14:53:55 +00:00
|
|
|
bool unload();
|
2012-02-17 16:19:17 +00:00
|
|
|
virtual bool received(Message& msg, int id);
|
|
|
|
virtual bool received(Message& msg, int id, ChanAssist* assist);
|
2015-11-12 21:29:55 +00:00
|
|
|
void msgPostExecute(const Message& msg, bool handled);
|
2012-02-17 16:19:17 +00:00
|
|
|
inline JsParser& parser()
|
|
|
|
{ return m_assistCode; }
|
2012-02-10 14:53:55 +00:00
|
|
|
protected:
|
2012-07-02 11:55:34 +00:00
|
|
|
virtual void statusParams(String& str);
|
2012-02-10 14:53:55 +00:00
|
|
|
virtual bool commandExecute(String& retVal, const String& line);
|
|
|
|
virtual bool commandComplete(Message& msg, const String& partLine, const String& partWord);
|
2012-02-17 16:19:17 +00:00
|
|
|
private:
|
2013-04-12 12:41:47 +00:00
|
|
|
bool evalContext(String& retVal, const String& cmd, ScriptContext* context = 0);
|
2015-11-12 21:29:55 +00:00
|
|
|
void clearPostHook();
|
2012-02-17 16:19:17 +00:00
|
|
|
JsParser m_assistCode;
|
2015-11-12 21:29:55 +00:00
|
|
|
MessagePostHook* m_postHook;
|
2016-01-04 12:49:52 +00:00
|
|
|
bool m_started;
|
2012-02-10 14:53:55 +00:00
|
|
|
};
|
|
|
|
|
2012-06-18 13:52:21 +00:00
|
|
|
INIT_PLUGIN(JsModule);
|
|
|
|
|
2012-06-20 14:02:18 +00:00
|
|
|
class JsMessage;
|
|
|
|
|
2012-02-17 16:19:17 +00:00
|
|
|
class JsAssist : public ChanAssist
|
|
|
|
{
|
|
|
|
public:
|
2012-05-02 15:11:48 +00:00
|
|
|
enum State {
|
2012-06-20 14:02:18 +00:00
|
|
|
NotStarted,
|
2012-05-02 15:11:48 +00:00
|
|
|
Routing,
|
|
|
|
ReRoute,
|
2012-06-20 14:02:18 +00:00
|
|
|
Ended,
|
|
|
|
Hangup
|
2012-05-02 15:11:48 +00:00
|
|
|
};
|
2012-02-17 16:19:17 +00:00
|
|
|
inline JsAssist(ChanAssistList* list, const String& id, ScriptRun* runner)
|
2012-06-20 14:02:18 +00:00
|
|
|
: ChanAssist(list, id),
|
2014-02-26 14:51:15 +00:00
|
|
|
m_runner(runner), m_state(NotStarted), m_handled(false), m_repeat(false)
|
2012-02-17 16:19:17 +00:00
|
|
|
{ }
|
|
|
|
virtual ~JsAssist();
|
|
|
|
virtual void msgStartup(Message& msg);
|
|
|
|
virtual void msgHangup(Message& msg);
|
|
|
|
virtual void msgExecute(Message& msg);
|
2012-06-20 15:54:43 +00:00
|
|
|
virtual bool msgRinging(Message& msg);
|
|
|
|
virtual bool msgAnswered(Message& msg);
|
2012-02-17 16:19:17 +00:00
|
|
|
virtual bool msgPreroute(Message& msg);
|
|
|
|
virtual bool msgRoute(Message& msg);
|
|
|
|
virtual bool msgDisconnect(Message& msg, const String& reason);
|
2015-11-12 21:29:55 +00:00
|
|
|
void msgPostExecute(const Message& msg, bool handled);
|
2012-02-17 16:19:17 +00:00
|
|
|
bool init();
|
2020-10-21 11:01:31 +00:00
|
|
|
bool evalAllocations(String& retVal, unsigned int top);
|
2012-06-22 09:38:51 +00:00
|
|
|
inline State state() const
|
|
|
|
{ return m_state; }
|
|
|
|
inline const char* stateName() const
|
|
|
|
{ return stateName(m_state); }
|
|
|
|
inline void end()
|
2014-02-26 14:51:15 +00:00
|
|
|
{ m_repeat = false; if (m_state < Ended) m_state = Ended; }
|
2012-06-20 14:02:18 +00:00
|
|
|
inline JsMessage* message()
|
|
|
|
{ return m_message; }
|
2012-06-22 09:38:51 +00:00
|
|
|
inline void handled()
|
2014-02-26 14:51:15 +00:00
|
|
|
{ m_repeat = false; m_handled = true; }
|
2013-04-12 12:41:47 +00:00
|
|
|
inline ScriptContext* context()
|
|
|
|
{ return m_runner ? m_runner->context() : 0; }
|
2012-06-22 09:38:51 +00:00
|
|
|
Message* getMsg(ScriptRun* runner) const;
|
|
|
|
static const char* stateName(State st);
|
2012-02-17 16:19:17 +00:00
|
|
|
private:
|
2015-11-12 21:29:55 +00:00
|
|
|
bool runFunction(const String& name, Message& msg, bool* handled = 0);
|
2012-06-20 14:02:18 +00:00
|
|
|
bool runScript(Message* msg, State newState);
|
|
|
|
bool setMsg(Message* msg);
|
2012-07-24 10:31:12 +00:00
|
|
|
void clearMsg(bool fromChannel);
|
2012-02-17 16:19:17 +00:00
|
|
|
ScriptRun* m_runner;
|
2012-05-02 15:11:48 +00:00
|
|
|
State m_state;
|
2012-06-20 14:02:18 +00:00
|
|
|
bool m_handled;
|
2014-02-26 14:51:15 +00:00
|
|
|
bool m_repeat;
|
2012-06-20 14:02:18 +00:00
|
|
|
RefPointer<JsMessage> m_message;
|
2012-02-17 16:19:17 +00:00
|
|
|
};
|
|
|
|
|
2012-06-16 23:21:13 +00:00
|
|
|
class JsGlobal : public NamedString
|
|
|
|
{
|
|
|
|
public:
|
2014-10-16 12:39:59 +00:00
|
|
|
JsGlobal(const char* scriptName, const char* fileName, bool relPath = true, bool fromCfg = true);
|
2012-06-16 23:21:13 +00:00
|
|
|
virtual ~JsGlobal();
|
2019-12-19 12:21:42 +00:00
|
|
|
bool load();
|
2012-06-16 23:21:13 +00:00
|
|
|
bool fileChanged(const char* fileName) const;
|
|
|
|
inline JsParser& parser()
|
|
|
|
{ return m_jsCode; }
|
|
|
|
inline ScriptContext* context()
|
|
|
|
{ return m_context; }
|
2015-01-30 13:39:52 +00:00
|
|
|
inline const String& fileName()
|
|
|
|
{ return m_file; }
|
2012-06-16 23:21:13 +00:00
|
|
|
bool runMain();
|
|
|
|
static void markUnused();
|
|
|
|
static void freeUnused();
|
2014-10-16 12:39:59 +00:00
|
|
|
static void reloadDynamic();
|
2014-12-09 11:33:04 +00:00
|
|
|
static bool initScript(const String& scriptName, const String& fileName, bool relPath = true, bool fromCfg = true);
|
2012-11-01 14:58:46 +00:00
|
|
|
static bool reloadScript(const String& scriptName);
|
2016-01-04 12:49:52 +00:00
|
|
|
static void loadScripts(const NamedList* sect);
|
2012-07-02 11:55:34 +00:00
|
|
|
inline static ObjList& globals()
|
|
|
|
{ return s_globals; }
|
2012-06-16 23:21:13 +00:00
|
|
|
inline static void unloadAll()
|
|
|
|
{ s_globals.clear(); }
|
2019-12-19 12:21:42 +00:00
|
|
|
|
|
|
|
static Mutex s_mutex;
|
|
|
|
static bool s_keepOldOnFail;
|
|
|
|
|
2012-06-16 23:21:13 +00:00
|
|
|
private:
|
2019-12-19 12:21:42 +00:00
|
|
|
static bool buildNewScript(Lock& lck, ObjList* old, const String& scriptName,
|
|
|
|
const String& fileName, bool relPath, bool fromCfg, bool fromInit = false);
|
|
|
|
|
2012-06-16 23:21:13 +00:00
|
|
|
JsParser m_jsCode;
|
|
|
|
RefPointer<ScriptContext> m_context;
|
|
|
|
bool m_inUse;
|
2014-10-16 12:39:59 +00:00
|
|
|
bool m_confLoaded;
|
2015-01-30 13:39:52 +00:00
|
|
|
String m_file;
|
2012-06-16 23:21:13 +00:00
|
|
|
static ObjList s_globals;
|
|
|
|
};
|
|
|
|
|
2012-06-27 17:49:49 +00:00
|
|
|
class JsShared : public JsObject
|
|
|
|
{
|
|
|
|
YCLASS(JsShared,JsObject)
|
|
|
|
public:
|
2020-10-21 11:01:31 +00:00
|
|
|
inline JsShared(ScriptMutex* mtx)
|
2021-09-28 10:55:08 +00:00
|
|
|
: JsObject("SharedVars",mtx,true)
|
2012-06-27 17:49:49 +00:00
|
|
|
{
|
|
|
|
params().addParam(new ExpFunction("inc"));
|
|
|
|
params().addParam(new ExpFunction("dec"));
|
|
|
|
params().addParam(new ExpFunction("get"));
|
|
|
|
params().addParam(new ExpFunction("set"));
|
2021-09-28 10:55:08 +00:00
|
|
|
params().addParam(new ExpFunction("add"));
|
|
|
|
params().addParam(new ExpFunction("sub"));
|
2012-06-27 17:49:49 +00:00
|
|
|
params().addParam(new ExpFunction("clear"));
|
2021-09-28 10:55:08 +00:00
|
|
|
params().addParam(new ExpFunction("clearAll"));
|
2012-06-27 17:49:49 +00:00
|
|
|
params().addParam(new ExpFunction("exists"));
|
2021-09-28 10:55:08 +00:00
|
|
|
params().addParam(new ExpFunction("getVars"));
|
|
|
|
setVars(String::empty());
|
2012-06-27 17:49:49 +00:00
|
|
|
}
|
2021-09-28 10:55:08 +00:00
|
|
|
inline JsShared(ScriptMutex* mtx, unsigned int line, const String& varsName = String::empty())
|
|
|
|
: JsObject(mtx,"[object SharedVars]",line)
|
|
|
|
{ setVars(varsName); }
|
|
|
|
virtual JsObject* runConstructor(ObjList& stack, const ExpOperation& oper, GenObject* context);
|
|
|
|
static void initialize(ScriptContext* context);
|
|
|
|
static inline uint64_t modulo(ExpOperation* mod) {
|
|
|
|
if (!(mod && mod->isInteger()))
|
|
|
|
return 0;
|
|
|
|
int64_t m = mod->number();
|
|
|
|
return m > 1 ? --m : 0;
|
|
|
|
}
|
|
|
|
|
2012-06-27 17:49:49 +00:00
|
|
|
protected:
|
2021-09-28 10:55:08 +00:00
|
|
|
inline void setVars(const String& name) {
|
|
|
|
if (!name)
|
|
|
|
m_vars = &Engine::sharedVars();
|
|
|
|
else
|
|
|
|
SharedVars::getList(m_vars,name);
|
|
|
|
m_varsName = name;
|
|
|
|
}
|
|
|
|
inline JsShared(ScriptMutex* mtx, const char* name, unsigned int line, const String& varsName = String::empty())
|
|
|
|
: JsObject(mtx,name,line)
|
|
|
|
{ setVars(varsName); }
|
|
|
|
virtual JsObject* clone(const char* name, const ExpOperation& oper) const
|
|
|
|
{ return new JsShared(mutex(),name,oper.lineNumber(),m_varsName); }
|
2012-06-27 17:49:49 +00:00
|
|
|
bool runNative(ObjList& stack, const ExpOperation& oper, GenObject* context);
|
2021-09-28 10:55:08 +00:00
|
|
|
|
|
|
|
private:
|
|
|
|
RefPointer<SharedVars> m_vars;
|
|
|
|
String m_varsName;
|
2012-06-27 17:49:49 +00:00
|
|
|
};
|
|
|
|
|
2013-04-12 14:00:39 +00:00
|
|
|
class JsTimeEvent : public RefObject
|
|
|
|
{
|
|
|
|
public:
|
2019-11-26 11:17:24 +00:00
|
|
|
JsTimeEvent(JsEngineWorker* worker, const ExpFunction& callback, unsigned int interval,bool repeatable, unsigned int id,
|
|
|
|
ObjList* args = 0);
|
|
|
|
~JsTimeEvent()
|
|
|
|
{ TelEngine::destruct(m_args); }
|
2013-04-12 14:00:39 +00:00
|
|
|
void processTimeout(const Time& when);
|
|
|
|
inline bool repeatable() const
|
|
|
|
{ return m_repeat; }
|
|
|
|
inline u_int64_t fireTime() const
|
|
|
|
{ return m_fire; }
|
|
|
|
inline bool timeout(const Time& when) const
|
|
|
|
{ return when.msec() >= m_fire; }
|
|
|
|
inline unsigned int getId() const
|
|
|
|
{ return m_id; }
|
|
|
|
private:
|
|
|
|
JsEngineWorker* m_worker;
|
|
|
|
ExpFunction m_callbackFunction;
|
|
|
|
unsigned int m_interval;
|
|
|
|
u_int64_t m_fire;
|
|
|
|
bool m_repeat;
|
|
|
|
unsigned int m_id;
|
2019-11-26 11:17:24 +00:00
|
|
|
ObjList* m_args;
|
2013-04-12 14:00:39 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
class JsEngineWorker : public Thread
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
JsEngineWorker(JsEngine* engine, ScriptContext* context, ScriptCode* code);
|
|
|
|
~JsEngineWorker();
|
2019-11-26 11:17:24 +00:00
|
|
|
unsigned int addEvent(const ExpFunction& callback, unsigned int interval, bool repeat, ObjList* args = 0);
|
2013-04-12 14:00:39 +00:00
|
|
|
bool removeEvent(unsigned int id, bool repeatable);
|
2017-05-03 08:39:48 +00:00
|
|
|
ScriptRun* getRunner();
|
2013-04-12 14:00:39 +00:00
|
|
|
protected:
|
|
|
|
virtual void run();
|
|
|
|
void postponeEvent(JsTimeEvent* ev);
|
|
|
|
private:
|
|
|
|
ObjList m_events;
|
|
|
|
Mutex m_eventsMutex;
|
|
|
|
unsigned int m_id;
|
2017-05-03 08:39:48 +00:00
|
|
|
ScriptRun* m_runner;
|
|
|
|
RefPointer<JsEngine> m_engine;
|
2013-04-12 14:00:39 +00:00
|
|
|
};
|
|
|
|
|
2017-08-01 06:20:58 +00:00
|
|
|
class JsSemaphore : public JsObject
|
|
|
|
{
|
|
|
|
YCLASS(JsSemaphore,JsObject)
|
|
|
|
public:
|
2020-10-21 11:01:31 +00:00
|
|
|
inline JsSemaphore(ScriptMutex* mtx)
|
2017-08-01 06:20:58 +00:00
|
|
|
: JsObject("Semaphore",mtx,true), m_constructor(0), m_exit(false)
|
|
|
|
{
|
|
|
|
XDebug(DebugAll,"JsSemaphore::JsSemaphore() [%p]",this);
|
2017-08-02 13:48:40 +00:00
|
|
|
params().addParam(new ExpFunction("wait"));
|
|
|
|
params().addParam(new ExpFunction("signal"));
|
2017-08-01 06:20:58 +00:00
|
|
|
}
|
|
|
|
|
2020-10-21 11:01:31 +00:00
|
|
|
inline JsSemaphore(JsSemaphore* constructor, ScriptMutex* mtx, unsigned int line, unsigned int maxCount, unsigned int initialCount,
|
2017-08-01 06:20:58 +00:00
|
|
|
const char* name)
|
2020-10-21 11:01:31 +00:00
|
|
|
: JsObject(mtx,"[object Semaphore]",line,false), m_name(name),
|
2017-08-01 06:20:58 +00:00
|
|
|
m_semaphore(maxCount,m_name.c_str(),initialCount), m_constructor(constructor), m_exit(false)
|
|
|
|
{
|
|
|
|
XDebug(DebugAll,"JsSemaphore::JsSemaphore(%u,'%s',%u) [%p]",maxCount,
|
|
|
|
name,initialCount,this);
|
|
|
|
}
|
|
|
|
virtual ~JsSemaphore()
|
|
|
|
{
|
|
|
|
XDebug(DebugAll,"~JsSemaphore() [%p]",this);
|
|
|
|
if (m_constructor)
|
|
|
|
m_constructor->removeSemaphore(this);
|
|
|
|
// Notify all the semaphores that we are exiting.
|
|
|
|
Lock myLock(mutex());
|
|
|
|
JsSemaphore* js = 0;;
|
|
|
|
while ((js = static_cast<JsSemaphore*>(m_semaphores.remove(false))))
|
|
|
|
js->forceExit();
|
|
|
|
}
|
|
|
|
|
|
|
|
void runAsync(ObjList& stack, long maxWait);
|
|
|
|
virtual JsObject* runConstructor(ObjList& stack, const ExpOperation& oper, GenObject* context);
|
|
|
|
void removeSemaphore(JsSemaphore* sem);
|
|
|
|
void forceExit();
|
|
|
|
protected:
|
|
|
|
bool runNative(ObjList& stack, const ExpOperation& oper, GenObject* context);
|
|
|
|
private:
|
|
|
|
String m_name;
|
|
|
|
Semaphore m_semaphore;
|
|
|
|
JsSemaphore* m_constructor;
|
|
|
|
ObjList m_semaphores;
|
|
|
|
bool m_exit;
|
|
|
|
};
|
|
|
|
|
2017-09-18 12:14:44 +00:00
|
|
|
class JsHashList : public JsObject
|
|
|
|
{
|
|
|
|
public:
|
2020-10-21 11:01:31 +00:00
|
|
|
inline JsHashList(ScriptMutex* mtx)
|
2017-09-18 12:14:44 +00:00
|
|
|
: JsObject("HashList",mtx,true),
|
|
|
|
m_list()
|
|
|
|
{
|
|
|
|
XDebug(DebugAll,"JsHashList::JsHashList() [%p]",this);
|
2017-09-29 14:52:33 +00:00
|
|
|
params().addParam(new ExpFunction("count"));
|
2017-09-18 12:14:44 +00:00
|
|
|
}
|
2020-10-21 11:01:31 +00:00
|
|
|
inline JsHashList(unsigned int size, ScriptMutex* mtx, unsigned int line)
|
|
|
|
: JsObject(mtx,"[object HashList]",line,false),
|
2017-09-18 12:14:44 +00:00
|
|
|
m_list(size)
|
|
|
|
{
|
|
|
|
XDebug(DebugAll,"JsHashList::JsHashList(%u) [%p]",size,this);
|
|
|
|
}
|
|
|
|
virtual ~JsHashList()
|
|
|
|
{
|
|
|
|
XDebug(DebugAll,"~JsHashList() [%p]",this);
|
|
|
|
m_list.clear();
|
|
|
|
}
|
|
|
|
virtual void* getObject(const String& name) const;
|
|
|
|
virtual JsObject* runConstructor(ObjList& stack, const ExpOperation& oper, GenObject* context);
|
|
|
|
virtual void fillFieldNames(ObjList& names);
|
|
|
|
virtual bool runField(ObjList& stack, const ExpOperation& oper, GenObject* context);
|
|
|
|
virtual bool runAssign(ObjList& stack, const ExpOperation& oper, GenObject* context);
|
|
|
|
virtual void clearField(const String& name)
|
|
|
|
{ m_list.remove(name); }
|
2020-10-14 14:03:56 +00:00
|
|
|
virtual const HashList* getHashListParams() const
|
|
|
|
{ return &m_list; }
|
|
|
|
|
2017-09-29 14:52:33 +00:00
|
|
|
protected:
|
|
|
|
bool runNative(ObjList& stack, const ExpOperation& oper, GenObject* context);
|
2017-09-18 12:14:44 +00:00
|
|
|
private:
|
|
|
|
HashList m_list;
|
|
|
|
};
|
|
|
|
|
2020-02-21 14:41:19 +00:00
|
|
|
class JsURI : public JsObject
|
|
|
|
{
|
|
|
|
public:
|
2020-10-21 11:01:31 +00:00
|
|
|
inline JsURI(ScriptMutex* mtx)
|
2020-02-21 14:41:19 +00:00
|
|
|
: JsObject("URI",mtx,true)
|
|
|
|
{
|
|
|
|
XDebug(DebugAll,"JsURI::JsURI() [%p]",this);
|
|
|
|
params().addParam(new ExpFunction("getDescription"));
|
|
|
|
params().addParam(new ExpFunction("getProtocol"));
|
|
|
|
params().addParam(new ExpFunction("getUser"));
|
|
|
|
params().addParam(new ExpFunction("getHost"));
|
|
|
|
params().addParam(new ExpFunction("getPort"));
|
|
|
|
params().addParam(new ExpFunction("getExtra"));
|
|
|
|
params().addParam(new ExpFunction("getCanonical"));
|
|
|
|
}
|
2020-10-21 11:01:31 +00:00
|
|
|
inline JsURI(const char* str, ScriptMutex* mtx, unsigned int line)
|
|
|
|
: JsObject(mtx,str,line,false),
|
2020-02-21 14:41:19 +00:00
|
|
|
m_uri(str)
|
|
|
|
{
|
2020-03-03 14:52:36 +00:00
|
|
|
XDebug(DebugAll,"JsURI::JsURI('%s') [%p]",str,this);
|
2020-02-21 14:41:19 +00:00
|
|
|
}
|
|
|
|
virtual ~JsURI()
|
|
|
|
{
|
|
|
|
XDebug(DebugAll,"~JsURI() [%p]",this);
|
|
|
|
}
|
|
|
|
virtual void* getObject(const String& name) const;
|
|
|
|
virtual JsObject* runConstructor(ObjList& stack, const ExpOperation& oper, GenObject* context);
|
|
|
|
protected:
|
|
|
|
bool runNative(ObjList& stack, const ExpOperation& oper, GenObject* context);
|
|
|
|
private:
|
|
|
|
URI m_uri;
|
|
|
|
};
|
|
|
|
|
2013-08-07 10:18:23 +00:00
|
|
|
#define MKDEBUG(lvl) params().addParam(new ExpOperation((int64_t)Debug ## lvl,"Debug" # lvl))
|
2017-01-20 13:28:58 +00:00
|
|
|
#define MKTIME(typ) params().addParam(new ExpOperation((int64_t)SysUsage:: typ ## Time,# typ "Time"))
|
2020-10-14 10:38:31 +00:00
|
|
|
#define MKDUMP(typ) params().addParam(new ExpOperation((int64_t)JsObject:: Dump ## typ,"Dump" # typ))
|
2013-04-12 15:18:50 +00:00
|
|
|
class JsEngine : public JsObject, public DebugEnabler
|
2012-02-17 16:19:17 +00:00
|
|
|
{
|
|
|
|
YCLASS(JsEngine,JsObject)
|
|
|
|
public:
|
2020-10-21 11:01:31 +00:00
|
|
|
inline JsEngine(ScriptMutex* mtx, const char* name = 0)
|
2013-04-12 15:18:50 +00:00
|
|
|
: JsObject("Engine",mtx,true),
|
|
|
|
m_worker(0), m_debugName("javascript")
|
2012-02-17 16:19:17 +00:00
|
|
|
{
|
2013-07-05 12:50:18 +00:00
|
|
|
debugName(m_debugName);
|
2013-04-12 15:18:50 +00:00
|
|
|
debugChain(&__plugin);
|
2012-02-17 16:19:17 +00:00
|
|
|
MKDEBUG(Fail);
|
2012-03-05 09:53:31 +00:00
|
|
|
MKDEBUG(Test);
|
2017-08-01 13:08:23 +00:00
|
|
|
MKDEBUG(Crit);
|
2012-02-17 16:19:17 +00:00
|
|
|
MKDEBUG(GoOn);
|
|
|
|
MKDEBUG(Conf);
|
|
|
|
MKDEBUG(Stub);
|
|
|
|
MKDEBUG(Warn);
|
|
|
|
MKDEBUG(Mild);
|
|
|
|
MKDEBUG(Note);
|
2017-08-01 13:08:23 +00:00
|
|
|
MKDEBUG(Call);
|
2012-02-17 16:19:17 +00:00
|
|
|
MKDEBUG(Info);
|
|
|
|
MKDEBUG(All);
|
2017-01-20 13:28:58 +00:00
|
|
|
MKTIME(Wall);
|
|
|
|
MKTIME(User);
|
|
|
|
MKTIME(Kernel);
|
2020-10-14 10:38:31 +00:00
|
|
|
MKDUMP(PropOnly),
|
|
|
|
MKDUMP(FuncOnly),
|
|
|
|
MKDUMP(Func),
|
|
|
|
MKDUMP(Prop),
|
|
|
|
MKDUMP(Recursive),
|
|
|
|
MKDUMP(Type),
|
|
|
|
MKDUMP(Proto),
|
|
|
|
MKDUMP(PropObjType),
|
2012-05-02 15:11:48 +00:00
|
|
|
params().addParam(new ExpFunction("output"));
|
|
|
|
params().addParam(new ExpFunction("debug"));
|
2020-04-22 12:05:53 +00:00
|
|
|
params().addParam(new ExpFunction("traceDebug"));
|
|
|
|
params().addParam(new ExpFunction("trace"));
|
|
|
|
params().addParam(new ExpFunction("setTraceId"));
|
2013-07-05 12:50:18 +00:00
|
|
|
params().addParam(new ExpFunction("alarm"));
|
2020-04-22 12:05:53 +00:00
|
|
|
params().addParam(new ExpFunction("traceAlarm"));
|
2020-04-01 11:47:55 +00:00
|
|
|
params().addParam(new ExpFunction("lineNo"));
|
|
|
|
params().addParam(new ExpFunction("fileName"));
|
|
|
|
params().addParam(new ExpFunction("fileNo"));
|
2020-10-21 11:01:31 +00:00
|
|
|
params().addParam(new ExpFunction("creationLine"));
|
2012-06-22 09:38:51 +00:00
|
|
|
params().addParam(new ExpFunction("sleep"));
|
|
|
|
params().addParam(new ExpFunction("usleep"));
|
|
|
|
params().addParam(new ExpFunction("yield"));
|
|
|
|
params().addParam(new ExpFunction("idle"));
|
2015-08-18 16:09:40 +00:00
|
|
|
params().addParam(new ExpFunction("restart"));
|
2018-03-12 14:10:45 +00:00
|
|
|
params().addParam(new ExpFunction("init"));
|
2012-05-30 08:32:47 +00:00
|
|
|
params().addParam(new ExpFunction("dump_r"));
|
|
|
|
params().addParam(new ExpFunction("print_r"));
|
2020-10-14 10:38:31 +00:00
|
|
|
params().addParam(new ExpFunction("dump_var_r"));
|
|
|
|
params().addParam(new ExpFunction("print_var_r"));
|
|
|
|
params().addParam(new ExpFunction("dump_root_r"));
|
|
|
|
params().addParam(new ExpFunction("print_root_r"));
|
2014-08-06 14:38:28 +00:00
|
|
|
params().addParam(new ExpFunction("dump_t"));
|
|
|
|
params().addParam(new ExpFunction("print_t"));
|
2013-04-12 15:18:50 +00:00
|
|
|
params().addParam(new ExpFunction("debugName"));
|
2013-08-05 09:56:52 +00:00
|
|
|
params().addParam(new ExpFunction("debugLevel"));
|
|
|
|
params().addParam(new ExpFunction("debugEnabled"));
|
|
|
|
params().addParam(new ExpFunction("debugAt"));
|
|
|
|
params().addParam(new ExpFunction("setDebug"));
|
2017-01-20 13:28:58 +00:00
|
|
|
params().addParam(new ExpFunction("uptime"));
|
2016-01-04 12:49:52 +00:00
|
|
|
params().addParam(new ExpFunction("started"));
|
2017-04-27 10:31:07 +00:00
|
|
|
params().addParam(new ExpFunction("exiting"));
|
2017-01-09 15:04:04 +00:00
|
|
|
params().addParam(new ExpFunction("accepting"));
|
2021-05-18 12:19:21 +00:00
|
|
|
params().addParam(new ExpFunction("getCongestion"));
|
2021-05-18 18:07:43 +00:00
|
|
|
params().addParam(new ExpFunction("setCongestion"));
|
2021-05-21 15:26:13 +00:00
|
|
|
if (name) {
|
|
|
|
m_schedName << "js:" << name;
|
2015-08-27 10:58:42 +00:00
|
|
|
params().addParam(new ExpOperation(name,"name"));
|
2021-05-21 15:26:13 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
m_schedName = "JsScheduler";
|
2012-06-27 17:49:49 +00:00
|
|
|
params().addParam(new ExpWrapper(new JsShared(mtx),"shared"));
|
2013-11-05 15:50:09 +00:00
|
|
|
params().addParam(new ExpFunction("runParams"));
|
2014-04-01 11:27:51 +00:00
|
|
|
params().addParam(new ExpFunction("configFile"));
|
2013-04-12 14:00:39 +00:00
|
|
|
params().addParam(new ExpFunction("setInterval"));
|
|
|
|
params().addParam(new ExpFunction("clearInterval"));
|
|
|
|
params().addParam(new ExpFunction("setTimeout"));
|
|
|
|
params().addParam(new ExpFunction("clearTimeout"));
|
2014-08-06 08:08:06 +00:00
|
|
|
params().addParam(new ExpFunction("loadLibrary"));
|
|
|
|
params().addParam(new ExpFunction("loadObject"));
|
2015-09-04 20:04:02 +00:00
|
|
|
params().addParam(new ExpFunction("replaceParams"));
|
2020-04-15 13:50:14 +00:00
|
|
|
params().addParam(new ExpFunction("pluginLoaded"));
|
2014-03-26 10:45:01 +00:00
|
|
|
params().addParam(new ExpFunction("atob"));
|
|
|
|
params().addParam(new ExpFunction("btoa"));
|
|
|
|
params().addParam(new ExpFunction("atoh"));
|
|
|
|
params().addParam(new ExpFunction("htoa"));
|
2014-07-07 07:52:42 +00:00
|
|
|
params().addParam(new ExpFunction("btoh"));
|
|
|
|
params().addParam(new ExpFunction("htob"));
|
2021-09-28 10:55:08 +00:00
|
|
|
addConstructor(params(),"Semaphore",new JsSemaphore(mtx));
|
2017-09-18 12:14:44 +00:00
|
|
|
addConstructor(params(),"HashList",new JsHashList(mtx));
|
2020-02-21 14:41:19 +00:00
|
|
|
addConstructor(params(),"URI",new JsURI(mtx));
|
2021-09-28 10:55:08 +00:00
|
|
|
addConstructor(params(),"SharedVars",new JsShared(mtx));
|
2012-02-17 16:19:17 +00:00
|
|
|
}
|
2015-08-27 10:58:42 +00:00
|
|
|
static void initialize(ScriptContext* context, const char* name = 0);
|
2013-04-12 14:00:39 +00:00
|
|
|
inline void resetWorker()
|
|
|
|
{ m_worker = 0; }
|
2021-05-21 15:26:13 +00:00
|
|
|
inline const String& schedName() const
|
|
|
|
{ return m_schedName; }
|
2012-02-17 16:19:17 +00:00
|
|
|
protected:
|
|
|
|
bool runNative(ObjList& stack, const ExpOperation& oper, GenObject* context);
|
2013-04-12 14:00:39 +00:00
|
|
|
virtual void destroyed();
|
|
|
|
private:
|
|
|
|
JsEngineWorker* m_worker;
|
2013-04-12 15:18:50 +00:00
|
|
|
String m_debugName;
|
2021-05-21 15:26:13 +00:00
|
|
|
String m_schedName;
|
2012-02-17 16:19:17 +00:00
|
|
|
};
|
|
|
|
#undef MKDEBUG
|
2017-01-20 13:28:58 +00:00
|
|
|
#undef MKTIME
|
2012-02-17 16:19:17 +00:00
|
|
|
|
|
|
|
class JsMessage : public JsObject
|
|
|
|
{
|
|
|
|
public:
|
2012-06-27 17:49:49 +00:00
|
|
|
|
2020-10-21 11:01:31 +00:00
|
|
|
inline JsMessage(ScriptMutex* mtx)
|
2013-04-12 12:55:51 +00:00
|
|
|
: JsObject("Message",mtx,true),
|
2020-04-01 11:47:55 +00:00
|
|
|
m_message(0), m_dispatch(false), m_owned(false), m_trackPrio(true),
|
|
|
|
m_traceLvl(DebugInfo), m_traceLst(0)
|
2012-02-17 16:19:17 +00:00
|
|
|
{
|
2012-06-18 13:52:21 +00:00
|
|
|
XDebug(&__plugin,DebugAll,"JsMessage::JsMessage() [%p]",this);
|
2012-03-05 09:53:31 +00:00
|
|
|
params().addParam(new ExpFunction("enqueue"));
|
|
|
|
params().addParam(new ExpFunction("dispatch"));
|
2012-06-19 18:55:45 +00:00
|
|
|
params().addParam(new ExpFunction("name"));
|
2012-02-17 16:19:17 +00:00
|
|
|
params().addParam(new ExpFunction("broadcast"));
|
2012-06-19 18:55:45 +00:00
|
|
|
params().addParam(new ExpFunction("retValue"));
|
2013-11-05 15:50:09 +00:00
|
|
|
params().addParam(new ExpFunction("msgTime"));
|
2017-04-27 12:30:45 +00:00
|
|
|
params().addParam(new ExpFunction("msgAge"));
|
2017-01-20 15:16:19 +00:00
|
|
|
params().addParam(new ExpFunction("getParam"));
|
|
|
|
params().addParam(new ExpFunction("setParam"));
|
2012-06-28 18:23:04 +00:00
|
|
|
params().addParam(new ExpFunction("getColumn"));
|
|
|
|
params().addParam(new ExpFunction("getRow"));
|
|
|
|
params().addParam(new ExpFunction("getResult"));
|
2017-05-22 12:37:22 +00:00
|
|
|
params().addParam(new ExpFunction("copyParams"));
|
2018-02-12 14:42:45 +00:00
|
|
|
params().addParam(new ExpFunction("clearParam"));
|
2020-04-01 11:47:55 +00:00
|
|
|
params().addParam(new ExpFunction("trace"));
|
2012-02-17 16:19:17 +00:00
|
|
|
}
|
2020-10-21 11:01:31 +00:00
|
|
|
inline JsMessage(Message* message, ScriptMutex* mtx, unsigned int line, bool disp, bool owned = false)
|
|
|
|
: JsObject(mtx,"[object Message]",line),
|
2020-04-01 11:47:55 +00:00
|
|
|
m_message(message), m_dispatch(disp), m_owned(owned), m_trackPrio(true),
|
|
|
|
m_traceLvl(DebugInfo), m_traceLst(0)
|
2017-05-08 09:03:05 +00:00
|
|
|
{
|
|
|
|
XDebug(&__plugin,DebugAll,"JsMessage::JsMessage(%p) [%p]",message,this);
|
2020-04-01 11:47:55 +00:00
|
|
|
setTrace();
|
2017-05-08 09:03:05 +00:00
|
|
|
}
|
2012-02-17 16:19:17 +00:00
|
|
|
virtual ~JsMessage()
|
|
|
|
{
|
2012-06-18 13:52:21 +00:00
|
|
|
XDebug(&__plugin,DebugAll,"JsMessage::~JsMessage() [%p]",this);
|
2012-03-05 09:53:31 +00:00
|
|
|
if (m_owned)
|
|
|
|
TelEngine::destruct(m_message);
|
2012-11-01 11:18:35 +00:00
|
|
|
if (Engine::exiting())
|
|
|
|
while (m_handlers.remove(false))
|
|
|
|
;
|
2013-04-12 13:56:00 +00:00
|
|
|
for (ObjList* o = m_hooks.skipNull();o;o = o->skipNext()) {
|
|
|
|
MessageHook* hook = static_cast<MessageHook*>(o->get());
|
|
|
|
Engine::uninstallHook(hook);
|
|
|
|
}
|
2020-04-01 11:47:55 +00:00
|
|
|
TelEngine::destruct(m_traceLst);
|
2012-02-17 16:19:17 +00:00
|
|
|
}
|
2014-10-29 16:32:20 +00:00
|
|
|
virtual void* getObject(const String& name) const;
|
2012-06-19 18:55:45 +00:00
|
|
|
virtual NamedList* nativeParams() const
|
|
|
|
{ return m_message; }
|
|
|
|
virtual void fillFieldNames(ObjList& names)
|
|
|
|
{ if (m_message) ScriptContext::fillFieldNames(names,*m_message); }
|
|
|
|
virtual bool runAssign(ObjList& stack, const ExpOperation& oper, GenObject* context);
|
2012-06-18 13:52:21 +00:00
|
|
|
virtual JsObject* runConstructor(ObjList& stack, const ExpOperation& oper, GenObject* context);
|
|
|
|
virtual void initConstructor(JsFunction* construct)
|
|
|
|
{
|
|
|
|
construct->params().addParam(new ExpFunction("install"));
|
2012-06-19 18:55:45 +00:00
|
|
|
construct->params().addParam(new ExpFunction("uninstall"));
|
2014-07-24 13:03:16 +00:00
|
|
|
construct->params().addParam(new ExpFunction("handlers"));
|
2013-04-12 13:56:00 +00:00
|
|
|
construct->params().addParam(new ExpFunction("uninstallHook"));
|
|
|
|
construct->params().addParam(new ExpFunction("installHook"));
|
2013-04-12 12:55:51 +00:00
|
|
|
construct->params().addParam(new ExpFunction("trackName"));
|
2012-06-18 13:52:21 +00:00
|
|
|
}
|
2012-03-05 09:53:31 +00:00
|
|
|
inline void clearMsg()
|
2020-04-01 11:47:55 +00:00
|
|
|
{
|
|
|
|
dumpTraceToMsg(m_message,m_traceLst);
|
|
|
|
m_message = 0;
|
|
|
|
m_owned = false;
|
|
|
|
m_dispatch = false;
|
|
|
|
setTrace();
|
|
|
|
}
|
2017-11-01 16:37:48 +00:00
|
|
|
inline void setMsg(Message* message)
|
2020-04-01 11:47:55 +00:00
|
|
|
{ m_message = message; m_owned = false; m_dispatch = false; setTrace(); }
|
2012-02-17 16:19:17 +00:00
|
|
|
static void initialize(ScriptContext* context);
|
2017-11-01 16:37:48 +00:00
|
|
|
void runAsync(ObjList& stack, Message* msg, bool owned);
|
2012-02-17 16:19:17 +00:00
|
|
|
protected:
|
|
|
|
bool runNative(ObjList& stack, const ExpOperation& oper, GenObject* context);
|
2020-10-21 11:01:31 +00:00
|
|
|
void getColumn(ObjList& stack, const ExpOperation* col, GenObject* context, unsigned int lineNo);
|
|
|
|
void getRow(ObjList& stack, const ExpOperation* row, GenObject* context, unsigned int lineNo);
|
2012-06-28 18:23:04 +00:00
|
|
|
void getResult(ObjList& stack, const ExpOperation& row, const ExpOperation& col, GenObject* context);
|
2013-04-12 13:56:00 +00:00
|
|
|
bool installHook(ObjList& stack, const ExpOperation& oper, GenObject* context);
|
2020-04-01 11:47:55 +00:00
|
|
|
inline void setTrace()
|
|
|
|
{
|
|
|
|
m_traceId = m_message ? m_message->getValue(YSTRING("trace_id")) : "";
|
|
|
|
m_traceLvl = m_message ? m_message->getIntValue(YSTRING("trace_lvl"),DebugInfo,DebugGoOn,DebugAll) : DebugInfo;
|
|
|
|
TelEngine::destruct(m_traceLst);
|
|
|
|
m_traceLst = m_message ? (m_message->getBoolValue(YSTRING("trace_to_msg"),false) ? new ObjList() : 0) : 0;
|
|
|
|
}
|
2012-06-18 13:52:21 +00:00
|
|
|
ObjList m_handlers;
|
2013-04-12 13:56:00 +00:00
|
|
|
ObjList m_hooks;
|
2013-04-12 12:55:51 +00:00
|
|
|
String m_trackName;
|
2012-02-17 16:19:17 +00:00
|
|
|
Message* m_message;
|
2017-11-01 16:37:48 +00:00
|
|
|
bool m_dispatch;
|
2012-03-05 09:53:31 +00:00
|
|
|
bool m_owned;
|
2013-04-12 12:55:51 +00:00
|
|
|
bool m_trackPrio;
|
2020-04-01 11:47:55 +00:00
|
|
|
String m_traceId;
|
|
|
|
int m_traceLvl;
|
|
|
|
ObjList* m_traceLst;
|
2012-03-05 09:53:31 +00:00
|
|
|
};
|
|
|
|
|
2012-06-18 13:52:21 +00:00
|
|
|
class JsHandler : public MessageHandler
|
|
|
|
{
|
|
|
|
YCLASS(JsHandler,MessageHandler)
|
|
|
|
public:
|
2020-10-21 11:01:31 +00:00
|
|
|
inline JsHandler(const char* name, unsigned priority, const ExpFunction& func, GenObject* context, unsigned int lineNo)
|
2012-06-18 13:52:21 +00:00
|
|
|
: MessageHandler(name,priority,__plugin.name()),
|
2020-10-21 11:01:31 +00:00
|
|
|
m_function(func.name(),1), m_lineNo(lineNo)
|
2012-06-18 13:52:21 +00:00
|
|
|
{
|
2020-10-21 11:01:31 +00:00
|
|
|
XDebug(&__plugin,DebugAll,"JsHandler::JsHandler('%s',%u,'%s',%p,%u) [%p]",
|
|
|
|
name,priority,func.name().c_str(),context,lineNo,this);
|
2012-06-18 13:52:21 +00:00
|
|
|
ScriptRun* runner = YOBJECT(ScriptRun,context);
|
|
|
|
if (runner) {
|
|
|
|
m_context = runner->context();
|
|
|
|
m_code = runner->code();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
virtual ~JsHandler()
|
|
|
|
{
|
|
|
|
XDebug(&__plugin,DebugAll,"JsHandler::~JsHandler() '%s' [%p]",c_str(),this);
|
|
|
|
}
|
2017-01-23 19:53:55 +00:00
|
|
|
virtual bool received(Message& msg)
|
|
|
|
{ return false; }
|
2014-07-24 13:03:16 +00:00
|
|
|
inline const ExpFunction& function() const
|
|
|
|
{ return m_function; }
|
2017-01-23 19:53:55 +00:00
|
|
|
protected:
|
|
|
|
virtual bool receivedInternal(Message& msg);
|
2012-06-18 13:52:21 +00:00
|
|
|
private:
|
|
|
|
ExpFunction m_function;
|
|
|
|
RefPointer<ScriptContext> m_context;
|
|
|
|
RefPointer<ScriptCode> m_code;
|
2020-10-21 11:01:31 +00:00
|
|
|
unsigned int m_lineNo;
|
2012-06-18 13:52:21 +00:00
|
|
|
};
|
|
|
|
|
2013-04-12 13:56:00 +00:00
|
|
|
class JsMessageQueue : public MessageQueue
|
|
|
|
{
|
|
|
|
YCLASS(JsMessageQueue,MessageQueue)
|
|
|
|
public:
|
2020-10-21 11:01:31 +00:00
|
|
|
inline JsMessageQueue(unsigned int line, const ExpFunction* received,const char* name, unsigned threads, const ExpFunction* trap, unsigned trapLunch, GenObject* context)
|
|
|
|
: MessageQueue(name,threads), m_lineNo(line), m_receivedFunction(0), m_trapFunction(0), m_trapLunch(trapLunch), m_trapCalled(false)
|
2013-04-12 13:56:00 +00:00
|
|
|
{
|
|
|
|
ScriptRun* runner = YOBJECT(ScriptRun,context);
|
|
|
|
if (runner) {
|
|
|
|
m_context = runner->context();
|
|
|
|
m_code = runner->code();
|
|
|
|
}
|
|
|
|
if (received)
|
|
|
|
m_receivedFunction = new ExpFunction(received->name(),1);
|
|
|
|
if (trap)
|
|
|
|
m_trapFunction = new ExpFunction(trap->name(),0);
|
|
|
|
}
|
|
|
|
virtual ~JsMessageQueue()
|
|
|
|
{
|
|
|
|
TelEngine::destruct(m_receivedFunction);
|
|
|
|
TelEngine::destruct(m_trapFunction);
|
|
|
|
}
|
|
|
|
virtual bool enqueue(Message* msg);
|
|
|
|
bool matchesFilters(const NamedList& filters);
|
|
|
|
protected:
|
|
|
|
virtual void received(Message& msg);
|
|
|
|
private:
|
2020-10-21 11:01:31 +00:00
|
|
|
unsigned int m_lineNo;
|
2013-04-12 13:56:00 +00:00
|
|
|
ExpFunction* m_receivedFunction;
|
|
|
|
ExpFunction* m_trapFunction;
|
|
|
|
RefPointer<ScriptContext> m_context;
|
|
|
|
RefPointer<ScriptCode> m_code;
|
|
|
|
unsigned int m_trapLunch;
|
|
|
|
bool m_trapCalled;
|
|
|
|
};
|
|
|
|
|
2012-03-05 09:53:31 +00:00
|
|
|
class JsFile : public JsObject
|
|
|
|
{
|
|
|
|
YCLASS(JsFile,JsObject)
|
|
|
|
public:
|
2020-10-21 11:01:31 +00:00
|
|
|
inline JsFile(ScriptMutex* mtx)
|
2012-03-05 09:53:31 +00:00
|
|
|
: JsObject("File",mtx,true)
|
|
|
|
{
|
|
|
|
XDebug(DebugAll,"JsFile::JsFile() [%p]",this);
|
|
|
|
params().addParam(new ExpFunction("exists"));
|
|
|
|
params().addParam(new ExpFunction("remove"));
|
|
|
|
params().addParam(new ExpFunction("rename"));
|
|
|
|
params().addParam(new ExpFunction("mkdir"));
|
|
|
|
params().addParam(new ExpFunction("rmdir"));
|
|
|
|
params().addParam(new ExpFunction("getFileTime"));
|
|
|
|
params().addParam(new ExpFunction("setFileTime"));
|
2018-12-11 16:57:32 +00:00
|
|
|
params().addParam(new ExpFunction("getContent"));
|
|
|
|
params().addParam(new ExpFunction("setContent"));
|
2012-03-05 09:53:31 +00:00
|
|
|
}
|
|
|
|
static void initialize(ScriptContext* context);
|
|
|
|
protected:
|
|
|
|
bool runNative(ObjList& stack, const ExpOperation& oper, GenObject* context);
|
2012-02-17 16:19:17 +00:00
|
|
|
};
|
|
|
|
|
2014-04-01 11:27:51 +00:00
|
|
|
class JsConfigFile : public JsObject
|
|
|
|
{
|
|
|
|
public:
|
2020-10-21 11:01:31 +00:00
|
|
|
inline JsConfigFile(ScriptMutex* mtx)
|
2014-04-01 11:27:51 +00:00
|
|
|
: JsObject("ConfigFile",mtx,true)
|
|
|
|
{
|
|
|
|
XDebug(DebugAll,"JsConfigFile::JsConfigFile() [%p]",this);
|
|
|
|
params().addParam(new ExpFunction("name"));
|
|
|
|
params().addParam(new ExpFunction("load"));
|
|
|
|
params().addParam(new ExpFunction("save"));
|
|
|
|
params().addParam(new ExpFunction("count"));
|
|
|
|
params().addParam(new ExpFunction("sections"));
|
|
|
|
params().addParam(new ExpFunction("getSection"));
|
|
|
|
params().addParam(new ExpFunction("getValue"));
|
2014-12-22 11:56:16 +00:00
|
|
|
params().addParam(new ExpFunction("getIntValue"));
|
|
|
|
params().addParam(new ExpFunction("getBoolValue"));
|
2014-04-01 11:27:51 +00:00
|
|
|
params().addParam(new ExpFunction("setValue"));
|
2015-08-25 10:18:26 +00:00
|
|
|
params().addParam(new ExpFunction("addValue"));
|
2021-12-22 07:03:35 +00:00
|
|
|
params().addParam(new ExpFunction("setValues"));
|
|
|
|
params().addParam(new ExpFunction("addValues"));
|
2015-08-25 09:37:59 +00:00
|
|
|
params().addParam(new ExpFunction("clearSection"));
|
2014-04-01 11:27:51 +00:00
|
|
|
params().addParam(new ExpFunction("clearKey"));
|
|
|
|
params().addParam(new ExpFunction("keys"));
|
|
|
|
}
|
2020-10-21 11:01:31 +00:00
|
|
|
inline JsConfigFile(ScriptMutex* mtx, unsigned int line, const char* name, bool warn)
|
|
|
|
: JsObject(mtx,"[object ConfigFile]",line),
|
|
|
|
m_config(name,warn)
|
|
|
|
{
|
|
|
|
XDebug(DebugAll,"JsConfigFile::JsConfigFile('%s') [%p]",name,this);
|
|
|
|
}
|
2014-10-29 16:32:20 +00:00
|
|
|
virtual void* getObject(const String& name) const;
|
2014-04-01 11:27:51 +00:00
|
|
|
virtual JsObject* runConstructor(ObjList& stack, const ExpOperation& oper, GenObject* context);
|
|
|
|
static void initialize(ScriptContext* context);
|
|
|
|
inline Configuration& config()
|
|
|
|
{ return m_config; }
|
|
|
|
inline const Configuration& config() const
|
|
|
|
{ return m_config; }
|
|
|
|
protected:
|
|
|
|
bool runNative(ObjList& stack, const ExpOperation& oper, GenObject* context);
|
|
|
|
private:
|
|
|
|
Configuration m_config;
|
|
|
|
};
|
|
|
|
|
|
|
|
class JsConfigSection : public JsObject
|
|
|
|
{
|
|
|
|
friend class JsConfigFile;
|
|
|
|
YCLASS(JsConfigSection,JsObject)
|
|
|
|
protected:
|
2020-10-21 11:01:31 +00:00
|
|
|
inline JsConfigSection(JsConfigFile* owner, const char* name, unsigned int lineNo)
|
|
|
|
: JsObject(owner->mutex(),name,lineNo,true),
|
2014-04-01 11:27:51 +00:00
|
|
|
m_owner(owner)
|
|
|
|
{
|
|
|
|
XDebug(DebugAll,"JsConfigSection::JsConfigSection(%p,'%s') [%p]",owner,name,this);
|
|
|
|
params().addParam(new ExpFunction("configFile"));
|
|
|
|
params().addParam(new ExpFunction("getValue"));
|
2014-12-22 11:56:16 +00:00
|
|
|
params().addParam(new ExpFunction("getIntValue"));
|
|
|
|
params().addParam(new ExpFunction("getBoolValue"));
|
2014-04-01 11:27:51 +00:00
|
|
|
params().addParam(new ExpFunction("setValue"));
|
2015-08-25 09:37:59 +00:00
|
|
|
params().addParam(new ExpFunction("addValue"));
|
2021-12-22 07:03:35 +00:00
|
|
|
params().addParam(new ExpFunction("setValues"));
|
|
|
|
params().addParam(new ExpFunction("addValues"));
|
2014-04-01 11:27:51 +00:00
|
|
|
params().addParam(new ExpFunction("clearKey"));
|
|
|
|
params().addParam(new ExpFunction("keys"));
|
|
|
|
}
|
|
|
|
bool runNative(ObjList& stack, const ExpOperation& oper, GenObject* context);
|
|
|
|
private:
|
|
|
|
RefPointer<JsConfigFile> m_owner;
|
|
|
|
};
|
|
|
|
|
2022-01-11 09:02:56 +00:00
|
|
|
/**
|
|
|
|
* XML path class
|
|
|
|
* @short Javascript XML path
|
|
|
|
*/
|
|
|
|
class JsXPath : public JsObject
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
inline JsXPath(ScriptMutex* mtx)
|
|
|
|
: JsObject("XPath",mtx,true),
|
|
|
|
m_path(0,XPath::LateParse)
|
|
|
|
{
|
|
|
|
XDebug(DebugAll,"JsXPath::JsXPath() [%p]",this);
|
|
|
|
params().addParam(new ExpFunction("valid"));
|
|
|
|
params().addParam(new ExpFunction("absolute"));
|
|
|
|
params().addParam(new ExpFunction("getPath"));
|
|
|
|
params().addParam(new ExpFunction("getItems"));
|
|
|
|
params().addParam(new ExpFunction("getError"));
|
|
|
|
params().addParam(new ExpFunction("describeError"));
|
|
|
|
}
|
|
|
|
virtual void* getObject(const String& name) const;
|
|
|
|
virtual JsObject* runConstructor(ObjList& stack, const ExpOperation& oper, GenObject* context);
|
|
|
|
virtual void initConstructor(JsFunction* construct)
|
|
|
|
{
|
|
|
|
// Find contents
|
|
|
|
construct->params().addParam(new ExpOperation((int64_t)XPath::FindXml,"FindXml"));
|
|
|
|
construct->params().addParam(new ExpOperation((int64_t)XPath::FindText,"FindText"));
|
|
|
|
construct->params().addParam(new ExpOperation((int64_t)XPath::FindAttr,"FindAttr"));
|
|
|
|
construct->params().addParam(new ExpOperation((int64_t)XPath::FindAny,"FindAny"));
|
|
|
|
// XPath flags
|
|
|
|
construct->params().addParam(new ExpOperation((int64_t)XPath::StrictParse,"StrictParse"));
|
|
|
|
construct->params().addParam(new ExpOperation((int64_t)XPath::IgnoreEmptyResult,"IgnoreEmptyResult"));
|
|
|
|
construct->params().addParam(new ExpOperation((int64_t)XPath::NoXmlNameCheck,"NoXmlNameCheck"));
|
|
|
|
}
|
|
|
|
virtual const XPath& path() const
|
|
|
|
{ return m_path; }
|
|
|
|
virtual const String& toString() const
|
|
|
|
{ return m_path; }
|
|
|
|
static void initialize(ScriptContext* context);
|
|
|
|
|
|
|
|
protected:
|
|
|
|
inline JsXPath(ScriptMutex* mtx, unsigned int line, const char* path, unsigned int flags = 0)
|
|
|
|
: JsObject(mtx,path,line),
|
|
|
|
m_path(path,flags)
|
|
|
|
{ }
|
|
|
|
inline JsXPath(ScriptMutex* mtx, const char* name, unsigned int line, const XPath& path)
|
|
|
|
: JsObject(mtx,name,line),
|
|
|
|
m_path(path)
|
|
|
|
{ }
|
|
|
|
virtual JsObject* clone(const char* name, const ExpOperation& oper) const
|
|
|
|
{ return new JsXPath(mutex(),name,oper.lineNumber(),m_path); }
|
|
|
|
bool runNative(ObjList& stack, const ExpOperation& oper, GenObject* context);
|
|
|
|
|
|
|
|
private:
|
|
|
|
XPath m_path;
|
|
|
|
};
|
|
|
|
|
2012-12-21 10:21:16 +00:00
|
|
|
class JsXML : public JsObject
|
|
|
|
{
|
|
|
|
public:
|
2020-10-21 11:01:31 +00:00
|
|
|
inline JsXML(ScriptMutex* mtx)
|
2012-12-21 10:21:16 +00:00
|
|
|
: JsObject("XML",mtx,true),
|
|
|
|
m_xml(0)
|
|
|
|
{
|
|
|
|
XDebug(DebugAll,"JsXML::JsXML() [%p]",this);
|
|
|
|
params().addParam(new ExpFunction("put"));
|
|
|
|
params().addParam(new ExpFunction("getOwner"));
|
|
|
|
params().addParam(new ExpFunction("getParent"));
|
2013-04-12 12:08:13 +00:00
|
|
|
params().addParam(new ExpFunction("unprefixedTag"));
|
|
|
|
params().addParam(new ExpFunction("getTag"));
|
2012-12-21 10:21:16 +00:00
|
|
|
params().addParam(new ExpFunction("getAttribute"));
|
|
|
|
params().addParam(new ExpFunction("setAttribute"));
|
2013-04-12 12:08:13 +00:00
|
|
|
params().addParam(new ExpFunction("removeAttribute"));
|
2016-02-15 15:06:10 +00:00
|
|
|
params().addParam(new ExpFunction("attributes"));
|
2012-12-21 10:21:16 +00:00
|
|
|
params().addParam(new ExpFunction("addChild"));
|
|
|
|
params().addParam(new ExpFunction("getChild"));
|
|
|
|
params().addParam(new ExpFunction("getChildren"));
|
2013-04-12 12:08:13 +00:00
|
|
|
params().addParam(new ExpFunction("clearChildren"));
|
2012-12-21 10:21:16 +00:00
|
|
|
params().addParam(new ExpFunction("addText"));
|
|
|
|
params().addParam(new ExpFunction("getText"));
|
2014-01-10 11:55:36 +00:00
|
|
|
params().addParam(new ExpFunction("setText"));
|
2012-12-21 10:21:16 +00:00
|
|
|
params().addParam(new ExpFunction("getChildText"));
|
2022-01-11 09:02:56 +00:00
|
|
|
params().addParam(new ExpFunction("getChildByPath"));
|
|
|
|
params().addParam(new ExpFunction("getChildrenByPath"));
|
|
|
|
params().addParam(new ExpFunction("getTextByPath"));
|
|
|
|
params().addParam(new ExpFunction("getAnyByPath"));
|
2012-12-21 10:21:16 +00:00
|
|
|
params().addParam(new ExpFunction("xmlText"));
|
2018-04-10 11:08:25 +00:00
|
|
|
params().addParam(new ExpFunction("replaceParams"));
|
2018-04-12 12:44:38 +00:00
|
|
|
params().addParam(new ExpFunction("saveFile"));
|
2012-12-21 10:21:16 +00:00
|
|
|
}
|
2020-10-21 11:01:31 +00:00
|
|
|
inline JsXML(ScriptMutex* mtx, unsigned int line, XmlElement* xml, JsXML* owner = 0)
|
|
|
|
: JsObject(mtx,"[object XML]",line,false),
|
2012-12-21 10:21:16 +00:00
|
|
|
m_xml(xml), m_owner(owner)
|
|
|
|
{
|
|
|
|
XDebug(DebugAll,"JsXML::JsXML(%p,%p) [%p]",xml,owner,this);
|
|
|
|
if (owner) {
|
|
|
|
JsObject* proto = YOBJECT(JsObject,owner->params().getParam(protoName()));
|
|
|
|
if (proto && proto->ref())
|
|
|
|
params().addParam(new ExpWrapper(proto,protoName()));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
virtual ~JsXML()
|
|
|
|
{
|
|
|
|
if (m_owner) {
|
|
|
|
m_xml = 0;
|
|
|
|
m_owner = 0;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
TelEngine::destruct(m_xml);
|
|
|
|
}
|
2014-10-29 16:32:20 +00:00
|
|
|
virtual void* getObject(const String& name) const;
|
2012-12-21 10:21:16 +00:00
|
|
|
virtual JsObject* runConstructor(ObjList& stack, const ExpOperation& oper, GenObject* context);
|
2015-09-09 13:05:34 +00:00
|
|
|
virtual void initConstructor(JsFunction* construct)
|
|
|
|
{
|
|
|
|
construct->params().addParam(new ExpOperation((int64_t)0,"PutObject"));
|
|
|
|
construct->params().addParam(new ExpOperation((int64_t)1,"PutText"));
|
|
|
|
construct->params().addParam(new ExpOperation((int64_t)2,"PutBoth"));
|
2018-04-12 12:44:38 +00:00
|
|
|
construct->params().addParam(new ExpFunction("loadFile"));
|
2015-09-09 13:05:34 +00:00
|
|
|
}
|
2012-12-21 10:21:16 +00:00
|
|
|
inline JsXML* owner()
|
|
|
|
{ return m_owner ? (JsXML*)m_owner : this; }
|
|
|
|
inline const XmlElement* element() const
|
|
|
|
{ return m_xml; }
|
|
|
|
static void initialize(ScriptContext* context);
|
|
|
|
protected:
|
|
|
|
bool runNative(ObjList& stack, const ExpOperation& oper, GenObject* context);
|
|
|
|
private:
|
2022-01-11 09:02:56 +00:00
|
|
|
inline ExpWrapper* xmlWrapper(const ExpOperation& oper, const XmlElement* xml)
|
|
|
|
{ return new ExpWrapper(new JsXML(mutex(),oper.lineNumber(),(XmlElement*)xml,owner())); }
|
|
|
|
inline ExpOperation* buildAny(const GenObject* gen, const ExpOperation& oper, GenObject* context) {
|
|
|
|
if (!gen)
|
|
|
|
return 0;
|
|
|
|
GenObject* g = (GenObject*)gen;
|
|
|
|
XmlElement* xml = YOBJECT(XmlElement,g);
|
|
|
|
if (xml)
|
|
|
|
return xmlWrapper(oper,xml);
|
|
|
|
// Attribute ?
|
|
|
|
NamedString* ns = YOBJECT(NamedString,g);
|
|
|
|
if (!ns)
|
|
|
|
return new ExpOperation(g->toString().safe(),"text");
|
|
|
|
JsObject* jso = new JsObject(context,oper.lineNumber(),mutex());
|
|
|
|
jso->setStringField("name",ns->name());
|
|
|
|
jso->setStringField("value",*ns);
|
|
|
|
return new ExpWrapper(jso,"attribute");
|
|
|
|
}
|
2012-12-21 10:21:16 +00:00
|
|
|
static XmlElement* getXml(const String* obj, bool take);
|
2015-08-31 08:09:15 +00:00
|
|
|
static XmlElement* buildXml(const String* name, const String* text = 0);
|
2012-12-21 10:21:16 +00:00
|
|
|
XmlElement* m_xml;
|
|
|
|
RefPointer<JsXML> m_owner;
|
|
|
|
};
|
|
|
|
|
2014-06-11 12:18:01 +00:00
|
|
|
class JsHasher : public JsObject
|
|
|
|
{
|
|
|
|
YCLASS(JsHasher,JsObject)
|
|
|
|
public:
|
2020-10-21 11:01:31 +00:00
|
|
|
inline JsHasher(ScriptMutex* mtx)
|
2014-06-11 12:18:01 +00:00
|
|
|
: JsObject("Hasher",mtx,true),
|
|
|
|
m_hasher(0)
|
|
|
|
{
|
|
|
|
XDebug(DebugAll,"JsHasher::JsHasher() [%p]",this);
|
|
|
|
params().addParam(new ExpFunction("update"));
|
|
|
|
params().addParam(new ExpFunction("hmac"));
|
|
|
|
params().addParam(new ExpFunction("hexDigest"));
|
|
|
|
params().addParam(new ExpFunction("clear"));
|
|
|
|
params().addParam(new ExpFunction("finalize"));
|
|
|
|
params().addParam(new ExpFunction("hashLength"));
|
|
|
|
params().addParam(new ExpFunction("hmacBlockSize"));
|
|
|
|
}
|
2020-10-21 11:01:31 +00:00
|
|
|
inline JsHasher(GenObject* context, ScriptMutex* mtx, unsigned int line, Hasher* h)
|
|
|
|
: JsObject(mtx,"[object Hasher]",line,false),
|
2014-06-11 12:18:01 +00:00
|
|
|
m_hasher(h)
|
|
|
|
{
|
|
|
|
XDebug(DebugAll,"JsHasher::JsHasher(%p) [%p]",m_hasher,this);
|
|
|
|
setPrototype(context,YSTRING("Hasher"));
|
|
|
|
}
|
|
|
|
virtual ~JsHasher()
|
|
|
|
{
|
|
|
|
if (m_hasher) {
|
|
|
|
delete m_hasher;
|
|
|
|
m_hasher = 0;
|
|
|
|
}
|
|
|
|
}
|
2015-02-05 17:58:39 +00:00
|
|
|
virtual void initConstructor(JsFunction* construct)
|
|
|
|
{
|
|
|
|
construct->params().addParam(new ExpFunction("fips186prf"));
|
|
|
|
}
|
2014-06-11 12:18:01 +00:00
|
|
|
virtual JsObject* runConstructor(ObjList& stack, const ExpOperation& oper, GenObject* context);
|
|
|
|
static void initialize(ScriptContext* context);
|
|
|
|
protected:
|
|
|
|
bool runNative(ObjList& stack, const ExpOperation& oper, GenObject* context);
|
|
|
|
private:
|
|
|
|
Hasher* m_hasher;
|
|
|
|
};
|
|
|
|
|
2014-07-14 08:06:41 +00:00
|
|
|
class JsJSON : public JsObject
|
|
|
|
{
|
|
|
|
YCLASS(JsJSON,JsObject)
|
|
|
|
public:
|
2020-10-21 11:01:31 +00:00
|
|
|
inline JsJSON(ScriptMutex* mtx)
|
2014-07-14 08:06:41 +00:00
|
|
|
: JsObject("JSON",mtx,true)
|
|
|
|
{
|
|
|
|
params().addParam(new ExpFunction("parse"));
|
|
|
|
params().addParam(new ExpFunction("stringify"));
|
|
|
|
params().addParam(new ExpFunction("loadFile"));
|
|
|
|
params().addParam(new ExpFunction("saveFile"));
|
2018-04-10 12:16:20 +00:00
|
|
|
params().addParam(new ExpFunction("replaceParams"));
|
2021-10-27 10:22:53 +00:00
|
|
|
params().addParam(new ExpFunction("replaceReferences"));
|
|
|
|
params().addParam(new ExpFunction("findPath"));
|
2014-07-14 08:06:41 +00:00
|
|
|
}
|
|
|
|
static void initialize(ScriptContext* context);
|
|
|
|
protected:
|
|
|
|
bool runNative(ObjList& stack, const ExpOperation& oper, GenObject* context);
|
2018-04-10 12:16:20 +00:00
|
|
|
void replaceParams(GenObject* obj, const NamedList& params, bool sqlEsc, char extraEsc);
|
2014-07-14 08:06:41 +00:00
|
|
|
};
|
|
|
|
|
2014-07-22 11:04:28 +00:00
|
|
|
class JsDNS : public JsObject
|
|
|
|
{
|
|
|
|
YCLASS(JsDNS,JsObject)
|
|
|
|
public:
|
2020-10-21 11:01:31 +00:00
|
|
|
inline JsDNS(ScriptMutex* mtx)
|
2014-07-22 11:04:28 +00:00
|
|
|
: JsObject("DNS",mtx,true)
|
|
|
|
{
|
|
|
|
params().addParam(new ExpFunction("query"));
|
|
|
|
params().addParam(new ExpFunction("queryA"));
|
|
|
|
params().addParam(new ExpFunction("queryAaaa"));
|
|
|
|
params().addParam(new ExpFunction("queryNaptr"));
|
|
|
|
params().addParam(new ExpFunction("querySrv"));
|
|
|
|
params().addParam(new ExpFunction("queryTxt"));
|
2014-08-26 17:21:36 +00:00
|
|
|
params().addParam(new ExpFunction("resolve"));
|
|
|
|
params().addParam(new ExpFunction("local"));
|
2014-12-18 15:11:42 +00:00
|
|
|
params().addParam(new ExpFunction("pack"));
|
|
|
|
params().addParam(new ExpFunction("unpack"));
|
2017-11-17 15:57:31 +00:00
|
|
|
params().addParam(new ExpFunction("dscp"));
|
2014-07-22 11:04:28 +00:00
|
|
|
}
|
|
|
|
static void initialize(ScriptContext* context);
|
2020-10-21 11:01:31 +00:00
|
|
|
void runQuery(ObjList& stack, const String& name, Resolver::Type type, GenObject* context, unsigned int lineNo);
|
2014-07-22 11:04:28 +00:00
|
|
|
protected:
|
|
|
|
bool runNative(ObjList& stack, const ExpOperation& oper, GenObject* context);
|
|
|
|
};
|
|
|
|
|
2012-02-17 16:19:17 +00:00
|
|
|
class JsChannel : public JsObject
|
|
|
|
{
|
|
|
|
YCLASS(JsChannel,JsObject)
|
|
|
|
public:
|
2020-10-21 11:01:31 +00:00
|
|
|
inline JsChannel(JsAssist* assist, ScriptMutex* mtx)
|
2012-06-20 14:02:18 +00:00
|
|
|
: JsObject("Channel",mtx,false), m_assist(assist)
|
2012-02-17 16:19:17 +00:00
|
|
|
{
|
|
|
|
params().addParam(new ExpFunction("id"));
|
2012-06-20 14:02:18 +00:00
|
|
|
params().addParam(new ExpFunction("peerid"));
|
2012-03-05 09:53:31 +00:00
|
|
|
params().addParam(new ExpFunction("status"));
|
2012-06-20 14:02:18 +00:00
|
|
|
params().addParam(new ExpFunction("direction"));
|
2012-06-22 14:42:41 +00:00
|
|
|
params().addParam(new ExpFunction("answered"));
|
2012-03-05 09:53:31 +00:00
|
|
|
params().addParam(new ExpFunction("answer"));
|
|
|
|
params().addParam(new ExpFunction("hangup"));
|
|
|
|
params().addParam(new ExpFunction("callTo"));
|
2012-06-20 14:02:18 +00:00
|
|
|
params().addParam(new ExpFunction("callJust"));
|
2012-03-05 09:53:31 +00:00
|
|
|
params().addParam(new ExpFunction("playFile"));
|
|
|
|
params().addParam(new ExpFunction("recFile"));
|
2012-02-17 16:19:17 +00:00
|
|
|
}
|
|
|
|
static void initialize(ScriptContext* context, JsAssist* assist);
|
|
|
|
protected:
|
|
|
|
bool runNative(ObjList& stack, const ExpOperation& oper, GenObject* context);
|
2014-02-26 14:57:57 +00:00
|
|
|
void callToRoute(ObjList& stack, const ExpOperation& oper, GenObject* context, const NamedList* params);
|
|
|
|
void callToReRoute(ObjList& stack, const ExpOperation& oper, GenObject* context, const NamedList* params);
|
2012-02-17 16:19:17 +00:00
|
|
|
JsAssist* m_assist;
|
|
|
|
};
|
2012-02-10 14:53:55 +00:00
|
|
|
|
2012-06-22 09:38:51 +00:00
|
|
|
class JsEngAsync : public ScriptAsync
|
|
|
|
{
|
|
|
|
YCLASS(JsEngAsync,ScriptAsync)
|
|
|
|
public:
|
|
|
|
enum Oper {
|
|
|
|
AsyncSleep,
|
|
|
|
AsyncUsleep,
|
|
|
|
AsyncYield,
|
|
|
|
AsyncIdle
|
|
|
|
};
|
2013-08-07 09:49:52 +00:00
|
|
|
inline JsEngAsync(ScriptRun* runner, Oper op, int64_t val = 0)
|
2012-06-22 09:38:51 +00:00
|
|
|
: ScriptAsync(runner),
|
|
|
|
m_oper(op), m_val(val)
|
2013-08-07 09:49:52 +00:00
|
|
|
{ XDebug(DebugAll,"JsEngAsync %d " FMT64,op,val); }
|
2012-06-22 09:38:51 +00:00
|
|
|
virtual bool run();
|
|
|
|
private:
|
|
|
|
Oper m_oper;
|
2013-08-07 09:49:52 +00:00
|
|
|
int64_t m_val;
|
2012-06-22 09:38:51 +00:00
|
|
|
};
|
|
|
|
|
2013-04-12 15:18:50 +00:00
|
|
|
class JsMsgAsync : public ScriptAsync
|
|
|
|
{
|
|
|
|
YCLASS(JsMsgAsync,ScriptAsync)
|
|
|
|
public:
|
2017-11-01 16:37:48 +00:00
|
|
|
inline JsMsgAsync(ScriptRun* runner, ObjList* stack, JsMessage* jsMsg, Message* msg, bool owned)
|
2013-04-12 15:18:50 +00:00
|
|
|
: ScriptAsync(runner),
|
2017-11-01 16:37:48 +00:00
|
|
|
m_stack(stack), m_msg(jsMsg), m_message(msg), m_owned(owned)
|
2013-04-12 15:18:50 +00:00
|
|
|
{ XDebug(DebugAll,"JsMsgAsync"); }
|
|
|
|
virtual bool run()
|
2017-11-01 16:37:48 +00:00
|
|
|
{ m_msg->runAsync(*m_stack,m_message,m_owned); return true; }
|
2013-04-12 15:18:50 +00:00
|
|
|
private:
|
|
|
|
ObjList* m_stack;
|
|
|
|
RefPointer<JsMessage> m_msg;
|
|
|
|
Message* m_message;
|
2017-11-01 16:37:48 +00:00
|
|
|
bool m_owned;
|
2013-04-12 15:18:50 +00:00
|
|
|
};
|
|
|
|
|
2017-08-01 06:20:58 +00:00
|
|
|
class JsSemaphoreAsync : public ScriptAsync
|
|
|
|
{
|
|
|
|
YCLASS(JsSemaphoreAsync,ScriptAsync)
|
|
|
|
public:
|
|
|
|
inline JsSemaphoreAsync(ScriptRun* runner, ObjList* stack, JsSemaphore* se, long wait)
|
|
|
|
: ScriptAsync(runner), m_stack(stack), m_semaphore(se), m_wait(wait)
|
|
|
|
{ XDebug(DebugAll,"JsSemaphoreAsync(%p, %ld) [%p]",se,wait,this); }
|
|
|
|
|
|
|
|
virtual ~JsSemaphoreAsync()
|
|
|
|
{ XDebug(DebugAll,"~JsSemaphoreAsync() [%p]",this); }
|
|
|
|
virtual bool run()
|
|
|
|
{
|
|
|
|
if (m_wait > 0)
|
|
|
|
m_wait *= 1000;
|
|
|
|
m_semaphore->runAsync(*m_stack, m_wait);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
private:
|
|
|
|
ObjList* m_stack;
|
|
|
|
RefPointer<JsSemaphore> m_semaphore;
|
|
|
|
long m_wait;
|
|
|
|
};
|
|
|
|
|
2014-07-22 11:04:28 +00:00
|
|
|
class JsDnsAsync : public ScriptAsync
|
|
|
|
{
|
|
|
|
YCLASS(JsDnsAsync,ScriptAsync)
|
|
|
|
public:
|
|
|
|
inline JsDnsAsync(ScriptRun* runner, JsDNS* jsDns, ObjList* stack,
|
2020-10-21 11:01:31 +00:00
|
|
|
const String& name, Resolver::Type type, GenObject* context, unsigned int lineNo)
|
2014-07-22 11:04:28 +00:00
|
|
|
: ScriptAsync(runner),
|
2020-10-21 11:01:31 +00:00
|
|
|
m_stack(stack), m_name(name), m_type(type), m_context(context), m_dns(jsDns), m_lineNo(lineNo)
|
2014-07-22 11:04:28 +00:00
|
|
|
{ XDebug(DebugAll,"JsDnsAsync"); }
|
|
|
|
virtual bool run()
|
2020-10-21 11:01:31 +00:00
|
|
|
{ m_dns->runQuery(*m_stack,m_name,m_type,m_context,m_lineNo); return true; }
|
2014-07-22 11:04:28 +00:00
|
|
|
private:
|
|
|
|
ObjList* m_stack;
|
|
|
|
String m_name;
|
|
|
|
Resolver::Type m_type;
|
|
|
|
GenObject* m_context;
|
|
|
|
RefPointer<JsDNS> m_dns;
|
2020-10-21 11:01:31 +00:00
|
|
|
unsigned int m_lineNo;
|
2014-07-22 11:04:28 +00:00
|
|
|
};
|
|
|
|
|
2015-11-12 21:29:55 +00:00
|
|
|
class JsPostExecute : public MessagePostHook
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
virtual void dispatched(const Message& msg, bool handled)
|
|
|
|
{ if (msg == YSTRING("call.execute")) __plugin.msgPostExecute(msg,handled); }
|
|
|
|
};
|
|
|
|
|
2012-02-17 16:19:17 +00:00
|
|
|
static String s_basePath;
|
2014-03-14 14:45:41 +00:00
|
|
|
static String s_libsPath;
|
2013-04-12 12:46:21 +00:00
|
|
|
static bool s_engineStop = false;
|
2012-11-20 16:08:25 +00:00
|
|
|
static bool s_allowAbort = false;
|
2013-04-12 12:46:21 +00:00
|
|
|
static bool s_allowTrace = false;
|
2013-02-14 14:37:20 +00:00
|
|
|
static bool s_allowLink = true;
|
2020-10-14 13:24:46 +00:00
|
|
|
static bool s_trackObj = false;
|
2020-10-21 11:01:31 +00:00
|
|
|
static unsigned int s_trackCreation = 0;
|
2014-08-06 08:08:06 +00:00
|
|
|
static bool s_autoExt = true;
|
2016-05-18 13:31:47 +00:00
|
|
|
static unsigned int s_maxFile = 500000;
|
2012-02-17 16:19:17 +00:00
|
|
|
|
2012-02-10 14:53:55 +00:00
|
|
|
UNLOAD_PLUGIN(unloadNow)
|
|
|
|
{
|
2012-06-16 23:21:13 +00:00
|
|
|
if (unloadNow) {
|
2013-04-12 12:46:21 +00:00
|
|
|
s_engineStop = true;
|
2012-06-16 23:21:13 +00:00
|
|
|
JsGlobal::unloadAll();
|
2012-02-10 14:53:55 +00:00
|
|
|
return __plugin.unload();
|
2012-06-16 23:21:13 +00:00
|
|
|
}
|
2012-02-10 14:53:55 +00:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2014-08-06 08:08:06 +00:00
|
|
|
// Load extensions in a script context
|
|
|
|
static bool contextLoad(ScriptContext* ctx, const char* name, const char* libs = 0, const char* objs = 0)
|
|
|
|
{
|
|
|
|
if (!ctx)
|
|
|
|
return false;
|
|
|
|
bool start = !(libs || objs);
|
|
|
|
Message msg("script.init",0,start);
|
|
|
|
msg.userData(ctx);
|
|
|
|
msg.addParam("module",__plugin.name());
|
|
|
|
msg.addParam("language","javascript");
|
|
|
|
msg.addParam("startup",String::boolText(start));
|
|
|
|
if (name)
|
|
|
|
msg.addParam("instance",name);
|
|
|
|
if (libs)
|
|
|
|
msg.addParam("libraries",libs);
|
|
|
|
if (objs)
|
|
|
|
msg.addParam("objects",objs);
|
|
|
|
return Engine::dispatch(msg);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Load extensions in a script runner context
|
|
|
|
static bool contextLoad(ScriptRun* runner, const char* name, const char* libs = 0, const char* objs = 0)
|
|
|
|
{
|
|
|
|
return runner && contextLoad(runner->context(),name,libs,objs);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Initialize a script context, populate global objects
|
|
|
|
static void contextInit(ScriptRun* runner, const char* name = 0, JsAssist* assist = 0)
|
|
|
|
{
|
|
|
|
if (!runner)
|
|
|
|
return;
|
|
|
|
ScriptContext* ctx = runner->context();
|
|
|
|
if (!ctx)
|
|
|
|
return;
|
|
|
|
JsObject::initialize(ctx);
|
2015-08-27 10:58:42 +00:00
|
|
|
JsEngine::initialize(ctx,name);
|
2014-08-06 08:08:06 +00:00
|
|
|
if (assist)
|
|
|
|
JsChannel::initialize(ctx,assist);
|
|
|
|
JsMessage::initialize(ctx);
|
|
|
|
JsFile::initialize(ctx);
|
|
|
|
JsConfigFile::initialize(ctx);
|
|
|
|
JsXML::initialize(ctx);
|
|
|
|
JsHasher::initialize(ctx);
|
|
|
|
JsJSON::initialize(ctx);
|
|
|
|
JsDNS::initialize(ctx);
|
2021-09-28 10:55:08 +00:00
|
|
|
JsShared::initialize(ctx);
|
2022-01-11 09:02:56 +00:00
|
|
|
JsXPath::initialize(ctx);
|
2014-08-06 08:08:06 +00:00
|
|
|
if (s_autoExt)
|
|
|
|
contextLoad(ctx,name);
|
|
|
|
}
|
|
|
|
|
2020-10-21 11:01:31 +00:00
|
|
|
// sort list of object allocations descending
|
|
|
|
static int counterSort(GenObject* obj1, GenObject* obj2, void* context)
|
|
|
|
{
|
|
|
|
const NamedCounter* s1 = static_cast<NamedCounter*>(obj1);
|
|
|
|
const NamedCounter* s2 = static_cast<NamedCounter*>(obj2);
|
|
|
|
int c1 = s1 ? s1->count() : 0;
|
|
|
|
int c2 = s2 ? s2->count() : 0;
|
|
|
|
return c1 < c2 ? 1 : (c1 > c2 ? -1 : 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Obtain a string with top object allocations from context ctx
|
|
|
|
static bool evalCtxtAllocations(String& retVal, unsigned int count, ScriptContext* ctx,
|
|
|
|
ScriptCode* code, const String& scrName)
|
|
|
|
{
|
|
|
|
if (!(ctx && code)) {
|
|
|
|
retVal << "Script '" << scrName << "' has no associated context\r\n";
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
ObjList* objCounters = ctx->countAllocations();
|
|
|
|
if (!objCounters) {
|
|
|
|
retVal << "Script '" << scrName << "' has no active object tracking\r\n";
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
objCounters->sort(counterSort);
|
|
|
|
String tmp;
|
|
|
|
unsigned int i = 0;
|
|
|
|
for (ObjList* o = objCounters->skipNull(); o && i < count; o = o->skipNext(), i++) {
|
|
|
|
NamedCounter* c = static_cast<NamedCounter*>(o->get());
|
|
|
|
uint64_t line = c->toString().toUInt64();
|
|
|
|
String fn;
|
|
|
|
unsigned int fl = 0;
|
|
|
|
code->getFileLine(line,fn,fl,false);
|
|
|
|
tmp << "\r\n" << fn << ":" << fl << " " << c->count();
|
|
|
|
}
|
|
|
|
if (!tmp)
|
|
|
|
retVal << "Script '" << scrName << "' has no active object tracking counters\r\n";
|
|
|
|
else
|
|
|
|
retVal << "Top " << count << " object allocations for '" << scrName <<"':" << tmp << "\r\n";
|
|
|
|
TelEngine::destruct(objCounters);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2018-04-10 11:08:25 +00:00
|
|
|
// Utility: return a list of parameters to be used for replaceParams
|
|
|
|
static inline const NamedList* getReplaceParams(GenObject* gen)
|
|
|
|
{
|
|
|
|
JsObject* obj = YOBJECT(JsObject,gen);
|
|
|
|
if (obj) {
|
|
|
|
if (obj->nativeParams())
|
|
|
|
return obj->nativeParams();
|
|
|
|
return &obj->params();
|
|
|
|
}
|
|
|
|
return YOBJECT(NamedList,gen);
|
|
|
|
}
|
|
|
|
|
2014-08-06 14:38:28 +00:00
|
|
|
// Build a tabular dump of an Object or Array
|
2021-12-13 07:29:32 +00:00
|
|
|
static void dumpTable(const ExpOperation& oper, String& str, const char* eol,
|
|
|
|
const NamedList* hdrMap = 0, bool forceEmpty = false, bool allHeaders = false)
|
2014-08-06 14:38:28 +00:00
|
|
|
{
|
|
|
|
class Header : public ObjList
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
Header(const char* name)
|
2021-10-07 12:49:07 +00:00
|
|
|
: m_name(new String(name)), m_rows(0)
|
|
|
|
{ set(m_name); m_width = m_name->length(); }
|
2014-08-06 14:38:28 +00:00
|
|
|
virtual const String& toString() const
|
2021-10-07 12:49:07 +00:00
|
|
|
{ return *m_name; }
|
2014-08-06 14:38:28 +00:00
|
|
|
inline unsigned int width() const
|
|
|
|
{ return m_width; }
|
|
|
|
inline unsigned int rows() const
|
|
|
|
{ return m_rows; }
|
|
|
|
inline void setWidth(unsigned int w)
|
|
|
|
{ if (m_width < w) m_width = w; }
|
2021-12-13 07:29:32 +00:00
|
|
|
inline void setName(const char* n) {
|
|
|
|
if (TelEngine::null(n))
|
|
|
|
return;
|
|
|
|
*m_name = n;
|
|
|
|
setWidth(m_name->length());
|
|
|
|
}
|
|
|
|
inline void addString(const String& val, unsigned int row) {
|
2021-10-07 12:49:07 +00:00
|
|
|
if (row <= m_rows)
|
|
|
|
return;
|
|
|
|
setWidth(val.length());
|
|
|
|
ObjList* a = this;
|
2014-08-06 14:38:28 +00:00
|
|
|
while (++m_rows < row)
|
2021-10-07 12:49:07 +00:00
|
|
|
a = a->append(0,false);
|
|
|
|
a->append(new String(val),false);
|
2014-08-06 14:38:28 +00:00
|
|
|
}
|
|
|
|
inline const String* getString(unsigned int row) const
|
2021-10-07 12:49:07 +00:00
|
|
|
{ return (row < m_rows) ? static_cast<const String*>(at(++row)) : 0; }
|
2014-08-06 14:38:28 +00:00
|
|
|
private:
|
2021-10-07 12:49:07 +00:00
|
|
|
String* m_name;
|
2014-08-06 14:38:28 +00:00
|
|
|
unsigned int m_width;
|
|
|
|
unsigned int m_rows;
|
|
|
|
};
|
|
|
|
|
|
|
|
const JsObject* jso = YOBJECT(JsObject,&oper);
|
|
|
|
if (!jso || JsParser::isNull(oper)) {
|
|
|
|
if (JsParser::isUndefined(oper))
|
|
|
|
str = "undefined";
|
|
|
|
else
|
|
|
|
str = oper;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
ObjList header;
|
|
|
|
const JsArray* jsa = YOBJECT(JsArray,jso);
|
|
|
|
if (jsa) {
|
2021-10-07 12:49:07 +00:00
|
|
|
// Array. Each item is a table row
|
|
|
|
// Array of Objects: each row is an object, property names are header string
|
2014-08-06 14:38:28 +00:00
|
|
|
// [ { name1: "val11", name2: "val12" }, { name1: "val21", name3: "val23" } ]
|
2021-10-07 12:49:07 +00:00
|
|
|
// Array of Arrays: each row is an array of strings, first row contains header strings
|
|
|
|
// [ [ "name1", "name2", "name3" ], [ "val11", "val12" ], ["val21", undefined, "val23" ] ]
|
|
|
|
const JsArray* jsaRow = 0;
|
|
|
|
unsigned int cols = 0;
|
2014-08-06 14:38:28 +00:00
|
|
|
unsigned int row = 0;
|
|
|
|
for (int i = 0; i < jsa->length(); i++) {
|
|
|
|
jso = YOBJECT(JsObject,jsa->params().getParam(String(i)));
|
|
|
|
if (!jso)
|
|
|
|
continue;
|
2021-10-07 12:49:07 +00:00
|
|
|
if (!i)
|
|
|
|
jsaRow = YOBJECT(JsArray,jso);
|
|
|
|
if (jsaRow) {
|
|
|
|
const JsArray* a = i ? YOBJECT(JsArray,jso) : jsaRow;
|
|
|
|
if (!a)
|
|
|
|
continue;
|
|
|
|
if (i) {
|
|
|
|
row++;
|
|
|
|
unsigned int n = a->length();
|
|
|
|
if (n > cols)
|
|
|
|
n = cols;
|
|
|
|
ObjList* hdr = &header;
|
|
|
|
for (unsigned int j = 0; j < n; j++, hdr = hdr->next()) {
|
|
|
|
const NamedString* ns = a->params().getParam(String(j));
|
|
|
|
if (ns)
|
|
|
|
(static_cast<Header*>(hdr->get()))->addString(*ns,row);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
for (unsigned int j = 0; j < (unsigned int)a->length(); j++) {
|
|
|
|
const NamedString* ns = a->params().getParam(String(j));
|
|
|
|
if (!ns)
|
|
|
|
continue;
|
|
|
|
cols++;
|
|
|
|
header.append(new Header(*ns));
|
|
|
|
}
|
|
|
|
if (!cols)
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
continue;
|
|
|
|
}
|
2021-12-13 07:29:32 +00:00
|
|
|
// Array of objects
|
2021-10-07 12:49:07 +00:00
|
|
|
row++;
|
2014-08-06 14:38:28 +00:00
|
|
|
for (ObjList* l = jso->params().paramList()->skipNull(); l; l = l->skipNext()) {
|
|
|
|
const NamedString* ns = static_cast<const NamedString*>(l->get());
|
|
|
|
if (ns->name() == JsObject::protoName())
|
|
|
|
continue;
|
|
|
|
Header* h = static_cast<Header*>(header[ns->name()]);
|
|
|
|
if (!h) {
|
|
|
|
h = new Header(ns->name());
|
|
|
|
header.append(h);
|
|
|
|
}
|
|
|
|
h->addString(*ns,row);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
// Object containing Arrays
|
2021-10-07 12:49:07 +00:00
|
|
|
// Each propery is a column in table
|
2014-08-06 14:38:28 +00:00
|
|
|
// { name1: [ "val11", "val21" ], name2: [ "val12" ], name3: [ undefined, "val23" ] }
|
|
|
|
for (ObjList* l = jso->params().paramList()->skipNull(); l; l = l->skipNext()) {
|
|
|
|
const NamedString* ns = static_cast<const NamedString*>(l->get());
|
|
|
|
jsa = YOBJECT(JsArray,ns);
|
|
|
|
if (!jsa)
|
|
|
|
continue;
|
|
|
|
Header* h = new Header(ns->name());
|
|
|
|
header.append(h);
|
|
|
|
for (int r = 0; r < jsa->length(); r++) {
|
|
|
|
ns = jsa->params().getParam(String(r));
|
2021-10-07 12:49:07 +00:00
|
|
|
if (ns)
|
2014-08-06 14:38:28 +00:00
|
|
|
h->addString(*ns,r + 1);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2021-12-13 07:29:32 +00:00
|
|
|
if (!header.skipNull()) {
|
|
|
|
if (!(hdrMap && forceEmpty))
|
|
|
|
return;
|
|
|
|
for (ObjList* o = hdrMap->paramList()->skipNull(); o; o = o->skipNext()) {
|
|
|
|
NamedString* ns = static_cast<NamedString*>(o->get());
|
|
|
|
if (ns->name() != JsObject::protoName())
|
|
|
|
header.append(new Header(ns->name()));
|
|
|
|
}
|
|
|
|
if (!header.skipNull())
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
// Re-arrange headers
|
|
|
|
ObjList* hdrs = &header;
|
|
|
|
ObjList newHdrs;
|
|
|
|
if (hdrMap) {
|
|
|
|
hdrs = &newHdrs;
|
|
|
|
ObjList* hAdd = hdrs;
|
|
|
|
for (ObjList* o = hdrMap->paramList()->skipNull(); o; o = o->skipNext()) {
|
|
|
|
NamedString* ns = static_cast<NamedString*>(o->get());
|
|
|
|
if (ns->name() == JsObject::protoName())
|
|
|
|
continue;
|
|
|
|
ObjList* oh = header.find(ns->name());
|
|
|
|
Header* h = oh ? static_cast<Header*>(oh->remove(false)) : new Header(ns->name());
|
|
|
|
h->setName(*ns);
|
|
|
|
hAdd = hAdd->append(h);
|
|
|
|
}
|
|
|
|
if (allHeaders) {
|
|
|
|
while (true) {
|
|
|
|
ObjList* o = header.skipNull();
|
|
|
|
if (!o)
|
|
|
|
break;
|
|
|
|
hAdd = hAdd->append(o->remove(false));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2014-08-06 14:38:28 +00:00
|
|
|
str.clear();
|
|
|
|
String tmp;
|
|
|
|
unsigned int rows = 0;
|
2021-12-13 07:29:32 +00:00
|
|
|
for (ObjList* l = hdrs->skipNull(); l; l = l->skipNext()) {
|
2014-08-06 14:38:28 +00:00
|
|
|
Header* h = static_cast<Header*>(l->get());
|
|
|
|
if (rows < h->rows())
|
|
|
|
rows = h->rows();
|
|
|
|
str.append(h->toString()," ",true);
|
|
|
|
unsigned int sp = h->width() - h->toString().length();
|
|
|
|
if (sp)
|
|
|
|
str << String(' ',sp);
|
|
|
|
tmp.append(String('-',h->width())," ",true);
|
|
|
|
}
|
2021-12-13 07:29:32 +00:00
|
|
|
if (!tmp)
|
|
|
|
return;
|
|
|
|
if (!(rows || forceEmpty))
|
2014-08-06 14:38:28 +00:00
|
|
|
return;
|
|
|
|
str << eol << tmp << eol;
|
|
|
|
for (unsigned int r = 0; r < rows; r++) {
|
|
|
|
tmp.clear();
|
|
|
|
// add each row data
|
2021-12-13 07:29:32 +00:00
|
|
|
for (ObjList* l = hdrs->skipNull(); l; l = l->skipNext()) {
|
2014-08-06 14:38:28 +00:00
|
|
|
Header* h = static_cast<Header*>(l->get());
|
|
|
|
const String* s = h->getString(r);
|
|
|
|
if (!s)
|
|
|
|
s = &String::empty();
|
|
|
|
tmp.append(*s," ",true);
|
|
|
|
unsigned int sp = h->width() - s->length();
|
|
|
|
if (sp)
|
|
|
|
tmp << String(' ',sp);
|
|
|
|
}
|
|
|
|
str << tmp << eol;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-06-11 12:18:01 +00:00
|
|
|
// Extract arguments from stack
|
|
|
|
// Maximum allowed number of arguments is given by arguments to extract
|
|
|
|
// Return false if the number of arguments is not the expected one
|
|
|
|
static bool extractStackArgs(int minArgc, JsObject* obj,
|
|
|
|
ObjList& stack, const ExpOperation& oper, GenObject* context, ObjList& args,
|
2020-10-14 10:38:31 +00:00
|
|
|
ExpOperation** op1, ExpOperation** op2 = 0, ExpOperation** op3 = 0)
|
2014-06-11 12:18:01 +00:00
|
|
|
{
|
|
|
|
if (!obj)
|
|
|
|
return false;
|
|
|
|
int argc = obj->extractArgs(stack,oper,context,args);
|
|
|
|
if (minArgc > argc)
|
|
|
|
return false;
|
|
|
|
switch (argc) {
|
|
|
|
#define EXTRACT_ARG_CHECK(var,n) { \
|
|
|
|
case n: \
|
|
|
|
if (!var) \
|
|
|
|
return false; \
|
|
|
|
*var = static_cast<ExpOperation*>(args[n - 1]); \
|
|
|
|
}
|
|
|
|
EXTRACT_ARG_CHECK(op3,3);
|
|
|
|
EXTRACT_ARG_CHECK(op2,2);
|
|
|
|
EXTRACT_ARG_CHECK(op1,1);
|
|
|
|
return true;
|
|
|
|
#undef EXTRACT_ARG_CHECK
|
2020-10-14 10:38:31 +00:00
|
|
|
case 0:
|
|
|
|
if (!minArgc)
|
|
|
|
return true;
|
2014-06-11 12:18:01 +00:00
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
2012-02-17 16:19:17 +00:00
|
|
|
|
2015-11-24 15:38:35 +00:00
|
|
|
// Copy parameters from one list to another skipping those starting with two underlines
|
|
|
|
static void copyObjParams(NamedList& dest, const NamedList* src)
|
|
|
|
{
|
|
|
|
if (!src)
|
|
|
|
return;
|
2018-04-12 12:44:38 +00:00
|
|
|
for (const ObjList* o = src->paramList()->skipNull(); o; o = o->skipNext()) {
|
|
|
|
const NamedString* p = static_cast<const NamedString*>(o->get());
|
|
|
|
if (!(p->name().startsWith("__") || YOBJECT(ExpWrapper,p)))
|
2015-11-24 15:38:35 +00:00
|
|
|
dest.setParam(p->name(),*p);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-11-26 11:17:24 +00:00
|
|
|
static void copyArgList(ObjList& dst, ObjList& args)
|
|
|
|
{
|
|
|
|
for (ObjList* o = &args; o; o = o->next()) {
|
|
|
|
ExpOperation* param = static_cast<ExpOperation*>(o->get());
|
|
|
|
if (param)
|
|
|
|
dst.append(param->clone());
|
|
|
|
}
|
|
|
|
}
|
2015-11-24 15:38:35 +00:00
|
|
|
|
2012-06-22 09:38:51 +00:00
|
|
|
bool JsEngAsync::run()
|
|
|
|
{
|
|
|
|
switch (m_oper) {
|
|
|
|
case AsyncSleep:
|
2013-08-07 11:24:10 +00:00
|
|
|
Thread::sleep((unsigned int)m_val);
|
2012-06-22 09:38:51 +00:00
|
|
|
break;
|
|
|
|
case AsyncUsleep:
|
2013-08-07 11:24:10 +00:00
|
|
|
Thread::usleep((unsigned long)m_val);
|
2012-06-22 09:38:51 +00:00
|
|
|
break;
|
|
|
|
case AsyncYield:
|
|
|
|
Thread::yield();
|
|
|
|
break;
|
|
|
|
case AsyncIdle:
|
|
|
|
Thread::idle();
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2012-02-17 16:19:17 +00:00
|
|
|
bool JsEngine::runNative(ObjList& stack, const ExpOperation& oper, GenObject* context)
|
|
|
|
{
|
2012-05-02 15:11:48 +00:00
|
|
|
if (oper.name() == YSTRING("output")) {
|
2012-02-17 16:19:17 +00:00
|
|
|
String str;
|
2013-08-07 11:24:10 +00:00
|
|
|
for (int i = (int)oper.number(); i; i--) {
|
2012-02-17 16:19:17 +00:00
|
|
|
ExpOperation* op = popValue(stack,context);
|
2021-05-17 08:42:30 +00:00
|
|
|
if (!op)
|
|
|
|
continue;
|
2021-04-16 10:24:17 +00:00
|
|
|
if (*op) {
|
|
|
|
if (str)
|
|
|
|
str = *op + " " + str;
|
|
|
|
else
|
|
|
|
str = *op;
|
|
|
|
}
|
2012-05-30 08:32:47 +00:00
|
|
|
TelEngine::destruct(op);
|
2012-02-17 16:19:17 +00:00
|
|
|
}
|
2020-04-22 12:05:53 +00:00
|
|
|
if (str) {
|
|
|
|
const String& traceId = YOBJECT(ScriptRun,context) ? context->traceId() : String::empty();
|
|
|
|
if (traceId)
|
|
|
|
Output("Trace:%s %s",traceId.c_str(),str.c_str());
|
|
|
|
else
|
|
|
|
Output("%s",str.c_str());
|
|
|
|
}
|
2012-02-17 16:19:17 +00:00
|
|
|
}
|
2012-05-02 15:11:48 +00:00
|
|
|
else if (oper.name() == YSTRING("debug")) {
|
2012-02-17 16:19:17 +00:00
|
|
|
int level = DebugNote;
|
|
|
|
String str;
|
2013-08-07 11:24:10 +00:00
|
|
|
for (int i = (int)oper.number(); i; i--) {
|
2012-02-17 16:19:17 +00:00
|
|
|
ExpOperation* op = popValue(stack,context);
|
2012-03-05 09:53:31 +00:00
|
|
|
if (!op)
|
|
|
|
continue;
|
2012-02-17 16:19:17 +00:00
|
|
|
if ((i == 1) && oper.number() > 1 && op->isInteger())
|
2013-08-07 11:24:10 +00:00
|
|
|
level = (int)op->number();
|
2012-03-05 09:53:31 +00:00
|
|
|
else if (*op) {
|
2012-02-17 16:19:17 +00:00
|
|
|
if (str)
|
|
|
|
str = *op + " " + str;
|
|
|
|
else
|
|
|
|
str = *op;
|
|
|
|
}
|
2012-05-30 08:32:47 +00:00
|
|
|
TelEngine::destruct(op);
|
2012-02-17 16:19:17 +00:00
|
|
|
}
|
|
|
|
if (str) {
|
2013-11-01 14:36:18 +00:00
|
|
|
int limit = s_allowAbort ? DebugFail : DebugTest;
|
2012-02-17 16:19:17 +00:00
|
|
|
if (level > DebugAll)
|
|
|
|
level = DebugAll;
|
2012-11-20 16:08:25 +00:00
|
|
|
else if (level < limit)
|
|
|
|
level = limit;
|
2020-04-22 12:05:53 +00:00
|
|
|
TraceDebug(YOBJECT(ScriptRun,context) ? context->traceId() : "",this,level,"%s",str.c_str());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (oper.name() == YSTRING("traceDebug") || oper.name() == YSTRING("trace")) {
|
|
|
|
ObjList args;
|
|
|
|
unsigned int c = extractArgs(stack,oper,context,args);
|
|
|
|
if (c < 2)
|
|
|
|
return false;
|
|
|
|
ExpOperation* traceID = static_cast<ExpOperation*>(args[0]);
|
|
|
|
ExpOperation* op = static_cast<ExpOperation*>(args[1]);
|
|
|
|
|
|
|
|
int level = DebugNote;
|
|
|
|
int limit = s_allowAbort ? DebugFail : DebugTest;
|
|
|
|
if (op->number() > 1 && op->isInteger()) {
|
|
|
|
level = (int)op->number();
|
|
|
|
if (level > DebugAll)
|
|
|
|
level = DebugAll;
|
|
|
|
else if (level < limit)
|
|
|
|
level = limit;
|
|
|
|
}
|
|
|
|
|
|
|
|
String str;
|
|
|
|
for (unsigned int i = 2; i < c; i++) {
|
|
|
|
ExpOperation* op = static_cast<ExpOperation*>(args[i]);
|
|
|
|
if (!op)
|
|
|
|
continue;
|
|
|
|
else if (*op) {
|
|
|
|
if (str)
|
|
|
|
str << " ";
|
|
|
|
str << *op;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (str) {
|
|
|
|
const char* t = 0;
|
|
|
|
if (!(TelEngine::null(*traceID) || JsParser::isNull(*traceID)))
|
|
|
|
t = *traceID;
|
|
|
|
if (oper.name() == YSTRING("trace"))
|
|
|
|
Trace(t,this,level,"%s",str.c_str());
|
|
|
|
else
|
|
|
|
TraceDebug(t,this,level,"%s",str.c_str());
|
2012-02-17 16:19:17 +00:00
|
|
|
}
|
|
|
|
}
|
2020-04-22 12:05:53 +00:00
|
|
|
else if (oper.name() == YSTRING("alarm") || oper.name() == YSTRING("traceAlarm")) {
|
|
|
|
int idx = (oper.name() == YSTRING("traceAlarm")) ? 1 : 0;
|
|
|
|
if (oper.number() < 2 + idx)
|
2013-07-05 12:50:18 +00:00
|
|
|
return false;
|
|
|
|
int level = -1;
|
|
|
|
String info;
|
|
|
|
String str;
|
2020-04-22 12:05:53 +00:00
|
|
|
String traceId = YOBJECT(ScriptRun,context) ? context->traceId() : String::empty();
|
2013-08-07 11:24:10 +00:00
|
|
|
for (int i = (int)oper.number(); i; i--) {
|
2013-07-05 12:50:18 +00:00
|
|
|
ExpOperation* op = popValue(stack,context);
|
|
|
|
if (!op)
|
|
|
|
continue;
|
2020-04-22 12:05:53 +00:00
|
|
|
if (i == 0 + idx)
|
|
|
|
traceId = *op;
|
|
|
|
else if (i == 1 + idx) {
|
2013-07-05 12:50:18 +00:00
|
|
|
if (level < 0) {
|
|
|
|
if (op->isInteger())
|
2013-08-07 11:24:10 +00:00
|
|
|
level = (int)op->number();
|
2019-06-25 13:00:25 +00:00
|
|
|
else {
|
|
|
|
TelEngine::destruct(op);
|
2013-07-05 12:50:18 +00:00
|
|
|
return false;
|
2019-06-25 13:00:25 +00:00
|
|
|
}
|
2013-07-05 12:50:18 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
info = *op;
|
|
|
|
}
|
2020-04-22 12:05:53 +00:00
|
|
|
else if ((i == 2 + idx) && oper.number() > 2 + idx && op->isInteger())
|
2013-08-07 11:24:10 +00:00
|
|
|
level = (int)op->number();
|
2013-07-05 12:50:18 +00:00
|
|
|
else if (*op) {
|
|
|
|
if (str)
|
|
|
|
str = *op + " " + str;
|
|
|
|
else
|
|
|
|
str = *op;
|
|
|
|
}
|
|
|
|
TelEngine::destruct(op);
|
|
|
|
}
|
|
|
|
if (str && level >= 0) {
|
2013-11-01 14:36:18 +00:00
|
|
|
int limit = s_allowAbort ? DebugFail : DebugTest;
|
2013-07-05 12:50:18 +00:00
|
|
|
if (level > DebugAll)
|
|
|
|
level = DebugAll;
|
|
|
|
else if (level < limit)
|
|
|
|
level = limit;
|
2020-04-22 12:05:53 +00:00
|
|
|
TraceAlarm(traceId,this,info,level,"%s",str.c_str());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (oper.name() == YSTRING("setTraceId")) {
|
|
|
|
ScriptRun* runner = YOBJECT(ScriptRun,context);
|
|
|
|
if (!runner)
|
|
|
|
return false;
|
|
|
|
String tmp;
|
|
|
|
switch (oper.number()) {
|
|
|
|
case 1:
|
|
|
|
{
|
|
|
|
ExpOperation* op = popValue(stack,context);
|
|
|
|
if (!op)
|
|
|
|
return false;
|
|
|
|
if (!JsParser::isNull(*op))
|
|
|
|
tmp = *op;
|
|
|
|
TelEngine::destruct(op);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case 0:
|
|
|
|
// reset trace ID
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
return false;
|
2013-07-05 12:50:18 +00:00
|
|
|
}
|
2020-04-22 12:05:53 +00:00
|
|
|
runner->setTraceId(tmp);
|
2013-07-05 12:50:18 +00:00
|
|
|
}
|
2020-04-01 11:47:55 +00:00
|
|
|
else if (oper.name() == YSTRING("lineNo")) {
|
|
|
|
if (oper.number())
|
|
|
|
return false;
|
|
|
|
ScriptRun* runner = YOBJECT(ScriptRun,context);
|
|
|
|
if (!runner)
|
|
|
|
return false;
|
|
|
|
ExpEvaluator::pushOne(stack,new ExpOperation((int64_t)runner->currentLineNo()));
|
|
|
|
}
|
|
|
|
else if (oper.name() == YSTRING("fileName") || oper.name() == YSTRING("fileNo")) {
|
|
|
|
if (oper.number() > 1)
|
|
|
|
return false;
|
|
|
|
bool wholePath = false;
|
|
|
|
if (oper.number() == 1) {
|
|
|
|
ExpOperation* op = popValue(stack,context);
|
|
|
|
if (!op)
|
|
|
|
return false;
|
|
|
|
wholePath = op->valBoolean();
|
|
|
|
}
|
|
|
|
ScriptRun* runner = YOBJECT(ScriptRun,context);
|
|
|
|
if (!runner)
|
|
|
|
return false;
|
|
|
|
String fileName = runner->currentFileName(wholePath);
|
|
|
|
if (oper.name() == YSTRING("fileNo"))
|
|
|
|
fileName << ":" << runner->currentLineNo();
|
|
|
|
ExpEvaluator::pushOne(stack,new ExpOperation(fileName));
|
|
|
|
}
|
2020-10-21 11:01:31 +00:00
|
|
|
else if (oper.name() == YSTRING("creationLine")) {
|
|
|
|
ObjList args;
|
|
|
|
unsigned int c = extractArgs(stack,oper,context,args);
|
|
|
|
if (c < 1)
|
|
|
|
return false;
|
|
|
|
JsObject* jso= 0;
|
|
|
|
ExpWrapper* w = YOBJECT(ExpWrapper,args[0]);
|
|
|
|
if (w)
|
|
|
|
jso = YOBJECT(JsObject,w->object());
|
|
|
|
if (!jso)
|
|
|
|
ExpEvaluator::pushOne(stack,new ExpWrapper(0,0));
|
|
|
|
else {
|
|
|
|
bool wholePath = false;
|
|
|
|
ExpOperation* op = static_cast<ExpOperation*>(args[1]);
|
|
|
|
if (op)
|
|
|
|
wholePath = op->valBoolean();
|
|
|
|
ScriptRun* runner = YOBJECT(ScriptRun,context);
|
|
|
|
if (!(runner && runner->code()))
|
|
|
|
return false;
|
|
|
|
String fn;
|
|
|
|
unsigned int fl = 0;
|
|
|
|
runner->code()->getFileLine(jso->lineNo(),fn,fl,wholePath);
|
|
|
|
ExpEvaluator::pushOne(stack,new ExpOperation(fn << ":" << fl));
|
|
|
|
}
|
|
|
|
}
|
2012-06-22 09:38:51 +00:00
|
|
|
else if (oper.name() == YSTRING("sleep")) {
|
|
|
|
if (oper.number() != 1)
|
|
|
|
return false;
|
|
|
|
ExpOperation* op = popValue(stack,context);
|
|
|
|
if (!op)
|
|
|
|
return false;
|
2013-08-07 09:49:52 +00:00
|
|
|
int64_t val = op->valInteger();
|
2012-06-22 09:38:51 +00:00
|
|
|
TelEngine::destruct(op);
|
|
|
|
if (val < 0)
|
|
|
|
val = 0;
|
|
|
|
ScriptRun* runner = YOBJECT(ScriptRun,context);
|
|
|
|
if (!runner)
|
|
|
|
return false;
|
|
|
|
runner->insertAsync(new JsEngAsync(runner,JsEngAsync::AsyncSleep,val));
|
|
|
|
runner->pause();
|
|
|
|
}
|
|
|
|
else if (oper.name() == YSTRING("usleep")) {
|
|
|
|
if (oper.number() != 1)
|
|
|
|
return false;
|
|
|
|
ExpOperation* op = popValue(stack,context);
|
|
|
|
if (!op)
|
|
|
|
return false;
|
2013-08-07 09:49:52 +00:00
|
|
|
int64_t val = op->valInteger();
|
2012-06-22 09:38:51 +00:00
|
|
|
TelEngine::destruct(op);
|
|
|
|
if (val < 0)
|
|
|
|
val = 0;
|
|
|
|
ScriptRun* runner = YOBJECT(ScriptRun,context);
|
|
|
|
if (!runner)
|
|
|
|
return false;
|
|
|
|
runner->insertAsync(new JsEngAsync(runner,JsEngAsync::AsyncUsleep,val));
|
|
|
|
runner->pause();
|
|
|
|
}
|
|
|
|
else if (oper.name() == YSTRING("yield")) {
|
|
|
|
if (oper.number() != 0)
|
|
|
|
return false;
|
|
|
|
ScriptRun* runner = YOBJECT(ScriptRun,context);
|
|
|
|
if (!runner)
|
|
|
|
return false;
|
|
|
|
runner->insertAsync(new JsEngAsync(runner,JsEngAsync::AsyncYield));
|
|
|
|
runner->pause();
|
|
|
|
}
|
|
|
|
else if (oper.name() == YSTRING("idle")) {
|
|
|
|
if (oper.number() != 0)
|
|
|
|
return false;
|
|
|
|
ScriptRun* runner = YOBJECT(ScriptRun,context);
|
|
|
|
if (!runner)
|
|
|
|
return false;
|
|
|
|
runner->insertAsync(new JsEngAsync(runner,JsEngAsync::AsyncIdle));
|
|
|
|
runner->pause();
|
|
|
|
}
|
2012-05-30 08:32:47 +00:00
|
|
|
else if (oper.name() == YSTRING("dump_r")) {
|
|
|
|
String buf;
|
|
|
|
if (oper.number() == 0) {
|
|
|
|
ScriptRun* run = YOBJECT(ScriptRun,context);
|
|
|
|
if (run)
|
|
|
|
dumpRecursive(run->context(),buf);
|
|
|
|
else
|
|
|
|
dumpRecursive(context,buf);
|
|
|
|
}
|
|
|
|
else if (oper.number() == 1) {
|
|
|
|
ExpOperation* op = popValue(stack,context);
|
|
|
|
if (!op)
|
|
|
|
return false;
|
|
|
|
dumpRecursive(op,buf);
|
|
|
|
TelEngine::destruct(op);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
return false;
|
|
|
|
ExpEvaluator::pushOne(stack,new ExpOperation(buf));
|
|
|
|
}
|
|
|
|
else if (oper.name() == YSTRING("print_r")) {
|
|
|
|
if (oper.number() == 0) {
|
|
|
|
ScriptRun* run = YOBJECT(ScriptRun,context);
|
|
|
|
if (run)
|
|
|
|
printRecursive(run->context());
|
|
|
|
else
|
|
|
|
printRecursive(context);
|
|
|
|
}
|
|
|
|
else if (oper.number() == 1) {
|
|
|
|
ExpOperation* op = popValue(stack,context);
|
|
|
|
if (!op)
|
|
|
|
return false;
|
|
|
|
printRecursive(op);
|
|
|
|
TelEngine::destruct(op);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
return false;
|
|
|
|
}
|
2020-10-14 10:38:31 +00:00
|
|
|
else if (oper.name() == YSTRING("dump_var_r")) {
|
|
|
|
// str = Engine.dump_var_r(obj[,flags])
|
|
|
|
ObjList args;
|
|
|
|
ExpOperation* obj = 0;
|
|
|
|
ExpOperation* flags = 0;
|
|
|
|
if (!extractStackArgs(1,this,stack,oper,context,args,&obj,&flags))
|
|
|
|
return false;
|
|
|
|
String buf;
|
|
|
|
dumpRecursive(obj,buf,flags ? flags->valInteger(DumpPropOnly) : DumpPropOnly);
|
|
|
|
ExpEvaluator::pushOne(stack,new ExpOperation(buf));
|
|
|
|
}
|
|
|
|
else if (oper.name() == YSTRING("print_var_r")) {
|
|
|
|
// Engine.print_var_r(obj[,flags])
|
|
|
|
ObjList args;
|
|
|
|
ExpOperation* obj = 0;
|
|
|
|
ExpOperation* flags = 0;
|
|
|
|
if (!extractStackArgs(1,this,stack,oper,context,args,&obj,&flags))
|
|
|
|
return false;
|
|
|
|
printRecursive(obj,flags ? flags->valInteger(DumpPropOnly) : DumpPropOnly);
|
|
|
|
}
|
|
|
|
else if (oper.name() == YSTRING("dump_root_r")) {
|
|
|
|
// str = Engine.dump_root_r([flags])
|
|
|
|
ObjList args;
|
|
|
|
ExpOperation* flags = 0;
|
|
|
|
if (!extractStackArgs(0,this,stack,oper,context,args,&flags))
|
|
|
|
return false;
|
|
|
|
String buf;
|
|
|
|
ScriptRun* run = YOBJECT(ScriptRun,context);
|
|
|
|
dumpRecursive(run ? run->context() : context,buf,
|
|
|
|
flags ? flags->valInteger(DumpPropOnly) : DumpPropOnly);
|
|
|
|
ExpEvaluator::pushOne(stack,new ExpOperation(buf));
|
|
|
|
}
|
|
|
|
else if (oper.name() == YSTRING("print_root_r")) {
|
|
|
|
// Engine.print_root_r([flags])
|
|
|
|
ObjList args;
|
|
|
|
ExpOperation* flags = 0;
|
|
|
|
if (!extractStackArgs(0,this,stack,oper,context,args,&flags))
|
|
|
|
return false;
|
|
|
|
ScriptRun* run = YOBJECT(ScriptRun,context);
|
|
|
|
printRecursive(run ? run->context() : context,
|
|
|
|
flags ? flags->valInteger(DumpPropOnly) : DumpPropOnly);
|
|
|
|
}
|
2021-12-13 07:29:32 +00:00
|
|
|
else if (oper.name() == YSTRING("dump_t") || oper.name() == YSTRING("print_t")) {
|
|
|
|
ObjList args;
|
|
|
|
ExpOperation* opObj = 0;
|
|
|
|
ExpOperation* opHdrMap = 0;
|
|
|
|
ExpOperation* params = 0;
|
|
|
|
if (!extractStackArgs(1,this,stack,oper,context,args,&opObj,&opHdrMap,¶ms))
|
2014-08-06 14:38:28 +00:00
|
|
|
return false;
|
2021-12-13 07:29:32 +00:00
|
|
|
NamedList* hdrMap = 0;
|
|
|
|
bool forceEmpty = false;
|
|
|
|
bool allHeaders = false;
|
|
|
|
JsObject* jso = YOBJECT(JsObject,opHdrMap);
|
|
|
|
if (jso)
|
|
|
|
hdrMap = jso->nativeParams() ? jso->nativeParams() : &jso->params();
|
|
|
|
jso = YOBJECT(JsObject,params);
|
|
|
|
if (jso) {
|
|
|
|
jso->getBoolField(YSTRING("force_empty"),forceEmpty);
|
|
|
|
jso->getBoolField(YSTRING("all_headers"),allHeaders);
|
|
|
|
}
|
2014-08-06 14:38:28 +00:00
|
|
|
String buf;
|
2021-12-13 07:29:32 +00:00
|
|
|
dumpTable(*opObj,buf,"\r\n",hdrMap,forceEmpty,allHeaders);
|
|
|
|
if (oper.name() == YSTRING("dump_t"))
|
|
|
|
ExpEvaluator::pushOne(stack,new ExpOperation(buf));
|
|
|
|
else
|
|
|
|
Output("%s",buf.safe());
|
2014-08-06 14:38:28 +00:00
|
|
|
}
|
2013-04-12 15:18:50 +00:00
|
|
|
else if (oper.name() == YSTRING("debugName")) {
|
|
|
|
if (oper.number() == 0)
|
|
|
|
ExpEvaluator::pushOne(stack,new ExpOperation(m_debugName));
|
|
|
|
else if (oper.number() == 1) {
|
|
|
|
ExpOperation* op = popValue(stack,context);
|
|
|
|
String tmp;
|
|
|
|
if (op && !JsParser::isNull(*op))
|
|
|
|
tmp = *op;
|
|
|
|
TelEngine::destruct(op);
|
|
|
|
tmp.trimSpaces();
|
|
|
|
if (tmp.null())
|
|
|
|
tmp = "javascript";
|
|
|
|
m_debugName = tmp;
|
|
|
|
debugName(m_debugName);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
return false;
|
|
|
|
}
|
2013-08-05 09:56:52 +00:00
|
|
|
else if (oper.name() == YSTRING("debugLevel")) {
|
|
|
|
if (oper.number() == 0)
|
2013-08-07 10:18:23 +00:00
|
|
|
ExpEvaluator::pushOne(stack,new ExpOperation((int64_t)debugLevel()));
|
2013-08-05 09:56:52 +00:00
|
|
|
else if (oper.number() == 1) {
|
|
|
|
ExpOperation* op = popValue(stack,context);
|
|
|
|
if (op && op->isInteger())
|
2013-08-07 11:24:10 +00:00
|
|
|
debugLevel((int)op->valInteger());
|
2013-08-05 09:56:52 +00:00
|
|
|
TelEngine::destruct(op);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
else if (oper.name() == YSTRING("debugEnabled")) {
|
|
|
|
if (oper.number() == 0)
|
|
|
|
ExpEvaluator::pushOne(stack,new ExpOperation(debugEnabled()));
|
|
|
|
else if (oper.number() == 1) {
|
|
|
|
ExpOperation* op = popValue(stack,context);
|
|
|
|
if (op)
|
|
|
|
debugEnabled(op->valBoolean());
|
|
|
|
TelEngine::destruct(op);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
else if (oper.name() == YSTRING("debugAt")) {
|
|
|
|
if (oper.number() == 1) {
|
|
|
|
ExpOperation* op = popValue(stack,context);
|
2019-06-25 13:00:25 +00:00
|
|
|
if (!(op && op->isInteger())) {
|
|
|
|
TelEngine::destruct(op);
|
2013-08-05 09:56:52 +00:00
|
|
|
return false;
|
2019-06-25 13:00:25 +00:00
|
|
|
}
|
2013-08-07 11:24:10 +00:00
|
|
|
ExpEvaluator::pushOne(stack,new ExpOperation(debugAt((int)op->valInteger())));
|
2013-08-05 09:56:52 +00:00
|
|
|
TelEngine::destruct(op);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
else if (oper.name() == YSTRING("setDebug")) {
|
|
|
|
if (oper.number() == 1) {
|
|
|
|
ExpOperation* op = popValue(stack,context);
|
|
|
|
if (!op)
|
|
|
|
return false;
|
|
|
|
if (op->startSkip("level")) {
|
|
|
|
int dbg = debugLevel();
|
|
|
|
*op >> dbg;
|
2017-06-05 12:33:38 +00:00
|
|
|
if (*op == "+") {
|
|
|
|
if (debugLevel() > dbg)
|
|
|
|
dbg = debugLevel();
|
|
|
|
}
|
|
|
|
else if (*op == "-") {
|
|
|
|
if (debugLevel() < dbg)
|
|
|
|
dbg = debugLevel();
|
|
|
|
}
|
2013-08-05 09:56:52 +00:00
|
|
|
debugLevel(dbg);
|
|
|
|
}
|
|
|
|
else if (*op == "reset")
|
|
|
|
debugChain(&__plugin);
|
|
|
|
else if (*op == "engine")
|
|
|
|
debugCopy();
|
|
|
|
else if (op->isBoolean())
|
|
|
|
debugEnabled(op->toBoolean(debugEnabled()));
|
|
|
|
TelEngine::destruct(op);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
return false;
|
|
|
|
}
|
2013-11-05 15:50:09 +00:00
|
|
|
else if (oper.name() == YSTRING("runParams")) {
|
|
|
|
if (oper.number() == 0) {
|
2020-10-21 11:01:31 +00:00
|
|
|
JsObject* jso = new JsObject(context,oper.lineNumber(),mutex());
|
2013-11-05 15:50:09 +00:00
|
|
|
jso->params().copyParams(Engine::runParams());
|
|
|
|
ExpEvaluator::pushOne(stack,new ExpWrapper(jso,oper.name()));
|
|
|
|
}
|
|
|
|
else if (oper.number() == 1) {
|
|
|
|
ExpOperation* op = popValue(stack,context);
|
|
|
|
if (op)
|
|
|
|
ExpEvaluator::pushOne(stack,new ExpOperation(Engine::runParams()[*op]));
|
|
|
|
TelEngine::destruct(op);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
return false;
|
|
|
|
}
|
2014-04-01 11:27:51 +00:00
|
|
|
else if (oper.name() == YSTRING("configFile")) {
|
|
|
|
bool user = false;
|
|
|
|
ObjList args;
|
|
|
|
switch (extractArgs(stack,oper,context,args)) {
|
|
|
|
case 2:
|
|
|
|
user = static_cast<ExpOperation*>(args[1])->valBoolean();
|
|
|
|
// fall through
|
|
|
|
case 1:
|
|
|
|
ExpEvaluator::pushOne(stack,new ExpOperation(
|
|
|
|
Engine::configFile(*static_cast<ExpOperation*>(args[0]),user)));
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
2013-04-12 14:00:39 +00:00
|
|
|
else if (oper.name() == YSTRING("setInterval") || oper.name() == YSTRING("setTimeout")) {
|
|
|
|
ObjList args;
|
|
|
|
if (extractArgs(stack,oper,context,args) < 2)
|
|
|
|
return false;
|
|
|
|
const ExpFunction* callback = YOBJECT(ExpFunction,args[0]);
|
|
|
|
if (!callback) {
|
|
|
|
JsFunction* jsf = YOBJECT(JsFunction,args[0]);
|
|
|
|
if (jsf)
|
|
|
|
callback = jsf->getFunc();
|
|
|
|
}
|
|
|
|
if (!callback)
|
|
|
|
return false;
|
|
|
|
ExpOperation* interval = static_cast<ExpOperation*>(args[1]);
|
|
|
|
if (!m_worker) {
|
|
|
|
ScriptRun* runner = YOBJECT(ScriptRun,context);
|
|
|
|
if (!runner)
|
|
|
|
return false;
|
|
|
|
ScriptContext* scontext = runner->context();
|
|
|
|
ScriptCode* scode = runner->code();
|
|
|
|
if (!(scontext && scode))
|
|
|
|
return false;
|
|
|
|
m_worker = new JsEngineWorker(this,scontext,scode);
|
|
|
|
m_worker->startup();
|
|
|
|
}
|
2019-11-26 11:17:24 +00:00
|
|
|
ObjList* cbkArgs = 0;
|
|
|
|
if (args.length() > 2) {
|
|
|
|
cbkArgs = new ObjList;
|
|
|
|
copyArgList(*cbkArgs,*(args + 2));
|
|
|
|
}
|
2013-04-12 14:00:39 +00:00
|
|
|
unsigned int id = m_worker->addEvent(*callback,interval->toInteger(),
|
2019-11-26 11:17:24 +00:00
|
|
|
oper.name() == YSTRING("setInterval"),cbkArgs);
|
2013-08-07 10:18:23 +00:00
|
|
|
ExpEvaluator::pushOne(stack,new ExpOperation((int64_t)id));
|
2013-04-12 14:00:39 +00:00
|
|
|
}
|
|
|
|
else if (oper.name() == YSTRING("clearInterval") || oper.name() == YSTRING("clearTimeout")) {
|
|
|
|
if (!m_worker)
|
|
|
|
return false;
|
|
|
|
ObjList args;
|
|
|
|
if (!extractArgs(stack,oper,context,args))
|
|
|
|
return false;
|
|
|
|
ExpOperation* id = static_cast<ExpOperation*>(args[0]);
|
2013-08-07 11:24:10 +00:00
|
|
|
bool ret = m_worker->removeEvent((unsigned int)id->valInteger(),oper.name() == YSTRING("clearInterval"));
|
2013-04-12 14:00:39 +00:00
|
|
|
ExpEvaluator::pushOne(stack,new ExpOperation(ret));
|
|
|
|
}
|
2014-08-06 08:08:06 +00:00
|
|
|
else if (oper.name() == YSTRING("loadLibrary") || oper.name() == YSTRING("loadObject")) {
|
|
|
|
bool obj = oper.name() == YSTRING("loadObject");
|
|
|
|
bool ok = false;
|
|
|
|
ObjList args;
|
|
|
|
ScriptRun* runner = YOBJECT(ScriptRun,context);
|
|
|
|
int argc = extractArgs(stack,oper,context,args);
|
|
|
|
if (runner && argc) {
|
|
|
|
ok = true;
|
|
|
|
for (int i = 0; i < argc; i++) {
|
|
|
|
ExpOperation* op = static_cast<ExpOperation*>(args[i]);
|
|
|
|
if (!op || op->isBoolean() || op->isNumber() || YOBJECT(ExpWrapper,op))
|
|
|
|
ok = false;
|
|
|
|
else if (obj)
|
|
|
|
ok = contextLoad(runner,0,0,*op) && ok;
|
|
|
|
else
|
|
|
|
ok = contextLoad(runner,0,*op) && ok;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
ExpEvaluator::pushOne(stack,new ExpOperation(ok));
|
|
|
|
}
|
2020-04-15 13:50:14 +00:00
|
|
|
else if (oper.name() == YSTRING("pluginLoaded")) {
|
|
|
|
ObjList args;
|
|
|
|
if (extractArgs(stack,oper,context,args) != 1)
|
|
|
|
return false;
|
|
|
|
ExpEvaluator::pushOne(stack,new ExpOperation(
|
|
|
|
Engine::self()->pluginLoaded(*static_cast<ExpOperation*>(args[0]))));
|
|
|
|
}
|
2015-09-04 20:04:02 +00:00
|
|
|
else if (oper.name() == YSTRING("replaceParams")) {
|
|
|
|
ObjList args;
|
|
|
|
int argc = extractArgs(stack,oper,context,args);
|
|
|
|
if (argc < 2 || argc > 4)
|
|
|
|
return false;
|
|
|
|
GenObject* arg0 = args[0];
|
|
|
|
ExpOperation* text = static_cast<ExpOperation*>(arg0);
|
|
|
|
bool sqlEsc = (argc >= 3) && static_cast<ExpOperation*>(args[2])->valBoolean();
|
|
|
|
char extraEsc = 0;
|
|
|
|
if (argc >= 4)
|
|
|
|
extraEsc = static_cast<ExpOperation*>(args[3])->at(0);
|
2018-04-10 11:08:25 +00:00
|
|
|
const NamedList* params = getReplaceParams(args[1]);
|
|
|
|
if (params) {
|
2015-09-04 20:04:02 +00:00
|
|
|
String str(*text);
|
|
|
|
params->replaceParams(str,sqlEsc,extraEsc);
|
|
|
|
ExpEvaluator::pushOne(stack,new ExpOperation(str,text->name()));
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
args.remove(arg0,false);
|
|
|
|
ExpEvaluator::pushOne(stack,text);
|
|
|
|
}
|
|
|
|
}
|
2015-08-18 16:09:40 +00:00
|
|
|
else if (oper.name() == YSTRING("restart")) {
|
|
|
|
ObjList args;
|
|
|
|
int argc = extractArgs(stack,oper,context,args);
|
|
|
|
if (argc > 2)
|
|
|
|
return false;
|
|
|
|
bool ok = s_allowAbort;
|
|
|
|
if (ok) {
|
|
|
|
int code = 0;
|
|
|
|
if (argc >= 1) {
|
|
|
|
code = static_cast<ExpOperation*>(args[0])->valInteger();
|
|
|
|
if (code < 0)
|
|
|
|
code = 0;
|
|
|
|
}
|
|
|
|
bool gracefull = (argc >= 2) && static_cast<ExpOperation*>(args[1])->valBoolean();
|
|
|
|
ok = Engine::restart(code,gracefull);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
Debug(&__plugin,DebugNote,"Engine restart is disabled by allow_abort configuration");
|
|
|
|
ExpEvaluator::pushOne(stack,new ExpOperation(ok));
|
|
|
|
}
|
2018-03-12 14:10:45 +00:00
|
|
|
else if (oper.name() == YSTRING("init")) {
|
|
|
|
bool ok = true;
|
|
|
|
if (!oper.number())
|
|
|
|
Engine::init();
|
|
|
|
else if (oper.number() == 1) {
|
|
|
|
ExpOperation* module = popValue(stack,context);
|
|
|
|
if (!module)
|
|
|
|
return false;
|
|
|
|
ok = Engine::init(*module);
|
|
|
|
TelEngine::destruct(module);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
return false;
|
|
|
|
ExpEvaluator::pushOne(stack,new ExpOperation(ok));
|
|
|
|
}
|
2017-01-20 13:28:58 +00:00
|
|
|
else if (oper.name() == YSTRING("uptime")) {
|
|
|
|
SysUsage::Type typ = SysUsage::WallTime;
|
|
|
|
bool msec = false;
|
|
|
|
ObjList args;
|
|
|
|
switch (extractArgs(stack,oper,context,args)) {
|
|
|
|
case 2:
|
|
|
|
msec = static_cast<ExpOperation*>(args[1])->valBoolean();
|
|
|
|
// fall through
|
|
|
|
case 1:
|
|
|
|
typ = (SysUsage::Type)static_cast<ExpOperation*>(args[0])->toInteger(typ);
|
|
|
|
// fall through
|
|
|
|
case 0:
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
ExpEvaluator::pushOne(stack,new ExpOperation(
|
|
|
|
msec ? (int64_t)SysUsage::msecRunTime(typ) : (int64_t)SysUsage::secRunTime(typ)));
|
|
|
|
}
|
2016-01-04 12:49:52 +00:00
|
|
|
else if (oper.name() == YSTRING("started")) {
|
|
|
|
if (oper.number() != 0)
|
|
|
|
return false;
|
|
|
|
ExpEvaluator::pushOne(stack,new ExpOperation(Engine::started()));
|
|
|
|
}
|
2017-04-27 10:31:07 +00:00
|
|
|
else if (oper.name() == YSTRING("exiting")) {
|
|
|
|
if (oper.number() != 0)
|
|
|
|
return false;
|
|
|
|
ExpEvaluator::pushOne(stack,new ExpOperation(Engine::exiting()));
|
|
|
|
}
|
2017-01-09 15:04:04 +00:00
|
|
|
else if (oper.name() == YSTRING("accepting")) {
|
|
|
|
ObjList args;
|
|
|
|
switch (extractArgs(stack,oper,context,args)) {
|
|
|
|
case 0:
|
|
|
|
ExpEvaluator::pushOne(stack,new ExpOperation(
|
|
|
|
lookup(Engine::accept(),Engine::getCallAcceptStates())));
|
|
|
|
break;
|
|
|
|
case 1:
|
|
|
|
{
|
|
|
|
int arg = static_cast<ExpOperation*>(args[0])->toInteger(
|
|
|
|
Engine::getCallAcceptStates(),-1);
|
|
|
|
if ((Engine::Accept <= arg) && (Engine::Reject >= arg))
|
|
|
|
Engine::setAccept((Engine::CallAccept)arg);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
2021-05-18 12:19:21 +00:00
|
|
|
else if (oper.name() == YSTRING("getCongestion")) {
|
|
|
|
if (oper.number() != 0)
|
|
|
|
return false;
|
|
|
|
ExpEvaluator::pushOne(stack,new ExpOperation((int64_t)Engine::getCongestion()));
|
|
|
|
}
|
2021-05-18 18:07:43 +00:00
|
|
|
else if (oper.name() == YSTRING("setCongestion")) {
|
|
|
|
ExpOperation* op = 0;
|
|
|
|
switch (oper.number()) {
|
|
|
|
case 0:
|
|
|
|
break;
|
|
|
|
case 1:
|
|
|
|
op = popValue(stack,context);
|
|
|
|
if (op)
|
|
|
|
break;
|
|
|
|
// fall through
|
|
|
|
default:
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
Engine::setCongestion(c_str(op));
|
|
|
|
TelEngine::destruct(op);
|
|
|
|
}
|
2014-03-26 10:45:01 +00:00
|
|
|
else if (oper.name() == YSTRING("atob")) {
|
|
|
|
// str = Engine.atob(b64_str)
|
|
|
|
ObjList args;
|
|
|
|
int argc = extractArgs(stack,oper,context,args);
|
|
|
|
if (argc < 1)
|
|
|
|
return false;
|
|
|
|
Base64 b64;
|
|
|
|
b64 << *static_cast<ExpOperation*>(args[0]);
|
|
|
|
DataBlock buf;
|
|
|
|
if (b64.decode(buf)) {
|
|
|
|
String tmp((const char*)buf.data(),buf.length());
|
|
|
|
ExpEvaluator::pushOne(stack,new ExpOperation(tmp,"bin"));
|
|
|
|
}
|
|
|
|
else
|
|
|
|
ExpEvaluator::pushOne(stack,new ExpOperation(false));
|
|
|
|
}
|
|
|
|
else if (oper.name() == YSTRING("btoa")) {
|
|
|
|
// b64_str = Engine.btoa(str,line_len,add_eol)
|
|
|
|
ObjList args;
|
|
|
|
int argc = extractArgs(stack,oper,context,args);
|
|
|
|
if (argc < 1)
|
|
|
|
return false;
|
|
|
|
int len = 0;
|
|
|
|
bool eol = false;
|
|
|
|
if (argc >= 3)
|
|
|
|
eol = static_cast<ExpOperation*>(args[2])->valBoolean();
|
|
|
|
if (argc >= 2) {
|
|
|
|
len = static_cast<ExpOperation*>(args[1])->valInteger();
|
|
|
|
if (len < 0)
|
|
|
|
len = 0;
|
|
|
|
}
|
|
|
|
Base64 b64;
|
|
|
|
b64 << *static_cast<ExpOperation*>(args[0]);
|
|
|
|
String buf;
|
|
|
|
b64.encode(buf,len,eol);
|
|
|
|
ExpEvaluator::pushOne(stack,new ExpOperation(buf,"b64"));
|
|
|
|
}
|
|
|
|
else if (oper.name() == YSTRING("atoh")) {
|
|
|
|
// hex_str = Engine.atoh(b64_str,hex_sep,hex_upcase)
|
|
|
|
ObjList args;
|
|
|
|
int argc = extractArgs(stack,oper,context,args);
|
|
|
|
if (argc < 1)
|
|
|
|
return false;
|
|
|
|
Base64 b64;
|
|
|
|
b64 << *static_cast<ExpOperation*>(args[0]);
|
|
|
|
DataBlock buf;
|
|
|
|
if (b64.decode(buf)) {
|
|
|
|
char sep = (argc >= 2) ? static_cast<ExpOperation*>(args[1])->at(0) : '\0';
|
|
|
|
bool upCase = (argc >= 3) && static_cast<ExpOperation*>(args[2])->valBoolean();
|
|
|
|
String tmp;
|
|
|
|
tmp.hexify(buf.data(),buf.length(),sep,upCase);
|
|
|
|
ExpEvaluator::pushOne(stack,new ExpOperation(tmp,"hex"));
|
|
|
|
}
|
|
|
|
else
|
|
|
|
ExpEvaluator::pushOne(stack,new ExpOperation(false));
|
|
|
|
}
|
|
|
|
else if (oper.name() == YSTRING("htoa")) {
|
|
|
|
// b64_str = Engine.htoa(hex_str,line_len,add_eol)
|
|
|
|
ObjList args;
|
|
|
|
int argc = extractArgs(stack,oper,context,args);
|
|
|
|
if (argc < 1)
|
|
|
|
return false;
|
|
|
|
Base64 b64;
|
|
|
|
if (b64.unHexify(*static_cast<ExpOperation*>(args[0]))) {
|
|
|
|
int len = 0;
|
|
|
|
bool eol = false;
|
|
|
|
if (argc >= 3)
|
|
|
|
eol = static_cast<ExpOperation*>(args[2])->valBoolean();
|
|
|
|
if (argc >= 2) {
|
|
|
|
len = static_cast<ExpOperation*>(args[1])->valInteger();
|
|
|
|
if (len < 0)
|
|
|
|
len = 0;
|
|
|
|
}
|
|
|
|
String buf;
|
|
|
|
b64.encode(buf,len,eol);
|
|
|
|
ExpEvaluator::pushOne(stack,new ExpOperation(buf,"b64"));
|
|
|
|
}
|
|
|
|
else
|
|
|
|
ExpEvaluator::pushOne(stack,new ExpOperation(false));
|
|
|
|
}
|
2014-07-07 07:52:42 +00:00
|
|
|
else if (oper.name() == YSTRING("btoh")) {
|
|
|
|
// hex_str = Engine.btoh(str[,sep[,upCase]])
|
|
|
|
ObjList args;
|
|
|
|
ExpOperation* data = 0;
|
|
|
|
ExpOperation* sep = 0;
|
|
|
|
ExpOperation* upCase = 0;
|
|
|
|
if (!extractStackArgs(1,this,stack,oper,context,args,&data,&sep,&upCase))
|
|
|
|
return false;
|
|
|
|
String tmp;
|
|
|
|
tmp.hexify((void*)data->c_str(),data->length(),(sep ? sep->at(0) : 0),
|
|
|
|
(upCase && upCase->toBoolean()));
|
|
|
|
ExpEvaluator::pushOne(stack,new ExpOperation(tmp,"hex"));
|
|
|
|
}
|
|
|
|
else if (oper.name() == YSTRING("htob")) {
|
|
|
|
// str = Engine.unHexify(hex_str[,sep])
|
|
|
|
ObjList args;
|
|
|
|
ExpOperation* data = 0;
|
|
|
|
ExpOperation* sep = 0;
|
|
|
|
if (!extractStackArgs(1,this,stack,oper,context,args,&data,&sep))
|
|
|
|
return false;
|
|
|
|
bool ok = true;
|
|
|
|
DataBlock buf;
|
|
|
|
if (!sep)
|
|
|
|
ok = buf.unHexify(data->c_str(),data->length());
|
|
|
|
else
|
|
|
|
ok = buf.unHexify(data->c_str(),data->length(),sep->at(0));
|
|
|
|
if (ok) {
|
|
|
|
String tmp((const char*)buf.data(),buf.length());
|
|
|
|
ExpEvaluator::pushOne(stack,new ExpOperation(tmp,"bin"));
|
|
|
|
}
|
|
|
|
else
|
|
|
|
ExpEvaluator::pushOne(stack,new ExpOperation(false));
|
|
|
|
}
|
2012-02-17 16:19:17 +00:00
|
|
|
else
|
|
|
|
return JsObject::runNative(stack,oper,context);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2013-04-12 14:00:39 +00:00
|
|
|
void JsEngine::destroyed()
|
|
|
|
{
|
|
|
|
JsObject::destroyed();
|
|
|
|
if (!m_worker)
|
|
|
|
return;
|
|
|
|
m_worker->cancel();
|
|
|
|
while (m_worker)
|
|
|
|
Thread::idle();
|
|
|
|
}
|
|
|
|
|
2015-08-27 10:58:42 +00:00
|
|
|
void JsEngine::initialize(ScriptContext* context, const char* name)
|
2012-02-17 16:19:17 +00:00
|
|
|
{
|
|
|
|
if (!context)
|
|
|
|
return;
|
2020-10-21 11:01:31 +00:00
|
|
|
ScriptMutex* mtx = context->mutex();
|
2012-02-17 16:19:17 +00:00
|
|
|
Lock mylock(mtx);
|
|
|
|
NamedList& params = context->params();
|
|
|
|
if (!params.getParam(YSTRING("Engine")))
|
2015-08-27 10:58:42 +00:00
|
|
|
addObject(params,"Engine",new JsEngine(mtx,name));
|
2012-02-17 16:19:17 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2012-06-27 17:49:49 +00:00
|
|
|
bool JsShared::runNative(ObjList& stack, const ExpOperation& oper, GenObject* context)
|
|
|
|
{
|
2016-01-20 10:23:35 +00:00
|
|
|
XDebug(&__plugin,DebugAll,"JsShared::runNative '%s'(" FMT64 ")",oper.name().c_str(),oper.number());
|
2012-06-27 17:49:49 +00:00
|
|
|
if (oper.name() == YSTRING("inc")) {
|
|
|
|
ObjList args;
|
2021-09-28 10:55:08 +00:00
|
|
|
ExpOperation* param = 0;
|
|
|
|
ExpOperation* mod = 0;
|
|
|
|
if (!extractStackArgs(1,this,stack,oper,context,args,¶m,&mod))
|
|
|
|
return false;
|
|
|
|
if (m_vars)
|
|
|
|
ExpEvaluator::pushOne(stack,new ExpOperation((int64_t)m_vars->inc(*param,modulo(mod))));
|
2012-06-27 17:49:49 +00:00
|
|
|
else
|
2021-09-28 10:55:08 +00:00
|
|
|
ExpEvaluator::pushOne(stack,JsParser::nullClone());
|
2012-06-27 17:49:49 +00:00
|
|
|
}
|
|
|
|
else if (oper.name() == YSTRING("dec")) {
|
|
|
|
ObjList args;
|
2021-09-28 10:55:08 +00:00
|
|
|
ExpOperation* param = 0;
|
|
|
|
ExpOperation* mod = 0;
|
|
|
|
if (!extractStackArgs(1,this,stack,oper,context,args,¶m,&mod))
|
|
|
|
return false;
|
|
|
|
if (m_vars)
|
|
|
|
ExpEvaluator::pushOne(stack,new ExpOperation((int64_t)m_vars->dec(*param,modulo(mod))));
|
2012-06-27 17:49:49 +00:00
|
|
|
else
|
2021-09-28 10:55:08 +00:00
|
|
|
ExpEvaluator::pushOne(stack,JsParser::nullClone());
|
2012-06-27 17:49:49 +00:00
|
|
|
}
|
|
|
|
else if (oper.name() == YSTRING("get")) {
|
|
|
|
if (oper.number() != 1)
|
|
|
|
return false;
|
|
|
|
ExpOperation* param = popValue(stack,context);
|
|
|
|
if (!param)
|
|
|
|
return false;
|
|
|
|
String buf;
|
2021-09-28 10:55:08 +00:00
|
|
|
if (m_vars)
|
|
|
|
m_vars->get(*param,buf);
|
2012-06-27 17:49:49 +00:00
|
|
|
TelEngine::destruct(param);
|
|
|
|
ExpEvaluator::pushOne(stack,new ExpOperation(buf));
|
|
|
|
}
|
|
|
|
else if (oper.name() == YSTRING("set")) {
|
|
|
|
if (oper.number() != 2)
|
|
|
|
return false;
|
|
|
|
ExpOperation* val = popValue(stack,context);
|
|
|
|
if (!val)
|
|
|
|
return false;
|
|
|
|
ExpOperation* param = popValue(stack,context);
|
|
|
|
if (!param) {
|
|
|
|
TelEngine::destruct(val);
|
|
|
|
return false;
|
|
|
|
}
|
2021-09-28 10:55:08 +00:00
|
|
|
if (m_vars)
|
|
|
|
m_vars->set(*param,*val);
|
2012-06-27 17:49:49 +00:00
|
|
|
TelEngine::destruct(param);
|
|
|
|
TelEngine::destruct(val);
|
|
|
|
}
|
2021-09-28 10:55:08 +00:00
|
|
|
else if (oper.name() == YSTRING("add") || oper.name() == YSTRING("sub")) {
|
|
|
|
ObjList args;
|
|
|
|
ExpOperation* param = 0;
|
|
|
|
ExpOperation* val = 0;
|
|
|
|
ExpOperation* mod = 0;
|
|
|
|
if (!extractStackArgs(2,this,stack,oper,context,args,¶m,&val,&mod))
|
|
|
|
return false;
|
|
|
|
if (m_vars) {
|
|
|
|
int64_t value = val->isInteger() ? val->number() : 0;
|
|
|
|
if (oper.name() == YSTRING("add"))
|
|
|
|
value = (int64_t)m_vars->add(*param,value > 0 ? value : 0,modulo(mod));
|
|
|
|
else
|
|
|
|
value = (int64_t)m_vars->sub(*param,value > 0 ? value : 0,modulo(mod));
|
|
|
|
ExpEvaluator::pushOne(stack,new ExpOperation(value));
|
|
|
|
}
|
|
|
|
else
|
|
|
|
ExpEvaluator::pushOne(stack,JsParser::nullClone());
|
|
|
|
}
|
2012-06-27 17:49:49 +00:00
|
|
|
else if (oper.name() == YSTRING("clear")) {
|
|
|
|
if (oper.number() != 1)
|
|
|
|
return false;
|
|
|
|
ExpOperation* param = popValue(stack,context);
|
|
|
|
if (!param)
|
|
|
|
return false;
|
2021-09-28 10:55:08 +00:00
|
|
|
if (m_vars)
|
|
|
|
m_vars->clear(*param);
|
2012-06-27 17:49:49 +00:00
|
|
|
TelEngine::destruct(param);
|
|
|
|
}
|
2021-09-28 10:55:08 +00:00
|
|
|
else if (oper.name() == YSTRING("clearAll")) {
|
|
|
|
if (m_vars)
|
|
|
|
m_vars->clearAll();
|
|
|
|
}
|
2012-06-27 17:49:49 +00:00
|
|
|
else if (oper.name() == YSTRING("exists")) {
|
|
|
|
if (oper.number() != 1)
|
|
|
|
return false;
|
|
|
|
ExpOperation* param = popValue(stack,context);
|
|
|
|
if (!param)
|
|
|
|
return false;
|
2021-09-28 10:55:08 +00:00
|
|
|
ExpEvaluator::pushOne(stack,new ExpOperation(m_vars && m_vars->exists(*param)));
|
2012-06-27 17:49:49 +00:00
|
|
|
TelEngine::destruct(param);
|
|
|
|
}
|
2021-09-28 10:55:08 +00:00
|
|
|
else if (oper.name() == YSTRING("getVars")) {
|
|
|
|
// getVars([params])
|
|
|
|
// params:
|
|
|
|
// js_props: Boolean. Force Javascript ExpOperation in returned result. Default: true
|
|
|
|
// autonum: Boolean. Force ExpOperation auto number in returned result. Default: false.
|
|
|
|
// Ignored if not returning ExpOperation
|
|
|
|
// prefix: String. Optional prefix for variables
|
|
|
|
// skip_prefix: Boolean. Skip prefix when returned. Default: true. Ignored if prefix is empty
|
|
|
|
ObjList args;
|
|
|
|
ExpOperation* pOp = 0;
|
|
|
|
if (!extractStackArgs(0,this,stack,oper,context,args,&pOp))
|
|
|
|
return false;
|
|
|
|
if (m_vars) {
|
|
|
|
bool expOper = true;
|
|
|
|
bool autoNum = false;
|
|
|
|
String prefix;
|
|
|
|
bool skipPrefix = true;
|
|
|
|
JsObject* params = YOBJECT(JsObject,pOp);
|
|
|
|
if (params) {
|
|
|
|
params->getBoolField(YSTRING("js_props"),expOper);
|
|
|
|
if (expOper)
|
|
|
|
params->getBoolField(YSTRING("autonum"),autoNum);
|
|
|
|
params->getStringField(YSTRING("prefix"),prefix);
|
|
|
|
if (prefix)
|
|
|
|
params->getBoolField(YSTRING("skip_prefix"),skipPrefix);
|
|
|
|
}
|
|
|
|
JsObject* jso = new JsObject(context,oper.lineNumber(),mutex());
|
|
|
|
if (expOper) {
|
|
|
|
NamedList tmp("");
|
|
|
|
m_vars->copy(tmp,prefix,skipPrefix);
|
|
|
|
for (ObjList* o = tmp.paramList()->skipNull(); o; o = o->skipNext()) {
|
|
|
|
NamedString* ns = static_cast<NamedString*>(o->get());
|
|
|
|
jso->params().addParam(new ExpOperation(*ns,ns->name(),autoNum));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
m_vars->copy(jso->params(),prefix,skipPrefix);
|
|
|
|
ExpEvaluator::pushOne(stack,new ExpWrapper(jso,"vars"));
|
|
|
|
}
|
|
|
|
else
|
|
|
|
ExpEvaluator::pushOne(stack,JsParser::nullClone());
|
|
|
|
}
|
2012-06-27 17:49:49 +00:00
|
|
|
else
|
|
|
|
return JsObject::runNative(stack,oper,context);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2021-09-28 10:55:08 +00:00
|
|
|
JsObject* JsShared::runConstructor(ObjList& stack, const ExpOperation& oper, GenObject* context)
|
|
|
|
{
|
|
|
|
ObjList args;
|
|
|
|
ExpOperation* sharedOp = 0;
|
|
|
|
if (!extractStackArgs(1,this,stack,oper,context,args,&sharedOp))
|
|
|
|
return 0;
|
|
|
|
JsShared* obj = new JsShared(mutex(),oper.lineNumber(),*sharedOp);
|
|
|
|
if (ref())
|
|
|
|
obj->params().addParam(new ExpWrapper(this,protoName()));
|
|
|
|
else
|
|
|
|
TelEngine::destruct(obj);
|
|
|
|
return obj;
|
|
|
|
}
|
|
|
|
|
|
|
|
void JsShared::initialize(ScriptContext* context)
|
|
|
|
{
|
|
|
|
if (!context)
|
|
|
|
return;
|
|
|
|
ScriptMutex* mtx = context->mutex();
|
|
|
|
Lock mylock(mtx);
|
|
|
|
NamedList& params = context->params();
|
|
|
|
if (!params.getParam(YSTRING("SharedVars")))
|
|
|
|
addObject(params,"SharedVars",new JsShared(mtx));
|
|
|
|
}
|
2012-06-27 17:49:49 +00:00
|
|
|
|
2014-10-29 16:32:20 +00:00
|
|
|
void* JsMessage::getObject(const String& name) const
|
|
|
|
{
|
|
|
|
void* obj = (name == YATOM("JsMessage")) ? const_cast<JsMessage*>(this) : JsObject::getObject(name);
|
|
|
|
if (m_message && !obj)
|
|
|
|
obj = m_message->getObject(name);
|
|
|
|
return obj;
|
|
|
|
}
|
|
|
|
|
2012-06-19 18:55:45 +00:00
|
|
|
bool JsMessage::runAssign(ObjList& stack, const ExpOperation& oper, GenObject* context)
|
|
|
|
{
|
2012-06-26 13:31:30 +00:00
|
|
|
XDebug(&__plugin,DebugAll,"JsMessage::runAssign '%s'='%s'",oper.name().c_str(),oper.c_str());
|
2012-06-19 19:28:30 +00:00
|
|
|
if (ScriptContext::hasField(stack,oper.name(),context))
|
2012-06-19 18:55:45 +00:00
|
|
|
return JsObject::runAssign(stack,oper,context);
|
2015-11-12 21:29:55 +00:00
|
|
|
if (frozen() || !m_message) {
|
|
|
|
Debug(&__plugin,DebugWarn,"Message is frozen or missing");
|
2012-06-19 18:55:45 +00:00
|
|
|
return false;
|
2015-11-12 21:29:55 +00:00
|
|
|
}
|
2012-06-26 13:31:30 +00:00
|
|
|
if (JsParser::isUndefined(oper))
|
2012-06-19 18:55:45 +00:00
|
|
|
m_message->clearParam(oper.name());
|
|
|
|
else
|
|
|
|
m_message->setParam(new NamedString(oper.name(),oper));
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2012-02-17 16:19:17 +00:00
|
|
|
bool JsMessage::runNative(ObjList& stack, const ExpOperation& oper, GenObject* context)
|
|
|
|
{
|
2016-01-20 10:23:35 +00:00
|
|
|
XDebug(&__plugin,DebugAll,"JsMessage::runNative '%s'(" FMT64 ")",oper.name().c_str(),oper.number());
|
2012-05-15 14:43:15 +00:00
|
|
|
if (oper.name() == YSTRING("broadcast")) {
|
2012-03-05 09:53:31 +00:00
|
|
|
if (oper.number() != 0)
|
|
|
|
return false;
|
|
|
|
ExpEvaluator::pushOne(stack,new ExpOperation(m_message && m_message->broadcast()));
|
|
|
|
}
|
2012-06-19 18:55:45 +00:00
|
|
|
else if (oper.name() == YSTRING("name")) {
|
|
|
|
if (oper.number() != 0)
|
|
|
|
return false;
|
|
|
|
if (m_message)
|
|
|
|
ExpEvaluator::pushOne(stack,new ExpOperation(*m_message));
|
|
|
|
else
|
|
|
|
ExpEvaluator::pushOne(stack,JsParser::nullClone());
|
|
|
|
}
|
|
|
|
else if (oper.name() == YSTRING("retValue")) {
|
|
|
|
switch (oper.number()) {
|
|
|
|
case 0:
|
|
|
|
if (m_message)
|
2013-04-12 12:54:30 +00:00
|
|
|
ExpEvaluator::pushOne(stack,new ExpOperation(m_message->retValue(),0,true));
|
2012-06-19 18:55:45 +00:00
|
|
|
else
|
|
|
|
ExpEvaluator::pushOne(stack,JsParser::nullClone());
|
|
|
|
break;
|
|
|
|
case 1:
|
|
|
|
{
|
|
|
|
ExpOperation* op = popValue(stack,context);
|
|
|
|
if (!op)
|
|
|
|
return false;
|
2015-11-12 21:29:55 +00:00
|
|
|
if (m_message && !frozen())
|
2012-06-19 18:55:45 +00:00
|
|
|
m_message->retValue() = *op;
|
|
|
|
TelEngine::destruct(op);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
2013-11-05 15:50:09 +00:00
|
|
|
else if (oper.name() == YSTRING("msgTime")) {
|
2017-04-21 14:06:16 +00:00
|
|
|
switch (oper.number()) {
|
|
|
|
case 0:
|
|
|
|
if (m_message)
|
|
|
|
ExpEvaluator::pushOne(stack,new ExpOperation((int64_t)m_message->msgTime().msec()));
|
|
|
|
else
|
|
|
|
ExpEvaluator::pushOne(stack,JsParser::nullClone());
|
|
|
|
break;
|
|
|
|
case 1:
|
|
|
|
{
|
|
|
|
ExpOperation* op = popValue(stack,context);
|
|
|
|
if (!op)
|
|
|
|
return false;
|
|
|
|
uint64_t newTime = 0;
|
|
|
|
if (op->isBoolean()) {
|
|
|
|
if (op->valBoolean())
|
|
|
|
newTime = Time::now();
|
|
|
|
}
|
|
|
|
else if (op->isInteger()) {
|
|
|
|
if (op->number() > 0)
|
|
|
|
newTime = 1000 * op->number();
|
|
|
|
}
|
|
|
|
TelEngine::destruct(op);
|
|
|
|
if (newTime && m_message && !frozen())
|
|
|
|
m_message->msgTime() = newTime;
|
|
|
|
else
|
|
|
|
newTime = 0;
|
|
|
|
ExpEvaluator::pushOne(stack,new ExpOperation(0 != newTime));
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
return false;
|
|
|
|
}
|
2013-11-05 15:50:09 +00:00
|
|
|
}
|
2017-04-27 12:30:45 +00:00
|
|
|
else if (oper.name() == YSTRING("msgAge")) {
|
|
|
|
if (oper.number())
|
|
|
|
return false;
|
|
|
|
if (m_message)
|
|
|
|
ExpEvaluator::pushOne(stack,new ExpOperation(
|
|
|
|
(int64_t)(Time::msecNow() - m_message->msgTime().msec())));
|
|
|
|
else
|
|
|
|
ExpEvaluator::pushOne(stack,JsParser::nullClone());
|
|
|
|
}
|
2017-01-20 15:16:19 +00:00
|
|
|
else if (oper.name() == YSTRING("getParam")) {
|
|
|
|
bool autoNum = true;
|
|
|
|
ObjList args;
|
|
|
|
switch (extractArgs(stack,oper,context,args)) {
|
|
|
|
case 3:
|
|
|
|
// fall through
|
|
|
|
autoNum = static_cast<ExpOperation*>(args[2])->valBoolean();
|
|
|
|
case 2:
|
|
|
|
case 1:
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
const String& name = *static_cast<ExpOperation*>(args[0]);
|
|
|
|
const String* val = m_message ? m_message->getParam(name) : 0;
|
|
|
|
if (val)
|
|
|
|
ExpEvaluator::pushOne(stack,new ExpOperation(*val,name,autoNum));
|
|
|
|
else {
|
|
|
|
if (args[1])
|
|
|
|
ExpEvaluator::pushOne(stack,static_cast<ExpOperation*>(args[1])->clone(name));
|
|
|
|
else
|
|
|
|
ExpEvaluator::pushOne(stack,new ExpWrapper(0,name));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (oper.name() == YSTRING("setParam")) {
|
|
|
|
ObjList args;
|
|
|
|
if (extractArgs(stack,oper,context,args) != 2)
|
|
|
|
return false;
|
|
|
|
const String& name = *static_cast<ExpOperation*>(args[0]);
|
|
|
|
const ExpOperation& val = *static_cast<const ExpOperation*>(args[1]);
|
|
|
|
if (m_message && name) {
|
|
|
|
if (JsParser::isUndefined(val))
|
|
|
|
m_message->clearParam(name);
|
|
|
|
else
|
|
|
|
m_message->setParam(name,val);
|
|
|
|
ExpEvaluator::pushOne(stack,new ExpOperation(true));
|
|
|
|
}
|
|
|
|
else
|
|
|
|
ExpEvaluator::pushOne(stack,new ExpOperation(false));
|
|
|
|
}
|
2012-06-28 18:23:04 +00:00
|
|
|
else if (oper.name() == YSTRING("getColumn")) {
|
|
|
|
ObjList args;
|
|
|
|
switch (extractArgs(stack,oper,context,args)) {
|
|
|
|
case 0:
|
|
|
|
case 1:
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
return false;
|
|
|
|
}
|
2020-10-21 11:01:31 +00:00
|
|
|
getColumn(stack,static_cast<ExpOperation*>(args[0]),context,oper.lineNumber());
|
2012-06-28 18:23:04 +00:00
|
|
|
}
|
|
|
|
else if (oper.name() == YSTRING("getRow")) {
|
|
|
|
ObjList args;
|
|
|
|
switch (extractArgs(stack,oper,context,args)) {
|
|
|
|
case 0:
|
|
|
|
case 1:
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
return false;
|
|
|
|
}
|
2020-10-21 11:01:31 +00:00
|
|
|
getRow(stack,static_cast<ExpOperation*>(args[0]),context,oper.lineNumber());
|
2012-06-28 18:23:04 +00:00
|
|
|
}
|
|
|
|
else if (oper.name() == YSTRING("getResult")) {
|
|
|
|
ObjList args;
|
|
|
|
if (extractArgs(stack,oper,context,args) != 2)
|
|
|
|
return false;
|
|
|
|
if (!(args[0] && args[1]))
|
|
|
|
return false;
|
|
|
|
getResult(stack,*static_cast<ExpOperation*>(args[0]),
|
|
|
|
*static_cast<ExpOperation*>(args[1]),context);
|
|
|
|
}
|
2012-03-05 09:53:31 +00:00
|
|
|
else if (oper.name() == YSTRING("enqueue")) {
|
|
|
|
if (oper.number() != 0)
|
|
|
|
return false;
|
|
|
|
bool ok = false;
|
2015-11-12 21:29:55 +00:00
|
|
|
if (m_owned && !frozen()) {
|
2012-03-05 09:53:31 +00:00
|
|
|
Message* m = m_message;
|
|
|
|
clearMsg();
|
|
|
|
if (m)
|
|
|
|
freeze();
|
|
|
|
ok = m && Engine::enqueue(m);
|
|
|
|
}
|
|
|
|
ExpEvaluator::pushOne(stack,new ExpOperation(ok));
|
|
|
|
}
|
|
|
|
else if (oper.name() == YSTRING("dispatch")) {
|
2013-04-12 15:18:50 +00:00
|
|
|
if (oper.number() > 1)
|
2012-03-05 09:53:31 +00:00
|
|
|
return false;
|
2013-04-12 15:18:50 +00:00
|
|
|
ObjList args;
|
|
|
|
extractArgs(stack,oper,context,args);
|
2012-03-05 09:53:31 +00:00
|
|
|
bool ok = false;
|
2017-11-01 16:37:48 +00:00
|
|
|
if (m_dispatch && m_message && !frozen()) {
|
2012-03-05 09:53:31 +00:00
|
|
|
Message* m = m_message;
|
2017-11-01 16:37:48 +00:00
|
|
|
bool own = m_owned;
|
2012-03-05 09:53:31 +00:00
|
|
|
clearMsg();
|
2013-04-12 15:18:50 +00:00
|
|
|
ExpOperation* async = static_cast<ExpOperation*>(args[0]);
|
|
|
|
if (async && async->valBoolean()) {
|
|
|
|
ScriptRun* runner = YOBJECT(ScriptRun,context);
|
|
|
|
if (!runner)
|
|
|
|
return false;
|
2017-11-01 16:37:48 +00:00
|
|
|
runner->insertAsync(new JsMsgAsync(runner,&stack,this,m,own));
|
2013-04-12 15:18:50 +00:00
|
|
|
runner->pause();
|
|
|
|
return true;
|
|
|
|
}
|
2012-03-05 09:53:31 +00:00
|
|
|
ok = Engine::dispatch(*m);
|
|
|
|
m_message = m;
|
2017-11-01 16:37:48 +00:00
|
|
|
m_owned = own;
|
|
|
|
m_dispatch = true;
|
2012-03-05 09:53:31 +00:00
|
|
|
}
|
|
|
|
ExpEvaluator::pushOne(stack,new ExpOperation(ok));
|
2012-02-17 16:19:17 +00:00
|
|
|
}
|
2012-06-18 13:52:21 +00:00
|
|
|
else if (oper.name() == YSTRING("install")) {
|
|
|
|
ObjList args;
|
|
|
|
if (extractArgs(stack,oper,context,args) < 2)
|
|
|
|
return false;
|
2012-11-20 16:11:38 +00:00
|
|
|
const ExpFunction* func = YOBJECT(ExpFunction,args[0]);
|
|
|
|
if (!func) {
|
|
|
|
JsFunction* jsf = YOBJECT(JsFunction,args[0]);
|
|
|
|
if (jsf)
|
|
|
|
func = jsf->getFunc();
|
|
|
|
}
|
2012-06-18 13:52:21 +00:00
|
|
|
if (!func)
|
|
|
|
return false;
|
|
|
|
ExpOperation* name = static_cast<ExpOperation*>(args[1]);
|
|
|
|
ExpOperation* prio = static_cast<ExpOperation*>(args[2]);
|
|
|
|
if (!name)
|
|
|
|
return false;
|
|
|
|
unsigned int priority = 100;
|
|
|
|
if (prio) {
|
|
|
|
if (prio->isInteger() && (prio->number() >= 0))
|
2013-08-07 11:24:10 +00:00
|
|
|
priority = (unsigned int)prio->number();
|
2012-06-18 13:52:21 +00:00
|
|
|
else
|
|
|
|
return false;
|
|
|
|
}
|
2020-10-21 11:01:31 +00:00
|
|
|
JsHandler* h = new JsHandler(*name,priority,*func,context,oper.lineNumber());
|
2013-04-12 12:53:10 +00:00
|
|
|
ExpOperation* filterName = static_cast<ExpOperation*>(args[3]);
|
|
|
|
ExpOperation* filterValue = static_cast<ExpOperation*>(args[4]);
|
2020-09-22 11:29:22 +00:00
|
|
|
if (filterName && filterValue && *filterName) {
|
|
|
|
JsRegExp* rexp = YOBJECT(JsRegExp,filterValue);
|
|
|
|
if (rexp)
|
|
|
|
h->setFilter(new NamedPointer(*filterName,new Regexp(rexp->regexp())));
|
|
|
|
else
|
|
|
|
h->setFilter(*filterName,*filterValue);
|
|
|
|
}
|
2013-04-12 12:55:51 +00:00
|
|
|
if (m_trackName) {
|
|
|
|
if (m_trackPrio)
|
|
|
|
h->trackName(m_trackName + ":" + String(priority));
|
|
|
|
else
|
|
|
|
h->trackName(m_trackName);
|
|
|
|
}
|
2012-06-18 13:52:21 +00:00
|
|
|
m_handlers.append(h);
|
|
|
|
Engine::install(h);
|
|
|
|
}
|
2012-06-19 18:55:45 +00:00
|
|
|
else if (oper.name() == YSTRING("uninstall")) {
|
|
|
|
ObjList args;
|
|
|
|
switch (extractArgs(stack,oper,context,args)) {
|
|
|
|
case 0:
|
|
|
|
m_handlers.clear();
|
|
|
|
return true;
|
|
|
|
case 1:
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
ExpOperation* name = static_cast<ExpOperation*>(args[0]);
|
|
|
|
if (!name)
|
|
|
|
return false;
|
|
|
|
m_handlers.remove(*name);
|
2013-04-12 12:55:51 +00:00
|
|
|
}
|
2014-07-24 13:03:16 +00:00
|
|
|
else if (oper.name() == YSTRING("handlers")) {
|
|
|
|
ObjList args;
|
|
|
|
switch (extractArgs(stack,oper,context,args)) {
|
|
|
|
case 0:
|
|
|
|
case 1:
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
ExpOperation* name = static_cast<ExpOperation*>(args[0]);
|
|
|
|
JsRegExp* rexp = YOBJECT(JsRegExp,name);
|
|
|
|
JsArray* jsa = 0;
|
|
|
|
for (ObjList* l = m_handlers.skipNull(); l; l = l->skipNext()) {
|
|
|
|
const JsHandler* h = static_cast<JsHandler*>(l->get());
|
|
|
|
if (rexp) {
|
|
|
|
if (!rexp->regexp().matches(*h))
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
else if (name && (*h != *name))
|
|
|
|
continue;
|
|
|
|
if (!jsa)
|
2020-10-21 11:01:31 +00:00
|
|
|
jsa = new JsArray(context,oper.lineNumber(),mutex());
|
|
|
|
JsObject* jso = new JsObject(context,oper.lineNumber(),mutex());
|
2014-07-24 13:03:16 +00:00
|
|
|
jso->params().setParam(new ExpOperation(*h,"name"));
|
|
|
|
jso->params().setParam(new ExpOperation((int64_t)h->priority(),"priority"));
|
|
|
|
jso->params().setParam(new ExpOperation(h->function().name(),"handler"));
|
|
|
|
const NamedString* f = h->filter();
|
|
|
|
if (f) {
|
|
|
|
jso->params().setParam(new ExpOperation(f->name(),"filterName"));
|
2020-09-22 11:29:22 +00:00
|
|
|
if (h->filterRegexp())
|
2020-10-21 11:01:31 +00:00
|
|
|
jso->params().setParam(new ExpWrapper(new JsRegExp(mutex(),*(h->filterRegexp()),oper.lineNumber()),"filterValue"));
|
2020-09-22 11:29:22 +00:00
|
|
|
else
|
|
|
|
jso->params().setParam(new ExpOperation(*f,"filterValue"));
|
2014-07-24 13:03:16 +00:00
|
|
|
}
|
|
|
|
if (h->trackName())
|
|
|
|
jso->params().setParam(new ExpOperation(h->trackName(),"trackName"));
|
|
|
|
jsa->push(new ExpWrapper(jso));
|
|
|
|
}
|
|
|
|
if (jsa)
|
|
|
|
ExpEvaluator::pushOne(stack,new ExpWrapper(jsa,"handlers"));
|
|
|
|
else
|
|
|
|
ExpEvaluator::pushOne(stack,JsParser::nullClone());
|
|
|
|
}
|
2013-04-12 13:56:00 +00:00
|
|
|
else if (oper.name() == YSTRING("installHook"))
|
|
|
|
return installHook(stack,oper,context);
|
|
|
|
else if (oper.name() == YSTRING("uninstallHook")) {
|
|
|
|
ObjList args;
|
|
|
|
if (extractArgs(stack,oper,context,args) < 1)
|
|
|
|
return false;
|
|
|
|
ObjList* o = args.skipNull();
|
|
|
|
ExpOperation* name = static_cast<ExpOperation*>(o->get());
|
|
|
|
NamedList hook(*name);
|
|
|
|
for (;o;o = o->skipNext()) {
|
|
|
|
ExpOperation* filter = static_cast<ExpOperation*>(o->get());
|
|
|
|
ObjList* pair = filter->split('=',false);
|
|
|
|
if (pair->count() == 2)
|
|
|
|
hook.addParam(*(static_cast<String*>((*pair)[0])), *(static_cast<String*>((*pair)[1])));
|
|
|
|
TelEngine::destruct(pair);
|
|
|
|
}
|
|
|
|
for (o = m_hooks.skipNull();o;o = o->skipNext()) {
|
|
|
|
JsMessageQueue* queue = static_cast<JsMessageQueue*>(o->get());
|
|
|
|
if (!queue->matchesFilters(hook))
|
|
|
|
continue;
|
|
|
|
Engine::uninstallHook(queue);
|
|
|
|
m_hooks.remove(queue);
|
|
|
|
}
|
|
|
|
}
|
2013-04-12 12:55:51 +00:00
|
|
|
else if (oper.name() == YSTRING("trackName")) {
|
|
|
|
ObjList args;
|
|
|
|
switch (extractArgs(stack,oper,context,args)) {
|
|
|
|
case 0:
|
|
|
|
ExpEvaluator::pushOne(stack,new ExpOperation(m_trackName,oper.name()));
|
|
|
|
break;
|
|
|
|
case 1:
|
|
|
|
case 2:
|
|
|
|
{
|
|
|
|
ExpOperation* name = static_cast<ExpOperation*>(args[0]);
|
|
|
|
ExpOperation* prio = static_cast<ExpOperation*>(args[1]);
|
|
|
|
if (!name)
|
|
|
|
return false;
|
|
|
|
m_trackName = *name;
|
|
|
|
m_trackName.trimSpaces();
|
|
|
|
if (prio)
|
|
|
|
m_trackPrio = prio->valBoolean();
|
|
|
|
else
|
|
|
|
m_trackPrio = true;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
return false;
|
|
|
|
}
|
2012-06-19 18:55:45 +00:00
|
|
|
}
|
2017-05-22 12:37:22 +00:00
|
|
|
else if (oper.name() == YSTRING("copyParams")) {
|
2017-11-01 16:37:48 +00:00
|
|
|
if (!m_message)
|
2017-05-22 12:37:22 +00:00
|
|
|
return true;
|
|
|
|
ObjList args;
|
|
|
|
bool skip = true;
|
|
|
|
String prefix;
|
|
|
|
NamedList* from = 0;
|
|
|
|
NamedList* fromNative = 0;
|
|
|
|
switch (extractArgs(stack,oper,context,args)) {
|
|
|
|
case 3:
|
|
|
|
skip = static_cast<ExpOperation*>(args[2])->valBoolean(skip);
|
2020-04-01 11:47:55 +00:00
|
|
|
// intentional
|
2017-05-22 12:37:22 +00:00
|
|
|
case 2:
|
|
|
|
prefix = static_cast<ExpOperation*>(args[1]);
|
|
|
|
// intentional
|
|
|
|
case 1:
|
|
|
|
{
|
|
|
|
ExpOperation* op = static_cast<ExpOperation*>(args[0]);
|
|
|
|
if (JsParser::isUndefined(*op) || JsParser::isNull(*op))
|
|
|
|
return true;
|
|
|
|
JsObject* obj = YOBJECT(JsObject,op);
|
|
|
|
if (obj) {
|
|
|
|
if (prefix) {
|
|
|
|
from = new NamedList("");
|
|
|
|
JsObject* subObj = YOBJECT(JsObject,obj->getField(stack,prefix,context));
|
|
|
|
if (subObj) {
|
|
|
|
copyObjParams(*from,&subObj->params());
|
|
|
|
if (subObj->nativeParams())
|
|
|
|
copyObjParams(*from,subObj->nativeParams());
|
|
|
|
|
|
|
|
for (ObjList* o = from->paramList()->skipNull(); o; o = o->skipNext()) {
|
|
|
|
NamedString* ns = static_cast<NamedString*>(o->get());
|
|
|
|
const_cast<String&>(ns->name()) = prefix + "." + ns->name();
|
|
|
|
}
|
|
|
|
prefix += ".";
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
copyObjParams(*from,&obj->params());
|
|
|
|
if (obj->nativeParams())
|
|
|
|
copyObjParams(*from,obj->nativeParams());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
from = &obj->params();
|
|
|
|
fromNative = obj->nativeParams();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
from = YOBJECT(NamedList,op);
|
|
|
|
if (!(from || fromNative))
|
|
|
|
return false;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
default:
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (prefix) {
|
|
|
|
m_message->copySubParams(*from,prefix,skip,true);
|
|
|
|
TelEngine::destruct(from);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
if (from)
|
|
|
|
copyObjParams(*m_message,from);
|
|
|
|
if (fromNative)
|
|
|
|
copyObjParams(*m_message,fromNative);
|
|
|
|
}
|
|
|
|
}
|
2018-02-12 14:42:45 +00:00
|
|
|
else if (oper.name() == YSTRING("clearParam")) {
|
|
|
|
if (!m_message)
|
|
|
|
return true;
|
|
|
|
ObjList args;
|
|
|
|
char sep = 0;
|
|
|
|
switch (extractArgs(stack,oper,context,args)) {
|
|
|
|
case 2:
|
|
|
|
{
|
|
|
|
ExpOperation* op = static_cast<ExpOperation*>(args[1]);
|
|
|
|
if (JsParser::isFilled(op)) {
|
|
|
|
if (op->length() > 1)
|
|
|
|
return false;
|
|
|
|
sep = (*op)[0];
|
|
|
|
}
|
|
|
|
// intentional
|
|
|
|
}
|
|
|
|
case 1:
|
|
|
|
{
|
|
|
|
String* name = static_cast<String*>(args[0]);
|
|
|
|
if (TelEngine::null(name))
|
|
|
|
return true;
|
|
|
|
m_message->clearParam(*name,sep);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
default:
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
2020-04-01 11:47:55 +00:00
|
|
|
else if (oper.name() == YSTRING("trace")) {
|
|
|
|
if (!m_message)
|
|
|
|
return true;
|
|
|
|
ObjList args;
|
|
|
|
unsigned int c = extractArgs(stack,oper,context,args);
|
|
|
|
if (c < 2)
|
|
|
|
return false;
|
|
|
|
ExpOperation* ret = static_cast<ExpOperation*>(args[0]);
|
|
|
|
ExpOperation* op = static_cast<ExpOperation*>(args[1]);
|
|
|
|
|
|
|
|
int level = -1;
|
|
|
|
int limit = s_allowAbort ? DebugFail : DebugTest;
|
|
|
|
if (op->number() > 1 && op->isInteger()) {
|
|
|
|
level = (int)op->number();
|
|
|
|
if (level > DebugAll)
|
|
|
|
level = DebugAll;
|
|
|
|
else if (level < limit)
|
|
|
|
level = limit;
|
|
|
|
}
|
|
|
|
|
|
|
|
String str;
|
|
|
|
ScriptRun* runner = YOBJECT(ScriptRun,context);
|
|
|
|
if (m_traceId) {
|
|
|
|
if (!runner)
|
|
|
|
return false;
|
|
|
|
str = runner->currentFileName();
|
|
|
|
str << ":" << runner->currentLineNo();
|
|
|
|
if (ret->isBoolean())
|
|
|
|
str << " - return:" << ret->valBoolean();
|
|
|
|
}
|
|
|
|
|
|
|
|
for (unsigned int i = 2; i < c; i++) {
|
|
|
|
ExpOperation* op = static_cast<ExpOperation*>(args[i]);
|
|
|
|
if (!op)
|
|
|
|
continue;
|
|
|
|
else if (*op) {
|
|
|
|
if (str)
|
|
|
|
str << " ";
|
|
|
|
str << *op;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
DebugEnabler* dbg = &__plugin;
|
|
|
|
if (runner && runner->context()) {
|
|
|
|
JsEngine* engine = YOBJECT(JsEngine,runner->context()->params().getParam(YSTRING("Engine")));
|
|
|
|
if (engine)
|
|
|
|
dbg = engine;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (m_traceId) {
|
|
|
|
if (level > m_traceLvl || level == -1)
|
|
|
|
level = m_traceLvl;
|
|
|
|
if (level < limit)
|
|
|
|
level = limit;
|
|
|
|
Debug(dbg,level,"Trace:%s %s",m_traceId.c_str(),str.c_str());
|
|
|
|
if (m_traceLst)
|
|
|
|
m_traceLst->append(new String(str));
|
|
|
|
}
|
|
|
|
else if (level > -1 && str)
|
|
|
|
Debug(dbg,level,"%s",str.c_str());
|
|
|
|
|
|
|
|
if (!JsParser::isUndefined(*ret))
|
|
|
|
ExpEvaluator::pushOne(stack,JsParser::isNull(*ret) ?
|
|
|
|
JsParser::nullClone() : new ExpOperation(*ret));
|
|
|
|
else
|
|
|
|
ExpEvaluator::pushOne(stack,new ExpWrapper(0,0));
|
|
|
|
}
|
2012-02-17 16:19:17 +00:00
|
|
|
else
|
|
|
|
return JsObject::runNative(stack,oper,context);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2017-11-01 16:37:48 +00:00
|
|
|
void JsMessage::runAsync(ObjList& stack, Message* msg, bool owned)
|
2013-04-12 15:18:50 +00:00
|
|
|
{
|
|
|
|
bool ok = Engine::dispatch(*msg);
|
|
|
|
if ((m_message || m_owned) && (msg != m_message))
|
|
|
|
Debug(&__plugin,DebugWarn,"Message replaced while async dispatching!");
|
|
|
|
else {
|
|
|
|
m_message = msg;
|
2017-11-01 16:37:48 +00:00
|
|
|
m_owned = owned;
|
|
|
|
m_dispatch = true;
|
2013-04-12 15:18:50 +00:00
|
|
|
}
|
|
|
|
ExpEvaluator::pushOne(stack,new ExpOperation(ok));
|
|
|
|
}
|
|
|
|
|
2013-04-12 13:56:00 +00:00
|
|
|
bool JsMessage::installHook(ObjList& stack, const ExpOperation& oper, GenObject* context)
|
|
|
|
{
|
|
|
|
ObjList args;
|
|
|
|
unsigned int argsCount = extractArgs(stack,oper,context,args);
|
|
|
|
if (argsCount < 2)
|
|
|
|
return false;
|
|
|
|
ObjList* o = args.skipNull();
|
|
|
|
const ExpFunction* receivedFunc = YOBJECT(ExpFunction,o->get());
|
|
|
|
if (!receivedFunc) {
|
|
|
|
JsFunction* jsf = YOBJECT(JsFunction,o->get());
|
|
|
|
if (jsf)
|
|
|
|
receivedFunc = jsf->getFunc();
|
|
|
|
}
|
|
|
|
if (receivedFunc) {
|
|
|
|
if (argsCount < 3)
|
|
|
|
return false;
|
|
|
|
o = o->skipNext();
|
|
|
|
}
|
|
|
|
ExpOperation* name = static_cast<ExpOperation*>(o->get());
|
|
|
|
if (TelEngine::null(name))
|
|
|
|
return false;
|
|
|
|
o = o->skipNext();
|
|
|
|
ExpOperation* threads = static_cast<ExpOperation*>(o->get());
|
|
|
|
int threadsCount = threads->toInteger(-1);
|
|
|
|
if (threadsCount < 1)
|
|
|
|
return false;
|
|
|
|
o = o->skipNext();
|
|
|
|
const ExpFunction* trapFunction = 0;
|
|
|
|
int trapLunch = 0;
|
|
|
|
while (o) {
|
|
|
|
trapFunction = YOBJECT(ExpFunction,o->get());
|
|
|
|
if (!trapFunction) {
|
|
|
|
JsFunction* jsf = YOBJECT(JsFunction,o->get());
|
|
|
|
if (jsf)
|
|
|
|
trapFunction = jsf->getFunc();
|
|
|
|
}
|
|
|
|
if (!trapFunction)
|
|
|
|
break;
|
|
|
|
o = o->skipNext();
|
|
|
|
if (!o)
|
|
|
|
return false;
|
|
|
|
ExpOperation* trap = static_cast<ExpOperation*>(o->get());
|
|
|
|
trapLunch = trap->toInteger(-1);
|
|
|
|
if (trapLunch < 0)
|
|
|
|
return false;
|
|
|
|
o = o->skipNext();
|
|
|
|
}
|
2020-10-21 11:01:31 +00:00
|
|
|
JsMessageQueue* msgQueue = new JsMessageQueue(oper.lineNumber(),receivedFunc,*name,threadsCount,trapFunction,trapLunch,context);
|
2013-04-12 13:56:00 +00:00
|
|
|
for (;o;o = o->skipNext()) {
|
|
|
|
ExpOperation* filter = static_cast<ExpOperation*>(o->get());
|
|
|
|
ObjList* pair = filter->split('=',false);
|
|
|
|
if (pair->count() == 2)
|
|
|
|
msgQueue->addFilter(*(static_cast<String*>((*pair)[0])), *(static_cast<String*>((*pair)[1])));
|
|
|
|
TelEngine::destruct(pair);
|
|
|
|
}
|
|
|
|
msgQueue->ref();
|
|
|
|
m_hooks.append(msgQueue);
|
|
|
|
return Engine::installHook(msgQueue);
|
|
|
|
}
|
|
|
|
|
2020-10-21 11:01:31 +00:00
|
|
|
void JsMessage::getColumn(ObjList& stack, const ExpOperation* col, GenObject* context, unsigned int lineNo)
|
2012-06-28 18:23:04 +00:00
|
|
|
{
|
|
|
|
Array* arr = m_message ? YOBJECT(Array,m_message->userData()) : 0;
|
|
|
|
if (arr && arr->getRows()) {
|
|
|
|
int rows = arr->getRows() - 1;
|
|
|
|
int cols = arr->getColumns();
|
|
|
|
if (col) {
|
|
|
|
// [ val1, val2, val3 ]
|
|
|
|
int idx = -1;
|
|
|
|
if (col->isInteger())
|
2013-08-07 11:24:10 +00:00
|
|
|
idx = (int)col->number();
|
2012-06-28 18:23:04 +00:00
|
|
|
else {
|
|
|
|
for (int i = 0; i < cols; i++) {
|
|
|
|
GenObject* o = arr->get(i,0);
|
|
|
|
if (o && (o->toString() == *col)) {
|
|
|
|
idx = i;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (idx >= 0 && idx < cols) {
|
2020-10-21 11:01:31 +00:00
|
|
|
JsArray* jsa = new JsArray(context,lineNo,mutex());
|
2012-06-28 18:23:04 +00:00
|
|
|
for (int r = 1; r <= rows; r++) {
|
|
|
|
GenObject* o = arr->get(idx,r);
|
2015-10-29 08:33:09 +00:00
|
|
|
if (o) {
|
|
|
|
const DataBlock* d = YOBJECT(DataBlock,o);
|
|
|
|
if (d) {
|
|
|
|
String x;
|
|
|
|
jsa->push(new ExpOperation(x.hexify(d->data(),d->length()),0,false));
|
|
|
|
}
|
|
|
|
else
|
|
|
|
jsa->push(new ExpOperation(o->toString(),0,true));
|
|
|
|
}
|
2012-06-28 18:23:04 +00:00
|
|
|
else
|
|
|
|
jsa->push(JsParser::nullClone());
|
|
|
|
}
|
|
|
|
ExpEvaluator::pushOne(stack,new ExpWrapper(jsa,"column"));
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
// { col1: [ val11, val12, val13], col2: [ val21, val22, val23 ] }
|
2020-10-21 11:01:31 +00:00
|
|
|
JsObject* jso = new JsObject(context,lineNo,mutex());
|
2012-06-28 18:23:04 +00:00
|
|
|
for (int c = 0; c < cols; c++) {
|
|
|
|
const String* name = YOBJECT(String,arr->get(c,0));
|
|
|
|
if (TelEngine::null(name))
|
|
|
|
continue;
|
2020-10-21 11:01:31 +00:00
|
|
|
JsArray* jsa = new JsArray(context,lineNo,mutex());
|
2012-06-28 18:23:04 +00:00
|
|
|
for (int r = 1; r <= rows; r++) {
|
|
|
|
GenObject* o = arr->get(c,r);
|
2015-10-29 08:33:09 +00:00
|
|
|
if (o) {
|
|
|
|
const DataBlock* d = YOBJECT(DataBlock,o);
|
|
|
|
if (d) {
|
|
|
|
String x;
|
|
|
|
jsa->push(new ExpOperation(x.hexify(d->data(),d->length()),*name,false));
|
|
|
|
}
|
|
|
|
else
|
|
|
|
jsa->push(new ExpOperation(o->toString(),*name,true));
|
|
|
|
}
|
2012-06-28 18:23:04 +00:00
|
|
|
else
|
|
|
|
jsa->push(JsParser::nullClone());
|
|
|
|
}
|
|
|
|
jso->params().setParam(new ExpWrapper(jsa,*name));
|
|
|
|
}
|
|
|
|
ExpEvaluator::pushOne(stack,new ExpWrapper(jso,"columns"));
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
ExpEvaluator::pushOne(stack,JsParser::nullClone());
|
|
|
|
}
|
|
|
|
|
2020-10-21 11:01:31 +00:00
|
|
|
void JsMessage::getRow(ObjList& stack, const ExpOperation* row, GenObject* context, unsigned int lineNo)
|
2012-06-28 18:23:04 +00:00
|
|
|
{
|
|
|
|
Array* arr = m_message ? YOBJECT(Array,m_message->userData()) : 0;
|
|
|
|
if (arr && arr->getRows()) {
|
|
|
|
int rows = arr->getRows() - 1;
|
|
|
|
int cols = arr->getColumns();
|
|
|
|
if (row) {
|
|
|
|
// { col1: val1, col2: val2 }
|
|
|
|
if (row->isInteger()) {
|
2013-08-07 11:24:10 +00:00
|
|
|
int idx = (int)row->number() + 1;
|
2012-06-28 18:23:04 +00:00
|
|
|
if (idx > 0 && idx <= rows) {
|
2020-10-21 11:01:31 +00:00
|
|
|
JsObject* jso = new JsObject(context,lineNo,mutex());
|
2012-06-28 18:23:04 +00:00
|
|
|
for (int c = 0; c < cols; c++) {
|
|
|
|
const String* name = YOBJECT(String,arr->get(c,0));
|
|
|
|
if (TelEngine::null(name))
|
|
|
|
continue;
|
|
|
|
GenObject* o = arr->get(c,idx);
|
2015-10-29 08:33:09 +00:00
|
|
|
if (o) {
|
|
|
|
const DataBlock* d = YOBJECT(DataBlock,o);
|
|
|
|
if (d) {
|
|
|
|
String x;
|
|
|
|
jso->params().setParam(new ExpOperation(x.hexify(d->data(),d->length()),*name,false));
|
|
|
|
}
|
|
|
|
else
|
|
|
|
jso->params().setParam(new ExpOperation(o->toString(),*name,true));
|
|
|
|
}
|
2012-06-28 18:23:04 +00:00
|
|
|
else
|
|
|
|
jso->params().setParam((JsParser::nullClone(*name)));
|
|
|
|
}
|
|
|
|
ExpEvaluator::pushOne(stack,new ExpWrapper(jso,"row"));
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
// [ { col1: val11, col2: val12 }, { col1: val21, col2: val22 } ]
|
2020-10-21 11:01:31 +00:00
|
|
|
JsArray* jsa = new JsArray(context,lineNo,mutex());
|
2012-06-28 18:23:04 +00:00
|
|
|
for (int r = 1; r <= rows; r++) {
|
2020-10-21 11:01:31 +00:00
|
|
|
JsObject* jso = new JsObject(context,lineNo,mutex());
|
2012-06-28 18:23:04 +00:00
|
|
|
for (int c = 0; c < cols; c++) {
|
|
|
|
const String* name = YOBJECT(String,arr->get(c,0));
|
|
|
|
if (TelEngine::null(name))
|
|
|
|
continue;
|
|
|
|
GenObject* o = arr->get(c,r);
|
2015-10-29 08:33:09 +00:00
|
|
|
if (o) {
|
|
|
|
const DataBlock* d = YOBJECT(DataBlock,o);
|
|
|
|
if (d) {
|
|
|
|
String x;
|
|
|
|
jso->params().setParam(new ExpOperation(x.hexify(d->data(),d->length()),*name,false));
|
|
|
|
}
|
|
|
|
else
|
|
|
|
jso->params().setParam(new ExpOperation(o->toString(),*name,true));
|
|
|
|
}
|
2012-06-28 18:23:04 +00:00
|
|
|
else
|
|
|
|
jso->params().setParam((JsParser::nullClone(*name)));
|
|
|
|
}
|
|
|
|
jsa->push(new ExpWrapper(jso));
|
|
|
|
}
|
|
|
|
ExpEvaluator::pushOne(stack,new ExpWrapper(jsa,"rows"));
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
ExpEvaluator::pushOne(stack,JsParser::nullClone());
|
|
|
|
}
|
|
|
|
|
|
|
|
void JsMessage::getResult(ObjList& stack, const ExpOperation& row, const ExpOperation& col, GenObject* context)
|
|
|
|
{
|
|
|
|
Array* arr = m_message ? YOBJECT(Array,m_message->userData()) : 0;
|
|
|
|
if (arr && arr->getRows() && row.isInteger()) {
|
|
|
|
int rows = arr->getRows() - 1;
|
|
|
|
int cols = arr->getColumns();
|
2013-08-07 11:24:10 +00:00
|
|
|
int r = (int)row.number();
|
2012-06-28 18:23:04 +00:00
|
|
|
if (r >= 0 && r < rows) {
|
|
|
|
int c = -1;
|
|
|
|
if (col.isInteger())
|
2013-08-07 11:24:10 +00:00
|
|
|
c = (int)col.number();
|
2012-06-28 18:23:04 +00:00
|
|
|
else {
|
|
|
|
for (int i = 0; i < cols; i++) {
|
|
|
|
GenObject* o = arr->get(i,0);
|
|
|
|
if (o && (o->toString() == col)) {
|
|
|
|
c = i;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (c >= 0 && c < cols) {
|
|
|
|
GenObject* o = arr->get(c,r + 1);
|
|
|
|
if (o) {
|
2013-04-12 12:54:30 +00:00
|
|
|
ExpEvaluator::pushOne(stack,new ExpOperation(o->toString(),0,true));
|
2012-06-28 18:23:04 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
ExpEvaluator::pushOne(stack,JsParser::nullClone());
|
|
|
|
}
|
|
|
|
|
2012-06-18 13:52:21 +00:00
|
|
|
JsObject* JsMessage::runConstructor(ObjList& stack, const ExpOperation& oper, GenObject* context)
|
2012-05-15 14:43:15 +00:00
|
|
|
{
|
2016-01-20 10:23:35 +00:00
|
|
|
XDebug(&__plugin,DebugAll,"JsMessage::runConstructor '%s'(" FMT64 ")",oper.name().c_str(),oper.number());
|
2012-06-18 13:52:21 +00:00
|
|
|
ObjList args;
|
|
|
|
switch (extractArgs(stack,oper,context,args)) {
|
|
|
|
case 1:
|
|
|
|
case 2:
|
2017-04-26 15:53:15 +00:00
|
|
|
case 3:
|
2012-06-18 13:52:21 +00:00
|
|
|
break;
|
|
|
|
default:
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
ExpOperation* name = static_cast<ExpOperation*>(args[0]);
|
|
|
|
ExpOperation* broad = static_cast<ExpOperation*>(args[1]);
|
2017-04-26 15:53:15 +00:00
|
|
|
JsObject* objParams = YOBJECT(JsObject,args[2]);
|
2012-06-18 13:52:21 +00:00
|
|
|
if (!name)
|
|
|
|
return 0;
|
2012-06-18 17:17:43 +00:00
|
|
|
if (!ref())
|
|
|
|
return 0;
|
2012-06-18 13:52:21 +00:00
|
|
|
Message* m = new Message(*name,0,broad && broad->valBoolean());
|
2017-04-26 15:53:15 +00:00
|
|
|
if (objParams) {
|
|
|
|
copyObjParams(*m,&objParams->params());
|
|
|
|
if (objParams->nativeParams())
|
|
|
|
copyObjParams(*m,objParams->nativeParams());
|
|
|
|
}
|
2020-04-22 12:05:53 +00:00
|
|
|
const String& traceId = YOBJECT(ScriptRun,context) ? context->traceId() : String::empty();
|
|
|
|
if (traceId)
|
|
|
|
m->setParam(YSTRING("trace_id"),traceId);
|
2020-10-21 11:01:31 +00:00
|
|
|
JsMessage* obj = new JsMessage(m,mutex(),oper.lineNumber(),true,true);
|
2012-06-18 17:17:43 +00:00
|
|
|
obj->params().addParam(new ExpWrapper(this,protoName()));
|
|
|
|
return obj;
|
2012-05-15 14:43:15 +00:00
|
|
|
}
|
|
|
|
|
2012-02-17 16:19:17 +00:00
|
|
|
void JsMessage::initialize(ScriptContext* context)
|
|
|
|
{
|
|
|
|
if (!context)
|
|
|
|
return;
|
2020-10-21 11:01:31 +00:00
|
|
|
ScriptMutex* mtx = context->mutex();
|
2012-02-17 16:19:17 +00:00
|
|
|
Lock mylock(mtx);
|
|
|
|
NamedList& params = context->params();
|
|
|
|
if (!params.getParam(YSTRING("Message")))
|
2012-06-18 13:52:21 +00:00
|
|
|
addConstructor(params,"Message",new JsMessage(mtx));
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2017-01-23 19:53:55 +00:00
|
|
|
bool JsHandler::receivedInternal(Message& msg)
|
2012-06-18 13:52:21 +00:00
|
|
|
{
|
2017-01-23 19:53:55 +00:00
|
|
|
if (s_engineStop || !m_code) {
|
|
|
|
safeNowInternal();
|
2012-06-18 13:52:21 +00:00
|
|
|
return false;
|
2017-01-23 19:53:55 +00:00
|
|
|
}
|
2012-06-20 15:54:43 +00:00
|
|
|
DDebug(&__plugin,DebugInfo,"Running %s(message) handler for '%s'",
|
|
|
|
m_function.name().c_str(),c_str());
|
2012-06-20 14:02:18 +00:00
|
|
|
#ifdef DEBUG
|
|
|
|
u_int64_t tm = Time::now();
|
|
|
|
#endif
|
2013-04-12 12:46:21 +00:00
|
|
|
ScriptRun* runner = m_code->createRunner(m_context,NATIVE_TITLE);
|
2017-01-23 19:53:55 +00:00
|
|
|
if (!runner) {
|
|
|
|
safeNowInternal();
|
2012-06-18 13:52:21 +00:00
|
|
|
return false;
|
2017-01-23 19:53:55 +00:00
|
|
|
}
|
2020-10-21 11:01:31 +00:00
|
|
|
JsMessage* jm = new JsMessage(&msg,runner->context()->mutex(),m_lineNo,true);
|
2017-05-08 09:03:05 +00:00
|
|
|
jm->setPrototype(runner->context(),YSTRING("Message"));
|
2012-06-18 13:52:21 +00:00
|
|
|
jm->ref();
|
2017-01-23 19:53:55 +00:00
|
|
|
String name = m_function.name();
|
|
|
|
safeNowInternal(); // Staring from here the handler may be safely uninstalled
|
2012-06-18 13:52:21 +00:00
|
|
|
ObjList args;
|
|
|
|
args.append(new ExpWrapper(jm,"message"));
|
2017-01-23 19:53:55 +00:00
|
|
|
ScriptRun::Status rval = runner->call(name,args);
|
2012-06-18 13:52:21 +00:00
|
|
|
jm->clearMsg();
|
2012-06-19 18:55:45 +00:00
|
|
|
bool ok = false;
|
|
|
|
if (ScriptRun::Succeeded == rval) {
|
|
|
|
ExpOperation* op = ExpEvaluator::popOne(runner->stack());
|
|
|
|
if (op) {
|
|
|
|
ok = op->valBoolean();
|
|
|
|
TelEngine::destruct(op);
|
|
|
|
}
|
|
|
|
}
|
2012-06-18 13:52:21 +00:00
|
|
|
TelEngine::destruct(jm);
|
|
|
|
TelEngine::destruct(runner);
|
2012-06-20 14:02:18 +00:00
|
|
|
|
|
|
|
#ifdef DEBUG
|
|
|
|
tm = Time::now() - tm;
|
2012-06-20 15:54:43 +00:00
|
|
|
Debug(&__plugin,DebugInfo,"Handler for '%s' ran for " FMT64U " usec",c_str(),tm);
|
2012-06-20 14:02:18 +00:00
|
|
|
#endif
|
2012-06-19 18:55:45 +00:00
|
|
|
return ok;
|
2012-02-17 16:19:17 +00:00
|
|
|
}
|
|
|
|
|
2014-10-29 16:32:20 +00:00
|
|
|
|
2013-04-12 13:56:00 +00:00
|
|
|
void JsMessageQueue::received(Message& msg)
|
|
|
|
{
|
|
|
|
if (s_engineStop || !m_code)
|
|
|
|
return;
|
|
|
|
if (!m_receivedFunction) {
|
|
|
|
MessageQueue::received(msg);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
ScriptRun* runner = m_code->createRunner(m_context,NATIVE_TITLE);
|
|
|
|
if (!runner)
|
|
|
|
return;
|
2020-10-21 11:01:31 +00:00
|
|
|
JsMessage* jm = new JsMessage(&msg,runner->context()->mutex(),m_lineNo,true);
|
2017-05-08 09:03:05 +00:00
|
|
|
jm->setPrototype(runner->context(),YSTRING("Message"));
|
2013-04-12 13:56:00 +00:00
|
|
|
jm->ref();
|
|
|
|
ObjList args;
|
|
|
|
args.append(new ExpWrapper(jm,"message"));
|
|
|
|
runner->call(m_receivedFunction->name(),args);
|
|
|
|
jm->clearMsg();
|
|
|
|
TelEngine::destruct(jm);
|
|
|
|
TelEngine::destruct(runner);
|
|
|
|
}
|
|
|
|
|
|
|
|
bool JsMessageQueue::enqueue(Message* msg)
|
|
|
|
{
|
|
|
|
if (!count())
|
|
|
|
m_trapCalled = false;
|
|
|
|
bool ret = MessageQueue::enqueue(msg);
|
|
|
|
if (!ret || !m_trapLunch || !m_trapFunction || m_trapCalled || count() < m_trapLunch)
|
|
|
|
return ret;
|
|
|
|
if (s_engineStop || !m_code)
|
|
|
|
return ret;
|
|
|
|
|
|
|
|
ScriptRun* runner = m_code->createRunner(m_context,NATIVE_TITLE);
|
|
|
|
if (!runner)
|
|
|
|
return ret;
|
|
|
|
ObjList args;
|
|
|
|
runner->call(m_trapFunction->name(),args);
|
|
|
|
TelEngine::destruct(runner);
|
|
|
|
m_trapCalled = true;
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool JsMessageQueue::matchesFilters(const NamedList& filters)
|
|
|
|
{
|
|
|
|
const NamedList origFilters = getFilters();
|
|
|
|
if (origFilters != filters)
|
|
|
|
return false;
|
|
|
|
unsigned int ofCount = origFilters.count(), fcount = filters.count();
|
|
|
|
if (ofCount != fcount)
|
|
|
|
return false;
|
|
|
|
if (!ofCount)
|
|
|
|
return true;
|
|
|
|
for (unsigned int i = 0;i < origFilters.length();i++) {
|
|
|
|
NamedString* param = origFilters.getParam(i);
|
|
|
|
NamedString* secParam = filters.getParam(*param);
|
|
|
|
if (!secParam || *secParam != *param)
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
2012-02-17 16:19:17 +00:00
|
|
|
|
2014-10-29 16:32:20 +00:00
|
|
|
|
2012-03-05 09:53:31 +00:00
|
|
|
bool JsFile::runNative(ObjList& stack, const ExpOperation& oper, GenObject* context)
|
|
|
|
{
|
2016-01-20 10:23:35 +00:00
|
|
|
XDebug(&__plugin,DebugAll,"JsFile::runNative '%s'(" FMT64 ")",oper.name().c_str(),oper.number());
|
2012-03-05 09:53:31 +00:00
|
|
|
if (oper.name() == YSTRING("exists")) {
|
|
|
|
if (oper.number() != 1)
|
|
|
|
return false;
|
|
|
|
ExpOperation* op = popValue(stack,context);
|
|
|
|
if (!op)
|
|
|
|
return false;
|
|
|
|
ExpEvaluator::pushOne(stack,new ExpOperation(File::exists(*op)));
|
|
|
|
TelEngine::destruct(op);
|
|
|
|
}
|
|
|
|
else if (oper.name() == YSTRING("remove")) {
|
|
|
|
if (oper.number() != 1)
|
|
|
|
return false;
|
|
|
|
ExpOperation* op = popValue(stack,context);
|
|
|
|
if (!op)
|
|
|
|
return false;
|
|
|
|
ExpEvaluator::pushOne(stack,new ExpOperation(File::remove(*op)));
|
|
|
|
TelEngine::destruct(op);
|
|
|
|
}
|
|
|
|
else if (oper.name() == YSTRING("rename")) {
|
|
|
|
if (oper.number() != 2)
|
|
|
|
return false;
|
|
|
|
ExpOperation* newName = popValue(stack,context);
|
|
|
|
if (!newName)
|
|
|
|
return false;
|
|
|
|
ExpOperation* oldName = popValue(stack,context);
|
|
|
|
if (!oldName) {
|
|
|
|
TelEngine::destruct(newName);
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
ExpEvaluator::pushOne(stack,new ExpOperation(File::rename(*oldName,*newName)));
|
|
|
|
TelEngine::destruct(oldName);
|
|
|
|
TelEngine::destruct(newName);
|
|
|
|
}
|
|
|
|
else if (oper.name() == YSTRING("mkdir")) {
|
2015-11-11 17:58:05 +00:00
|
|
|
int mode = -1;
|
|
|
|
ExpOperation* op = 0;
|
|
|
|
switch (oper.number()) {
|
|
|
|
case 2:
|
|
|
|
op = popValue(stack,context);
|
|
|
|
if (op && op->isInteger())
|
|
|
|
mode = op->number();
|
2018-12-11 16:57:32 +00:00
|
|
|
TelEngine::destruct(op);
|
2015-11-11 17:58:05 +00:00
|
|
|
// fall through
|
|
|
|
case 1:
|
|
|
|
op = popValue(stack,context);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
return false;
|
|
|
|
}
|
2012-03-05 09:53:31 +00:00
|
|
|
if (!op)
|
|
|
|
return false;
|
2015-11-11 17:58:05 +00:00
|
|
|
ExpEvaluator::pushOne(stack,new ExpOperation(File::mkDir(*op,0,mode)));
|
2012-03-05 09:53:31 +00:00
|
|
|
TelEngine::destruct(op);
|
|
|
|
}
|
|
|
|
else if (oper.name() == YSTRING("rmdir")) {
|
|
|
|
if (oper.number() != 1)
|
|
|
|
return false;
|
|
|
|
ExpOperation* op = popValue(stack,context);
|
|
|
|
if (!op)
|
|
|
|
return false;
|
|
|
|
ExpEvaluator::pushOne(stack,new ExpOperation(File::rmDir(*op)));
|
|
|
|
TelEngine::destruct(op);
|
|
|
|
}
|
|
|
|
else if (oper.name() == YSTRING("getFileTime")) {
|
|
|
|
if (oper.number() != 1)
|
|
|
|
return false;
|
|
|
|
ExpOperation* op = popValue(stack,context);
|
|
|
|
if (!op)
|
|
|
|
return false;
|
|
|
|
unsigned int epoch = 0;
|
2013-08-07 09:49:52 +00:00
|
|
|
int64_t fTime = File::getFileTime(*op,epoch) ? (int64_t)epoch : -1;
|
2012-03-05 09:53:31 +00:00
|
|
|
ExpEvaluator::pushOne(stack,new ExpOperation(fTime));
|
|
|
|
TelEngine::destruct(op);
|
|
|
|
}
|
|
|
|
else if (oper.name() == YSTRING("setFileTime")) {
|
|
|
|
if (oper.number() != 2)
|
|
|
|
return false;
|
|
|
|
ExpOperation* fTime = popValue(stack,context);
|
|
|
|
if (!fTime)
|
|
|
|
return false;
|
|
|
|
ExpOperation* fName = popValue(stack,context);
|
|
|
|
if (!fName) {
|
|
|
|
TelEngine::destruct(fTime);
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
bool ok = fTime->isInteger() && (fTime->number() >= 0) &&
|
2013-08-07 11:24:10 +00:00
|
|
|
File::setFileTime(*fName,(unsigned int)fTime->number());
|
2012-03-05 09:53:31 +00:00
|
|
|
TelEngine::destruct(fTime);
|
|
|
|
TelEngine::destruct(fName);
|
|
|
|
ExpEvaluator::pushOne(stack,new ExpOperation(ok));
|
|
|
|
}
|
2018-12-11 16:57:32 +00:00
|
|
|
else if (oper.name() == YSTRING("getContent")) {
|
|
|
|
// str = File.getContent(name[,binary[,maxlen]])
|
|
|
|
bool binary = false;
|
|
|
|
int maxRead = 65536;
|
|
|
|
ExpOperation* op = 0;
|
|
|
|
switch (oper.number()) {
|
|
|
|
case 3:
|
|
|
|
op = popValue(stack,context);
|
|
|
|
if (op)
|
|
|
|
maxRead = op->toInteger(maxRead,0,0,262144);
|
|
|
|
TelEngine::destruct(op);
|
|
|
|
// fall through
|
|
|
|
case 2:
|
|
|
|
op = popValue(stack,context);
|
|
|
|
binary = op && op->toBoolean();
|
|
|
|
TelEngine::destruct(op);
|
|
|
|
// fall through
|
|
|
|
case 1:
|
|
|
|
op = popValue(stack,context);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
ExpOperation* ret = 0;
|
|
|
|
if (op) {
|
|
|
|
File f;
|
|
|
|
if (f.openPath(*op,false,true,false,false,binary)) {
|
|
|
|
DataBlock buf(0,maxRead);
|
|
|
|
int rd = f.readData(buf.data(),buf.length());
|
|
|
|
if (rd >= 0) {
|
|
|
|
buf.truncate(rd);
|
|
|
|
ret = new ExpOperation("");
|
|
|
|
if (binary)
|
|
|
|
ret->hexify(buf.data(),buf.length());
|
|
|
|
else
|
|
|
|
ret->assign((const char*)buf.data(),buf.length());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
TelEngine::destruct(op);
|
|
|
|
if (!ret)
|
|
|
|
ret = JsParser::nullClone();
|
|
|
|
ExpEvaluator::pushOne(stack,ret);
|
|
|
|
}
|
|
|
|
else if (oper.name() == YSTRING("setContent")) {
|
2021-04-05 08:46:50 +00:00
|
|
|
// len = File.setContent(name,content[,binary|params])
|
|
|
|
bool create = true;
|
|
|
|
bool append = false;
|
2018-12-11 16:57:32 +00:00
|
|
|
bool binary = false;
|
2021-04-05 08:46:50 +00:00
|
|
|
bool pubRead = false;
|
|
|
|
bool pubWrite = false;
|
2018-12-11 16:57:32 +00:00
|
|
|
ExpOperation* op = 0;
|
|
|
|
ExpOperation* cont = 0;
|
|
|
|
switch (oper.number()) {
|
|
|
|
case 3:
|
|
|
|
op = popValue(stack,context);
|
2021-04-05 08:46:50 +00:00
|
|
|
{
|
|
|
|
JsObject* obj = YOBJECT(JsObject,op);
|
|
|
|
if (obj) {
|
|
|
|
obj->getBoolField(YSTRING("create"),create);
|
|
|
|
obj->getBoolField(YSTRING("append"),append);
|
|
|
|
obj->getBoolField(YSTRING("binary"),binary);
|
|
|
|
obj->getBoolField(YSTRING("pubread"),pubRead);
|
|
|
|
obj->getBoolField(YSTRING("pubwrite"),pubWrite);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
binary = op && op->toBoolean();
|
|
|
|
}
|
2018-12-11 16:57:32 +00:00
|
|
|
TelEngine::destruct(op);
|
|
|
|
// fall through
|
|
|
|
case 2:
|
|
|
|
cont = popValue(stack,context);
|
|
|
|
op = popValue(stack,context);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
int64_t wr = -1;
|
|
|
|
if (op && cont) {
|
|
|
|
File f;
|
2021-04-05 08:46:50 +00:00
|
|
|
if (f.openPath(*op,true,false,create,append,binary,pubRead,pubWrite)) {
|
2018-12-11 16:57:32 +00:00
|
|
|
if (binary) {
|
|
|
|
DataBlock buf;
|
2021-04-05 08:46:50 +00:00
|
|
|
if (buf.unHexify(cont->c_str(),cont->length()))
|
|
|
|
wr = static_cast<Stream&>(f).writeData(buf);
|
2018-12-11 16:57:32 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
wr = static_cast<Stream&>(f).writeData(*cont);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
TelEngine::destruct(op);
|
|
|
|
TelEngine::destruct(cont);
|
|
|
|
ExpEvaluator::pushOne(stack,new ExpOperation(wr));
|
|
|
|
}
|
2012-03-05 09:53:31 +00:00
|
|
|
else
|
|
|
|
return JsObject::runNative(stack,oper,context);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
void JsFile::initialize(ScriptContext* context)
|
|
|
|
{
|
|
|
|
if (!context)
|
|
|
|
return;
|
2020-10-21 11:01:31 +00:00
|
|
|
ScriptMutex* mtx = context->mutex();
|
2012-03-05 09:53:31 +00:00
|
|
|
Lock mylock(mtx);
|
|
|
|
NamedList& params = context->params();
|
|
|
|
if (!params.getParam(YSTRING("File")))
|
|
|
|
addObject(params,"File",new JsFile(mtx));
|
|
|
|
}
|
|
|
|
|
2017-08-01 06:20:58 +00:00
|
|
|
void JsSemaphore::runAsync(ObjList& stack, long maxWait)
|
|
|
|
{
|
|
|
|
if (m_exit) {
|
|
|
|
ExpEvaluator::pushOne(stack,new ExpOperation(false));
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
bool ret = m_semaphore.lock(maxWait);
|
|
|
|
if (m_exit)
|
|
|
|
ret = false;
|
|
|
|
ExpEvaluator::pushOne(stack,new ExpOperation(ret));
|
|
|
|
}
|
|
|
|
|
|
|
|
bool JsSemaphore::runNative(ObjList& stack, const ExpOperation& oper, GenObject* context)
|
|
|
|
{
|
|
|
|
XDebug(&__plugin,DebugAll,"JsSemaphore::runNative '%s'(" FMT64 ")",oper.name().c_str(),oper.number());
|
|
|
|
if (oper.name() == YSTRING("wait")) {
|
|
|
|
if (oper.number() != 1)
|
|
|
|
return false;
|
|
|
|
ExpOperation* op = popValue(stack,context);
|
|
|
|
long wait = 0;
|
|
|
|
if (JsParser::isNull(*op))
|
|
|
|
wait = -1;
|
|
|
|
else if ((wait = op->toInteger()) < 0)
|
|
|
|
wait = 0;
|
|
|
|
TelEngine::destruct(op);
|
|
|
|
ScriptRun* runner = YOBJECT(ScriptRun,context);
|
|
|
|
if (!runner)
|
|
|
|
return false;
|
|
|
|
runner->insertAsync(new JsSemaphoreAsync(runner,&stack,this,wait));
|
|
|
|
runner->pause();
|
|
|
|
}
|
|
|
|
else if (oper.name() == YSTRING("signal")) {
|
|
|
|
if (oper.number())
|
|
|
|
return false;
|
|
|
|
ExpEvaluator::pushOne(stack,new ExpOperation(m_semaphore.unlock()));
|
|
|
|
}
|
|
|
|
else
|
|
|
|
return false;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
void JsSemaphore::removeSemaphore(JsSemaphore* sem)
|
|
|
|
{
|
|
|
|
Lock myLock(mutex());
|
|
|
|
m_semaphores.remove(sem,false);
|
|
|
|
}
|
|
|
|
|
|
|
|
void JsSemaphore::forceExit()
|
|
|
|
{
|
|
|
|
m_exit = true;
|
|
|
|
m_constructor = 0;
|
|
|
|
m_semaphore.unlock();
|
|
|
|
}
|
|
|
|
|
|
|
|
JsObject* JsSemaphore::runConstructor(ObjList& stack, const ExpOperation& oper, GenObject* context)
|
|
|
|
{
|
|
|
|
ObjList args;
|
|
|
|
int maxcount = 1;
|
|
|
|
int initialCount = 0;
|
|
|
|
const char* name = "JsSemaphore";
|
|
|
|
switch (extractArgs(stack,oper,context,args)) {
|
|
|
|
case 3:
|
|
|
|
name = static_cast<ExpOperation*>(args[2])->c_str();
|
|
|
|
// Intentional
|
|
|
|
case 2:
|
|
|
|
initialCount = static_cast<ExpOperation*>(args[1])->toInteger(-1);
|
|
|
|
if (initialCount < 0)
|
|
|
|
initialCount = 0;
|
|
|
|
// Intentional
|
|
|
|
case 1:
|
|
|
|
maxcount = static_cast<ExpOperation*>(args[0])->toInteger();
|
|
|
|
if (maxcount < 1)
|
|
|
|
maxcount = 1;
|
|
|
|
// Intentional
|
|
|
|
case 0:
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
return 0;
|
|
|
|
}
|
2020-10-21 11:01:31 +00:00
|
|
|
JsSemaphore* sem = new JsSemaphore(this,mutex(),oper.lineNumber(),maxcount,initialCount,name);
|
2017-08-01 06:20:58 +00:00
|
|
|
mutex()->lock();
|
|
|
|
m_semaphores.append(sem);
|
|
|
|
mutex()->unlock();
|
2017-08-02 13:48:40 +00:00
|
|
|
// Set the object prototype.
|
|
|
|
// Custom because the Constructor is part of Engine object.
|
|
|
|
ScriptContext* ctxt = YOBJECT(ScriptContext,context);
|
|
|
|
if (!ctxt) {
|
|
|
|
ScriptRun* sr = YOBJECT(ScriptRun,context);
|
|
|
|
if (!(sr && (ctxt = YOBJECT(ScriptContext,sr->context()))))
|
|
|
|
return sem;
|
|
|
|
}
|
|
|
|
JsObject* engine = YOBJECT(JsObject,ctxt->params().getParam(YSTRING("Engine")));
|
|
|
|
if (!engine)
|
|
|
|
return sem;
|
|
|
|
JsObject* semCtr = YOBJECT(JsObject,engine->params().getParam(YSTRING("Semaphore")));
|
|
|
|
if (semCtr) {
|
|
|
|
JsObject* proto = YOBJECT(JsObject,semCtr->params().getParam(YSTRING("prototype")));
|
|
|
|
if (proto && proto->ref())
|
|
|
|
sem->params().addParam(new ExpWrapper(proto,protoName()));
|
|
|
|
}
|
2017-08-01 06:20:58 +00:00
|
|
|
return sem;
|
|
|
|
}
|
2012-03-05 09:53:31 +00:00
|
|
|
|
2014-10-29 16:32:20 +00:00
|
|
|
void* JsConfigFile::getObject(const String& name) const
|
|
|
|
{
|
|
|
|
void* obj = (name == YATOM("JsConfigFile")) ? const_cast<JsConfigFile*>(this) : JsObject::getObject(name);
|
|
|
|
if (!obj)
|
|
|
|
obj = m_config.getObject(name);
|
|
|
|
return obj;
|
|
|
|
}
|
|
|
|
|
2021-12-22 07:03:35 +00:00
|
|
|
static void handleCfgSetValues(bool set, Configuration& cfg, const String& sName,
|
|
|
|
GenObject* params, const String* prefix)
|
|
|
|
{
|
|
|
|
const NamedList* pList = sName ? getReplaceParams(params) : 0;
|
|
|
|
if (!pList)
|
|
|
|
return;
|
|
|
|
NamedList* sect = cfg.createSection(sName);
|
|
|
|
if (TelEngine::null(prefix))
|
|
|
|
prefix = 0;
|
|
|
|
for (ObjList* o = pList->paramList()->skipNull(); o; o = o->skipNext()) {
|
|
|
|
NamedString* ns = static_cast<NamedString*>(o->get());
|
|
|
|
JsObject* jso = YOBJECT(JsObject,ns);
|
|
|
|
if (jso || ns->name() == JsObject::protoName())
|
|
|
|
continue;
|
|
|
|
if (set) {
|
|
|
|
if (prefix)
|
|
|
|
sect->setParam(*prefix + ns->name(),*ns);
|
|
|
|
else
|
|
|
|
sect->setParam(ns->name(),*ns);
|
|
|
|
}
|
|
|
|
else if (prefix)
|
|
|
|
sect->addParam(*prefix + ns->name(),*ns);
|
|
|
|
else
|
|
|
|
sect->addParam(ns->name(),*ns);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-04-01 11:27:51 +00:00
|
|
|
bool JsConfigFile::runNative(ObjList& stack, const ExpOperation& oper, GenObject* context)
|
|
|
|
{
|
2016-01-20 10:23:35 +00:00
|
|
|
XDebug(&__plugin,DebugAll,"JsConfigFile::runNative '%s'(" FMT64 ")",oper.name().c_str(),oper.number());
|
2014-04-01 11:27:51 +00:00
|
|
|
ObjList args;
|
|
|
|
if (oper.name() == YSTRING("name")) {
|
2014-07-11 16:54:28 +00:00
|
|
|
switch (extractArgs(stack,oper,context,args)) {
|
2014-04-01 11:27:51 +00:00
|
|
|
case 0:
|
|
|
|
ExpEvaluator::pushOne(stack,new ExpOperation(m_config));
|
|
|
|
break;
|
|
|
|
case 1:
|
|
|
|
m_config = *static_cast<ExpOperation*>(args[0]);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (oper.name() == YSTRING("load")) {
|
2014-07-11 16:54:28 +00:00
|
|
|
switch (extractArgs(stack,oper,context,args)) {
|
2014-04-01 11:27:51 +00:00
|
|
|
case 0:
|
|
|
|
case 1:
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
ExpEvaluator::pushOne(stack,new ExpOperation(m_config.load(args[0]
|
|
|
|
&& static_cast<ExpOperation*>(args[0])->valBoolean())));
|
|
|
|
}
|
|
|
|
else if (oper.name() == YSTRING("save")) {
|
2014-07-11 16:54:28 +00:00
|
|
|
if (extractArgs(stack,oper,context,args) != 0)
|
2014-04-01 11:27:51 +00:00
|
|
|
return false;
|
|
|
|
ExpEvaluator::pushOne(stack,new ExpOperation(m_config.save()));
|
|
|
|
}
|
|
|
|
else if (oper.name() == YSTRING("count")) {
|
2014-07-11 16:54:28 +00:00
|
|
|
if (extractArgs(stack,oper,context,args) != 0)
|
2014-04-01 11:27:51 +00:00
|
|
|
return false;
|
|
|
|
ExpEvaluator::pushOne(stack,new ExpOperation((int64_t)m_config.sections()));
|
|
|
|
}
|
|
|
|
else if (oper.name() == YSTRING("sections")) {
|
2014-07-11 16:54:28 +00:00
|
|
|
if (extractArgs(stack,oper,context,args) != 0)
|
2014-04-01 11:27:51 +00:00
|
|
|
return false;
|
2020-10-21 11:53:57 +00:00
|
|
|
JsObject* jso = new JsObject(context,oper.lineNumber(),mutex());
|
2014-04-01 11:27:51 +00:00
|
|
|
unsigned int n = m_config.sections();
|
|
|
|
for (unsigned int i = 0; i < n; i++) {
|
|
|
|
NamedList* nl = m_config.getSection(i);
|
|
|
|
if (nl)
|
2020-10-21 11:53:57 +00:00
|
|
|
jso->params().addParam(new ExpWrapper(new JsConfigSection(this,*nl,oper.lineNumber()),*nl));
|
2014-04-01 11:27:51 +00:00
|
|
|
}
|
2020-10-21 11:53:57 +00:00
|
|
|
ExpEvaluator::pushOne(stack,new ExpWrapper(jso,"sections"));
|
2014-04-01 11:27:51 +00:00
|
|
|
}
|
|
|
|
else if (oper.name() == YSTRING("getSection")) {
|
|
|
|
bool create = false;
|
2014-07-11 16:54:28 +00:00
|
|
|
switch (extractArgs(stack,oper,context,args)) {
|
2014-04-01 11:27:51 +00:00
|
|
|
case 2:
|
|
|
|
create = static_cast<ExpOperation*>(args[1])->valBoolean();
|
|
|
|
break;
|
|
|
|
case 1:
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
const String& name = *static_cast<ExpOperation*>(args[0]);
|
|
|
|
if (create ? m_config.createSection(name) : m_config.getSection(name))
|
2020-10-21 11:01:31 +00:00
|
|
|
ExpEvaluator::pushOne(stack,new ExpWrapper(new JsConfigSection(this,name,oper.lineNumber()),name));
|
2014-04-01 11:27:51 +00:00
|
|
|
else
|
|
|
|
ExpEvaluator::pushOne(stack,JsParser::nullClone());
|
|
|
|
}
|
|
|
|
else if (oper.name() == YSTRING("getValue")) {
|
2014-07-11 16:54:28 +00:00
|
|
|
switch (extractArgs(stack,oper,context,args)) {
|
2014-04-01 11:27:51 +00:00
|
|
|
case 2:
|
|
|
|
case 3:
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
const String& name = *static_cast<ExpOperation*>(args[1]);
|
|
|
|
static const char defVal[] = "default";
|
|
|
|
const char* val = m_config.getValue(*static_cast<ExpOperation*>(args[0]),name,defVal);
|
|
|
|
if (val == defVal) {
|
|
|
|
if (args[2])
|
|
|
|
ExpEvaluator::pushOne(stack,static_cast<ExpOperation*>(args[2])->clone(name));
|
|
|
|
else
|
|
|
|
ExpEvaluator::pushOne(stack,new ExpWrapper(0,name));
|
|
|
|
}
|
|
|
|
else
|
|
|
|
ExpEvaluator::pushOne(stack,new ExpOperation(val,name));
|
|
|
|
}
|
2014-12-22 11:56:16 +00:00
|
|
|
else if (oper.name() == YSTRING("getIntValue")) {
|
|
|
|
int64_t defVal = 0;
|
2015-08-27 10:56:06 +00:00
|
|
|
int64_t minVal = LLONG_MIN;
|
|
|
|
int64_t maxVal = LLONG_MAX;
|
|
|
|
bool clamp = true;
|
2014-12-22 11:56:16 +00:00
|
|
|
switch (extractArgs(stack,oper,context,args)) {
|
2015-08-27 10:56:06 +00:00
|
|
|
case 6:
|
|
|
|
clamp = static_cast<ExpOperation*>(args[5])->valBoolean(clamp);
|
|
|
|
// fall through
|
|
|
|
case 5:
|
|
|
|
maxVal = static_cast<ExpOperation*>(args[4])->valInteger(maxVal);
|
|
|
|
// fall through
|
|
|
|
case 4:
|
|
|
|
minVal = static_cast<ExpOperation*>(args[3])->valInteger(minVal);
|
|
|
|
// fall through
|
2014-12-22 11:56:16 +00:00
|
|
|
case 3:
|
|
|
|
defVal = static_cast<ExpOperation*>(args[2])->valInteger();
|
|
|
|
// fall through
|
|
|
|
case 2:
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
const String& sect = *static_cast<ExpOperation*>(args[0]);
|
|
|
|
const String& name = *static_cast<ExpOperation*>(args[1]);
|
2015-08-27 10:56:06 +00:00
|
|
|
ExpEvaluator::pushOne(stack,new ExpOperation(m_config.getInt64Value(sect,name,defVal,minVal,maxVal,clamp),name));
|
2014-12-22 11:56:16 +00:00
|
|
|
}
|
|
|
|
else if (oper.name() == YSTRING("getBoolValue")) {
|
|
|
|
bool defVal = false;
|
|
|
|
switch (extractArgs(stack,oper,context,args)) {
|
|
|
|
case 3:
|
|
|
|
defVal = static_cast<ExpOperation*>(args[2])->valBoolean();
|
|
|
|
// fall through
|
|
|
|
case 2:
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
const String& sect = *static_cast<ExpOperation*>(args[0]);
|
|
|
|
const String& name = *static_cast<ExpOperation*>(args[1]);
|
|
|
|
ExpEvaluator::pushOne(stack,new ExpOperation(m_config.getBoolValue(sect,name,defVal),name));
|
|
|
|
}
|
2014-04-01 11:27:51 +00:00
|
|
|
else if (oper.name() == YSTRING("setValue")) {
|
2014-07-11 16:54:28 +00:00
|
|
|
if (extractArgs(stack,oper,context,args) != 3)
|
2014-04-01 11:27:51 +00:00
|
|
|
return false;
|
|
|
|
m_config.setValue(*static_cast<ExpOperation*>(args[0]),*static_cast<ExpOperation*>(args[1]),
|
|
|
|
*static_cast<ExpOperation*>(args[2]));
|
|
|
|
}
|
2015-08-25 10:18:26 +00:00
|
|
|
else if (oper.name() == YSTRING("addValue")) {
|
|
|
|
if (extractArgs(stack,oper,context,args) != 3)
|
|
|
|
return false;
|
|
|
|
m_config.addValue(*static_cast<ExpOperation*>(args[0]),*static_cast<ExpOperation*>(args[1]),
|
|
|
|
*static_cast<ExpOperation*>(args[2]));
|
|
|
|
}
|
2021-12-22 07:03:35 +00:00
|
|
|
else if (oper.name() == YSTRING("setValues") || oper.name() == YSTRING("addValues")) {
|
|
|
|
// setValues(sect,params[,prefix])
|
|
|
|
// addValues(sect,params[,prefix])
|
|
|
|
ExpOperation* sName = 0;
|
|
|
|
ExpOperation* params = 0;
|
|
|
|
ExpOperation* prefix = 0;
|
|
|
|
if (!extractStackArgs(2,this,stack,oper,context,args,&sName,¶ms,&prefix))
|
|
|
|
return false;
|
|
|
|
handleCfgSetValues(oper.name() == YSTRING("setValues"),m_config,*sName,params,prefix);
|
|
|
|
}
|
2015-08-25 09:37:59 +00:00
|
|
|
else if (oper.name() == YSTRING("clearSection")) {
|
|
|
|
ExpOperation* op = 0;
|
|
|
|
switch (extractArgs(stack,oper,context,args)) {
|
|
|
|
case 0:
|
|
|
|
break;
|
|
|
|
case 1:
|
|
|
|
op = static_cast<ExpOperation*>(args[0]);
|
|
|
|
if (JsParser::isUndefined(*op) || JsParser::isNull(*op))
|
|
|
|
op = 0;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
m_config.clearSection(op ? (const char*)*op : 0);
|
|
|
|
}
|
2014-04-01 11:27:51 +00:00
|
|
|
else if (oper.name() == YSTRING("clearKey")) {
|
2014-07-11 16:54:28 +00:00
|
|
|
if (extractArgs(stack,oper,context,args) != 2)
|
2014-04-01 11:27:51 +00:00
|
|
|
return false;
|
|
|
|
m_config.clearKey(*static_cast<ExpOperation*>(args[0]),*static_cast<ExpOperation*>(args[1]));
|
|
|
|
}
|
|
|
|
else if (oper.name() == YSTRING("keys")) {
|
2014-07-11 16:54:28 +00:00
|
|
|
if (extractArgs(stack,oper,context,args) != 1)
|
2014-04-01 11:27:51 +00:00
|
|
|
return false;
|
|
|
|
NamedList* sect = m_config.getSection(*static_cast<ExpOperation*>(args[0]));
|
|
|
|
if (sect) {
|
2020-10-21 11:01:31 +00:00
|
|
|
JsArray* jsa = new JsArray(context,oper.lineNumber(),mutex());
|
2014-04-01 11:27:51 +00:00
|
|
|
int32_t len = 0;
|
|
|
|
for (const ObjList* l = sect->paramList()->skipNull(); l; l = l->skipNext()) {
|
|
|
|
jsa->push(new ExpOperation(static_cast<const NamedString*>(l->get())->name()));
|
|
|
|
len++;
|
|
|
|
}
|
|
|
|
jsa->setLength(len);
|
|
|
|
ExpEvaluator::pushOne(stack,new ExpWrapper(jsa,oper.name()));
|
|
|
|
}
|
|
|
|
else
|
|
|
|
ExpEvaluator::pushOne(stack,new ExpWrapper(0,oper.name()));
|
|
|
|
}
|
|
|
|
else
|
|
|
|
return JsObject::runNative(stack,oper,context);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
JsObject* JsConfigFile::runConstructor(ObjList& stack, const ExpOperation& oper, GenObject* context)
|
|
|
|
{
|
2016-01-20 10:23:35 +00:00
|
|
|
XDebug(&__plugin,DebugAll,"JsConfigFile::runConstructor '%s'(" FMT64 ") [%p]",oper.name().c_str(),oper.number(),this);
|
2014-04-01 11:27:51 +00:00
|
|
|
bool warn = false;
|
|
|
|
const char* name = 0;
|
|
|
|
ObjList args;
|
|
|
|
switch (extractArgs(stack,oper,context,args)) {
|
|
|
|
case 2:
|
|
|
|
warn = static_cast<ExpOperation*>(args[1])->valBoolean();
|
|
|
|
// fall through
|
|
|
|
case 1:
|
|
|
|
name = static_cast<ExpOperation*>(args[0])->c_str();
|
|
|
|
// fall through
|
|
|
|
case 0:
|
2020-10-21 11:01:31 +00:00
|
|
|
{
|
|
|
|
JsConfigFile* obj = new JsConfigFile(mutex(),oper.lineNumber(),name,warn);
|
|
|
|
if (!ref()) {
|
|
|
|
TelEngine::destruct(obj);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
obj->params().addParam(new ExpWrapper(this,protoName()));
|
|
|
|
return obj;
|
|
|
|
}
|
2014-04-01 11:27:51 +00:00
|
|
|
default:
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void JsConfigFile::initialize(ScriptContext* context)
|
|
|
|
{
|
|
|
|
if (!context)
|
|
|
|
return;
|
2020-10-21 11:01:31 +00:00
|
|
|
ScriptMutex* mtx = context->mutex();
|
2014-04-01 11:27:51 +00:00
|
|
|
Lock mylock(mtx);
|
|
|
|
NamedList& params = context->params();
|
|
|
|
if (!params.getParam(YSTRING("ConfigFile")))
|
|
|
|
addConstructor(params,"ConfigFile",new JsConfigFile(mtx));
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
bool JsConfigSection::runNative(ObjList& stack, const ExpOperation& oper, GenObject* context)
|
|
|
|
{
|
2016-01-20 10:23:35 +00:00
|
|
|
XDebug(&__plugin,DebugAll,"JsConfigSection::runNative '%s'(" FMT64 ")",oper.name().c_str(),oper.number());
|
2014-04-01 11:27:51 +00:00
|
|
|
ObjList args;
|
|
|
|
if (oper.name() == YSTRING("configFile")) {
|
2014-07-11 16:54:28 +00:00
|
|
|
if (extractArgs(stack,oper,context,args) != 0)
|
2014-04-01 11:27:51 +00:00
|
|
|
return false;
|
|
|
|
ExpEvaluator::pushOne(stack,new ExpWrapper(m_owner->ref() ? m_owner : 0));
|
|
|
|
}
|
|
|
|
else if (oper.name() == YSTRING("getValue")) {
|
2014-07-11 16:54:28 +00:00
|
|
|
switch (extractArgs(stack,oper,context,args)) {
|
2014-04-01 11:27:51 +00:00
|
|
|
case 2:
|
|
|
|
case 1:
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
NamedList* sect = m_owner->config().getSection(toString());
|
|
|
|
const String& name = *static_cast<ExpOperation*>(args[0]);
|
|
|
|
static const char defVal[] = "default";
|
|
|
|
const char* val = sect ? sect->getValue(name,defVal) : defVal;
|
|
|
|
if (val == defVal) {
|
|
|
|
if (args[1])
|
|
|
|
ExpEvaluator::pushOne(stack,static_cast<ExpOperation*>(args[1])->clone(name));
|
|
|
|
else
|
|
|
|
ExpEvaluator::pushOne(stack,new ExpWrapper(0,name));
|
|
|
|
}
|
|
|
|
else
|
|
|
|
ExpEvaluator::pushOne(stack,new ExpOperation(val,name));
|
2014-12-22 11:56:16 +00:00
|
|
|
}
|
|
|
|
else if (oper.name() == YSTRING("getIntValue")) {
|
|
|
|
int64_t val = 0;
|
2015-08-27 10:56:06 +00:00
|
|
|
int64_t minVal = LLONG_MIN;
|
|
|
|
int64_t maxVal = LLONG_MAX;
|
|
|
|
bool clamp = true;
|
2014-12-22 11:56:16 +00:00
|
|
|
switch (extractArgs(stack,oper,context,args)) {
|
2015-08-27 10:56:06 +00:00
|
|
|
case 5:
|
|
|
|
clamp = static_cast<ExpOperation*>(args[4])->valBoolean(clamp);
|
|
|
|
// fall through
|
|
|
|
case 4:
|
|
|
|
maxVal = static_cast<ExpOperation*>(args[3])->valInteger(maxVal);
|
|
|
|
// fall through
|
|
|
|
case 3:
|
|
|
|
minVal = static_cast<ExpOperation*>(args[2])->valInteger(minVal);
|
|
|
|
// fall through
|
2014-12-22 11:56:16 +00:00
|
|
|
case 2:
|
|
|
|
val = static_cast<ExpOperation*>(args[1])->valInteger();
|
|
|
|
// fall through
|
|
|
|
case 1:
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
const String& name = *static_cast<ExpOperation*>(args[0]);
|
|
|
|
NamedList* sect = m_owner->config().getSection(toString());
|
|
|
|
if (sect)
|
2015-08-27 10:56:06 +00:00
|
|
|
val = sect->getInt64Value(name,val,minVal,maxVal,clamp);
|
|
|
|
else if (val < minVal)
|
|
|
|
val = minVal;
|
|
|
|
else if (val > maxVal)
|
|
|
|
val = maxVal;
|
2014-12-22 11:56:16 +00:00
|
|
|
ExpEvaluator::pushOne(stack,new ExpOperation(val,name));
|
|
|
|
}
|
|
|
|
else if (oper.name() == YSTRING("getBoolValue")) {
|
|
|
|
bool val = false;
|
|
|
|
switch (extractArgs(stack,oper,context,args)) {
|
|
|
|
case 2:
|
|
|
|
val = static_cast<ExpOperation*>(args[1])->valBoolean();
|
|
|
|
// fall through
|
|
|
|
case 1:
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
const String& name = *static_cast<ExpOperation*>(args[0]);
|
|
|
|
NamedList* sect = m_owner->config().getSection(toString());
|
|
|
|
if (sect)
|
|
|
|
val = sect->getBoolValue(name,val);
|
|
|
|
ExpEvaluator::pushOne(stack,new ExpOperation(val,name));
|
2014-04-01 11:27:51 +00:00
|
|
|
}
|
|
|
|
else if (oper.name() == YSTRING("setValue")) {
|
2014-07-11 16:54:28 +00:00
|
|
|
if (extractArgs(stack,oper,context,args) != 2)
|
2014-04-01 11:27:51 +00:00
|
|
|
return false;
|
|
|
|
NamedList* sect = m_owner->config().getSection(toString());
|
|
|
|
if (sect)
|
|
|
|
sect->setParam(*static_cast<ExpOperation*>(args[0]),*static_cast<ExpOperation*>(args[1]));
|
2015-08-25 09:37:59 +00:00
|
|
|
}
|
|
|
|
else if (oper.name() == YSTRING("addValue")) {
|
|
|
|
if (extractArgs(stack,oper,context,args) != 2)
|
|
|
|
return false;
|
|
|
|
NamedList* sect = m_owner->config().getSection(toString());
|
|
|
|
if (sect)
|
|
|
|
sect->addParam(*static_cast<ExpOperation*>(args[0]),*static_cast<ExpOperation*>(args[1]));
|
2014-04-01 11:27:51 +00:00
|
|
|
}
|
2021-12-22 07:03:35 +00:00
|
|
|
else if (oper.name() == YSTRING("setValues") || oper.name() == YSTRING("addValues")) {
|
|
|
|
// setValues(params[,prefix])
|
|
|
|
// addValues(params[,prefix])
|
|
|
|
ExpOperation* params = 0;
|
|
|
|
ExpOperation* prefix = 0;
|
|
|
|
if (!extractStackArgs(1,this,stack,oper,context,args,¶ms,&prefix))
|
|
|
|
return false;
|
|
|
|
handleCfgSetValues(oper.name() == YSTRING("setValues"),m_owner->config(),toString(),params,prefix);
|
|
|
|
}
|
2014-04-01 11:27:51 +00:00
|
|
|
else if (oper.name() == YSTRING("clearKey")) {
|
2014-07-11 16:54:28 +00:00
|
|
|
if (extractArgs(stack,oper,context,args) != 1)
|
2014-04-01 11:27:51 +00:00
|
|
|
return false;
|
|
|
|
NamedList* sect = m_owner->config().getSection(toString());
|
|
|
|
if (sect)
|
|
|
|
sect->clearParam(*static_cast<ExpOperation*>(args[0]));
|
|
|
|
}
|
|
|
|
else if (oper.name() == YSTRING("keys")) {
|
2014-07-11 16:54:28 +00:00
|
|
|
if (extractArgs(stack,oper,context,args) != 0)
|
2014-04-01 11:27:51 +00:00
|
|
|
return false;
|
|
|
|
NamedList* sect = m_owner->config().getSection(toString());
|
|
|
|
if (sect) {
|
2020-10-21 11:01:31 +00:00
|
|
|
JsArray* jsa = new JsArray(context,oper.lineNumber(),mutex());
|
2014-04-01 11:27:51 +00:00
|
|
|
int32_t len = 0;
|
|
|
|
for (const ObjList* l = sect->paramList()->skipNull(); l; l = l->skipNext()) {
|
|
|
|
jsa->push(new ExpOperation(static_cast<const NamedString*>(l->get())->name()));
|
|
|
|
len++;
|
|
|
|
}
|
|
|
|
jsa->setLength(len);
|
|
|
|
ExpEvaluator::pushOne(stack,new ExpWrapper(jsa,oper.name()));
|
|
|
|
}
|
|
|
|
else
|
|
|
|
ExpEvaluator::pushOne(stack,new ExpWrapper(0,oper.name()));
|
|
|
|
}
|
|
|
|
else
|
|
|
|
return JsObject::runNative(stack,oper,context);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2014-06-11 12:18:01 +00:00
|
|
|
JsObject* JsHasher::runConstructor(ObjList& stack, const ExpOperation& oper,
|
|
|
|
GenObject* context)
|
|
|
|
{
|
2016-01-20 10:23:35 +00:00
|
|
|
XDebug(&__plugin,DebugAll,"JsHasher::runConstructor '%s'(" FMT64 ") [%p]",
|
2014-06-11 12:18:01 +00:00
|
|
|
oper.name().c_str(),oper.number(),this);
|
|
|
|
ObjList args;
|
|
|
|
if (extractArgs(stack,oper,context,args) != 1)
|
|
|
|
return 0;
|
|
|
|
ExpOperation* name = static_cast<ExpOperation*>(args[0]);
|
|
|
|
Hasher* h = 0;
|
|
|
|
if (*name == "md5")
|
|
|
|
h = new MD5;
|
|
|
|
else if (*name == "sha1")
|
|
|
|
h = new SHA1;
|
|
|
|
else if (*name == "sha256")
|
|
|
|
h = new SHA256;
|
|
|
|
else
|
|
|
|
return 0;
|
2020-10-21 11:01:31 +00:00
|
|
|
return new JsHasher(context,mutex(),oper.lineNumber(),h);
|
2014-06-11 12:18:01 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void JsHasher::initialize(ScriptContext* context)
|
|
|
|
{
|
|
|
|
if (!context)
|
|
|
|
return;
|
2020-10-21 11:01:31 +00:00
|
|
|
ScriptMutex* mtx = context->mutex();
|
2014-06-11 12:18:01 +00:00
|
|
|
Lock mylock(mtx);
|
|
|
|
NamedList& params = context->params();
|
|
|
|
if (!params.getParam(YSTRING("Hasher")))
|
|
|
|
addConstructor(params,"Hasher",new JsHasher(mtx));
|
|
|
|
}
|
|
|
|
|
|
|
|
bool JsHasher::runNative(ObjList& stack, const ExpOperation& oper, GenObject* context)
|
|
|
|
{
|
2016-01-20 10:23:35 +00:00
|
|
|
XDebug(&__plugin,DebugAll,"JsHasher::runNative '%s'(" FMT64 ") [%p]",
|
2014-06-11 12:18:01 +00:00
|
|
|
oper.name().c_str(),oper.number(),this);
|
|
|
|
if (oper.name() == YSTRING("update")) {
|
|
|
|
if (!m_hasher)
|
|
|
|
return false;
|
|
|
|
ObjList args;
|
|
|
|
ExpOperation* data = 0;
|
2014-06-11 12:59:46 +00:00
|
|
|
ExpOperation* isHex = 0;
|
|
|
|
if (!extractStackArgs(1,this,stack,oper,context,args,&data,&isHex))
|
2014-06-11 12:18:01 +00:00
|
|
|
return false;
|
|
|
|
bool ok = false;
|
2014-06-11 12:59:46 +00:00
|
|
|
if (!(isHex && isHex->valBoolean()))
|
2014-06-11 12:18:01 +00:00
|
|
|
ok = m_hasher->update(*data);
|
|
|
|
else {
|
|
|
|
DataBlock tmp;
|
2014-06-11 12:59:46 +00:00
|
|
|
ok = tmp.unHexify(*data) && m_hasher->update(tmp);
|
2014-06-11 12:18:01 +00:00
|
|
|
}
|
|
|
|
ExpEvaluator::pushOne(stack,new ExpOperation(ok));
|
|
|
|
}
|
|
|
|
else if (oper.name() == YSTRING("hmac")) {
|
|
|
|
if (!m_hasher)
|
|
|
|
return false;
|
|
|
|
ObjList args;
|
|
|
|
ExpOperation* key = 0;
|
|
|
|
ExpOperation* msg = 0;
|
2014-06-11 12:59:46 +00:00
|
|
|
ExpOperation* isHex = 0;
|
|
|
|
if (!extractStackArgs(2,this,stack,oper,context,args,&key,&msg,&isHex))
|
2014-06-11 12:18:01 +00:00
|
|
|
return false;
|
|
|
|
bool ok = false;
|
2014-06-11 12:59:46 +00:00
|
|
|
if (!(isHex && isHex->valBoolean()))
|
2014-06-11 12:18:01 +00:00
|
|
|
ok = m_hasher->hmac(*key,*msg);
|
|
|
|
else {
|
|
|
|
DataBlock k, m;
|
2014-06-11 12:59:46 +00:00
|
|
|
ok = k.unHexify(*key) && m.unHexify(*msg) && m_hasher->hmac(k,m);
|
2014-06-11 12:18:01 +00:00
|
|
|
}
|
|
|
|
ExpEvaluator::pushOne(stack,new ExpOperation(ok));
|
|
|
|
}
|
|
|
|
else if (oper.name() == YSTRING("hexDigest")) {
|
|
|
|
if (!m_hasher || oper.number())
|
|
|
|
return false;
|
|
|
|
ExpEvaluator::pushOne(stack,new ExpOperation(m_hasher->hexDigest()));
|
|
|
|
}
|
|
|
|
else if (oper.name() == YSTRING("clear")) {
|
|
|
|
if (!m_hasher || oper.number())
|
|
|
|
return false;
|
|
|
|
m_hasher->clear();
|
|
|
|
}
|
|
|
|
else if (oper.name() == YSTRING("finalize")) {
|
|
|
|
if (!m_hasher || oper.number())
|
|
|
|
return false;
|
|
|
|
m_hasher->finalize();
|
|
|
|
}
|
|
|
|
else if (oper.name() == YSTRING("hashLength")) {
|
|
|
|
if (!m_hasher || oper.number())
|
|
|
|
return false;
|
|
|
|
ExpEvaluator::pushOne(stack,new ExpOperation((int64_t)m_hasher->hashLength()));
|
|
|
|
}
|
|
|
|
else if (oper.name() == YSTRING("hmacBlockSize")) {
|
|
|
|
if (!m_hasher || oper.number())
|
|
|
|
return false;
|
|
|
|
ExpEvaluator::pushOne(stack,new ExpOperation((int64_t)m_hasher->hmacBlockSize()));
|
|
|
|
}
|
2015-02-05 17:58:39 +00:00
|
|
|
else if (oper.name() == YSTRING("fips186prf")) {
|
|
|
|
ObjList args;
|
|
|
|
ExpOperation* opSeed = 0;
|
|
|
|
ExpOperation* opLen = 0;
|
|
|
|
ExpOperation* opSep = 0;
|
|
|
|
if (!extractStackArgs(2,this,stack,oper,context,args,&opSeed,&opLen,&opSep))
|
|
|
|
return false;
|
|
|
|
DataBlock seed, out;
|
|
|
|
seed.unHexify(*opSeed);
|
|
|
|
SHA1::fips186prf(out,seed,opLen->valInteger());
|
|
|
|
if (out.data()) {
|
|
|
|
String tmp;
|
|
|
|
char sep = '\0';
|
|
|
|
if (opSep && !(JsParser::isNull(*opSep) || opSep->isBoolean() || opSep->isNumber()))
|
|
|
|
sep = opSep->at(0);
|
|
|
|
tmp.hexify(out.data(),out.length(),sep);
|
|
|
|
ExpEvaluator::pushOne(stack,new ExpOperation(tmp,"hex"));
|
|
|
|
}
|
|
|
|
else
|
|
|
|
ExpEvaluator::pushOne(stack,JsParser::nullClone());
|
|
|
|
}
|
2014-06-11 12:18:01 +00:00
|
|
|
else
|
|
|
|
return JsObject::runNative(stack,oper,context);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2022-01-11 09:02:56 +00:00
|
|
|
void* JsXPath::getObject(const String& name) const
|
|
|
|
{
|
|
|
|
void* obj = (name == YATOM("JsXPath")) ? const_cast<JsXPath*>(this)
|
|
|
|
: JsObject::getObject(name);
|
|
|
|
return obj ? obj : m_path.getObject(name);
|
|
|
|
}
|
|
|
|
|
|
|
|
JsObject* JsXPath::runConstructor(ObjList& stack, const ExpOperation& oper, GenObject* context)
|
|
|
|
{
|
|
|
|
XDebug(&__plugin,DebugAll,"JsXPath::runConstructor '%s'(" FMT64 ") [%p]",
|
|
|
|
oper.name().c_str(),oper.number(),this);
|
|
|
|
ObjList args;
|
|
|
|
ExpOperation* pathOp = 0;
|
|
|
|
ExpOperation* second = 0;
|
|
|
|
if (!extractStackArgs(1,this,stack,oper,context,args,&pathOp,&second))
|
|
|
|
return 0;
|
|
|
|
JsXPath* obj = 0;
|
|
|
|
if (second) {
|
|
|
|
// XPath(str,flags)
|
|
|
|
obj = new JsXPath(mutex(),oper.lineNumber(),*pathOp,second->valInteger());
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
// XPath(str) or XPath(JsXPath)
|
|
|
|
JsXPath* other = YOBJECT(JsXPath,pathOp);
|
|
|
|
if (other)
|
|
|
|
obj = new JsXPath(mutex(),oper.lineNumber(),other->path());
|
|
|
|
else
|
|
|
|
obj = new JsXPath(mutex(),oper.lineNumber(),*pathOp);
|
|
|
|
}
|
|
|
|
if (!ref()) {
|
|
|
|
TelEngine::destruct(obj);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
obj->params().addParam(new ExpWrapper(this,protoName()));
|
|
|
|
return obj;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool JsXPath::runNative(ObjList& stack, const ExpOperation& oper, GenObject* context)
|
|
|
|
{
|
|
|
|
XDebug(&__plugin,DebugAll,"JsXPath::runNative '%s'(" FMT64 ")",oper.name().c_str(),oper.number());
|
|
|
|
ObjList args;
|
|
|
|
if (oper.name() == YSTRING("valid"))
|
|
|
|
ExpEvaluator::pushOne(stack,new ExpOperation(0 == m_path.status()));
|
|
|
|
else if (oper.name() == YSTRING("absolute"))
|
|
|
|
ExpEvaluator::pushOne(stack,new ExpOperation(m_path.absolute()));
|
|
|
|
else if (oper.name() == YSTRING("getPath")) {
|
|
|
|
if (!m_path.status()) {
|
|
|
|
String str;
|
|
|
|
m_path.dump(str,true,"/",m_path.absolute());
|
|
|
|
ExpEvaluator::pushOne(stack,new ExpOperation(str));
|
|
|
|
}
|
|
|
|
else
|
|
|
|
ExpEvaluator::pushOne(stack,JsParser::nullClone());
|
|
|
|
}
|
|
|
|
else if (oper.name() == YSTRING("getItems")) {
|
|
|
|
// getItems([escape])
|
|
|
|
if (!m_path.status()) {
|
|
|
|
ExpOperation* esc = 0;
|
|
|
|
if (!extractStackArgs(0,this,stack,oper,context,args,&esc))
|
|
|
|
return false;
|
|
|
|
ObjList lst;
|
|
|
|
m_path.dump(lst,(esc && esc->isBoolean()) ? esc->toBoolean() : true);
|
|
|
|
JsArray* jsa = new JsArray(context,oper.lineNumber(),mutex());
|
|
|
|
jsa->push(lst);
|
|
|
|
ExpEvaluator::pushOne(stack,new ExpWrapper(jsa,"items"));
|
|
|
|
}
|
|
|
|
else
|
|
|
|
ExpEvaluator::pushOne(stack,JsParser::nullClone());
|
|
|
|
}
|
|
|
|
else if (oper.name() == YSTRING("getError")) {
|
|
|
|
if (m_path.status()) {
|
|
|
|
JsObject* jso = new JsObject(context,oper.lineNumber(),mutex());
|
|
|
|
jso->params().setParam(new ExpOperation((int64_t)m_path.status(),"status"));
|
|
|
|
jso->params().setParam(new ExpOperation((int64_t)m_path.errorItem(),"errorItem"));
|
|
|
|
if (m_path.error())
|
|
|
|
jso->params().setParam(new ExpOperation(m_path.error(),"error"));
|
|
|
|
ExpEvaluator::pushOne(stack,new ExpWrapper(jso,"error"));
|
|
|
|
}
|
|
|
|
else
|
|
|
|
ExpEvaluator::pushOne(stack,new ExpWrapper(0));
|
|
|
|
}
|
|
|
|
else if (oper.name() == YSTRING("describeError")) {
|
|
|
|
String tmp;
|
|
|
|
if (m_path.describeError(tmp))
|
|
|
|
ExpEvaluator::pushOne(stack,new ExpOperation(tmp,"error"));
|
|
|
|
else
|
|
|
|
ExpEvaluator::pushOne(stack,new ExpWrapper(0));
|
|
|
|
}
|
|
|
|
else
|
|
|
|
return JsObject::runNative(stack,oper,context);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
void JsXPath::initialize(ScriptContext* context)
|
|
|
|
{
|
|
|
|
if (!context)
|
|
|
|
return;
|
|
|
|
ScriptMutex* mtx = context->mutex();
|
|
|
|
Lock mylock(mtx);
|
|
|
|
NamedList& params = context->params();
|
|
|
|
if (!params.getParam(YSTRING("XPath")))
|
|
|
|
addConstructor(params,"XPath",new JsXPath(mtx));
|
|
|
|
}
|
2014-06-11 12:18:01 +00:00
|
|
|
|
2014-10-29 16:32:20 +00:00
|
|
|
void* JsXML::getObject(const String& name) const
|
|
|
|
{
|
|
|
|
void* obj = (name == YATOM("JsXML")) ? const_cast<JsXML*>(this) : JsObject::getObject(name);
|
|
|
|
if (m_xml && !obj)
|
|
|
|
obj = m_xml->getObject(name);
|
|
|
|
return obj;
|
|
|
|
}
|
|
|
|
|
2012-12-21 10:21:16 +00:00
|
|
|
bool JsXML::runNative(ObjList& stack, const ExpOperation& oper, GenObject* context)
|
|
|
|
{
|
2016-01-20 10:23:35 +00:00
|
|
|
XDebug(&__plugin,DebugAll,"JsXML::runNative '%s'(" FMT64 ")",oper.name().c_str(),oper.number());
|
2012-12-21 10:21:16 +00:00
|
|
|
ObjList args;
|
|
|
|
if (oper.name() == YSTRING("put")) {
|
2014-07-11 16:54:28 +00:00
|
|
|
int argc = extractArgs(stack,oper,context,args);
|
2012-12-21 10:21:16 +00:00
|
|
|
if (argc < 2 || argc > 3)
|
|
|
|
return false;
|
|
|
|
ScriptContext* list = YOBJECT(ScriptContext,static_cast<ExpOperation*>(args[0]));
|
|
|
|
ExpOperation* name = static_cast<ExpOperation*>(args[1]);
|
|
|
|
ExpOperation* text = static_cast<ExpOperation*>(args[2]);
|
|
|
|
if (!name || !list || !m_xml)
|
|
|
|
return false;
|
|
|
|
NamedList* params = list->nativeParams();
|
|
|
|
if (!params)
|
|
|
|
params = &list->params();
|
|
|
|
params->clearParam(*name);
|
|
|
|
String txt;
|
|
|
|
if (text && text->valBoolean())
|
|
|
|
m_xml->toString(txt);
|
|
|
|
if (!text || (text->valInteger() != 1))
|
|
|
|
params->addParam(new NamedPointer(*name,new XmlElement(*m_xml),txt));
|
|
|
|
else
|
|
|
|
params->addParam(*name,txt);
|
|
|
|
}
|
|
|
|
else if (oper.name() == YSTRING("getOwner")) {
|
2014-07-11 16:54:28 +00:00
|
|
|
if (extractArgs(stack,oper,context,args) != 0)
|
2012-12-21 10:21:16 +00:00
|
|
|
return false;
|
|
|
|
if (m_owner && m_owner->ref())
|
|
|
|
ExpEvaluator::pushOne(stack,new ExpWrapper(m_owner));
|
|
|
|
else
|
|
|
|
ExpEvaluator::pushOne(stack,JsParser::nullClone());
|
|
|
|
}
|
|
|
|
else if (oper.name() == YSTRING("getParent")) {
|
2014-07-11 16:54:28 +00:00
|
|
|
if (extractArgs(stack,oper,context,args) != 0)
|
2012-12-21 10:21:16 +00:00
|
|
|
return false;
|
|
|
|
XmlElement* xml = m_xml ? m_xml->parent() : 0;
|
|
|
|
if (xml)
|
2022-01-11 09:02:56 +00:00
|
|
|
ExpEvaluator::pushOne(stack,xmlWrapper(oper,xml));
|
2012-12-21 10:21:16 +00:00
|
|
|
else
|
|
|
|
ExpEvaluator::pushOne(stack,JsParser::nullClone());
|
|
|
|
}
|
2013-04-12 12:08:13 +00:00
|
|
|
else if (oper.name() == YSTRING("unprefixedTag")) {
|
2014-07-11 16:54:28 +00:00
|
|
|
if (extractArgs(stack,oper,context,args) != 0)
|
2013-04-12 12:08:13 +00:00
|
|
|
return false;
|
|
|
|
if (m_xml)
|
|
|
|
ExpEvaluator::pushOne(stack,new ExpOperation(m_xml->unprefixedTag(),m_xml->unprefixedTag()));
|
|
|
|
else
|
|
|
|
ExpEvaluator::pushOne(stack,JsParser::nullClone());
|
|
|
|
}
|
|
|
|
else if (oper.name() == YSTRING("getTag")) {
|
2014-07-11 16:54:28 +00:00
|
|
|
if (extractArgs(stack,oper,context,args) != 0)
|
2013-04-12 12:08:13 +00:00
|
|
|
return false;
|
|
|
|
if (m_xml)
|
|
|
|
ExpEvaluator::pushOne(stack,new ExpOperation(m_xml->getTag(),m_xml->getTag()));
|
|
|
|
else
|
|
|
|
ExpEvaluator::pushOne(stack,JsParser::nullClone());
|
|
|
|
}
|
2012-12-21 10:21:16 +00:00
|
|
|
else if (oper.name() == YSTRING("getAttribute")) {
|
2014-07-11 16:54:28 +00:00
|
|
|
if (extractArgs(stack,oper,context,args) != 1)
|
2012-12-21 10:21:16 +00:00
|
|
|
return false;
|
|
|
|
ExpOperation* name = static_cast<ExpOperation*>(args[0]);
|
|
|
|
if (!name)
|
|
|
|
return false;
|
|
|
|
const String* attr = 0;
|
|
|
|
if (m_xml)
|
|
|
|
attr = m_xml->getAttribute(*name);
|
|
|
|
if (attr)
|
|
|
|
ExpEvaluator::pushOne(stack,new ExpOperation(*attr,name->name()));
|
|
|
|
else
|
|
|
|
ExpEvaluator::pushOne(stack,JsParser::nullClone());
|
|
|
|
}
|
|
|
|
else if (oper.name() == YSTRING("setAttribute")) {
|
|
|
|
if (!m_xml)
|
|
|
|
return false;
|
2016-02-15 15:06:10 +00:00
|
|
|
ExpOperation* name = 0;
|
|
|
|
ExpOperation* val = 0;
|
|
|
|
if (!extractStackArgs(1,this,stack,oper,context,args,&name,&val))
|
2012-12-21 10:21:16 +00:00
|
|
|
return false;
|
2016-02-15 15:06:10 +00:00
|
|
|
if (JsParser::isUndefined(*name) || JsParser::isNull(*name))
|
|
|
|
return (val == 0);
|
|
|
|
if (val) {
|
|
|
|
if (JsParser::isUndefined(*val) || JsParser::isNull(*val))
|
|
|
|
m_xml->removeAttribute(*name);
|
|
|
|
else if (*name)
|
|
|
|
m_xml->setAttribute(*name,*val);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
JsObject* jso = YOBJECT(JsObject,name);
|
|
|
|
if (!jso)
|
|
|
|
return false;
|
|
|
|
const ObjList* o = jso->params().paramList()->skipNull();
|
|
|
|
for (; o; o = o->skipNext()) {
|
|
|
|
const NamedString* ns = static_cast<const NamedString*>(o->get());
|
|
|
|
if (ns->name() != JsObject::protoName())
|
|
|
|
m_xml->setAttribute(ns->name(),*ns);
|
|
|
|
}
|
|
|
|
}
|
2012-12-21 10:21:16 +00:00
|
|
|
}
|
2013-04-12 12:08:13 +00:00
|
|
|
else if (oper.name() == YSTRING("removeAttribute")) {
|
2014-07-11 16:54:28 +00:00
|
|
|
if (extractArgs(stack,oper,context,args) != 1)
|
2013-04-12 12:08:13 +00:00
|
|
|
return false;
|
|
|
|
ExpOperation* name = static_cast<ExpOperation*>(args[0]);
|
|
|
|
if (!name)
|
|
|
|
return false;
|
|
|
|
if (m_xml)
|
|
|
|
m_xml->removeAttribute(*name);
|
|
|
|
}
|
2016-02-15 15:06:10 +00:00
|
|
|
else if (oper.name() == YSTRING("attributes")) {
|
|
|
|
if (extractArgs(stack,oper,context,args))
|
|
|
|
return false;
|
|
|
|
const ObjList* o = m_xml ? m_xml->attributes().paramList()->skipNull() : 0;
|
|
|
|
JsObject* jso = 0;
|
|
|
|
if (o) {
|
2020-10-21 11:01:31 +00:00
|
|
|
jso = new JsObject(context,oper.lineNumber(),mutex());
|
2016-02-15 15:06:10 +00:00
|
|
|
for (; o; o = o->skipNext()) {
|
|
|
|
const NamedString* ns = static_cast<const NamedString*>(o->get());
|
|
|
|
if (ns->name() != JsObject::protoName())
|
|
|
|
jso->params().addParam(ns->name(),*ns);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (jso)
|
|
|
|
ExpEvaluator::pushOne(stack,new ExpWrapper(jso,"attributes"));
|
|
|
|
else
|
|
|
|
ExpEvaluator::pushOne(stack,JsParser::nullClone());
|
|
|
|
}
|
2012-12-21 10:21:16 +00:00
|
|
|
else if (oper.name() == YSTRING("addChild")) {
|
2014-07-11 16:54:28 +00:00
|
|
|
int argc = extractArgs(stack,oper,context,args);
|
2012-12-21 10:21:16 +00:00
|
|
|
if (argc < 1 || argc > 2)
|
|
|
|
return false;
|
|
|
|
ExpOperation* name = static_cast<ExpOperation*>(args[0]);
|
|
|
|
ExpOperation* val = static_cast<ExpOperation*>(args[1]);
|
|
|
|
if (!name)
|
|
|
|
return false;
|
|
|
|
if (!m_xml)
|
|
|
|
return false;
|
|
|
|
JsArray* jsa = YOBJECT(JsArray,name);
|
|
|
|
if (jsa) {
|
|
|
|
for (long i = 0; i < jsa->length(); i++) {
|
|
|
|
String n((unsigned int)i);
|
|
|
|
JsXML* x = YOBJECT(JsXML,jsa->getField(stack,n,context));
|
|
|
|
if (x && x->element()) {
|
|
|
|
XmlElement* xml = new XmlElement(*x->element());
|
|
|
|
if (XmlSaxParser::NoError != m_xml->addChild(xml)) {
|
|
|
|
TelEngine::destruct(xml);
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
XmlElement* xml = 0;
|
|
|
|
JsXML* x = YOBJECT(JsXML,name);
|
|
|
|
if (x && x->element())
|
|
|
|
xml = new XmlElement(*x->element());
|
2015-09-09 13:05:34 +00:00
|
|
|
else if (!(TelEngine::null(name) || JsParser::isNull(*name)))
|
2012-12-21 10:21:16 +00:00
|
|
|
xml = new XmlElement(name->c_str());
|
2015-09-09 13:05:34 +00:00
|
|
|
if (xml && val && !JsParser::isNull(*val))
|
2012-12-21 10:21:16 +00:00
|
|
|
xml->addText(*val);
|
2015-09-09 13:05:34 +00:00
|
|
|
if (xml && (XmlSaxParser::NoError == m_xml->addChild(xml)))
|
2020-10-21 11:01:31 +00:00
|
|
|
ExpEvaluator::pushOne(stack,new ExpWrapper(new JsXML(mutex(),oper.lineNumber(),xml,owner())));
|
2012-12-21 10:21:16 +00:00
|
|
|
else {
|
|
|
|
TelEngine::destruct(xml);
|
|
|
|
ExpEvaluator::pushOne(stack,JsParser::nullClone());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (oper.name() == YSTRING("getChild")) {
|
2014-07-11 16:54:28 +00:00
|
|
|
if (extractArgs(stack,oper,context,args) > 2)
|
2012-12-21 10:21:16 +00:00
|
|
|
return false;
|
|
|
|
XmlElement* xml = 0;
|
2015-09-09 13:05:34 +00:00
|
|
|
if (m_xml) {
|
|
|
|
ExpOperation* name = static_cast<ExpOperation*>(args[0]);
|
|
|
|
ExpOperation* ns = static_cast<ExpOperation*>(args[1]);
|
|
|
|
if (name && (JsParser::isUndefined(*name) || JsParser::isNull(*name)))
|
|
|
|
name = 0;
|
2016-02-15 12:44:43 +00:00
|
|
|
if (ns && (JsParser::isUndefined(*ns) || JsParser::isNull(*ns)))
|
2015-09-09 13:05:34 +00:00
|
|
|
ns = 0;
|
|
|
|
xml = m_xml->findFirstChild(name,ns);
|
|
|
|
}
|
2012-12-21 10:21:16 +00:00
|
|
|
if (xml)
|
2022-01-11 09:02:56 +00:00
|
|
|
ExpEvaluator::pushOne(stack,xmlWrapper(oper,xml));
|
2012-12-21 10:21:16 +00:00
|
|
|
else
|
|
|
|
ExpEvaluator::pushOne(stack,JsParser::nullClone());
|
|
|
|
}
|
|
|
|
else if (oper.name() == YSTRING("getChildren")) {
|
2014-07-11 16:54:28 +00:00
|
|
|
if (extractArgs(stack,oper,context,args) > 2)
|
2012-12-21 10:21:16 +00:00
|
|
|
return false;
|
|
|
|
ExpOperation* name = static_cast<ExpOperation*>(args[0]);
|
|
|
|
ExpOperation* ns = static_cast<ExpOperation*>(args[1]);
|
2015-09-09 13:05:34 +00:00
|
|
|
if (name && (JsParser::isUndefined(*name) || JsParser::isNull(*name)))
|
|
|
|
name = 0;
|
2016-02-15 12:44:43 +00:00
|
|
|
if (ns && (JsParser::isUndefined(*ns) || JsParser::isNull(*ns)))
|
2015-09-09 13:05:34 +00:00
|
|
|
ns = 0;
|
2012-12-21 10:21:16 +00:00
|
|
|
XmlElement* xml = 0;
|
|
|
|
if (m_xml)
|
|
|
|
xml = m_xml->findFirstChild(name,ns);
|
|
|
|
if (xml) {
|
2020-10-21 11:01:31 +00:00
|
|
|
JsArray* jsa = new JsArray(context,oper.lineNumber(),mutex());
|
2012-12-21 10:21:16 +00:00
|
|
|
while (xml) {
|
2022-01-11 09:02:56 +00:00
|
|
|
jsa->push(xmlWrapper(oper,xml));
|
2012-12-21 10:21:16 +00:00
|
|
|
xml = m_xml->findNextChild(xml,name,ns);
|
|
|
|
}
|
|
|
|
ExpEvaluator::pushOne(stack,new ExpWrapper(jsa,"children"));
|
|
|
|
}
|
|
|
|
else
|
|
|
|
ExpEvaluator::pushOne(stack,JsParser::nullClone());
|
|
|
|
}
|
2013-04-12 12:08:13 +00:00
|
|
|
else if (oper.name() == YSTRING("clearChildren")) {
|
2014-07-11 16:54:28 +00:00
|
|
|
if (extractArgs(stack,oper,context,args))
|
2013-04-12 12:08:13 +00:00
|
|
|
return false;
|
|
|
|
if (m_xml)
|
|
|
|
m_xml->clearChildren();
|
|
|
|
}
|
2012-12-21 10:21:16 +00:00
|
|
|
else if (oper.name() == YSTRING("addText")) {
|
2014-07-11 16:54:28 +00:00
|
|
|
if (extractArgs(stack,oper,context,args) != 1)
|
2012-12-21 10:21:16 +00:00
|
|
|
return false;
|
|
|
|
ExpOperation* text = static_cast<ExpOperation*>(args[0]);
|
|
|
|
if (!m_xml || !text)
|
|
|
|
return false;
|
2015-09-09 13:05:34 +00:00
|
|
|
if (!(TelEngine::null(text) || JsParser::isNull(*text)))
|
2012-12-21 10:21:16 +00:00
|
|
|
m_xml->addText(*text);
|
|
|
|
}
|
|
|
|
else if (oper.name() == YSTRING("getText")) {
|
2014-07-11 16:54:28 +00:00
|
|
|
if (extractArgs(stack,oper,context,args))
|
2012-12-21 10:21:16 +00:00
|
|
|
return false;
|
|
|
|
if (m_xml)
|
|
|
|
ExpEvaluator::pushOne(stack,new ExpOperation(m_xml->getText(),m_xml->unprefixedTag()));
|
|
|
|
else
|
|
|
|
ExpEvaluator::pushOne(stack,JsParser::nullClone());
|
|
|
|
}
|
2014-01-10 11:55:36 +00:00
|
|
|
else if (oper.name() == YSTRING("setText")) {
|
2014-07-11 16:54:28 +00:00
|
|
|
if (extractArgs(stack,oper,context,args) != 1)
|
2014-01-10 11:55:36 +00:00
|
|
|
return false;
|
|
|
|
ExpOperation* text = static_cast<ExpOperation*>(args[0]);
|
|
|
|
if (!(m_xml && text))
|
|
|
|
return false;
|
2015-09-09 13:05:34 +00:00
|
|
|
if (JsParser::isNull(*text))
|
|
|
|
m_xml->setText("");
|
|
|
|
else
|
|
|
|
m_xml->setText(*text);
|
2014-01-10 11:55:36 +00:00
|
|
|
}
|
2012-12-21 10:21:16 +00:00
|
|
|
else if (oper.name() == YSTRING("getChildText")) {
|
2014-07-11 16:54:28 +00:00
|
|
|
if (extractArgs(stack,oper,context,args) > 2)
|
2012-12-21 10:21:16 +00:00
|
|
|
return false;
|
2015-09-09 13:05:34 +00:00
|
|
|
ExpOperation* name = static_cast<ExpOperation*>(args[0]);
|
|
|
|
ExpOperation* ns = static_cast<ExpOperation*>(args[1]);
|
|
|
|
if (name && (JsParser::isUndefined(*name) || JsParser::isNull(*name)))
|
|
|
|
name = 0;
|
2016-02-15 12:44:43 +00:00
|
|
|
if (ns && (JsParser::isUndefined(*ns) || JsParser::isNull(*ns)))
|
2015-09-09 13:05:34 +00:00
|
|
|
ns = 0;
|
2012-12-21 10:21:16 +00:00
|
|
|
XmlElement* xml = 0;
|
|
|
|
if (m_xml)
|
2015-09-09 13:05:34 +00:00
|
|
|
xml = m_xml->findFirstChild(name,ns);
|
2012-12-21 10:21:16 +00:00
|
|
|
if (xml)
|
|
|
|
ExpEvaluator::pushOne(stack,new ExpOperation(xml->getText(),xml->unprefixedTag()));
|
|
|
|
else
|
|
|
|
ExpEvaluator::pushOne(stack,JsParser::nullClone());
|
|
|
|
}
|
2022-01-11 09:02:56 +00:00
|
|
|
else if (oper.name() == YSTRING("getChildByPath") || oper.name() == YSTRING("getChildrenByPath")) {
|
|
|
|
// getChildByPath(op). op: JsXPath or string
|
|
|
|
// Return: XML or null
|
|
|
|
// getChildrenByPath(op). op: JsXPath or string
|
|
|
|
// Return: non empty array or null
|
|
|
|
ExpOperation* pathOp = 0;
|
|
|
|
if (!extractStackArgs(1,this,stack,oper,context,args,&pathOp))
|
|
|
|
return false;
|
|
|
|
ExpOperation* ret = 0;
|
|
|
|
if (m_xml) {
|
|
|
|
ObjList lst;
|
|
|
|
bool single = oper.name() == YSTRING("getChildByPath");
|
|
|
|
XPathTmpParam path(*pathOp);
|
|
|
|
XmlElement* xml = path->findXml(*m_xml,single ? 0 : &lst);
|
|
|
|
if (xml) {
|
|
|
|
if (single)
|
|
|
|
ret = xmlWrapper(oper,xml);
|
|
|
|
else {
|
|
|
|
ObjList* o = lst.skipNull();
|
|
|
|
if (o) {
|
|
|
|
JsArray* jsa = new JsArray(context,oper.lineNumber(),mutex());
|
|
|
|
for (; o; o = o->skipNext())
|
|
|
|
jsa->push(xmlWrapper(oper,static_cast<XmlElement*>(o->get())));
|
|
|
|
ret = new ExpWrapper(jsa,"children");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
pushStackResNull(stack,ret);
|
|
|
|
}
|
|
|
|
else if (oper.name() == YSTRING("getTextByPath")) {
|
|
|
|
// getTextByPath(op). op: JsXPath or string
|
|
|
|
// Return: string or null
|
|
|
|
ExpOperation* pathOp = 0;
|
|
|
|
if (!extractStackArgs(1,this,stack,oper,context,args,&pathOp))
|
|
|
|
return false;
|
|
|
|
ExpOperation* ret = 0;
|
|
|
|
if (m_xml) {
|
|
|
|
XPathTmpParam path(*pathOp);
|
|
|
|
const String* txt = path->findText(*m_xml);
|
|
|
|
if (txt)
|
|
|
|
ret = new ExpOperation(*txt,"text");
|
|
|
|
}
|
|
|
|
pushStackResNull(stack,ret);
|
|
|
|
}
|
|
|
|
else if (oper.name() == YSTRING("getAnyByPath")) {
|
|
|
|
// getAnyByPath(op[,array[,what]]). op: JsXPath or string
|
|
|
|
// Return null or first found element (XML, string or object)
|
|
|
|
ExpOperation* pathOp = 0;
|
|
|
|
ExpOperation* destOp = 0;
|
|
|
|
ExpOperation* whatOp = 0;
|
|
|
|
if (!extractStackArgs(1,this,stack,oper,context,args,&pathOp,&destOp,&whatOp))
|
|
|
|
return false;
|
|
|
|
ExpOperation* ret = 0;
|
|
|
|
if (m_xml) {
|
|
|
|
XPathTmpParam path(*pathOp);
|
|
|
|
JsArray* jsa = YOBJECT(JsArray,destOp);
|
|
|
|
ObjList lst;
|
|
|
|
unsigned int what = (whatOp && whatOp->isInteger()) ?
|
|
|
|
(unsigned int)whatOp->toNumber() : XPath::FindAny;
|
|
|
|
ret = buildAny(path->find(*m_xml,what,jsa ? &lst : 0),oper,context);
|
|
|
|
if (ret && jsa) {
|
|
|
|
for (ObjList* o = lst.skipNull(); o; o = o->skipNext())
|
|
|
|
jsa->push(buildAny(o->get(),oper,context));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
pushStackResNull(stack,ret);
|
|
|
|
}
|
2012-12-21 10:21:16 +00:00
|
|
|
else if (oper.name() == YSTRING("xmlText")) {
|
2014-10-29 16:30:02 +00:00
|
|
|
if (extractArgs(stack,oper,context,args) > 1)
|
2012-12-21 10:21:16 +00:00
|
|
|
return false;
|
|
|
|
if (m_xml) {
|
2014-10-29 16:30:02 +00:00
|
|
|
int spaces = args[0] ? static_cast<ExpOperation*>(args[0])->number() : 0;
|
|
|
|
const String* line = &String::empty();
|
|
|
|
String indent;
|
|
|
|
if (spaces > 0) {
|
|
|
|
static const String crlf = "\r\n";
|
|
|
|
line = &crlf;
|
|
|
|
indent.assign(' ',spaces);
|
|
|
|
}
|
2012-12-21 10:21:16 +00:00
|
|
|
ExpOperation* op = new ExpOperation("",m_xml->unprefixedTag());
|
2014-10-29 16:30:02 +00:00
|
|
|
m_xml->toString(*op,true,*line,indent);
|
|
|
|
op->startSkip(*line,false);
|
2012-12-21 10:21:16 +00:00
|
|
|
ExpEvaluator::pushOne(stack,op);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
ExpEvaluator::pushOne(stack,JsParser::nullClone());
|
|
|
|
}
|
2018-04-10 11:08:25 +00:00
|
|
|
else if (oper.name() == YSTRING("replaceParams")) {
|
|
|
|
if (!m_xml || extractArgs(stack,oper,context,args) != 1)
|
|
|
|
return false;
|
|
|
|
const NamedList* params = getReplaceParams(args[0]);
|
|
|
|
if (params)
|
|
|
|
m_xml->replaceParams(*params);
|
|
|
|
}
|
2018-04-12 12:44:38 +00:00
|
|
|
else if (oper.name() == YSTRING("saveFile")) {
|
|
|
|
ExpOperation* file = 0;
|
|
|
|
ExpOperation* spaces = 0;
|
|
|
|
if (!(m_xml && extractStackArgs(1,this,stack,oper,context,args,&file,&spaces)))
|
|
|
|
return false;
|
|
|
|
XmlSaxParser::Error code = XmlSaxParser::Unknown;
|
|
|
|
XmlDocument doc;
|
|
|
|
while (JsParser::isFilled(file)) {
|
|
|
|
code = XmlSaxParser::NoError;
|
|
|
|
NamedString* ns = getField(stack,YSTRING("declaration"),context);
|
|
|
|
if (ns) {
|
|
|
|
XmlDeclaration* decl = 0;
|
|
|
|
if (const NamedList* params = getReplaceParams(ns)) {
|
|
|
|
NamedList tmp("");
|
|
|
|
// version is required. It will be overridden if present
|
|
|
|
tmp.addParam("version","1.0");
|
|
|
|
copyObjParams(tmp,params);
|
|
|
|
decl = new XmlDeclaration(tmp);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
ExpOperation* oper = YOBJECT(ExpOperation,ns);
|
|
|
|
if (oper && oper->isBoolean() && oper->toBoolean())
|
|
|
|
decl = new XmlDeclaration;
|
|
|
|
}
|
|
|
|
if (decl && !doc.addChildSafe(decl,&code))
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
// TODO: Other children present before root (Comment(s), DOCTYPE, CDATA)
|
|
|
|
code = doc.addChild(m_xml);
|
|
|
|
if (code != XmlSaxParser::NoError)
|
|
|
|
break;
|
|
|
|
// TODO: Other children present after root (Comment(s))
|
|
|
|
int sp = spaces ? spaces->number() : 0;
|
|
|
|
int error = 0;
|
|
|
|
if (sp > 0)
|
|
|
|
error = doc.saveFile(*file,true,String(' ',sp));
|
|
|
|
else
|
|
|
|
error = doc.saveFile(*file,true,String::empty(),true,0);
|
|
|
|
if (error)
|
|
|
|
code = XmlSaxParser::IOError;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
// Remove root from doc to avoid object delete
|
|
|
|
doc.takeRoot();
|
|
|
|
ExpEvaluator::pushOne(stack,new ExpOperation(code == XmlSaxParser::NoError));
|
|
|
|
}
|
|
|
|
else if (oper.name() == YSTRING("loadFile")) {
|
|
|
|
ExpOperation* file = 0;
|
|
|
|
if (!extractStackArgs(1,this,stack,oper,context,args,&file,0))
|
|
|
|
return false;
|
|
|
|
XmlDocument doc;
|
|
|
|
if (JsParser::isFilled(file) &&
|
|
|
|
(doc.loadFile(*file) == XmlSaxParser::NoError) && doc.root(true) &&
|
|
|
|
ref()) {
|
2020-10-21 11:01:31 +00:00
|
|
|
JsXML* xml = new JsXML(mutex(),oper.lineNumber(),doc.takeRoot(true));
|
2018-04-12 12:44:38 +00:00
|
|
|
xml->params().addParam(new ExpWrapper(this,protoName()));
|
|
|
|
const XmlFragment& before = doc.getFragment(true);
|
|
|
|
for (const ObjList* b = before.getChildren().skipNull(); b; b = b->skipNext()) {
|
|
|
|
XmlChild* ch = static_cast<XmlChild*>(b->get());
|
|
|
|
XmlDeclaration* decl = ch->xmlDeclaration();
|
|
|
|
if (decl) {
|
2020-10-21 11:01:31 +00:00
|
|
|
JsObject* jso = new JsObject(context,oper.lineNumber(),mutex());
|
2018-04-12 12:44:38 +00:00
|
|
|
jso->addFields(decl->getDec());
|
|
|
|
xml->params().addParam(new ExpWrapper(jso,"declaration"));
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
// TODO: Other children present before root (Comment(s), DOCTYPE, CDATA)
|
|
|
|
}
|
|
|
|
// TODO: Other children present after root (Comment(s))
|
|
|
|
ExpEvaluator::pushOne(stack,new ExpWrapper(xml));
|
|
|
|
}
|
|
|
|
else
|
|
|
|
ExpEvaluator::pushOne(stack,JsParser::nullClone());
|
|
|
|
}
|
2012-12-21 10:21:16 +00:00
|
|
|
else
|
|
|
|
return JsObject::runNative(stack,oper,context);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
JsObject* JsXML::runConstructor(ObjList& stack, const ExpOperation& oper, GenObject* context)
|
|
|
|
{
|
2016-01-20 10:23:35 +00:00
|
|
|
XDebug(&__plugin,DebugAll,"JsXML::runConstructor '%s'(" FMT64 ") [%p]",oper.name().c_str(),oper.number(),this);
|
2012-12-21 10:21:16 +00:00
|
|
|
JsXML* obj = 0;
|
|
|
|
ObjList args;
|
2014-01-10 11:55:36 +00:00
|
|
|
int n = extractArgs(stack,oper,context,args);
|
2015-08-31 08:09:15 +00:00
|
|
|
ExpOperation* arg1 = static_cast<ExpOperation*>(args[0]);
|
|
|
|
ExpOperation* arg2 = static_cast<ExpOperation*>(args[1]);
|
2014-01-10 11:55:36 +00:00
|
|
|
switch (n) {
|
2012-12-21 10:21:16 +00:00
|
|
|
case 1:
|
|
|
|
{
|
2015-08-31 08:09:15 +00:00
|
|
|
// new XML(xmlObj), new XML("<xml>document</xml>") or new XML("element-name")
|
|
|
|
XmlElement* xml = buildXml(arg1);
|
|
|
|
if (!xml)
|
|
|
|
xml = getXml(arg1,false);
|
2012-12-21 10:21:16 +00:00
|
|
|
if (!xml)
|
2014-05-14 09:06:36 +00:00
|
|
|
return JsParser::nullObject();
|
2020-10-21 11:01:31 +00:00
|
|
|
obj = new JsXML(mutex(),oper.lineNumber(),xml);
|
2012-12-21 10:21:16 +00:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
case 2:
|
2015-08-31 08:09:15 +00:00
|
|
|
{
|
|
|
|
// new XML(object,"field-name") or new XML("element-name","text-content")
|
|
|
|
XmlElement* xml = buildXml(arg1,arg2);
|
|
|
|
if (xml) {
|
2020-10-21 11:01:31 +00:00
|
|
|
obj = new JsXML(mutex(),oper.lineNumber(),xml);
|
2015-08-31 08:09:15 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
// fall through
|
2014-01-10 11:55:36 +00:00
|
|
|
case 3:
|
2012-12-21 10:21:16 +00:00
|
|
|
{
|
2015-08-31 08:09:15 +00:00
|
|
|
// new XML(object,"field-name",bool)
|
|
|
|
JsObject* jso = YOBJECT(JsObject,arg1);
|
|
|
|
if (!jso || !arg2)
|
2012-12-21 10:21:16 +00:00
|
|
|
return 0;
|
2015-08-31 08:09:15 +00:00
|
|
|
ExpOperation* arg3 = static_cast<ExpOperation*>(args[2]);
|
|
|
|
bool take = arg3 && arg3->valBoolean();
|
|
|
|
XmlElement* xml = getXml(jso->getField(stack,*arg2,context),take);
|
2012-12-21 10:21:16 +00:00
|
|
|
if (!xml)
|
2014-05-14 09:06:36 +00:00
|
|
|
return JsParser::nullObject();
|
2020-10-21 11:01:31 +00:00
|
|
|
obj = new JsXML(mutex(),oper.lineNumber(),xml);
|
2012-12-21 10:21:16 +00:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
if (!obj)
|
|
|
|
return 0;
|
|
|
|
if (!ref()) {
|
|
|
|
TelEngine::destruct(obj);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
obj->params().addParam(new ExpWrapper(this,protoName()));
|
|
|
|
return obj;
|
|
|
|
}
|
|
|
|
|
|
|
|
XmlElement* JsXML::getXml(const String* obj, bool take)
|
|
|
|
{
|
|
|
|
if (!obj)
|
|
|
|
return 0;
|
|
|
|
XmlElement* xml = 0;
|
|
|
|
NamedPointer* nptr = YOBJECT(NamedPointer,obj);
|
|
|
|
if (nptr) {
|
|
|
|
xml = YOBJECT(XmlElement,nptr);
|
|
|
|
if (xml) {
|
|
|
|
if (take) {
|
|
|
|
nptr->takeData();
|
|
|
|
return xml;
|
|
|
|
}
|
|
|
|
return new XmlElement(*xml);
|
|
|
|
}
|
|
|
|
}
|
2015-08-31 11:05:58 +00:00
|
|
|
else if (!take) {
|
|
|
|
xml = YOBJECT(XmlElement,obj);
|
|
|
|
if (xml)
|
|
|
|
return new XmlElement(*xml);
|
|
|
|
}
|
2012-12-21 10:21:16 +00:00
|
|
|
XmlDomParser parser;
|
2013-01-28 10:57:41 +00:00
|
|
|
if (!(parser.parse(obj->c_str()) || parser.completeText()))
|
2012-12-21 10:21:16 +00:00
|
|
|
return 0;
|
2018-04-12 12:44:38 +00:00
|
|
|
if (parser.document())
|
|
|
|
return parser.document()->takeRoot(true);
|
|
|
|
return 0;
|
2012-12-21 10:21:16 +00:00
|
|
|
}
|
|
|
|
|
2015-08-31 08:09:15 +00:00
|
|
|
XmlElement* JsXML::buildXml(const String* name, const String* text)
|
|
|
|
{
|
2017-05-08 09:04:33 +00:00
|
|
|
if (TelEngine::null(name) || name->getObject(YSTRING("JsObject")))
|
2015-08-31 08:09:15 +00:00
|
|
|
return 0;
|
|
|
|
static const Regexp s_elemName("^[[:alpha:]_][[:alnum:]_.-]*$");
|
|
|
|
if (name->startsWith("xml",false,true) || !s_elemName.matches(*name))
|
|
|
|
return 0;
|
|
|
|
return new XmlElement(name->c_str(),TelEngine::c_str(text));
|
|
|
|
}
|
|
|
|
|
2012-12-21 10:21:16 +00:00
|
|
|
void JsXML::initialize(ScriptContext* context)
|
|
|
|
{
|
|
|
|
if (!context)
|
|
|
|
return;
|
2020-10-21 11:01:31 +00:00
|
|
|
ScriptMutex* mtx = context->mutex();
|
2012-12-21 10:21:16 +00:00
|
|
|
Lock mylock(mtx);
|
|
|
|
NamedList& params = context->params();
|
|
|
|
if (!params.getParam(YSTRING("XML")))
|
|
|
|
addConstructor(params,"XML",new JsXML(mtx));
|
|
|
|
}
|
|
|
|
|
2017-09-18 12:14:44 +00:00
|
|
|
void* JsHashList::getObject(const String& name) const
|
|
|
|
{
|
|
|
|
void* obj = (name == YATOM("JsHashList")) ? const_cast<JsHashList*>(this) : JsObject::getObject(name);
|
|
|
|
if (!obj)
|
|
|
|
obj = m_list.getObject(name);
|
|
|
|
return obj;
|
|
|
|
}
|
|
|
|
|
|
|
|
JsObject* JsHashList::runConstructor(ObjList& stack, const ExpOperation& oper, GenObject* context)
|
|
|
|
{
|
|
|
|
XDebug(&__plugin,DebugAll,"JsHashList::runConstructor '%s'(" FMT64 ")",oper.name().c_str(),oper.number());
|
|
|
|
ObjList args;
|
|
|
|
unsigned int cnt = 17; // default value for HashList
|
|
|
|
switch (extractArgs(stack,oper,context,args)) {
|
|
|
|
case 1:
|
|
|
|
{
|
|
|
|
ExpOperation* op = static_cast<ExpOperation*>(args[0]);
|
|
|
|
if (!op || !op->isInteger() || op->toNumber() <= 0)
|
|
|
|
return 0;
|
|
|
|
cnt = op->toNumber();
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case 0:
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2020-10-21 11:01:31 +00:00
|
|
|
JsHashList* obj = new JsHashList(cnt,mutex(),oper.lineNumber());
|
2017-09-18 12:14:44 +00:00
|
|
|
if (!ref()) {
|
|
|
|
TelEngine::destruct(obj);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
obj->params().addParam(new ExpWrapper(this,protoName()));
|
|
|
|
return obj;
|
|
|
|
}
|
|
|
|
|
|
|
|
void JsHashList::fillFieldNames(ObjList& names)
|
|
|
|
{
|
|
|
|
JsObject::fillFieldNames(names);
|
|
|
|
ScriptContext::fillFieldNames(names,m_list);
|
|
|
|
#ifdef XDEBUG
|
|
|
|
String tmp;
|
|
|
|
tmp.append(names,",");
|
|
|
|
Debug(DebugInfo,"JsHashList::fillFieldNames: %s",tmp.c_str());
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
bool JsHashList::runField(ObjList& stack, const ExpOperation& oper, GenObject* context)
|
|
|
|
{
|
|
|
|
XDebug(DebugAll,"JsHashList::runField() '%s' in '%s' [%p]",
|
|
|
|
oper.name().c_str(),toString().c_str(),this);
|
|
|
|
ExpOperation* obj = static_cast<ExpOperation*>(m_list[oper.name()]);
|
|
|
|
if (obj) {
|
|
|
|
ExpWrapper* wrp = YOBJECT(ExpWrapper,obj);
|
|
|
|
if (wrp)
|
|
|
|
ExpEvaluator::pushOne(stack,wrp->clone(oper.name()));
|
|
|
|
else
|
|
|
|
ExpEvaluator::pushOne(stack,new ExpOperation(*obj,oper.name()));
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
return JsObject::runField(stack,oper,context);
|
|
|
|
}
|
|
|
|
|
|
|
|
bool JsHashList::runAssign(ObjList& stack, const ExpOperation& oper, GenObject* context)
|
|
|
|
{
|
|
|
|
XDebug(DebugAll,"JsHashList::runAssign() '%s'='%s' (%s) in '%s' [%p]",
|
|
|
|
oper.name().c_str(),oper.c_str(),oper.typeOf(),toString().c_str(),this);
|
|
|
|
if (frozen()) {
|
|
|
|
Debug(DebugWarn,"Object '%s' is frozen",toString().c_str());
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
ObjList* obj = m_list.find(oper.name());
|
|
|
|
ExpOperation* cln = 0;
|
|
|
|
ExpFunction* ef = YOBJECT(ExpFunction,&oper);
|
|
|
|
if (ef)
|
|
|
|
cln = ef->ExpOperation::clone();
|
|
|
|
else {
|
|
|
|
ExpWrapper* w = YOBJECT(ExpWrapper,&oper);
|
|
|
|
if (w) {
|
|
|
|
JsFunction* jsf = YOBJECT(JsFunction,w->object());
|
|
|
|
if (jsf)
|
|
|
|
jsf->firstName(oper.name());
|
|
|
|
cln = w->clone(oper.name());
|
|
|
|
}
|
|
|
|
else
|
|
|
|
cln = oper.clone();
|
|
|
|
}
|
|
|
|
if (!obj)
|
|
|
|
m_list.append(cln);
|
|
|
|
else
|
|
|
|
obj->set(cln);
|
|
|
|
return true;
|
|
|
|
}
|
2014-07-14 08:06:41 +00:00
|
|
|
|
2017-09-29 14:52:33 +00:00
|
|
|
bool JsHashList::runNative(ObjList& stack, const ExpOperation& oper, GenObject* context)
|
|
|
|
{
|
|
|
|
if (YSTRING("count") == oper.name()) {
|
|
|
|
ExpEvaluator::pushOne(stack,new ExpOperation((int64_t)m_list.count()));
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
return JsObject::runNative(stack,oper,context);
|
|
|
|
}
|
|
|
|
|
2020-02-21 14:41:19 +00:00
|
|
|
void* JsURI::getObject(const String& name) const
|
|
|
|
{
|
|
|
|
void* obj = (name == YATOM("JsURI")) ? const_cast<JsURI*>(this) : JsObject::getObject(name);
|
|
|
|
if (!obj)
|
|
|
|
obj = m_uri.getObject(name);
|
|
|
|
return obj;
|
|
|
|
}
|
|
|
|
|
|
|
|
JsObject* JsURI::runConstructor(ObjList& stack, const ExpOperation& oper, GenObject* context)
|
|
|
|
{
|
|
|
|
XDebug(&__plugin,DebugAll,"JsURI::runConstructor '%s'(" FMT64 ")",oper.name().c_str(),oper.number());
|
|
|
|
ObjList args;
|
|
|
|
const char* str = 0;
|
|
|
|
switch (extractArgs(stack,oper,context,args)) {
|
|
|
|
case 1:
|
|
|
|
{
|
|
|
|
ExpOperation* op = static_cast<ExpOperation*>(args[0]);
|
|
|
|
if (!op)
|
|
|
|
return 0;
|
|
|
|
str = *op;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case 0:
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2020-10-21 11:01:31 +00:00
|
|
|
JsURI* obj = new JsURI(str,mutex(),oper.lineNumber());
|
2020-02-21 14:41:19 +00:00
|
|
|
if (!ref()) {
|
|
|
|
TelEngine::destruct(obj);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
obj->params().addParam(new ExpWrapper(this,protoName()));
|
|
|
|
return obj;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool JsURI::runNative(ObjList& stack, const ExpOperation& oper, GenObject* context)
|
|
|
|
{
|
|
|
|
CALL_NATIVE_METH_STR(m_uri,getDescription);
|
|
|
|
CALL_NATIVE_METH_STR(m_uri,getProtocol);
|
|
|
|
CALL_NATIVE_METH_STR(m_uri,getUser);
|
|
|
|
CALL_NATIVE_METH_STR(m_uri,getHost);
|
|
|
|
CALL_NATIVE_METH_INT(m_uri,getPort);
|
|
|
|
CALL_NATIVE_METH_STR(m_uri,getExtra);
|
|
|
|
if (YSTRING("getCanonical") == oper.name()) {
|
|
|
|
String str;
|
|
|
|
if (m_uri.getProtocol())
|
|
|
|
str += m_uri.getProtocol() + ":";
|
|
|
|
if (m_uri.getUser())
|
|
|
|
str += m_uri.getUser();
|
|
|
|
if (m_uri.getHost()) {
|
|
|
|
if (m_uri.getUser())
|
|
|
|
str << "@";
|
|
|
|
if (m_uri.getPort())
|
|
|
|
SocketAddr::appendTo(str,m_uri.getHost(),m_uri.getPort());
|
|
|
|
else
|
|
|
|
str << m_uri.getHost();
|
|
|
|
}
|
|
|
|
ExpEvaluator::pushOne(stack,new ExpOperation(str));
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
return JsObject::runNative(stack,oper,context);
|
|
|
|
}
|
|
|
|
|
2014-07-14 08:06:41 +00:00
|
|
|
bool JsJSON::runNative(ObjList& stack, const ExpOperation& oper, GenObject* context)
|
|
|
|
{
|
|
|
|
ObjList args;
|
|
|
|
if (oper.name() == YSTRING("parse")) {
|
|
|
|
if (extractArgs(stack,oper,context,args) != 1)
|
|
|
|
return false;
|
2020-10-21 11:01:31 +00:00
|
|
|
ExpOperation* op = JsParser::parseJSON(static_cast<ExpOperation*>(args[0])->c_str(),mutex(),&stack,context,&oper);
|
2014-07-14 08:06:41 +00:00
|
|
|
if (!op)
|
|
|
|
op = new ExpWrapper(0,"JSON");
|
|
|
|
ExpEvaluator::pushOne(stack,op);
|
|
|
|
}
|
|
|
|
else if (oper.name() == YSTRING("stringify")) {
|
|
|
|
if (extractArgs(stack,oper,context,args) < 1)
|
|
|
|
return false;
|
|
|
|
int spaces = args[2] ? static_cast<ExpOperation*>(args[2])->number() : 0;
|
2018-06-15 13:39:48 +00:00
|
|
|
ExpOperation* op = JsObject::toJSON(static_cast<ExpOperation*>(args[0]),spaces);
|
2014-07-14 08:06:41 +00:00
|
|
|
if (!op)
|
|
|
|
op = new ExpWrapper(0,"JSON");
|
|
|
|
ExpEvaluator::pushOne(stack,op);
|
|
|
|
}
|
|
|
|
else if (oper.name() == YSTRING("loadFile")) {
|
|
|
|
if (extractArgs(stack,oper,context,args) != 1)
|
|
|
|
return false;
|
|
|
|
ExpOperation* op = 0;
|
|
|
|
ExpOperation* file = static_cast<ExpOperation*>(args[0]);
|
2017-09-18 13:03:30 +00:00
|
|
|
if (JsParser::isFilled(file)) {
|
2014-07-14 08:06:41 +00:00
|
|
|
File f;
|
|
|
|
if (f.openPath(*file)) {
|
|
|
|
int64_t len = f.length();
|
|
|
|
if (len > 0 && len <= 65536) {
|
|
|
|
DataBlock buf(0,len + 1);
|
|
|
|
char* text = (char*)buf.data();
|
|
|
|
if (f.readData(text,len) == len) {
|
|
|
|
text[len] = '\0';
|
2020-10-21 11:01:31 +00:00
|
|
|
op = JsParser::parseJSON(text,mutex(),&stack,context,&oper);
|
2014-07-14 08:06:41 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (!op)
|
|
|
|
op = new ExpWrapper(0,"JSON");
|
|
|
|
ExpEvaluator::pushOne(stack,op);
|
|
|
|
}
|
|
|
|
else if (oper.name() == YSTRING("saveFile")) {
|
|
|
|
if (extractArgs(stack,oper,context,args) < 2)
|
|
|
|
return false;
|
|
|
|
ExpOperation* file = static_cast<ExpOperation*>(args[0]);
|
2017-09-18 13:03:30 +00:00
|
|
|
bool ok = JsParser::isFilled(file);
|
2014-07-14 08:06:41 +00:00
|
|
|
if (ok) {
|
|
|
|
ok = false;
|
|
|
|
int spaces = args[2] ? static_cast<ExpOperation*>(args[2])->number() : 0;
|
2018-06-15 13:39:48 +00:00
|
|
|
ExpOperation* op = JsObject::toJSON(static_cast<ExpOperation*>(args[1]),spaces);
|
2014-07-14 08:06:41 +00:00
|
|
|
if (op) {
|
|
|
|
File f;
|
|
|
|
if (f.openPath(*file,true,false,true)) {
|
|
|
|
int len = op->length();
|
|
|
|
ok = f.writeData(op->c_str(),len) == len;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
TelEngine::destruct(op);
|
|
|
|
}
|
|
|
|
ExpEvaluator::pushOne(stack,new ExpOperation(ok));
|
|
|
|
}
|
2018-04-10 12:16:20 +00:00
|
|
|
else if (oper.name() == YSTRING("replaceParams")) {
|
|
|
|
ObjList args;
|
|
|
|
int argc = extractArgs(stack,oper,context,args);
|
|
|
|
if (argc < 2 || argc > 4)
|
|
|
|
return false;
|
|
|
|
const NamedList* params = getReplaceParams(args[1]);
|
|
|
|
if (params) {
|
|
|
|
bool sqlEsc = (argc >= 3) && static_cast<ExpOperation*>(args[2])->valBoolean();
|
|
|
|
char extraEsc = 0;
|
|
|
|
if (argc >= 4)
|
|
|
|
extraEsc = static_cast<ExpOperation*>(args[3])->at(0);
|
|
|
|
replaceParams(args[0],*params,sqlEsc,extraEsc);
|
|
|
|
}
|
|
|
|
}
|
2021-10-27 10:22:53 +00:00
|
|
|
else if (oper.name() == YSTRING("replaceReferences")) {
|
|
|
|
// JSON.replaceReferences(obj)
|
|
|
|
// Return boolean (success/failure)
|
|
|
|
ExpOperation* op = 0;
|
|
|
|
if (!extractStackArgs(1,this,stack,oper,context,args,&op))
|
|
|
|
return false;
|
|
|
|
bool ok = JsObject::resolveReferences(op);
|
|
|
|
ExpEvaluator::pushOne(stack,new ExpOperation(ok));
|
|
|
|
}
|
|
|
|
else if (oper.name() == YSTRING("findPath")) {
|
|
|
|
// JSON.findPath(obj,path). 'path' may be a JPath object or string
|
|
|
|
// Return found data, undefined if not found
|
|
|
|
ExpOperation* op = 0;
|
|
|
|
ExpOperation* pathOp = 0;
|
|
|
|
if (!extractStackArgs(2,this,stack,oper,context,args,&op,&pathOp))
|
|
|
|
return false;
|
|
|
|
JPathTmpParam jp(*pathOp);
|
|
|
|
ExpOperation* res = JsObject::find(op,*jp);
|
|
|
|
if (res)
|
|
|
|
ExpEvaluator::pushOne(stack,res->clone());
|
|
|
|
else
|
|
|
|
ExpEvaluator::pushOne(stack,new ExpWrapper((GenObject*)0));
|
|
|
|
}
|
2014-07-14 08:06:41 +00:00
|
|
|
else
|
|
|
|
return JsObject::runNative(stack,oper,context);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2018-04-10 12:16:20 +00:00
|
|
|
void JsJSON::replaceParams(GenObject* obj, const NamedList& params, bool sqlEsc, char extraEsc)
|
|
|
|
{
|
|
|
|
ExpOperation* oper = YOBJECT(ExpOperation,obj);
|
|
|
|
if (!oper || JsParser::isNull(*oper) || JsParser::isUndefined(*oper) ||
|
|
|
|
YOBJECT(JsFunction,oper) || YOBJECT(ExpFunction,oper))
|
|
|
|
return;
|
|
|
|
JsObject* jso = YOBJECT(JsObject,oper);
|
|
|
|
JsArray* jsa = YOBJECT(JsArray,jso);
|
|
|
|
if (jsa) {
|
|
|
|
if (jsa->length() <= 0)
|
|
|
|
return;
|
|
|
|
for (int32_t i = 0; i < jsa->length(); i++) {
|
|
|
|
NamedString* p = jsa->params().getParam(String(i));
|
|
|
|
if (p)
|
|
|
|
replaceParams(p,params,sqlEsc,extraEsc);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (jso) {
|
|
|
|
NamedString* proto = jso->params().getParam(protoName());
|
|
|
|
for (ObjList* o = jso->params().paramList()->skipNull(); o; o = o->skipNext()) {
|
|
|
|
NamedString* p = static_cast<NamedString*>(o->get());
|
|
|
|
if (p != proto)
|
|
|
|
replaceParams(p,params,sqlEsc,extraEsc);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (!(oper->isBoolean() || oper->isNumber()))
|
|
|
|
params.replaceParams(*oper,sqlEsc,extraEsc);
|
|
|
|
}
|
|
|
|
|
2014-07-14 08:06:41 +00:00
|
|
|
void JsJSON::initialize(ScriptContext* context)
|
|
|
|
{
|
|
|
|
if (!context)
|
|
|
|
return;
|
2020-10-21 11:01:31 +00:00
|
|
|
ScriptMutex* mtx = context->mutex();
|
2014-07-14 08:06:41 +00:00
|
|
|
Lock mylock(mtx);
|
|
|
|
NamedList& params = context->params();
|
|
|
|
if (!params.getParam(YSTRING("JSON")))
|
|
|
|
addObject(params,"JSON",new JsJSON(mtx));
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2014-07-22 11:04:28 +00:00
|
|
|
bool JsDNS::runNative(ObjList& stack, const ExpOperation& oper, GenObject* context)
|
|
|
|
{
|
2014-08-26 17:21:36 +00:00
|
|
|
ObjList args;
|
2014-07-22 11:04:28 +00:00
|
|
|
if (oper.name().startsWith("query")) {
|
|
|
|
String type = oper.name().substr(5);
|
|
|
|
ExpOperation* arg = 0;
|
|
|
|
ExpOperation* async = 0;
|
|
|
|
int argc = extractArgs(stack,oper,context,args);
|
|
|
|
if (type.null() && (argc >= 2)) {
|
|
|
|
type = static_cast<ExpOperation*>(args[0]);
|
|
|
|
arg = static_cast<ExpOperation*>(args[1]);
|
|
|
|
async = static_cast<ExpOperation*>(args[2]);
|
|
|
|
}
|
|
|
|
else if (type && (argc >= 1)) {
|
|
|
|
arg = static_cast<ExpOperation*>(args[0]);
|
|
|
|
async = static_cast<ExpOperation*>(args[1]);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
return false;
|
|
|
|
type.toUpper();
|
|
|
|
int qType = lookup(type,Resolver::s_types,-1);
|
2017-09-18 13:03:30 +00:00
|
|
|
if ((qType < 0) || JsParser::isEmpty(arg))
|
2014-07-22 11:04:28 +00:00
|
|
|
ExpEvaluator::pushOne(stack,new ExpWrapper(0,"DNS"));
|
|
|
|
else {
|
|
|
|
if (async && async->valBoolean()) {
|
|
|
|
ScriptRun* runner = YOBJECT(ScriptRun,context);
|
|
|
|
if (!runner)
|
|
|
|
return false;
|
2020-10-21 11:01:31 +00:00
|
|
|
runner->insertAsync(new JsDnsAsync(runner,this,&stack,*arg,(Resolver::Type)qType,context,oper.lineNumber()));
|
2014-07-22 11:04:28 +00:00
|
|
|
runner->pause();
|
|
|
|
return true;
|
|
|
|
}
|
2020-10-21 11:01:31 +00:00
|
|
|
runQuery(stack,*arg,(Resolver::Type)qType,context,oper.lineNumber());
|
2014-07-22 11:04:28 +00:00
|
|
|
}
|
|
|
|
}
|
2014-08-26 17:21:36 +00:00
|
|
|
else if ((oper.name() == YSTRING("resolve")) || (oper.name() == YSTRING("local"))) {
|
|
|
|
if (extractArgs(stack,oper,context,args) != 1)
|
|
|
|
return false;
|
|
|
|
ExpOperation* op = 0;
|
2017-09-18 13:03:30 +00:00
|
|
|
if (JsParser::isFilled(static_cast<ExpOperation*>(args[0]))) {
|
|
|
|
String tmp = static_cast<ExpOperation*>(args[0]);
|
|
|
|
if ((tmp[0] == '[') && (tmp[tmp.length() - 1] == ']'))
|
|
|
|
tmp = tmp.substr(1,tmp.length() - 2);
|
|
|
|
SocketAddr rAddr;
|
|
|
|
if (rAddr.host(tmp)) {
|
|
|
|
if (oper.name() == YSTRING("resolve"))
|
|
|
|
op = new ExpOperation(rAddr.host(),"IP");
|
|
|
|
else {
|
|
|
|
SocketAddr lAddr;
|
|
|
|
if (lAddr.local(rAddr))
|
|
|
|
op = new ExpOperation(lAddr.host(),"IP");
|
|
|
|
}
|
2014-08-26 17:21:36 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
if (!op)
|
|
|
|
op = new ExpWrapper(0,"IP");
|
|
|
|
ExpEvaluator::pushOne(stack,op);
|
|
|
|
}
|
2014-12-18 15:11:42 +00:00
|
|
|
else if (oper.name().startsWith("pack")) {
|
|
|
|
char sep = '\0';
|
|
|
|
ExpOperation* op;
|
|
|
|
switch (extractArgs(stack,oper,context,args)) {
|
|
|
|
case 2:
|
|
|
|
op = static_cast<ExpOperation*>(args[1]);
|
|
|
|
if (op->isBoolean())
|
|
|
|
sep = op->valBoolean() ? ' ' : '\0';
|
|
|
|
else if ((op->length() == 1) && !op->isNumber())
|
|
|
|
sep = op->at(0);
|
|
|
|
// fall through
|
|
|
|
case 1:
|
|
|
|
op = 0;
|
2017-09-18 13:03:30 +00:00
|
|
|
if (JsParser::isFilled(static_cast<ExpOperation*>(args[0]))) {
|
2014-12-18 15:11:42 +00:00
|
|
|
String tmp = static_cast<ExpOperation*>(args[0]);
|
|
|
|
if ((tmp[0] == '[') && (tmp[tmp.length() - 1] == ']'))
|
|
|
|
tmp = tmp.substr(1,tmp.length() - 2);
|
|
|
|
SocketAddr addr;
|
|
|
|
if (addr.host(tmp)) {
|
|
|
|
DataBlock d;
|
|
|
|
addr.copyAddr(d);
|
|
|
|
if (d.length()) {
|
|
|
|
tmp.hexify(d.data(),d.length(),sep);
|
|
|
|
op = new ExpOperation(tmp,"IP");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (!op)
|
|
|
|
op = new ExpWrapper(0,"IP");
|
|
|
|
ExpEvaluator::pushOne(stack,op);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (oper.name().startsWith("unpack")) {
|
|
|
|
if (extractArgs(stack,oper,context,args) != 1)
|
|
|
|
return false;
|
|
|
|
ExpOperation* op = 0;
|
|
|
|
DataBlock d;
|
|
|
|
if (d.unHexify(*static_cast<ExpOperation*>(args[0]))) {
|
|
|
|
SocketAddr addr;
|
|
|
|
if (addr.assign(d))
|
|
|
|
op = new ExpOperation(addr.host(),"IP");
|
|
|
|
}
|
|
|
|
if (!op)
|
|
|
|
op = new ExpWrapper(0,"IP");
|
|
|
|
ExpEvaluator::pushOne(stack,op);
|
|
|
|
}
|
2017-11-17 15:57:31 +00:00
|
|
|
else if (oper.name().startsWith("dscp")) {
|
|
|
|
if (extractArgs(stack,oper,context,args) != 1)
|
|
|
|
return false;
|
|
|
|
ExpOperation* op = static_cast<ExpOperation*>(args[0]);
|
|
|
|
if (!op)
|
|
|
|
return false;
|
|
|
|
int val = op->toInteger(Socket::tosValues(),-1);
|
|
|
|
if (0 <= val && 0xfc >= val)
|
|
|
|
ExpEvaluator::pushOne(stack,new ExpOperation((int64_t)(val & 0xfc),"DSCP"));
|
|
|
|
else
|
|
|
|
ExpEvaluator::pushOne(stack,new ExpWrapper(0,"DSCP"));
|
|
|
|
}
|
2014-07-22 11:04:28 +00:00
|
|
|
else
|
|
|
|
return JsObject::runNative(stack,oper,context);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2020-10-21 11:01:31 +00:00
|
|
|
void JsDNS::runQuery(ObjList& stack, const String& name, Resolver::Type type, GenObject* context, unsigned int lineNo)
|
2014-07-22 11:04:28 +00:00
|
|
|
{
|
2020-08-27 09:54:46 +00:00
|
|
|
if (!Resolver::init()) {
|
|
|
|
ExpEvaluator::pushOne(stack,JsParser::nullClone());
|
|
|
|
return;
|
|
|
|
}
|
2014-07-22 11:04:28 +00:00
|
|
|
JsArray* jsa = 0;
|
|
|
|
ObjList res;
|
|
|
|
if (Resolver::query(type,name,res) == 0) {
|
2020-10-21 11:01:31 +00:00
|
|
|
jsa = new JsArray(context,lineNo,mutex());
|
2014-07-22 11:04:28 +00:00
|
|
|
switch (type) {
|
|
|
|
case Resolver::A4:
|
|
|
|
case Resolver::A6:
|
|
|
|
case Resolver::Txt:
|
|
|
|
for (ObjList* l = res.skipNull(); l; l = l->skipNext()) {
|
|
|
|
TxtRecord* r = static_cast<TxtRecord*>(l->get());
|
|
|
|
jsa->push(new ExpOperation(r->text()));
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case Resolver::Naptr:
|
|
|
|
for (ObjList* l = res.skipNull(); l; l = l->skipNext()) {
|
|
|
|
NaptrRecord* r = static_cast<NaptrRecord*>(l->get());
|
2020-10-21 11:01:31 +00:00
|
|
|
JsObject* jso = new JsObject(context,lineNo,mutex());
|
2014-07-22 11:04:28 +00:00
|
|
|
jso->params().setParam(new ExpOperation(r->flags(),"flags"));
|
|
|
|
jso->params().setParam(new ExpOperation(r->serv(),"service"));
|
|
|
|
// Would be nice to create a RegExp here but does not stringify properly
|
|
|
|
jso->params().setParam(new ExpOperation(r->regexp(),"regexp"));
|
|
|
|
jso->params().setParam(new ExpOperation(r->repTemplate(),"replacement"));
|
|
|
|
jso->params().setParam(new ExpOperation(r->nextName(),"name"));
|
2014-07-31 13:32:54 +00:00
|
|
|
jso->params().setParam(new ExpOperation((int64_t)r->ttl(),"ttl"));
|
|
|
|
jso->params().setParam(new ExpOperation((int64_t)r->order(),"order"));
|
|
|
|
jso->params().setParam(new ExpOperation((int64_t)r->pref(),"preference"));
|
2014-07-22 11:04:28 +00:00
|
|
|
jsa->push(new ExpWrapper(jso));
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case Resolver::Srv:
|
|
|
|
for (ObjList* l = res.skipNull(); l; l = l->skipNext()) {
|
|
|
|
SrvRecord* r = static_cast<SrvRecord*>(l->get());
|
2020-10-21 11:01:31 +00:00
|
|
|
JsObject* jso = new JsObject(context,lineNo,mutex());
|
2014-07-22 11:04:28 +00:00
|
|
|
jso->params().setParam(new ExpOperation((int64_t)r->port(),"port"));
|
|
|
|
jso->params().setParam(new ExpOperation(r->address(),"name"));
|
2014-07-31 13:32:54 +00:00
|
|
|
jso->params().setParam(new ExpOperation((int64_t)r->ttl(),"ttl"));
|
|
|
|
jso->params().setParam(new ExpOperation((int64_t)r->order(),"order"));
|
|
|
|
jso->params().setParam(new ExpOperation((int64_t)r->pref(),"preference"));
|
2014-07-22 11:04:28 +00:00
|
|
|
jsa->push(new ExpWrapper(jso));
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
ExpEvaluator::pushOne(stack,new ExpWrapper(jsa,lookup(type,Resolver::s_types)));
|
|
|
|
}
|
|
|
|
|
|
|
|
void JsDNS::initialize(ScriptContext* context)
|
|
|
|
{
|
|
|
|
if (!context)
|
|
|
|
return;
|
2020-10-21 11:01:31 +00:00
|
|
|
ScriptMutex* mtx = context->mutex();
|
2014-07-22 11:04:28 +00:00
|
|
|
Lock mylock(mtx);
|
|
|
|
NamedList& params = context->params();
|
|
|
|
if (!params.getParam(YSTRING("DNS")))
|
|
|
|
addObject(params,"DNS",new JsDNS(mtx));
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2013-04-12 14:00:39 +00:00
|
|
|
/**
|
|
|
|
* class JsTimeEvent
|
|
|
|
*/
|
|
|
|
|
|
|
|
JsTimeEvent::JsTimeEvent(JsEngineWorker* worker, const ExpFunction& callback,
|
2019-11-26 11:17:24 +00:00
|
|
|
unsigned int interval,bool repeatable, unsigned int id, ObjList* args)
|
2013-04-12 14:00:39 +00:00
|
|
|
: m_worker(worker), m_callbackFunction(callback.name(),1),
|
2019-11-26 11:17:24 +00:00
|
|
|
m_interval(interval), m_repeat(repeatable), m_id(id), m_args(args)
|
2013-04-12 14:00:39 +00:00
|
|
|
{
|
|
|
|
XDebug(&__plugin,DebugAll,"Created new JsTimeEvent(%u,%s) [%p]",interval,
|
|
|
|
String::boolText(repeatable),this);
|
|
|
|
m_fire = Time::msecNow() + m_interval;
|
|
|
|
}
|
|
|
|
|
|
|
|
void JsTimeEvent::processTimeout(const Time& when)
|
|
|
|
{
|
|
|
|
if (m_repeat)
|
|
|
|
m_fire = when.msec() + m_interval;
|
2017-05-03 08:39:48 +00:00
|
|
|
ScriptRun* runner = m_worker->getRunner();
|
|
|
|
if (!runner)
|
|
|
|
return;
|
|
|
|
ObjList args;
|
2019-11-26 11:17:24 +00:00
|
|
|
if (m_args)
|
|
|
|
copyArgList(args,*m_args);
|
2017-05-03 08:39:48 +00:00
|
|
|
runner->call(m_callbackFunction.name(),args);
|
2013-04-12 14:00:39 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* class JsEngineWorker
|
|
|
|
*/
|
|
|
|
|
|
|
|
JsEngineWorker::JsEngineWorker(JsEngine* engine, ScriptContext* context, ScriptCode* code)
|
2021-05-21 15:26:13 +00:00
|
|
|
: Thread(engine->schedName()), m_eventsMutex(false,"JsEngine"), m_id(0),
|
2017-05-03 08:39:48 +00:00
|
|
|
m_runner(code->createRunner(context,NATIVE_TITLE)), m_engine(engine)
|
2013-04-12 14:00:39 +00:00
|
|
|
{
|
2017-05-03 08:39:48 +00:00
|
|
|
DDebug(&__plugin,DebugAll,"Creating JsEngineWorker engine=%p [%p]",(void*)m_engine,this);
|
2013-04-12 14:00:39 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
JsEngineWorker::~JsEngineWorker()
|
|
|
|
{
|
2017-05-03 08:39:48 +00:00
|
|
|
DDebug(&__plugin,DebugAll,"Destroying JsEngineWorker engine=%p [%p]",(void*)m_engine,this);
|
2021-05-20 12:24:31 +00:00
|
|
|
m_events.clear();
|
2013-04-12 14:00:39 +00:00
|
|
|
if (m_engine)
|
|
|
|
m_engine->resetWorker();
|
2017-05-03 08:39:48 +00:00
|
|
|
m_engine = 0;
|
|
|
|
TelEngine::destruct(m_runner);
|
2013-04-12 14:00:39 +00:00
|
|
|
}
|
|
|
|
|
2019-11-26 11:17:24 +00:00
|
|
|
unsigned int JsEngineWorker::addEvent(const ExpFunction& callback, unsigned int interval, bool repeat, ObjList* args)
|
2013-04-12 14:00:39 +00:00
|
|
|
{
|
|
|
|
Lock myLock(m_eventsMutex);
|
|
|
|
if (interval < MIN_CALLBACK_INTERVAL)
|
|
|
|
interval = MIN_CALLBACK_INTERVAL;
|
|
|
|
// TODO find a better way to generate the id's
|
2019-11-26 11:17:24 +00:00
|
|
|
postponeEvent(new JsTimeEvent(this,callback,interval,repeat,++m_id,args));
|
2013-04-12 14:00:39 +00:00
|
|
|
return m_id;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool JsEngineWorker::removeEvent(unsigned int id, bool repeatable)
|
|
|
|
{
|
|
|
|
Lock myLock(m_eventsMutex);
|
|
|
|
for (ObjList* o = m_events.skipNull();o ; o = o->skipNext()) {
|
|
|
|
JsTimeEvent* ev = static_cast<JsTimeEvent*>(o->get());
|
|
|
|
if (ev->getId() != id)
|
|
|
|
continue;
|
|
|
|
if (ev->repeatable() != repeatable)
|
|
|
|
return false;
|
|
|
|
o->remove();
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
void JsEngineWorker::run()
|
|
|
|
{
|
2017-04-26 10:40:04 +00:00
|
|
|
while (!Thread::check(false)) {
|
2017-05-03 08:39:48 +00:00
|
|
|
if (m_engine->refcount() == 1) {
|
|
|
|
m_engine->resetWorker();
|
|
|
|
return;
|
2017-04-26 10:40:04 +00:00
|
|
|
}
|
2013-04-12 14:00:39 +00:00
|
|
|
Lock myLock(m_eventsMutex);
|
|
|
|
ObjList* o = m_events.skipNull();
|
|
|
|
if (!o) {
|
|
|
|
myLock.drop();
|
|
|
|
Thread::idle(true);
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
RefPointer<JsTimeEvent> ev = static_cast<JsTimeEvent*>(o->get());
|
2021-05-19 14:16:06 +00:00
|
|
|
Time t;
|
2013-04-12 14:00:39 +00:00
|
|
|
if (!ev->timeout(t)) {
|
2021-05-19 14:16:06 +00:00
|
|
|
myLock.drop();
|
2016-11-07 18:20:07 +00:00
|
|
|
ev = 0;
|
2013-04-12 14:00:39 +00:00
|
|
|
Thread::idle(true);
|
|
|
|
continue;
|
|
|
|
}
|
2021-05-19 14:16:06 +00:00
|
|
|
if (o->remove(!ev->repeatable()))
|
2013-04-12 14:00:39 +00:00
|
|
|
postponeEvent(ev);
|
2021-05-19 14:16:06 +00:00
|
|
|
myLock.drop();
|
|
|
|
ev->processTimeout(t);
|
|
|
|
ev = 0;
|
2013-04-12 14:00:39 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void JsEngineWorker::postponeEvent(JsTimeEvent* evnt)
|
|
|
|
{
|
|
|
|
if (!evnt)
|
|
|
|
return;
|
|
|
|
for (ObjList* o = m_events.skipNull();o;o = o->skipNext()) {
|
|
|
|
JsTimeEvent* ev = static_cast<JsTimeEvent*>(o->get());
|
|
|
|
if (ev->fireTime() <= evnt->fireTime())
|
|
|
|
continue;
|
|
|
|
o->insert(evnt);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
m_events.append(evnt);
|
|
|
|
}
|
|
|
|
|
2017-05-03 08:39:48 +00:00
|
|
|
ScriptRun* JsEngineWorker::getRunner()
|
2013-04-12 14:00:39 +00:00
|
|
|
{
|
2017-05-03 08:39:48 +00:00
|
|
|
if (m_runner)
|
|
|
|
m_runner->reset();
|
|
|
|
return m_runner;
|
2013-04-12 14:00:39 +00:00
|
|
|
}
|
|
|
|
|
2012-12-21 10:21:16 +00:00
|
|
|
|
2012-02-17 16:19:17 +00:00
|
|
|
bool JsChannel::runNative(ObjList& stack, const ExpOperation& oper, GenObject* context)
|
|
|
|
{
|
2016-01-20 10:23:35 +00:00
|
|
|
XDebug(&__plugin,DebugAll,"JsChannel::runNative '%s'(" FMT64 ")",oper.name().c_str(),oper.number());
|
2012-02-17 16:19:17 +00:00
|
|
|
if (oper.name() == YSTRING("id")) {
|
2012-03-05 09:53:31 +00:00
|
|
|
if (oper.number())
|
|
|
|
return false;
|
2012-02-17 16:19:17 +00:00
|
|
|
RefPointer<JsAssist> ja = m_assist;
|
2012-06-22 09:38:51 +00:00
|
|
|
if (ja)
|
|
|
|
ExpEvaluator::pushOne(stack,new ExpOperation(ja->id()));
|
|
|
|
else
|
|
|
|
ExpEvaluator::pushOne(stack,JsParser::nullClone());
|
2012-06-20 14:02:18 +00:00
|
|
|
}
|
|
|
|
else if (oper.name() == YSTRING("peerid")) {
|
|
|
|
if (oper.number())
|
|
|
|
return false;
|
|
|
|
RefPointer<JsAssist> ja = m_assist;
|
|
|
|
if (!ja)
|
|
|
|
return false;
|
|
|
|
RefPointer<CallEndpoint> cp = ja->locate();
|
|
|
|
String id;
|
|
|
|
if (cp)
|
|
|
|
cp->getPeerId(id);
|
|
|
|
if (id)
|
|
|
|
ExpEvaluator::pushOne(stack,new ExpOperation(id));
|
|
|
|
else
|
|
|
|
ExpEvaluator::pushOne(stack,JsParser::nullClone());
|
2012-02-17 16:19:17 +00:00
|
|
|
}
|
2012-03-05 09:53:31 +00:00
|
|
|
else if (oper.name() == YSTRING("status")) {
|
|
|
|
if (oper.number())
|
|
|
|
return false;
|
2012-06-22 09:38:51 +00:00
|
|
|
RefPointer<CallEndpoint> cp;
|
2012-03-05 09:53:31 +00:00
|
|
|
RefPointer<JsAssist> ja = m_assist;
|
2012-06-22 09:38:51 +00:00
|
|
|
if (ja)
|
|
|
|
cp = ja->locate();
|
2012-06-20 14:02:18 +00:00
|
|
|
Channel* ch = YOBJECT(Channel,cp);
|
2020-05-29 14:03:35 +00:00
|
|
|
if (ch) {
|
|
|
|
String tmp;
|
|
|
|
ch->getStatus(tmp);
|
|
|
|
ExpEvaluator::pushOne(stack,new ExpOperation(tmp));
|
|
|
|
}
|
2012-03-05 09:53:31 +00:00
|
|
|
else
|
2012-06-20 14:02:18 +00:00
|
|
|
ExpEvaluator::pushOne(stack,JsParser::nullClone());
|
|
|
|
}
|
|
|
|
else if (oper.name() == YSTRING("direction")) {
|
|
|
|
if (oper.number())
|
|
|
|
return false;
|
2012-06-22 09:38:51 +00:00
|
|
|
RefPointer<CallEndpoint> cp;
|
2012-06-20 14:02:18 +00:00
|
|
|
RefPointer<JsAssist> ja = m_assist;
|
2012-06-22 09:38:51 +00:00
|
|
|
if (ja)
|
|
|
|
cp = ja->locate();
|
2012-06-20 14:02:18 +00:00
|
|
|
Channel* ch = YOBJECT(Channel,cp);
|
|
|
|
if (ch)
|
|
|
|
ExpEvaluator::pushOne(stack,new ExpOperation(ch->direction()));
|
|
|
|
else
|
|
|
|
ExpEvaluator::pushOne(stack,JsParser::nullClone());
|
2012-03-05 09:53:31 +00:00
|
|
|
}
|
2012-06-22 14:42:41 +00:00
|
|
|
else if (oper.name() == YSTRING("answered")) {
|
|
|
|
if (oper.number())
|
|
|
|
return false;
|
|
|
|
RefPointer<CallEndpoint> cp;
|
|
|
|
RefPointer<JsAssist> ja = m_assist;
|
|
|
|
if (ja)
|
|
|
|
cp = ja->locate();
|
|
|
|
Channel* ch = YOBJECT(Channel,cp);
|
|
|
|
ExpEvaluator::pushOne(stack,new ExpOperation(ch && ch->isAnswered()));
|
|
|
|
}
|
2012-06-22 09:38:51 +00:00
|
|
|
else if (oper.name() == YSTRING("answer")) {
|
|
|
|
if (oper.number())
|
2012-03-05 09:53:31 +00:00
|
|
|
return false;
|
|
|
|
RefPointer<JsAssist> ja = m_assist;
|
2012-06-22 09:38:51 +00:00
|
|
|
if (ja) {
|
|
|
|
Message* m = new Message("call.answered");
|
|
|
|
m->addParam("targetid",ja->id());
|
|
|
|
Engine::enqueue(m);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (oper.name() == YSTRING("hangup")) {
|
2015-11-24 15:38:35 +00:00
|
|
|
bool peer = false;
|
|
|
|
ExpOperation* params = 0;
|
|
|
|
switch (oper.number()) {
|
|
|
|
case 3:
|
|
|
|
params = popValue(stack,context);
|
|
|
|
peer = params && params->valBoolean();
|
2019-06-25 13:00:25 +00:00
|
|
|
TelEngine::destruct(params);
|
2015-11-24 15:38:35 +00:00
|
|
|
// fall through
|
|
|
|
case 2:
|
|
|
|
params = popValue(stack,context);
|
|
|
|
// fall through
|
|
|
|
case 1:
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
return false;
|
|
|
|
}
|
2012-06-22 09:38:51 +00:00
|
|
|
ExpOperation* op = popValue(stack,context);
|
2015-11-24 15:38:35 +00:00
|
|
|
ScriptRun* runner = YOBJECT(ScriptRun,context);
|
2012-06-22 09:38:51 +00:00
|
|
|
RefPointer<JsAssist> ja = m_assist;
|
|
|
|
if (ja) {
|
2015-11-24 15:38:35 +00:00
|
|
|
NamedList* lst = YOBJECT(NamedList,params);
|
|
|
|
if (!lst) {
|
|
|
|
ScriptContext* ctx = YOBJECT(ScriptContext,params);
|
|
|
|
if (ctx)
|
|
|
|
lst = &ctx->params();
|
|
|
|
}
|
|
|
|
String id;
|
|
|
|
if (peer) {
|
|
|
|
RefPointer<CallEndpoint> cp = ja->locate();
|
|
|
|
if (cp)
|
|
|
|
cp->getPeerId(id);
|
|
|
|
}
|
|
|
|
if (!id)
|
|
|
|
id = ja->id();
|
2012-06-22 09:38:51 +00:00
|
|
|
Message* m = new Message("call.drop");
|
2015-11-24 15:38:35 +00:00
|
|
|
m->addParam("id",id);
|
|
|
|
copyObjParams(*m,lst);
|
2012-06-22 09:38:51 +00:00
|
|
|
if (op && !op->null()) {
|
|
|
|
m->addParam("reason",*op);
|
|
|
|
// there may be a race between chan.disconnected and call.drop so set in both
|
|
|
|
Message* msg = ja->getMsg(runner);
|
2015-11-24 15:38:35 +00:00
|
|
|
if (msg) {
|
2015-11-17 13:31:15 +00:00
|
|
|
msg->setParam((ja->state() == JsAssist::Routing) ? "error" : "reason",*op);
|
2015-11-24 15:38:35 +00:00
|
|
|
copyObjParams(*msg,lst);
|
|
|
|
}
|
2012-06-22 09:38:51 +00:00
|
|
|
}
|
|
|
|
ja->end();
|
|
|
|
Engine::enqueue(m);
|
|
|
|
}
|
|
|
|
TelEngine::destruct(op);
|
2015-11-24 15:38:35 +00:00
|
|
|
TelEngine::destruct(params);
|
2012-06-22 09:38:51 +00:00
|
|
|
if (runner)
|
|
|
|
runner->pause();
|
2012-06-20 14:02:18 +00:00
|
|
|
}
|
2012-06-22 09:38:51 +00:00
|
|
|
else if (oper.name() == YSTRING("callTo") || oper.name() == YSTRING("callJust")) {
|
2014-02-26 14:57:57 +00:00
|
|
|
ExpOperation* params = 0;
|
|
|
|
switch (oper.number()) {
|
|
|
|
case 2:
|
|
|
|
params = popValue(stack,context);
|
|
|
|
// fall through
|
|
|
|
case 1:
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
return false;
|
|
|
|
}
|
2012-06-20 14:02:18 +00:00
|
|
|
ExpOperation* op = popValue(stack,context);
|
2014-02-26 14:57:57 +00:00
|
|
|
if (!op) {
|
|
|
|
op = params;
|
|
|
|
params = 0;
|
|
|
|
}
|
2012-06-20 14:02:18 +00:00
|
|
|
if (!op)
|
|
|
|
return false;
|
|
|
|
RefPointer<JsAssist> ja = m_assist;
|
2012-06-22 09:38:51 +00:00
|
|
|
if (!ja) {
|
|
|
|
TelEngine::destruct(op);
|
2014-02-26 14:57:57 +00:00
|
|
|
TelEngine::destruct(params);
|
2012-06-20 14:02:18 +00:00
|
|
|
return false;
|
2012-06-22 09:38:51 +00:00
|
|
|
}
|
2014-02-26 14:57:57 +00:00
|
|
|
NamedList* lst = YOBJECT(NamedList,params);
|
|
|
|
if (!lst) {
|
|
|
|
ScriptContext* ctx = YOBJECT(ScriptContext,params);
|
|
|
|
if (ctx)
|
|
|
|
lst = &ctx->params();
|
|
|
|
}
|
2012-06-22 09:38:51 +00:00
|
|
|
switch (ja->state()) {
|
|
|
|
case JsAssist::Routing:
|
2014-02-26 14:57:57 +00:00
|
|
|
callToRoute(stack,*op,context,lst);
|
2012-06-22 09:38:51 +00:00
|
|
|
break;
|
|
|
|
case JsAssist::ReRoute:
|
2014-02-26 14:57:57 +00:00
|
|
|
callToReRoute(stack,*op,context,lst);
|
2012-06-22 09:38:51 +00:00
|
|
|
break;
|
|
|
|
default:
|
2012-06-26 16:40:38 +00:00
|
|
|
break;
|
2012-06-22 09:38:51 +00:00
|
|
|
}
|
2012-06-26 16:40:38 +00:00
|
|
|
TelEngine::destruct(op);
|
2014-02-26 14:57:57 +00:00
|
|
|
TelEngine::destruct(params);
|
2012-06-22 09:38:51 +00:00
|
|
|
if (oper.name() == YSTRING("callJust"))
|
|
|
|
ja->end();
|
2012-03-05 09:53:31 +00:00
|
|
|
}
|
2012-02-17 16:19:17 +00:00
|
|
|
else
|
|
|
|
return JsObject::runNative(stack,oper,context);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2014-02-26 14:57:57 +00:00
|
|
|
void JsChannel::callToRoute(ObjList& stack, const ExpOperation& oper, GenObject* context, const NamedList* params)
|
2012-06-22 09:38:51 +00:00
|
|
|
{
|
|
|
|
ScriptRun* runner = YOBJECT(ScriptRun,context);
|
|
|
|
if (!runner)
|
|
|
|
return;
|
|
|
|
Message* msg = m_assist->getMsg(YOBJECT(ScriptRun,context));
|
|
|
|
if (!msg) {
|
|
|
|
Debug(&__plugin,DebugWarn,"JsChannel::callToRoute(): No message!");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if (oper.null() || JsParser::isNull(oper) || JsParser::isUndefined(oper)) {
|
|
|
|
Debug(&__plugin,DebugWarn,"JsChannel::callToRoute(): Invalid target!");
|
|
|
|
return;
|
|
|
|
}
|
2015-11-24 15:38:35 +00:00
|
|
|
copyObjParams(*msg,params);
|
2012-06-22 09:38:51 +00:00
|
|
|
msg->retValue() = oper;
|
|
|
|
m_assist->handled();
|
|
|
|
runner->pause();
|
|
|
|
}
|
|
|
|
|
2014-02-26 14:57:57 +00:00
|
|
|
void JsChannel::callToReRoute(ObjList& stack, const ExpOperation& oper, GenObject* context, const NamedList* params)
|
2012-06-22 09:38:51 +00:00
|
|
|
{
|
|
|
|
ScriptRun* runner = YOBJECT(ScriptRun,context);
|
|
|
|
if (!runner)
|
|
|
|
return;
|
2014-02-26 14:57:57 +00:00
|
|
|
RefPointer<CallEndpoint> ep;
|
2012-06-22 09:38:51 +00:00
|
|
|
Message* msg = m_assist->getMsg(YOBJECT(ScriptRun,context));
|
2014-02-26 14:57:57 +00:00
|
|
|
Channel* chan = msg ? YOBJECT(Channel,msg->userData()) : 0;
|
|
|
|
if (!chan) {
|
|
|
|
ep = m_assist->locate();
|
|
|
|
chan = YOBJECT(Channel,ep);
|
2012-06-22 09:38:51 +00:00
|
|
|
}
|
|
|
|
if (!chan) {
|
|
|
|
Debug(&__plugin,DebugWarn,"JsChannel::callToReRoute(): No channel!");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
String target = oper;
|
|
|
|
target.trimSpaces();
|
|
|
|
if (target.null() || JsParser::isNull(oper) || JsParser::isUndefined(oper)) {
|
|
|
|
Debug(&__plugin,DebugWarn,"JsChannel::callToRoute(): Invalid target!");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
Message* m = chan->message("call.execute",false,true);
|
|
|
|
m->setParam("callto",target);
|
|
|
|
// copy params except those already set
|
2014-02-26 14:57:57 +00:00
|
|
|
if (msg) {
|
|
|
|
unsigned int n = msg->length();
|
|
|
|
for (unsigned int i = 0; i < n; i++) {
|
|
|
|
const NamedString* p = msg->getParam(i);
|
|
|
|
if (p && !m->getParam(p->name()))
|
|
|
|
m->addParam(p->name(),*p);
|
|
|
|
}
|
|
|
|
}
|
2015-11-24 15:38:35 +00:00
|
|
|
copyObjParams(*m,params);
|
2012-06-22 09:38:51 +00:00
|
|
|
Engine::enqueue(m);
|
|
|
|
m_assist->handled();
|
|
|
|
runner->pause();
|
|
|
|
}
|
|
|
|
|
2012-02-17 16:19:17 +00:00
|
|
|
void JsChannel::initialize(ScriptContext* context, JsAssist* assist)
|
|
|
|
{
|
|
|
|
if (!context)
|
|
|
|
return;
|
2020-10-21 11:01:31 +00:00
|
|
|
ScriptMutex* mtx = context->mutex();
|
2012-02-17 16:19:17 +00:00
|
|
|
Lock mylock(mtx);
|
|
|
|
NamedList& params = context->params();
|
|
|
|
if (!params.getParam(YSTRING("Channel")))
|
|
|
|
addObject(params,"Channel",new JsChannel(assist,mtx));
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2012-06-22 09:38:51 +00:00
|
|
|
#define MKSTATE(x) { #x, JsAssist::x }
|
|
|
|
static const TokenDict s_states[] = {
|
|
|
|
MKSTATE(NotStarted),
|
|
|
|
MKSTATE(Routing),
|
|
|
|
MKSTATE(ReRoute),
|
|
|
|
MKSTATE(Ended),
|
|
|
|
MKSTATE(Hangup),
|
|
|
|
{ 0, 0 }
|
|
|
|
};
|
|
|
|
|
2012-02-17 16:19:17 +00:00
|
|
|
JsAssist::~JsAssist()
|
|
|
|
{
|
2012-06-18 13:52:21 +00:00
|
|
|
if (m_runner) {
|
|
|
|
ScriptContext* context = m_runner->context();
|
|
|
|
if (m_runner->callable("onUnload")) {
|
2013-04-12 12:46:21 +00:00
|
|
|
ScriptRun* runner = m_runner->code()->createRunner(context,NATIVE_TITLE);
|
2012-06-18 13:52:21 +00:00
|
|
|
if (runner) {
|
|
|
|
ObjList args;
|
|
|
|
runner->call("onUnload",args);
|
|
|
|
TelEngine::destruct(runner);
|
|
|
|
}
|
|
|
|
}
|
2012-06-20 14:02:18 +00:00
|
|
|
m_message = 0;
|
2017-01-24 18:53:16 +00:00
|
|
|
if (context) {
|
|
|
|
Lock mylock(context->mutex());
|
2012-06-18 13:52:21 +00:00
|
|
|
context->params().clearParams();
|
2017-01-24 18:53:16 +00:00
|
|
|
}
|
2012-06-18 13:52:21 +00:00
|
|
|
TelEngine::destruct(m_runner);
|
|
|
|
}
|
2012-06-20 14:02:18 +00:00
|
|
|
else
|
|
|
|
m_message = 0;
|
2012-02-17 16:19:17 +00:00
|
|
|
}
|
|
|
|
|
2012-06-22 09:38:51 +00:00
|
|
|
const char* JsAssist::stateName(State st)
|
|
|
|
{
|
|
|
|
return lookup(st,s_states,"???");
|
|
|
|
}
|
|
|
|
|
2012-02-17 16:19:17 +00:00
|
|
|
bool JsAssist::init()
|
|
|
|
{
|
|
|
|
if (!m_runner)
|
|
|
|
return false;
|
2014-08-06 08:08:06 +00:00
|
|
|
contextInit(m_runner,id(),this);
|
2013-02-12 15:47:54 +00:00
|
|
|
if (ScriptRun::Invalid == m_runner->reset(true))
|
2012-06-20 14:02:18 +00:00
|
|
|
return false;
|
2014-08-06 08:08:06 +00:00
|
|
|
ScriptContext* ctx = m_runner->context();
|
2020-10-21 11:01:31 +00:00
|
|
|
ctx->trackObjs(s_trackCreation);
|
2012-06-22 14:06:16 +00:00
|
|
|
ScriptContext* chan = YOBJECT(ScriptContext,ctx->getField(m_runner->stack(),YSTRING("Channel"),m_runner));
|
|
|
|
if (chan) {
|
|
|
|
JsMessage* jsm = YOBJECT(JsMessage,chan->getField(m_runner->stack(),YSTRING("message"),m_runner));
|
|
|
|
if (!jsm) {
|
2020-10-21 11:01:31 +00:00
|
|
|
jsm = new JsMessage(0,ctx->mutex(),0,false);
|
2012-06-22 14:06:16 +00:00
|
|
|
ExpWrapper wrap(jsm,"message");
|
2012-06-26 16:40:38 +00:00
|
|
|
if (!chan->runAssign(m_runner->stack(),wrap,m_runner))
|
|
|
|
return false;
|
2012-06-22 14:06:16 +00:00
|
|
|
}
|
2012-06-26 13:31:30 +00:00
|
|
|
if (jsm && jsm->ref()) {
|
2017-05-08 09:03:05 +00:00
|
|
|
jsm->setPrototype(ctx,YSTRING("Message"));
|
2012-06-26 13:31:30 +00:00
|
|
|
JsObject* cc = JsObject::buildCallContext(ctx->mutex(),jsm);
|
|
|
|
jsm->ref();
|
2012-06-27 12:57:18 +00:00
|
|
|
cc->params().setParam(new ExpWrapper(jsm,"message"));
|
|
|
|
ExpEvaluator::pushOne(m_runner->stack(),new ExpWrapper(cc,cc->toString(),true));
|
2012-06-26 13:31:30 +00:00
|
|
|
}
|
2012-06-22 14:06:16 +00:00
|
|
|
}
|
2012-06-20 14:02:18 +00:00
|
|
|
if (!m_runner->callable("onLoad"))
|
|
|
|
return true;
|
2013-04-12 12:46:21 +00:00
|
|
|
ScriptRun* runner = m_runner->code()->createRunner(m_runner->context(),NATIVE_TITLE);
|
2012-06-20 14:02:18 +00:00
|
|
|
if (runner) {
|
|
|
|
ObjList args;
|
|
|
|
runner->call("onLoad",args);
|
|
|
|
TelEngine::destruct(runner);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2020-10-21 11:01:31 +00:00
|
|
|
bool JsAssist::evalAllocations(String& retVal, unsigned int top)
|
|
|
|
{
|
|
|
|
if (!m_runner) {
|
|
|
|
retVal << "Script " << toString() << " has no associated runner\r\n";
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
return evalCtxtAllocations(retVal,top,m_runner->context(),m_runner->code(),toString());
|
|
|
|
}
|
|
|
|
|
2012-06-22 09:38:51 +00:00
|
|
|
Message* JsAssist::getMsg(ScriptRun* runner) const
|
|
|
|
{
|
|
|
|
if (!runner)
|
|
|
|
runner = m_runner;
|
|
|
|
if (!runner)
|
|
|
|
return 0;
|
|
|
|
ScriptContext* ctx = runner->context();
|
|
|
|
if (!ctx)
|
|
|
|
return 0;
|
|
|
|
ObjList stack;
|
|
|
|
ScriptContext* chan = YOBJECT(ScriptContext,ctx->getField(stack,YSTRING("Channel"),runner));
|
|
|
|
if (!chan)
|
|
|
|
return 0;
|
|
|
|
JsMessage* jsm = YOBJECT(JsMessage,chan->getField(stack,YSTRING("message"),runner));
|
|
|
|
if (!jsm)
|
|
|
|
return 0;
|
|
|
|
return static_cast<Message*>(jsm->nativeParams());
|
|
|
|
}
|
|
|
|
|
2012-06-20 14:02:18 +00:00
|
|
|
bool JsAssist::setMsg(Message* msg)
|
|
|
|
{
|
|
|
|
if (!m_runner)
|
|
|
|
return false;
|
|
|
|
ScriptContext* ctx = m_runner->context();
|
|
|
|
if (!ctx)
|
|
|
|
return false;
|
|
|
|
Lock mylock(ctx->mutex());
|
|
|
|
if (!mylock.locked())
|
|
|
|
return false;
|
|
|
|
if (m_message)
|
|
|
|
return false;
|
|
|
|
ObjList stack;
|
|
|
|
ScriptContext* chan = YOBJECT(ScriptContext,ctx->getField(stack,YSTRING("Channel"),m_runner));
|
|
|
|
if (!chan)
|
|
|
|
return false;
|
|
|
|
JsMessage* jsm = YOBJECT(JsMessage,chan->getField(stack,YSTRING("message"),m_runner));
|
|
|
|
if (jsm)
|
2017-11-01 16:37:48 +00:00
|
|
|
jsm->setMsg(msg);
|
2012-06-22 14:06:16 +00:00
|
|
|
else
|
|
|
|
return false;
|
2012-06-20 14:02:18 +00:00
|
|
|
m_message = jsm;
|
|
|
|
m_handled = false;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2012-07-24 10:31:12 +00:00
|
|
|
void JsAssist::clearMsg(bool fromChannel)
|
2012-06-20 14:02:18 +00:00
|
|
|
{
|
|
|
|
Lock mylock((m_runner && m_runner->context()) ? m_runner->context()->mutex() : 0);
|
|
|
|
if (!m_message)
|
|
|
|
return;
|
|
|
|
m_message->clearMsg();
|
|
|
|
m_message = 0;
|
2012-07-24 10:31:12 +00:00
|
|
|
if (fromChannel && mylock.locked()) {
|
2012-06-20 14:02:18 +00:00
|
|
|
ObjList stack;
|
|
|
|
ScriptContext* chan = YOBJECT(ScriptContext,m_runner->context()->getField(stack,YSTRING("Channel"),m_runner));
|
|
|
|
if (chan) {
|
|
|
|
static const ExpWrapper s_undef(0,"message");
|
|
|
|
chan->runAssign(stack,s_undef,m_runner);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
bool JsAssist::runScript(Message* msg, State newState)
|
|
|
|
{
|
2012-06-22 09:38:51 +00:00
|
|
|
XDebug(&__plugin,DebugInfo,"JsAssist::runScript('%s') for '%s' in state %s",
|
|
|
|
msg->c_str(),id().c_str(),stateName());
|
2012-06-20 14:02:18 +00:00
|
|
|
|
|
|
|
if (m_state >= Ended)
|
|
|
|
return false;
|
2012-06-20 15:54:43 +00:00
|
|
|
if (m_state < newState)
|
|
|
|
m_state = newState;
|
2012-06-20 14:02:18 +00:00
|
|
|
#ifdef DEBUG
|
|
|
|
u_int64_t tm = Time::now();
|
|
|
|
#endif
|
|
|
|
if (!setMsg(msg)) {
|
|
|
|
Debug(&__plugin,DebugWarn,"Failed to set message '%s' in '%s'",
|
|
|
|
msg->c_str(),id().c_str());
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2014-02-26 14:51:15 +00:00
|
|
|
m_repeat = true;
|
|
|
|
do {
|
|
|
|
switch (m_runner->execute()) {
|
|
|
|
case ScriptRun::Incomplete:
|
|
|
|
break;
|
|
|
|
case ScriptRun::Invalid:
|
|
|
|
case ScriptRun::Succeeded:
|
|
|
|
if (m_state < Ended)
|
|
|
|
m_state = Ended;
|
|
|
|
// fall through
|
|
|
|
default:
|
|
|
|
m_repeat = false;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
} while (m_repeat);
|
2012-06-20 14:02:18 +00:00
|
|
|
bool handled = m_handled;
|
2012-07-24 10:31:12 +00:00
|
|
|
clearMsg(m_state >= Ended);
|
2014-02-26 14:57:57 +00:00
|
|
|
if (Routing == m_state)
|
|
|
|
m_state = ReRoute;
|
2012-06-20 14:02:18 +00:00
|
|
|
|
|
|
|
#ifdef DEBUG
|
|
|
|
tm = Time::now() - tm;
|
2012-06-20 15:54:43 +00:00
|
|
|
Debug(&__plugin,DebugInfo,"Script for '%s' ran for " FMT64U " usec",id().c_str(),tm);
|
2012-06-20 14:02:18 +00:00
|
|
|
#endif
|
|
|
|
return handled;
|
2012-02-17 16:19:17 +00:00
|
|
|
}
|
|
|
|
|
2015-11-12 21:29:55 +00:00
|
|
|
bool JsAssist::runFunction(const String& name, Message& msg, bool* handled)
|
2012-02-17 16:19:17 +00:00
|
|
|
{
|
2012-06-16 23:21:13 +00:00
|
|
|
if (!(m_runner && m_runner->callable(name)))
|
|
|
|
return false;
|
2015-11-12 21:29:55 +00:00
|
|
|
DDebug(&__plugin,DebugInfo,"Running function %s(message%s) in '%s' state %s",
|
|
|
|
name.c_str(),(handled ? ",handled" : ""),id().c_str(),stateName());
|
2012-06-20 14:02:18 +00:00
|
|
|
#ifdef DEBUG
|
|
|
|
u_int64_t tm = Time::now();
|
|
|
|
#endif
|
2013-04-12 12:46:21 +00:00
|
|
|
ScriptRun* runner = __plugin.parser().createRunner(m_runner->context(),NATIVE_TITLE);
|
2012-06-16 23:21:13 +00:00
|
|
|
if (!runner)
|
2012-02-17 16:19:17 +00:00
|
|
|
return false;
|
2012-06-16 23:21:13 +00:00
|
|
|
|
2020-10-21 11:01:31 +00:00
|
|
|
JsMessage* jm = new JsMessage(&msg,runner->context()->mutex(),0,false);
|
2017-05-08 09:03:05 +00:00
|
|
|
jm->setPrototype(runner->context(),YSTRING("Message"));
|
2012-06-16 23:21:13 +00:00
|
|
|
jm->ref();
|
|
|
|
ObjList args;
|
|
|
|
args.append(new ExpWrapper(jm,"message"));
|
2015-11-12 21:29:55 +00:00
|
|
|
if (handled) {
|
|
|
|
jm->freeze();
|
|
|
|
args.append(new ExpOperation(*handled,"handled"));
|
|
|
|
}
|
2012-06-16 23:21:13 +00:00
|
|
|
ScriptRun::Status rval = runner->call(name,args);
|
2012-03-05 09:53:31 +00:00
|
|
|
jm->clearMsg();
|
2012-06-20 15:54:43 +00:00
|
|
|
bool ok = false;
|
|
|
|
if (ScriptRun::Succeeded == rval) {
|
|
|
|
ExpOperation* op = ExpEvaluator::popOne(runner->stack());
|
|
|
|
if (op) {
|
|
|
|
ok = op->valBoolean();
|
|
|
|
TelEngine::destruct(op);
|
|
|
|
}
|
|
|
|
}
|
2012-06-16 23:21:13 +00:00
|
|
|
TelEngine::destruct(jm);
|
2012-02-17 16:19:17 +00:00
|
|
|
TelEngine::destruct(runner);
|
2012-06-20 14:02:18 +00:00
|
|
|
|
|
|
|
#ifdef DEBUG
|
|
|
|
tm = Time::now() - tm;
|
2012-06-20 15:54:43 +00:00
|
|
|
Debug(&__plugin,DebugInfo,"Call to %s() ran for " FMT64U " usec",name.c_str(),tm);
|
2012-06-20 14:02:18 +00:00
|
|
|
#endif
|
2012-06-20 15:54:43 +00:00
|
|
|
return ok;
|
2012-02-17 16:19:17 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void JsAssist::msgStartup(Message& msg)
|
|
|
|
{
|
|
|
|
runFunction("onStartup",msg);
|
|
|
|
}
|
|
|
|
|
|
|
|
void JsAssist::msgHangup(Message& msg)
|
|
|
|
{
|
|
|
|
runFunction("onHangup",msg);
|
|
|
|
}
|
|
|
|
|
|
|
|
void JsAssist::msgExecute(Message& msg)
|
|
|
|
{
|
|
|
|
runFunction("onExecute",msg);
|
|
|
|
}
|
|
|
|
|
2012-06-20 15:54:43 +00:00
|
|
|
bool JsAssist::msgRinging(Message& msg)
|
2012-02-20 15:46:19 +00:00
|
|
|
{
|
2012-06-20 15:54:43 +00:00
|
|
|
return runFunction("onRinging",msg);
|
2012-02-20 15:46:19 +00:00
|
|
|
}
|
|
|
|
|
2012-06-20 15:54:43 +00:00
|
|
|
bool JsAssist::msgAnswered(Message& msg)
|
2012-02-20 15:46:19 +00:00
|
|
|
{
|
2012-06-20 15:54:43 +00:00
|
|
|
return runFunction("onAnswered",msg);
|
2012-02-20 15:46:19 +00:00
|
|
|
}
|
|
|
|
|
2012-02-17 16:19:17 +00:00
|
|
|
bool JsAssist::msgPreroute(Message& msg)
|
|
|
|
{
|
2012-06-20 15:54:43 +00:00
|
|
|
return runFunction("onPreroute",msg);
|
2012-02-17 16:19:17 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
bool JsAssist::msgRoute(Message& msg)
|
|
|
|
{
|
2012-06-20 14:02:18 +00:00
|
|
|
return runScript(&msg,Routing);
|
2012-02-17 16:19:17 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
bool JsAssist::msgDisconnect(Message& msg, const String& reason)
|
|
|
|
{
|
2012-06-22 14:42:41 +00:00
|
|
|
return runFunction("onDisconnected",msg) || runScript(&msg,ReRoute);
|
2012-02-17 16:19:17 +00:00
|
|
|
}
|
|
|
|
|
2015-11-12 21:29:55 +00:00
|
|
|
void JsAssist::msgPostExecute(const Message& msg, bool handled)
|
|
|
|
{
|
|
|
|
runFunction("onPostExecute",const_cast<Message&>(msg),&handled);
|
|
|
|
}
|
|
|
|
|
2012-02-17 16:19:17 +00:00
|
|
|
|
2012-06-16 23:21:13 +00:00
|
|
|
ObjList JsGlobal::s_globals;
|
2019-12-19 12:21:42 +00:00
|
|
|
Mutex JsGlobal::s_mutex(false,"JsGlobal");
|
|
|
|
bool JsGlobal::s_keepOldOnFail = false;
|
2012-06-16 23:21:13 +00:00
|
|
|
|
2014-10-16 12:39:59 +00:00
|
|
|
JsGlobal::JsGlobal(const char* scriptName, const char* fileName, bool relPath, bool fromCfg)
|
2012-06-16 23:21:13 +00:00
|
|
|
: NamedString(scriptName,fileName),
|
2015-01-30 13:39:52 +00:00
|
|
|
m_inUse(true), m_confLoaded(fromCfg), m_file(fileName)
|
2012-06-16 23:21:13 +00:00
|
|
|
{
|
2014-03-14 14:45:41 +00:00
|
|
|
m_jsCode.basePath(s_basePath,s_libsPath);
|
2012-11-01 14:58:46 +00:00
|
|
|
if (relPath)
|
|
|
|
m_jsCode.adjustPath(*this);
|
2016-05-18 13:31:47 +00:00
|
|
|
m_jsCode.setMaxFileLen(s_maxFile);
|
2013-02-14 14:37:20 +00:00
|
|
|
m_jsCode.link(s_allowLink);
|
2013-04-12 12:46:21 +00:00
|
|
|
m_jsCode.trace(s_allowTrace);
|
2012-06-16 23:21:13 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
JsGlobal::~JsGlobal()
|
|
|
|
{
|
|
|
|
DDebug(&__plugin,DebugAll,"Unloading global Javascript '%s'",name().c_str());
|
|
|
|
if (m_jsCode.callable("onUnload")) {
|
2013-04-12 12:46:21 +00:00
|
|
|
ScriptRun* runner = m_jsCode.createRunner(m_context,NATIVE_TITLE);
|
2012-06-16 23:21:13 +00:00
|
|
|
if (runner) {
|
|
|
|
ObjList args;
|
|
|
|
runner->call("onUnload",args);
|
|
|
|
TelEngine::destruct(runner);
|
|
|
|
}
|
|
|
|
}
|
2017-01-24 18:53:16 +00:00
|
|
|
if (m_context) {
|
|
|
|
Lock mylock(m_context->mutex());
|
2012-06-18 13:52:21 +00:00
|
|
|
m_context->params().clearParams();
|
2017-01-24 18:53:16 +00:00
|
|
|
}
|
2012-06-16 23:21:13 +00:00
|
|
|
}
|
|
|
|
|
2019-12-19 12:21:42 +00:00
|
|
|
bool JsGlobal::load()
|
|
|
|
{
|
|
|
|
DDebug(&__plugin,DebugAll,"Loading global Javascript '%s' from '%s'",name().c_str(),c_str());
|
|
|
|
if (m_jsCode.parseFile(*this)) {
|
|
|
|
Debug(&__plugin,DebugInfo,"Parsed '%s' script: %s",name().c_str(),c_str());
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
if (*this)
|
|
|
|
Debug(&__plugin,DebugWarn,"Failed to parse '%s' script: %s",name().c_str(),c_str());
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2012-06-16 23:21:13 +00:00
|
|
|
bool JsGlobal::fileChanged(const char* fileName) const
|
|
|
|
{
|
2014-03-14 14:45:41 +00:00
|
|
|
return m_jsCode.scriptChanged(fileName,s_basePath,s_libsPath);
|
2012-06-16 23:21:13 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void JsGlobal::markUnused()
|
|
|
|
{
|
2019-12-19 12:21:42 +00:00
|
|
|
for (ObjList* o = s_globals.skipNull(); o; o = o->skipNext()) {
|
|
|
|
JsGlobal* script = static_cast<JsGlobal*>(o->get());
|
2014-10-16 12:39:59 +00:00
|
|
|
script->m_inUse = !script->m_confLoaded;
|
2019-12-19 12:21:42 +00:00
|
|
|
}
|
2012-06-16 23:21:13 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void JsGlobal::freeUnused()
|
|
|
|
{
|
2019-12-19 12:21:42 +00:00
|
|
|
Lock mylock(JsGlobal::s_mutex);
|
2012-06-16 23:21:13 +00:00
|
|
|
ListIterator iter(s_globals);
|
|
|
|
while (JsGlobal* script = static_cast<JsGlobal*>(iter.get()))
|
2012-11-01 14:58:46 +00:00
|
|
|
if (!script->m_inUse) {
|
|
|
|
s_globals.remove(script,false);
|
|
|
|
mylock.drop();
|
|
|
|
TelEngine::destruct(script);
|
2019-12-19 12:21:42 +00:00
|
|
|
mylock.acquire(JsGlobal::s_mutex);
|
2012-11-01 14:58:46 +00:00
|
|
|
}
|
2012-06-16 23:21:13 +00:00
|
|
|
}
|
|
|
|
|
2014-10-16 12:39:59 +00:00
|
|
|
void JsGlobal::reloadDynamic()
|
|
|
|
{
|
2019-12-19 12:21:42 +00:00
|
|
|
Lock mylock(JsGlobal::s_mutex);
|
2014-10-16 12:39:59 +00:00
|
|
|
ListIterator iter(s_globals);
|
|
|
|
while (JsGlobal* script = static_cast<JsGlobal*>(iter.get()))
|
|
|
|
if (!script->m_confLoaded) {
|
2015-01-30 13:39:52 +00:00
|
|
|
String filename = script->fileName();
|
2014-10-16 12:39:59 +00:00
|
|
|
String name = script->name();
|
|
|
|
mylock.drop();
|
2015-01-30 13:39:52 +00:00
|
|
|
JsGlobal::initScript(name,filename,true,false);
|
2019-12-19 12:21:42 +00:00
|
|
|
mylock.acquire(JsGlobal::s_mutex);
|
2014-10-16 12:39:59 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-12-09 11:33:04 +00:00
|
|
|
bool JsGlobal::initScript(const String& scriptName, const String& fileName, bool relPath, bool fromCfg)
|
2012-06-16 23:21:13 +00:00
|
|
|
{
|
|
|
|
if (fileName.null())
|
2014-10-16 12:39:59 +00:00
|
|
|
return false;
|
2015-01-30 13:39:52 +00:00
|
|
|
DDebug(&__plugin,DebugInfo,"Initialize %s script '%s' from %s file '%s'",(fromCfg ? "configured" : "dynamically loaded"),
|
|
|
|
scriptName.c_str(),(relPath ? "relative" : "absolute"),fileName.c_str());
|
2019-12-19 12:21:42 +00:00
|
|
|
Lock mylock(JsGlobal::s_mutex);
|
|
|
|
ObjList* o = s_globals.find(scriptName);
|
|
|
|
if (o) {
|
|
|
|
JsGlobal* script = static_cast<JsGlobal*>(o->get());
|
2014-10-16 12:39:59 +00:00
|
|
|
if (script->m_confLoaded != fromCfg) {
|
|
|
|
Debug(&__plugin,DebugWarn,"Trying to load script '%s' %s, but it was already loaded %s",
|
|
|
|
scriptName.c_str(),fromCfg ? "from configuration file" : "dynamically",
|
|
|
|
fromCfg ? "dynamically" : "from configuration file");
|
|
|
|
return false;
|
|
|
|
}
|
2019-12-19 12:21:42 +00:00
|
|
|
if (!script->fileChanged(fileName)) {
|
2012-06-16 23:21:13 +00:00
|
|
|
script->m_inUse = true;
|
2014-10-16 12:39:59 +00:00
|
|
|
script->m_confLoaded = fromCfg;
|
|
|
|
return true;
|
2012-06-16 23:21:13 +00:00
|
|
|
}
|
|
|
|
}
|
2019-12-19 12:21:42 +00:00
|
|
|
return buildNewScript(mylock,o,scriptName,fileName,relPath,fromCfg,true);
|
2012-11-01 14:58:46 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
bool JsGlobal::reloadScript(const String& scriptName)
|
|
|
|
{
|
|
|
|
if (scriptName.null())
|
|
|
|
return false;
|
2019-12-19 12:21:42 +00:00
|
|
|
Lock mylock(JsGlobal::s_mutex);
|
|
|
|
ObjList* o = s_globals.find(scriptName);
|
|
|
|
if (!o)
|
2012-11-01 14:58:46 +00:00
|
|
|
return false;
|
2019-12-19 12:21:42 +00:00
|
|
|
JsGlobal* script = static_cast<JsGlobal*>(o->get());
|
2012-11-01 14:58:46 +00:00
|
|
|
String fileName = *script;
|
2019-12-19 12:21:42 +00:00
|
|
|
return fileName && buildNewScript(mylock,o,scriptName,fileName,false,script->m_confLoaded);
|
2012-06-16 23:21:13 +00:00
|
|
|
}
|
|
|
|
|
2016-01-04 12:49:52 +00:00
|
|
|
void JsGlobal::loadScripts(const NamedList* sect)
|
|
|
|
{
|
|
|
|
if (!sect)
|
|
|
|
return;
|
|
|
|
unsigned int len = sect->length();
|
|
|
|
for (unsigned int i=0; i<len; i++) {
|
|
|
|
const NamedString *n = sect->getParam(i);
|
|
|
|
if (!n)
|
|
|
|
continue;
|
|
|
|
String tmp = *n;
|
|
|
|
Engine::runParams().replaceParams(tmp);
|
|
|
|
JsGlobal::initScript(n->name(),tmp);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-06-16 23:21:13 +00:00
|
|
|
bool JsGlobal::runMain()
|
|
|
|
{
|
|
|
|
ScriptRun* runner = m_jsCode.createRunner(m_context);
|
|
|
|
if (!runner)
|
|
|
|
return false;
|
|
|
|
if (!m_context)
|
|
|
|
m_context = runner->context();
|
2020-10-21 11:01:31 +00:00
|
|
|
m_context->trackObjs(s_trackCreation);
|
2014-08-06 08:08:06 +00:00
|
|
|
contextInit(runner,name());
|
2012-06-16 23:21:13 +00:00
|
|
|
ScriptRun::Status st = runner->run();
|
|
|
|
TelEngine::destruct(runner);
|
|
|
|
return (ScriptRun::Succeeded == st);
|
|
|
|
}
|
|
|
|
|
2019-12-19 12:21:42 +00:00
|
|
|
bool JsGlobal::buildNewScript(Lock& lck, ObjList* old, const String& scriptName,
|
|
|
|
const String& fileName, bool relPath, bool fromCfg, bool fromInit)
|
|
|
|
{
|
2020-10-14 13:24:46 +00:00
|
|
|
bool objCount = s_trackObj && getObjCounting();
|
|
|
|
NamedCounter* saved = 0;
|
|
|
|
if (objCount)
|
|
|
|
saved = Thread::setCurrentObjCounter(getObjCounter("js:" + scriptName,true));
|
2019-12-19 12:21:42 +00:00
|
|
|
JsGlobal* oldScript = old ? static_cast<JsGlobal*>(old->get()) : 0;
|
|
|
|
JsGlobal* script = new JsGlobal(scriptName,fileName,relPath,fromCfg);
|
2020-10-14 13:24:46 +00:00
|
|
|
bool ok = false;
|
2019-12-19 12:21:42 +00:00
|
|
|
if (script->load() || !s_keepOldOnFail || !old) {
|
|
|
|
if (old)
|
|
|
|
old->set(script,false);
|
|
|
|
else
|
|
|
|
s_globals.append(script);
|
|
|
|
lck.drop();
|
|
|
|
TelEngine::destruct(oldScript);
|
2020-10-14 13:24:46 +00:00
|
|
|
ok = script->runMain();
|
2019-12-19 12:21:42 +00:00
|
|
|
}
|
2020-10-14 13:24:46 +00:00
|
|
|
else {
|
|
|
|
// Make sure we don't remove the old one if unused
|
|
|
|
if (oldScript && fromInit) {
|
|
|
|
oldScript->m_inUse = true;
|
|
|
|
oldScript->m_confLoaded = fromCfg;
|
|
|
|
}
|
|
|
|
lck.drop();
|
|
|
|
TelEngine::destruct(script);
|
2019-12-19 12:21:42 +00:00
|
|
|
}
|
2020-10-14 13:24:46 +00:00
|
|
|
if (objCount)
|
|
|
|
Thread::setCurrentObjCounter(saved);
|
|
|
|
return ok;
|
2019-12-19 12:21:42 +00:00
|
|
|
}
|
|
|
|
|
2012-06-16 23:21:13 +00:00
|
|
|
|
2012-07-02 11:55:34 +00:00
|
|
|
static const char* s_cmds[] = {
|
|
|
|
"info",
|
|
|
|
"eval",
|
2012-11-01 14:58:46 +00:00
|
|
|
"reload",
|
2014-10-16 12:39:59 +00:00
|
|
|
"load",
|
2020-10-21 11:01:31 +00:00
|
|
|
"allocations",
|
2012-07-02 11:55:34 +00:00
|
|
|
0
|
|
|
|
};
|
|
|
|
|
2020-10-21 11:01:31 +00:00
|
|
|
static const char* s_cmdsLine = " javascript {info|eval[=context] instructions...|reload script|load [script=]file|"
|
|
|
|
"allocations script top_no}";
|
2012-07-02 11:55:34 +00:00
|
|
|
|
|
|
|
|
2012-02-17 16:19:17 +00:00
|
|
|
JsModule::JsModule()
|
2015-11-12 21:29:55 +00:00
|
|
|
: ChanAssistList("javascript",true),
|
2016-01-04 12:49:52 +00:00
|
|
|
m_postHook(0), m_started(Engine::started())
|
2012-02-10 14:53:55 +00:00
|
|
|
{
|
|
|
|
Output("Loaded module Javascript");
|
|
|
|
}
|
|
|
|
|
2012-02-17 16:19:17 +00:00
|
|
|
JsModule::~JsModule()
|
2012-02-10 14:53:55 +00:00
|
|
|
{
|
|
|
|
Output("Unloading module Javascript");
|
2015-11-12 21:29:55 +00:00
|
|
|
clearPostHook();
|
|
|
|
}
|
|
|
|
|
|
|
|
void JsModule::clearPostHook()
|
|
|
|
{
|
|
|
|
if (m_postHook) {
|
|
|
|
Engine::self()->setHook(m_postHook,true);
|
|
|
|
TelEngine::destruct(m_postHook);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void JsModule::msgPostExecute(const Message& msg, bool handled)
|
|
|
|
{
|
|
|
|
const String& id = msg[YSTRING("id")];
|
|
|
|
if (id.null())
|
|
|
|
return;
|
|
|
|
lock();
|
|
|
|
RefPointer <JsAssist> ja = static_cast<JsAssist*>(find(id));
|
|
|
|
unlock();
|
|
|
|
if (ja)
|
|
|
|
ja->msgPostExecute(msg,handled);
|
2012-02-10 14:53:55 +00:00
|
|
|
}
|
|
|
|
|
2012-07-02 11:55:34 +00:00
|
|
|
void JsModule::statusParams(String& str)
|
|
|
|
{
|
2019-12-19 12:21:42 +00:00
|
|
|
Lock lck(JsGlobal::s_mutex);
|
|
|
|
str << "globals=" << JsGlobal::globals().count();
|
|
|
|
lck.acquire(this);
|
|
|
|
str << ",routing=" << calls().count();
|
2012-07-02 11:55:34 +00:00
|
|
|
}
|
|
|
|
|
2012-02-17 16:19:17 +00:00
|
|
|
bool JsModule::commandExecute(String& retVal, const String& line)
|
2012-02-10 14:53:55 +00:00
|
|
|
{
|
2012-07-02 11:55:34 +00:00
|
|
|
String cmd = line;
|
|
|
|
if (!cmd.startSkip(name()))
|
2012-02-10 14:53:55 +00:00
|
|
|
return false;
|
2012-07-02 11:55:34 +00:00
|
|
|
cmd.trimSpaces();
|
|
|
|
|
|
|
|
if (cmd.null() || cmd == YSTRING("info")) {
|
|
|
|
retVal.clear();
|
2019-12-19 12:21:42 +00:00
|
|
|
Lock lck(JsGlobal::s_mutex);
|
|
|
|
for (ObjList* o = JsGlobal::globals().skipNull(); o ; o = o->skipNext()) {
|
|
|
|
JsGlobal* script = static_cast<JsGlobal*>(o->get());
|
2012-07-02 11:55:34 +00:00
|
|
|
retVal << script->name() << " = " << *script << "\r\n";
|
2019-12-19 12:21:42 +00:00
|
|
|
}
|
|
|
|
lck.acquire(this);
|
|
|
|
for (unsigned int i = 0; i < calls().length(); i++) {
|
|
|
|
ObjList* o = calls().getList(i);
|
|
|
|
for (o ? o = o->skipNull() : 0; o; o = o->skipNext()) {
|
|
|
|
JsAssist* assist = static_cast<JsAssist*>(o->get());
|
|
|
|
retVal << assist->id() << ": " << assist->stateName() << "\r\n";
|
|
|
|
}
|
|
|
|
}
|
2012-07-02 11:55:34 +00:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2012-11-01 14:58:46 +00:00
|
|
|
if (cmd.startSkip("reload") && cmd.trimSpaces())
|
|
|
|
return JsGlobal::reloadScript(cmd);
|
|
|
|
|
2013-04-12 12:41:47 +00:00
|
|
|
if (cmd.startSkip("eval=",false) && cmd.trimSpaces()) {
|
|
|
|
String scr;
|
|
|
|
cmd.extractTo(" ",scr).trimSpaces();
|
|
|
|
if (scr.null() || cmd.null())
|
|
|
|
return false;
|
2019-12-19 12:21:42 +00:00
|
|
|
Lock mylock(JsGlobal::s_mutex);;
|
2013-04-12 12:41:47 +00:00
|
|
|
JsGlobal* script = static_cast<JsGlobal*>(JsGlobal::globals()[scr]);
|
|
|
|
if (script) {
|
|
|
|
RefPointer<ScriptContext> ctxt = script->context();
|
|
|
|
mylock.drop();
|
|
|
|
return evalContext(retVal,cmd,ctxt);
|
|
|
|
}
|
2019-12-19 12:21:42 +00:00
|
|
|
mylock.acquire(this);
|
2013-04-12 12:41:47 +00:00
|
|
|
JsAssist* assist = static_cast<JsAssist*>(calls()[scr]);
|
|
|
|
if (assist) {
|
|
|
|
RefPointer<ScriptContext> ctxt = assist->context();
|
|
|
|
mylock.drop();
|
|
|
|
return evalContext(retVal,cmd,ctxt);
|
|
|
|
}
|
|
|
|
retVal << "Cannot find script context: " << scr << "\n\r";
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (cmd.startSkip("eval") && cmd.trimSpaces())
|
|
|
|
return evalContext(retVal,cmd);
|
|
|
|
|
2020-10-21 11:01:31 +00:00
|
|
|
if (cmd.startSkip("allocations") && cmd.trimSpaces()) {
|
|
|
|
String scr;
|
|
|
|
cmd.extractTo(" ",scr).trimSpaces();
|
|
|
|
unsigned int top = cmd.toInteger(25,0,1,100);
|
|
|
|
if (scr.null())
|
|
|
|
return false;
|
|
|
|
Lock mylock(JsGlobal::s_mutex);;
|
|
|
|
JsGlobal* script = static_cast<JsGlobal*>(JsGlobal::globals()[scr]);
|
|
|
|
if (script)
|
|
|
|
return evalCtxtAllocations(retVal,top,script->context(),script->parser().code(),scr);
|
|
|
|
mylock.acquire(this);
|
|
|
|
RefPointer<JsAssist> assist = static_cast<JsAssist*>(calls()[scr]);
|
|
|
|
if (assist) {
|
|
|
|
mylock.drop();
|
|
|
|
return assist->evalAllocations(retVal,top);
|
|
|
|
}
|
|
|
|
retVal << "Cannot find script context: " << scr << "\n\r";
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2014-10-16 12:39:59 +00:00
|
|
|
if (cmd.startSkip("load") && cmd.trimSpaces()) {
|
|
|
|
if (!cmd) {
|
|
|
|
retVal << "Missing mandatory argument specifying which file to load\n\r";
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
String name;
|
|
|
|
int pos = cmd.find('=');
|
|
|
|
if (pos > -1) {
|
|
|
|
name = cmd.substr(0,pos);
|
|
|
|
cmd = cmd.c_str() + pos + 1;
|
|
|
|
}
|
|
|
|
if (!cmd) {
|
|
|
|
retVal << "Missing file name argument\n\r";
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
if (cmd.endsWith("/")
|
|
|
|
#ifdef _WINDOWS
|
|
|
|
|| cmd.endsWith("\\")
|
|
|
|
#endif
|
|
|
|
) {
|
|
|
|
retVal << "Missing file name. Cannot load directory '" << cmd <<"'\n\r";
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
int extPos = cmd.rfind('.');
|
|
|
|
int sepPos = cmd.rfind('/');
|
|
|
|
#ifdef _WINDOWS
|
|
|
|
int backPos = cmd.rfind('\\');
|
|
|
|
sepPos = sepPos > backPos ? sepPos : backPos;
|
|
|
|
#endif
|
|
|
|
if (extPos < 0 || sepPos > extPos) { // for "dir.name/filename" cases
|
|
|
|
extPos = cmd.length();
|
|
|
|
cmd += ".js";
|
|
|
|
}
|
|
|
|
if (!name)
|
|
|
|
name = cmd.substr(sepPos + 1,extPos - sepPos - 1);
|
2014-12-09 11:33:04 +00:00
|
|
|
if (!JsGlobal::initScript(name,cmd,true,false))
|
2014-10-16 12:39:59 +00:00
|
|
|
retVal << "Failed to load script from file '" << cmd << "'\n\r";
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2013-04-12 12:41:47 +00:00
|
|
|
return false;
|
|
|
|
}
|
2012-02-17 16:19:17 +00:00
|
|
|
|
2013-04-12 12:41:47 +00:00
|
|
|
bool JsModule::evalContext(String& retVal, const String& cmd, ScriptContext* context)
|
|
|
|
{
|
2012-02-17 16:19:17 +00:00
|
|
|
JsParser parser;
|
2014-03-14 14:45:41 +00:00
|
|
|
parser.basePath(s_basePath,s_libsPath);
|
2016-05-18 13:31:47 +00:00
|
|
|
parser.setMaxFileLen(s_maxFile);
|
2013-02-14 14:37:20 +00:00
|
|
|
parser.link(s_allowLink);
|
2013-04-12 12:46:21 +00:00
|
|
|
parser.trace(s_allowTrace);
|
2012-02-17 16:19:17 +00:00
|
|
|
if (!parser.parse(cmd)) {
|
|
|
|
retVal << "parsing failed\r\n";
|
|
|
|
return true;
|
|
|
|
}
|
2013-04-12 12:46:21 +00:00
|
|
|
ScriptRun* runner = parser.createRunner(context,"[command line]");
|
2014-08-06 08:08:06 +00:00
|
|
|
if (!context)
|
|
|
|
contextInit(runner);
|
2012-02-17 16:19:17 +00:00
|
|
|
ScriptRun::Status st = runner->run();
|
|
|
|
if (st == ScriptRun::Succeeded) {
|
|
|
|
while (ExpOperation* op = ExpEvaluator::popOne(runner->stack())) {
|
|
|
|
retVal << "'" << op->name() << "'='" << *op << "'\r\n";
|
|
|
|
TelEngine::destruct(op);
|
|
|
|
}
|
|
|
|
}
|
2012-02-10 14:53:55 +00:00
|
|
|
else
|
|
|
|
retVal << ScriptRun::textState(st) << "\r\n";
|
2012-02-17 16:19:17 +00:00
|
|
|
TelEngine::destruct(runner);
|
2012-02-10 14:53:55 +00:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2012-02-17 16:19:17 +00:00
|
|
|
bool JsModule::commandComplete(Message& msg, const String& partLine, const String& partWord)
|
2012-02-10 14:53:55 +00:00
|
|
|
{
|
|
|
|
if (partLine.null() && partWord.null())
|
|
|
|
return false;
|
|
|
|
if (partLine.null() || (partLine == "help"))
|
2012-07-02 11:55:34 +00:00
|
|
|
itemComplete(msg.retValue(),name(),partWord);
|
|
|
|
else if (partLine == name()) {
|
2013-04-12 12:41:47 +00:00
|
|
|
static const String s_eval("eval=");
|
|
|
|
if (partWord.startsWith(s_eval)) {
|
2019-12-19 12:21:42 +00:00
|
|
|
Lock lck(JsGlobal::s_mutex);
|
|
|
|
for (ObjList* o = JsGlobal::globals().skipNull(); o ; o = o->skipNext()) {
|
|
|
|
JsGlobal* script = static_cast<JsGlobal*>(o->get());
|
|
|
|
if (script->name())
|
2013-04-12 12:41:47 +00:00
|
|
|
itemComplete(msg.retValue(),s_eval + script->name(),partWord);
|
2019-12-19 12:21:42 +00:00
|
|
|
}
|
|
|
|
lck.acquire(this);
|
|
|
|
for (unsigned int i = 0; i < calls().length(); i++) {
|
|
|
|
ObjList* o = calls().getList(i);
|
|
|
|
for (o ? o = o->skipNull() : 0; o; o = o->skipNext()) {
|
|
|
|
JsAssist* assist = static_cast<JsAssist*>(o->get());
|
|
|
|
itemComplete(msg.retValue(),s_eval + assist->id(),partWord);
|
|
|
|
}
|
|
|
|
}
|
2013-04-12 12:41:47 +00:00
|
|
|
return true;
|
|
|
|
}
|
2012-07-02 11:55:34 +00:00
|
|
|
for (const char** list = s_cmds; *list; list++)
|
|
|
|
itemComplete(msg.retValue(),*list,partWord);
|
|
|
|
return true;
|
|
|
|
}
|
2020-10-21 11:01:31 +00:00
|
|
|
else if (partLine == YSTRING("javascript reload") || partLine == YSTRING("javascript allocations")) {
|
2019-12-19 12:21:42 +00:00
|
|
|
Lock lck(JsGlobal::s_mutex);
|
|
|
|
for (ObjList* o = JsGlobal::globals().skipNull(); o ; o = o->skipNext()) {
|
|
|
|
JsGlobal* script = static_cast<JsGlobal*>(o->get());
|
|
|
|
if (script->name())
|
2012-11-01 14:58:46 +00:00
|
|
|
itemComplete(msg.retValue(),script->name(),partWord);
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
2012-02-10 14:53:55 +00:00
|
|
|
return Module::commandComplete(msg,partLine,partWord);
|
|
|
|
}
|
|
|
|
|
2012-02-17 16:19:17 +00:00
|
|
|
bool JsModule::received(Message& msg, int id)
|
|
|
|
{
|
2012-02-20 15:46:19 +00:00
|
|
|
switch (id) {
|
2012-07-02 11:55:34 +00:00
|
|
|
case Help:
|
|
|
|
{
|
|
|
|
const String* line = msg.getParam("line");
|
|
|
|
if (TelEngine::null(line)) {
|
|
|
|
msg.retValue() << s_cmdsLine << "\r\n";
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
if (name() != *line)
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
msg.retValue() << s_cmdsLine << "\r\n";
|
|
|
|
msg.retValue() << "Controls and executes Javascript commands\r\n";
|
|
|
|
return true;
|
2012-02-20 15:46:19 +00:00
|
|
|
case Preroute:
|
|
|
|
case Route:
|
|
|
|
{
|
|
|
|
const String* chanId = msg.getParam("id");
|
|
|
|
if (TelEngine::null(chanId))
|
|
|
|
break;
|
|
|
|
Lock mylock(this);
|
|
|
|
RefPointer <JsAssist> ca = static_cast<JsAssist*>(find(*chanId));
|
|
|
|
switch (id) {
|
|
|
|
case Preroute:
|
|
|
|
if (ca) {
|
|
|
|
mylock.drop();
|
|
|
|
return ca->msgPreroute(msg);
|
|
|
|
}
|
|
|
|
ca = static_cast<JsAssist*>(create(msg,*chanId));
|
|
|
|
if (ca) {
|
|
|
|
calls().append(ca);
|
|
|
|
mylock.drop();
|
|
|
|
ca->msgStartup(msg);
|
|
|
|
return ca->msgPreroute(msg);
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
case Route:
|
|
|
|
if (ca) {
|
|
|
|
mylock.drop();
|
|
|
|
return ca->msgRoute(msg);
|
|
|
|
}
|
|
|
|
ca = static_cast<JsAssist*>(create(msg,*chanId));
|
|
|
|
if (ca) {
|
|
|
|
calls().append(ca);
|
|
|
|
mylock.drop();
|
|
|
|
ca->msgStartup(msg);
|
|
|
|
return ca->msgRoute(msg);
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
} // switch (id)
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case Ringing:
|
|
|
|
case Answered:
|
|
|
|
{
|
|
|
|
const String* chanId = msg.getParam("peerid");
|
|
|
|
if (TelEngine::null(chanId))
|
|
|
|
return false;
|
|
|
|
Lock mylock(this);
|
|
|
|
RefPointer <JsAssist> ca = static_cast<JsAssist*>(find(*chanId));
|
|
|
|
if (!ca)
|
|
|
|
return false;
|
|
|
|
switch (id) {
|
|
|
|
case Ringing:
|
2012-06-20 15:54:43 +00:00
|
|
|
return ca && ca->msgRinging(msg);
|
2012-02-20 15:46:19 +00:00
|
|
|
case Answered:
|
2012-06-20 15:54:43 +00:00
|
|
|
return ca && ca->msgAnswered(msg);
|
2012-02-17 16:19:17 +00:00
|
|
|
}
|
2012-02-20 15:46:19 +00:00
|
|
|
}
|
|
|
|
break;
|
2012-06-16 23:21:13 +00:00
|
|
|
case Halt:
|
2013-04-12 12:46:21 +00:00
|
|
|
s_engineStop = true;
|
2015-11-12 21:29:55 +00:00
|
|
|
clearPostHook();
|
2013-04-12 12:53:10 +00:00
|
|
|
JsGlobal::unloadAll();
|
2012-06-16 23:21:13 +00:00
|
|
|
return false;
|
2016-01-04 12:49:52 +00:00
|
|
|
case EngStart:
|
|
|
|
if (!m_started) {
|
|
|
|
m_started = true;
|
|
|
|
Configuration cfg(Engine::configFile("javascript"));
|
|
|
|
JsGlobal::loadScripts(cfg.getSection("late_scripts"));
|
|
|
|
}
|
|
|
|
return false;
|
2012-02-20 15:46:19 +00:00
|
|
|
} // switch (id)
|
2012-02-17 16:19:17 +00:00
|
|
|
return ChanAssistList::received(msg,id);
|
|
|
|
}
|
|
|
|
|
|
|
|
bool JsModule::received(Message& msg, int id, ChanAssist* assist)
|
|
|
|
{
|
|
|
|
return ChanAssistList::received(msg,id,assist);
|
|
|
|
}
|
|
|
|
|
|
|
|
ChanAssist* JsModule::create(Message& msg, const String& id)
|
|
|
|
{
|
2015-11-12 21:15:26 +00:00
|
|
|
if ((msg == YSTRING("chan.startup")) && (msg[YSTRING("direction")] == YSTRING("outgoing")))
|
|
|
|
return 0;
|
2019-12-19 12:21:42 +00:00
|
|
|
Lock lck(JsGlobal::s_mutex);
|
2013-04-12 12:46:21 +00:00
|
|
|
ScriptRun* runner = m_assistCode.createRunner(0,NATIVE_TITLE);
|
2019-12-19 12:21:42 +00:00
|
|
|
lck.drop();
|
2012-02-17 16:19:17 +00:00
|
|
|
if (!runner)
|
|
|
|
return 0;
|
2012-02-20 15:46:19 +00:00
|
|
|
DDebug(this,DebugInfo,"Creating Javascript for '%s'",id.c_str());
|
2012-02-17 16:19:17 +00:00
|
|
|
JsAssist* ca = new JsAssist(this,id,runner);
|
|
|
|
if (ca->init())
|
|
|
|
return ca;
|
|
|
|
TelEngine::destruct(ca);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool JsModule::unload()
|
2012-02-10 14:53:55 +00:00
|
|
|
{
|
2015-11-12 21:29:55 +00:00
|
|
|
clearPostHook();
|
2012-02-10 14:53:55 +00:00
|
|
|
uninstallRelays();
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2012-02-17 16:19:17 +00:00
|
|
|
void JsModule::initialize()
|
2012-02-10 14:53:55 +00:00
|
|
|
{
|
|
|
|
Output("Initializing module Javascript");
|
2012-02-17 16:19:17 +00:00
|
|
|
ChanAssistList::initialize();
|
2012-02-10 14:53:55 +00:00
|
|
|
setup();
|
2012-07-02 11:55:34 +00:00
|
|
|
installRelay(Help);
|
2015-11-12 21:29:55 +00:00
|
|
|
if (!m_postHook)
|
|
|
|
Engine::self()->setHook(m_postHook = new JsPostExecute);
|
2012-02-17 16:19:17 +00:00
|
|
|
Configuration cfg(Engine::configFile("javascript"));
|
|
|
|
String tmp = Engine::sharedPath();
|
|
|
|
tmp << Engine::pathSeparator() << "scripts";
|
|
|
|
tmp = cfg.getValue("general","scripts_dir",tmp);
|
2014-03-14 14:45:41 +00:00
|
|
|
Engine::runParams().replaceParams(tmp);
|
|
|
|
if (tmp && !tmp.endsWith(Engine::pathSeparator()))
|
2012-02-17 16:19:17 +00:00
|
|
|
tmp += Engine::pathSeparator();
|
|
|
|
s_basePath = tmp;
|
2014-03-14 14:45:41 +00:00
|
|
|
tmp = cfg.getValue("general","include_dir","${configpath}");
|
|
|
|
Engine::runParams().replaceParams(tmp);
|
|
|
|
if (tmp && !tmp.endsWith(Engine::pathSeparator()))
|
|
|
|
tmp += Engine::pathSeparator();
|
|
|
|
s_libsPath = tmp;
|
2016-05-18 13:31:47 +00:00
|
|
|
s_maxFile = cfg.getIntValue("general","max_length",500000,32768,2097152);
|
2014-08-06 08:08:06 +00:00
|
|
|
s_autoExt = cfg.getBoolValue("general","auto_extensions",true);
|
2012-11-20 16:08:25 +00:00
|
|
|
s_allowAbort = cfg.getBoolValue("general","allow_abort");
|
2020-10-14 13:24:46 +00:00
|
|
|
s_trackObj = cfg.getBoolValue("general","track_objects");
|
2020-10-21 11:01:31 +00:00
|
|
|
s_trackCreation = cfg.getIntValue("general","track_obj_life",s_trackCreation,0);
|
2019-12-19 12:21:42 +00:00
|
|
|
JsGlobal::s_keepOldOnFail = cfg.getBoolValue("general","keep_old_on_fail");
|
2013-08-28 13:19:42 +00:00
|
|
|
bool changed = false;
|
|
|
|
if (cfg.getBoolValue("general","allow_trace") != s_allowTrace) {
|
|
|
|
s_allowTrace = !s_allowTrace;
|
|
|
|
changed = true;
|
|
|
|
}
|
|
|
|
if (cfg.getBoolValue("general","allow_link",true) != s_allowLink) {
|
|
|
|
s_allowLink = !s_allowLink;
|
|
|
|
changed = true;
|
|
|
|
}
|
2012-06-16 23:21:13 +00:00
|
|
|
tmp = cfg.getValue("general","routing");
|
2014-03-14 14:45:41 +00:00
|
|
|
Engine::runParams().replaceParams(tmp);
|
2019-12-19 12:21:42 +00:00
|
|
|
Lock lck(JsGlobal::s_mutex);
|
2014-03-14 14:45:41 +00:00
|
|
|
if (changed || m_assistCode.scriptChanged(tmp,s_basePath,s_libsPath)) {
|
2013-08-28 13:19:42 +00:00
|
|
|
m_assistCode.clear();
|
2016-05-18 13:31:47 +00:00
|
|
|
m_assistCode.setMaxFileLen(s_maxFile);
|
2013-08-28 13:19:42 +00:00
|
|
|
m_assistCode.link(s_allowLink);
|
|
|
|
m_assistCode.trace(s_allowTrace);
|
2014-03-14 14:45:41 +00:00
|
|
|
m_assistCode.basePath(s_basePath,s_libsPath);
|
2013-08-28 13:19:42 +00:00
|
|
|
m_assistCode.adjustPath(tmp);
|
|
|
|
if (m_assistCode.parseFile(tmp))
|
|
|
|
Debug(this,DebugInfo,"Parsed routing script: %s",tmp.c_str());
|
|
|
|
else if (tmp)
|
|
|
|
Debug(this,DebugWarn,"Failed to parse script: %s",tmp.c_str());
|
|
|
|
}
|
2012-06-16 23:21:13 +00:00
|
|
|
JsGlobal::markUnused();
|
2019-12-19 12:21:42 +00:00
|
|
|
lck.drop();
|
2016-01-04 12:49:52 +00:00
|
|
|
JsGlobal::loadScripts(cfg.getSection("scripts"));
|
|
|
|
if (m_started)
|
|
|
|
JsGlobal::loadScripts(cfg.getSection("late_scripts"));
|
2014-10-16 12:39:59 +00:00
|
|
|
JsGlobal::reloadDynamic();
|
2012-06-16 23:21:13 +00:00
|
|
|
JsGlobal::freeUnused();
|
2012-02-17 16:19:17 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void JsModule::init(int priority)
|
|
|
|
{
|
|
|
|
ChanAssistList::init(priority);
|
2017-04-27 10:31:07 +00:00
|
|
|
installRelay(Halt,120);
|
2012-02-17 16:19:17 +00:00
|
|
|
installRelay(Route,priority);
|
2012-02-20 15:46:19 +00:00
|
|
|
installRelay(Ringing,priority);
|
|
|
|
installRelay(Answered,priority);
|
2012-06-12 23:47:01 +00:00
|
|
|
Engine::install(new MessageRelay("call.preroute",this,Preroute,priority,name()));
|
2016-01-04 12:49:52 +00:00
|
|
|
Engine::install(new MessageRelay("engine.start",this,EngStart,150,name()));
|
2012-02-10 14:53:55 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
}; // anonymous namespace
|
|
|
|
|
|
|
|
/* vi: set ts=8 sw=4 sts=4 noet: */
|