mirror of
https://github.com/polserver/polserver
synced 2026-08-13 08:23:08 -04:00
* Fix SCRIPTOPT_CAN_ACCESS_OFFLINE_MOBILES * Add SCRIPTOPT_SURVIVE_ATTACHED_DISCONNECT * wip beginning work on templatization * Use PolModule in pol-specific modules * wip, creating PolModule with getXYZParam * wip 1, moving getXYZ to UOExecutor * compilable with PolObjectImp / PolApplicObj * add type guard * wip, change signatures change signatures of script_method, script_method_id, and custom_script_method * compilable (windows) * linux fixes * namespace fixes * remove uoexhelp * formatting * compilable - move can_access_offline_mobiles back to uoexec - add guildscrobj and partyscrobj sources - move EGuildRefObjImp and EPartyRefObjImp - wip, implement asUOExec - formatting uoexec.cpp,.h * finish uoexec() helper * some cleanup
815 lines
22 KiB
C++
815 lines
22 KiB
C++
/** @file
|
|
*
|
|
* @par History
|
|
* - 2005/11/24 Shinigami: added itoa for Linux because it is not ANSI C/C++
|
|
* - 2005/11/29 Shinigami: mf_SplitWords will now accept each type of to-split-value as same as in
|
|
* the past
|
|
* - 2006/10/07 Shinigami: FreeBSD fix - changed __linux__ to __unix__
|
|
* - 2006/12/29 Shinigami: mf_SplitWords will not hang server on queue of delimiter
|
|
*/
|
|
|
|
|
|
#include "basicmod.h"
|
|
#include <cstdio>
|
|
#include <cstdlib>
|
|
#include <cstring>
|
|
#include <picojson.h>
|
|
#include <string>
|
|
|
|
#include "../../bscript/berror.h"
|
|
#include "../../bscript/bobject.h"
|
|
#include "../../bscript/dict.h"
|
|
#include "../../bscript/executor.h"
|
|
#include "../../bscript/impstr.h"
|
|
#include "../../clib/stlutil.h"
|
|
|
|
#include <module_defs/basic.h>
|
|
|
|
namespace Pol
|
|
{
|
|
namespace Module
|
|
{
|
|
using namespace Bscript;
|
|
|
|
static const std::string base64_chars =
|
|
"ABCDEFGHIJKLMNOPQRSTUVWXYZ"
|
|
"abcdefghijklmnopqrstuvwxyz"
|
|
"0123456789+/";
|
|
|
|
|
|
static inline bool is_base64( unsigned char c )
|
|
{
|
|
return ( isalnum( c ) || ( c == '+' ) || ( c == '/' ) );
|
|
}
|
|
|
|
BasicExecutorModule::BasicExecutorModule( Executor& exec )
|
|
: Bscript::TmplExecutorModule<BasicExecutorModule, Bscript::ExecutorModule>( exec )
|
|
{
|
|
}
|
|
|
|
Bscript::BObjectImp* BasicExecutorModule::mf_Len()
|
|
{
|
|
Bscript::BObjectImp* imp = exec.getParamImp( 0 );
|
|
if ( imp->isa( Bscript::BObjectImp::OTArray ) )
|
|
{
|
|
Bscript::ObjArray* arr = static_cast<Bscript::ObjArray*>( imp );
|
|
return new BLong( static_cast<int>( arr->ref_arr.size() ) );
|
|
}
|
|
else if ( imp->isa( Bscript::BObjectImp::OTString ) )
|
|
{
|
|
Bscript::String* str = static_cast<Bscript::String*>( imp );
|
|
return new BLong( static_cast<int>( str->length() ) );
|
|
}
|
|
else if ( imp->isa( Bscript::BObjectImp::OTError ) )
|
|
{
|
|
BError* err = static_cast<BError*>( imp );
|
|
return new BLong( static_cast<int>( err->mapcount() ) );
|
|
}
|
|
else
|
|
{
|
|
return new BLong( 0 );
|
|
}
|
|
}
|
|
|
|
Bscript::BObjectImp* BasicExecutorModule::mf_Find()
|
|
{
|
|
exec.makeString( 0 );
|
|
String* str = static_cast<String*>( exec.getParamImp( 0 ) );
|
|
const char* s = exec.paramAsString( 1 );
|
|
int d = static_cast<int>( exec.paramAsLong( 2 ) );
|
|
|
|
int posn = str->find( d ? ( d - 1 ) : 0, s ) + 1;
|
|
|
|
return new BLong( posn );
|
|
}
|
|
|
|
Bscript::BObjectImp* BasicExecutorModule::mf_SubStr()
|
|
{
|
|
exec.makeString( 0 );
|
|
String* str = static_cast<String*>( exec.getParamImp( 0 ) );
|
|
int start = static_cast<int>( exec.paramAsLong( 1 ) );
|
|
int length = static_cast<int>( exec.paramAsLong( 2 ) );
|
|
|
|
return str->StrStr( start, length );
|
|
}
|
|
|
|
Bscript::BObjectImp* BasicExecutorModule::mf_Trim()
|
|
{
|
|
Bscript::BObjectImp* imp = exec.getParamImp( 0 );
|
|
if ( !( imp->isa( Bscript::BObjectImp::OTString ) ) )
|
|
{
|
|
return new BError( "Param 1 must be a string." );
|
|
}
|
|
String* string = static_cast<String*>( imp );
|
|
int type = static_cast<int>( exec.paramAsLong( 1 ) );
|
|
const char* cset = exec.paramAsString( 2 );
|
|
if ( type > 3 )
|
|
type = 3;
|
|
if ( type < 1 )
|
|
type = 1;
|
|
|
|
return string->ETrim( cset, type );
|
|
}
|
|
|
|
/*
|
|
eScript Function Useage
|
|
|
|
StrReplace(str, to_replace, replace_with);
|
|
*/
|
|
Bscript::BObjectImp* BasicExecutorModule::mf_StrReplace()
|
|
{
|
|
Bscript::BObjectImp* imp = exec.getParamImp( 0 );
|
|
std::unique_ptr<String> string( new String( imp->getStringRep().c_str() ) );
|
|
String* to_replace = static_cast<String*>( exec.getParamImp( 1, Bscript::BObjectImp::OTString ) );
|
|
if ( !to_replace )
|
|
return new BError( "Invalid parameter type" );
|
|
String* replace_with =
|
|
static_cast<String*>( exec.getParamImp( 2, Bscript::BObjectImp::OTString ) );
|
|
if ( !replace_with )
|
|
return new BError( "Invalid parameter type" );
|
|
|
|
if ( string->length() < 1 )
|
|
return new BError( "Cannot use empty string for string haystack." );
|
|
if ( to_replace->length() < 1 )
|
|
return new BError( "Cannot use empty string for string needle." );
|
|
|
|
string->EStrReplace( to_replace, replace_with );
|
|
|
|
return string.release();
|
|
}
|
|
|
|
// SubStrReplace(str, replace_with, start, length:=0);
|
|
Bscript::BObjectImp* BasicExecutorModule::mf_SubStrReplace()
|
|
{
|
|
Bscript::BObjectImp* imp = exec.getParamImp( 0 );
|
|
std::unique_ptr<String> string( new String( imp->getStringRep().c_str() ) );
|
|
String* replace_with =
|
|
static_cast<String*>( exec.getParamImp( 1, Bscript::BObjectImp::OTString ) );
|
|
if ( !replace_with )
|
|
return new BError( "Invalid parameter type" );
|
|
int index = static_cast<int>( exec.paramAsLong( 2 ) );
|
|
int len = static_cast<int>( exec.paramAsLong( 3 ) );
|
|
|
|
if ( index < 0 )
|
|
return new BError( "Index must not be negative" );
|
|
if ( static_cast<unsigned>( index - 1 ) > string->length() )
|
|
return new BError( "Index out of range" );
|
|
|
|
// We set it to 1 because of doing -1 later to stay with eScript handling.
|
|
if ( !index )
|
|
index = 1;
|
|
|
|
if ( static_cast<unsigned>( len ) > ( string->length() - index ) )
|
|
return new BError( "Length out of range" );
|
|
if ( len < 0 )
|
|
return new BError( "Length must not be negative" );
|
|
|
|
if ( !len )
|
|
len = static_cast<int>( replace_with->length() - index );
|
|
|
|
string->ESubStrReplace( replace_with, static_cast<unsigned>( index ),
|
|
static_cast<unsigned>( len ) );
|
|
|
|
return string.release();
|
|
}
|
|
|
|
// OMG I HATED THIS REQUEST. Ugly code, but necessary for all the checks
|
|
// just in case someone's code is bugged :(
|
|
Bscript::BObjectImp* BasicExecutorModule::mf_Compare()
|
|
{
|
|
String str1( exec.paramAsString( 0 ) );
|
|
String str2( exec.paramAsString( 1 ) );
|
|
int pos1_index = static_cast<int>( exec.paramAsLong( 2 ) );
|
|
int pos1_len = static_cast<int>( exec.paramAsLong( 3 ) );
|
|
int pos2_index = static_cast<int>( exec.paramAsLong( 4 ) );
|
|
int pos2_len = static_cast<int>( exec.paramAsLong( 5 ) );
|
|
|
|
size_t str1length( str1.length() );
|
|
size_t str2length( str2.length() );
|
|
if ( pos1_index != 0 )
|
|
{
|
|
if ( pos1_index < 0 )
|
|
return new BError( "Index must not be negative for param 1" );
|
|
if ( static_cast<unsigned>( pos1_index - 1 ) > str1length )
|
|
return new BError( "Index out of range for param 1" );
|
|
}
|
|
if ( pos2_index != 0 )
|
|
{
|
|
if ( pos2_index < 0 )
|
|
return new BError( "Index must not be negative for param 2" );
|
|
if ( static_cast<unsigned>( pos2_index - 1 ) > str2length )
|
|
return new BError( "Index out of range for param 2" );
|
|
}
|
|
|
|
|
|
if ( pos1_len < 0 )
|
|
return new BError( "Length must not be negative for param 1" );
|
|
if ( static_cast<unsigned>( pos1_len ) > ( str1length - pos1_index ) )
|
|
return new BError( "Length out of range for param 1" );
|
|
if ( pos2_len < 0 )
|
|
return new BError( "Length must not be negative for param 2" );
|
|
if ( static_cast<unsigned>( pos2_len ) > ( str2length - pos2_index ) )
|
|
return new BError( "Length out of range for param 2" );
|
|
|
|
|
|
if ( pos1_index == 0 )
|
|
{
|
|
if ( !str1.compare( str2 ) )
|
|
return new BLong( 0 );
|
|
else
|
|
return new BLong( 1 );
|
|
}
|
|
else if ( pos1_index > 0 && pos2_index == 0 )
|
|
{
|
|
if ( !str1.compare( pos1_index - 1, pos1_len, str2 ) )
|
|
return new BLong( 0 );
|
|
else
|
|
return new BLong( 1 );
|
|
}
|
|
else
|
|
{
|
|
if ( !str1.compare( pos1_index - 1, pos1_len, str2, pos2_index - 1, pos2_len ) )
|
|
return new BLong( 0 );
|
|
else
|
|
return new BLong( 1 );
|
|
}
|
|
}
|
|
|
|
Bscript::BObjectImp* BasicExecutorModule::mf_Lower()
|
|
{
|
|
String* string = new String( exec.paramAsString( 0 ) );
|
|
string->toLower();
|
|
return string;
|
|
}
|
|
|
|
Bscript::BObjectImp* BasicExecutorModule::mf_Upper()
|
|
{
|
|
String* string = new String( exec.paramAsString( 0 ) );
|
|
string->toUpper();
|
|
return string;
|
|
}
|
|
|
|
Bscript::BObjectImp* BasicExecutorModule::mf_CInt()
|
|
{
|
|
Bscript::BObjectImp* imp = exec.getParamImp( 0 );
|
|
if ( imp->isa( Bscript::BObjectImp::OTLong ) )
|
|
{
|
|
return imp->copy();
|
|
}
|
|
else if ( imp->isa( Bscript::BObjectImp::OTString ) )
|
|
{
|
|
String* str = static_cast<String*>( imp );
|
|
return new BLong( strtoul( str->data(), nullptr, 0 ) );
|
|
}
|
|
else if ( imp->isa( Bscript::BObjectImp::OTDouble ) )
|
|
{
|
|
Double* dbl = static_cast<Double*>( imp );
|
|
return new BLong( static_cast<int>( dbl->value() ) );
|
|
}
|
|
else
|
|
{
|
|
return new BLong( 0 );
|
|
}
|
|
}
|
|
|
|
Bscript::BObjectImp* BasicExecutorModule::mf_CDbl()
|
|
{
|
|
Bscript::BObjectImp* imp = exec.getParamImp( 0 );
|
|
if ( imp->isa( Bscript::BObjectImp::OTLong ) )
|
|
{
|
|
BLong* lng = static_cast<BLong*>( imp );
|
|
return new Double( lng->value() );
|
|
}
|
|
else if ( imp->isa( Bscript::BObjectImp::OTString ) )
|
|
{
|
|
String* str = static_cast<String*>( imp );
|
|
return new Double( strtod( str->data(), nullptr ) );
|
|
}
|
|
else if ( imp->isa( Bscript::BObjectImp::OTDouble ) )
|
|
{
|
|
return imp->copy();
|
|
}
|
|
else
|
|
{
|
|
return new Double( 0 );
|
|
}
|
|
}
|
|
|
|
Bscript::BObjectImp* BasicExecutorModule::mf_CStr()
|
|
{
|
|
Bscript::BObjectImp* imp = exec.getParamImp( 0 );
|
|
return new String( imp->getStringRep() );
|
|
}
|
|
|
|
Bscript::BObjectImp* BasicExecutorModule::mf_CAsc()
|
|
{
|
|
Bscript::BObjectImp* imp = exec.getParamImp( 0 );
|
|
if ( imp->isa( Bscript::BObjectImp::OTString ) )
|
|
{
|
|
String* str = static_cast<String*>( imp );
|
|
std::unique_ptr<String> substr( str->StrStr( 1, 1 ) );
|
|
const auto& utf16 = substr->toUTF16();
|
|
if ( utf16.empty() )
|
|
return new BLong( 0 );
|
|
else if ( utf16.size() > 1 )
|
|
return new BError( "Cannot be represented by a single number" );
|
|
return new BLong( utf16[0] );
|
|
}
|
|
else
|
|
{
|
|
return new BError( "Invalid parameter type" );
|
|
}
|
|
}
|
|
|
|
Bscript::BObjectImp* BasicExecutorModule::mf_CAscZ()
|
|
{
|
|
Bscript::BObjectImp* imp = exec.getParamImp( 0 );
|
|
String tmp( imp->getStringRep() );
|
|
int nullterm = static_cast<int>( exec.paramAsLong( 1 ) );
|
|
std::unique_ptr<Bscript::ObjArray> arr( new Bscript::ObjArray );
|
|
const auto& utf16 = tmp.toUTF16();
|
|
for ( const auto& code : utf16 )
|
|
{
|
|
arr->addElement( new BLong( code ) );
|
|
}
|
|
if ( nullterm )
|
|
arr->addElement( new BLong( 0 ) );
|
|
|
|
return arr.release();
|
|
}
|
|
|
|
Bscript::BObjectImp* BasicExecutorModule::mf_CChr()
|
|
{
|
|
int val;
|
|
if ( getParam( 0, val ) )
|
|
{
|
|
return new String( String::fromUTF16( static_cast<u16>( val & 0xffff ) ) );
|
|
}
|
|
else
|
|
{
|
|
return new BError( "Invalid parameter type" );
|
|
}
|
|
}
|
|
|
|
Bscript::BObjectImp* BasicExecutorModule::mf_CChrZ()
|
|
{
|
|
std::string res;
|
|
Bscript::ObjArray* arr =
|
|
static_cast<Bscript::ObjArray*>( exec.getParamImp( 0, Bscript::BObjectImp::OTArray ) );
|
|
int break_first_null = static_cast<int>( exec.paramAsLong( 1 ) );
|
|
if ( !arr )
|
|
return new BError( "Invalid parameter type" );
|
|
return String::fromUCArray( arr, break_first_null != 0 );
|
|
}
|
|
|
|
Bscript::BObjectImp* BasicExecutorModule::mf_Hex()
|
|
{
|
|
Bscript::BObjectImp* imp = exec.getParamImp( 0 );
|
|
if ( imp->isa( Bscript::BObjectImp::OTLong ) )
|
|
{
|
|
BLong* plong = static_cast<BLong*>( imp );
|
|
char s[20];
|
|
sprintf( s, "0x%X", static_cast<unsigned int>( plong->value() ) );
|
|
return new String( s );
|
|
}
|
|
else if ( imp->isa( Bscript::BObjectImp::OTDouble ) )
|
|
{
|
|
Double* pdbl = static_cast<Double*>( imp );
|
|
char s[20];
|
|
sprintf( s, "0x%X", static_cast<unsigned int>( pdbl->value() ) );
|
|
return new String( s );
|
|
}
|
|
else if ( imp->isa( Bscript::BObjectImp::OTString ) )
|
|
{
|
|
String* str = static_cast<String*>( imp );
|
|
char s[20];
|
|
sprintf( s, "0x%X", static_cast<unsigned int>( strtoul( str->data(), nullptr, 0 ) ) );
|
|
return new String( s );
|
|
}
|
|
else
|
|
{
|
|
return new BError( "Hex() expects an Integer, Real, or String" );
|
|
}
|
|
}
|
|
|
|
#ifdef __unix__
|
|
char* itoa( int value, char* result, int base )
|
|
{
|
|
// check that the base is valid
|
|
if ( base < 2 || base > 16 )
|
|
{
|
|
*result = 0;
|
|
return result;
|
|
}
|
|
|
|
char* out = result;
|
|
int quotient = value;
|
|
|
|
do
|
|
{
|
|
*out = "0123456789abcdef"[std::abs( quotient % base )];
|
|
++out;
|
|
quotient /= base;
|
|
} while ( quotient );
|
|
|
|
// Only apply negative sign for base 10
|
|
if ( value < 0 && base == 10 )
|
|
*out++ = '-';
|
|
|
|
std::reverse( result, out );
|
|
*out = 0;
|
|
return result;
|
|
}
|
|
#endif
|
|
|
|
Bscript::BObjectImp* BasicExecutorModule::mf_Bin()
|
|
{
|
|
Bscript::BObjectImp* imp = exec.getParamImp( 0 );
|
|
if ( imp->isa( Bscript::BObjectImp::OTLong ) )
|
|
{
|
|
BLong* plong = static_cast<BLong*>( imp );
|
|
int number = plong->value();
|
|
char buffer[sizeof( int ) * 8 + 1];
|
|
return new String( itoa( number, buffer, 2 ) );
|
|
}
|
|
else
|
|
{
|
|
return new BError( "Bin() expects an Integer" );
|
|
}
|
|
}
|
|
|
|
Bscript::BObjectImp* BasicExecutorModule::mf_SplitWords()
|
|
{
|
|
Bscript::BObjectImp* bimp_split = exec.getParamImp( 0 );
|
|
std::string source = bimp_split->getStringRep();
|
|
|
|
const String* bimp_delimiter;
|
|
if ( !exec.getStringParam( 1, bimp_delimiter ) )
|
|
{
|
|
return new BError( "Invalid parameter type." );
|
|
}
|
|
std::string delimiter = bimp_delimiter->getStringRep();
|
|
|
|
// max_split parameter
|
|
int max_split = -1;
|
|
int count = 0;
|
|
|
|
if ( exec.hasParams( 3 ) )
|
|
{
|
|
max_split = static_cast<int>( exec.paramAsLong( 2 ) );
|
|
}
|
|
|
|
std::unique_ptr<Bscript::ObjArray> objarr( new Bscript::ObjArray );
|
|
|
|
// Support for how it previously worked.
|
|
// Kept to support spaces and tabs as the same.
|
|
if ( delimiter == " " )
|
|
{
|
|
ISTRINGSTREAM is( source );
|
|
std::string tmp;
|
|
std::streamoff tellg = -1;
|
|
bool splitted = false;
|
|
|
|
while ( is >> tmp )
|
|
{
|
|
tellg = is.tellg();
|
|
if ( count == max_split && tellg != -1 )
|
|
{ // added max_split parameter
|
|
splitted = true;
|
|
break;
|
|
}
|
|
objarr->addElement( new String( tmp ) );
|
|
tmp = "";
|
|
count += 1;
|
|
}
|
|
|
|
// Merges the remaining of the string
|
|
if ( splitted )
|
|
{
|
|
std::string remaining_string;
|
|
remaining_string = source.substr( tellg - tmp.length(), source.length() );
|
|
objarr->addElement( new String( remaining_string ) );
|
|
}
|
|
|
|
return objarr.release();
|
|
}
|
|
|
|
// New delimiter support.
|
|
std::string new_string = source;
|
|
std::string::size_type found;
|
|
do
|
|
{
|
|
found = new_string.find( delimiter, 0 );
|
|
if ( found == std::string::npos )
|
|
break;
|
|
else if ( count == max_split )
|
|
{ // added max_split parameter
|
|
break;
|
|
}
|
|
|
|
std::string add_string = new_string.substr( 0, found );
|
|
|
|
// Shinigami: will not hang server on queue of delimiter
|
|
// if ( add_string.empty() )
|
|
// continue;
|
|
|
|
objarr->addElement( new String( add_string ) );
|
|
std::string tmp_string = new_string.substr( found + delimiter.length(), new_string.length() );
|
|
new_string = tmp_string;
|
|
count += 1;
|
|
} while ( found != std::string::npos );
|
|
|
|
// Catch leftovers here.
|
|
if ( !new_string.empty() )
|
|
objarr->addElement( new String( new_string ) );
|
|
|
|
return objarr.release();
|
|
}
|
|
|
|
Bscript::BObjectImp* BasicExecutorModule::mf_Pack()
|
|
{
|
|
Bscript::BObjectImp* imp = exec.getParamImp( 0 );
|
|
return new String( imp->pack() );
|
|
}
|
|
|
|
Bscript::BObjectImp* BasicExecutorModule::mf_Unpack()
|
|
{
|
|
const String* str;
|
|
|
|
if ( exec.getStringParam( 0, str ) )
|
|
{
|
|
return Bscript::BObjectImp::unpack( str->data() );
|
|
}
|
|
else
|
|
{
|
|
return new BError( "Invalid parameter type" );
|
|
}
|
|
}
|
|
Bscript::BObjectImp* BasicExecutorModule::mf_TypeOf()
|
|
{
|
|
Bscript::BObjectImp* imp = exec.getParamImp( 0 );
|
|
return new String( imp->typeOf() );
|
|
}
|
|
Bscript::BObjectImp* BasicExecutorModule::mf_SizeOf()
|
|
{
|
|
Bscript::BObjectImp* imp = exec.getParamImp( 0 );
|
|
return new BLong( static_cast<int>( imp->sizeEstimate() ) );
|
|
}
|
|
Bscript::BObjectImp* BasicExecutorModule::mf_TypeOfInt()
|
|
{
|
|
BObjectImp* imp = exec.getParamImp( 0 );
|
|
return new BLong( imp->typeOfInt() );
|
|
}
|
|
|
|
picojson::value recurseE2J( BObjectImp* v )
|
|
{
|
|
if ( v->isa( BObjectImp::OTString ) )
|
|
{
|
|
return picojson::value( v->getStringRep() );
|
|
}
|
|
else if ( v->isa( BObjectImp::OTLong ) )
|
|
{
|
|
int intVal = static_cast<BLong*>( v )->value();
|
|
return picojson::value( static_cast<double>( intVal ) );
|
|
}
|
|
else if ( v->isa( BObjectImp::OTDouble ) )
|
|
{
|
|
return picojson::value( static_cast<Double*>( v )->value() );
|
|
}
|
|
else if ( v->isa( BObjectImp::OTBoolean ) )
|
|
{
|
|
return picojson::value( static_cast<BBoolean*>( v )->value() );
|
|
}
|
|
else if ( v->isa( BObjectImp::OTArray ) )
|
|
{
|
|
ObjArray* arr = static_cast<ObjArray*>( v );
|
|
picojson::array jsonArr;
|
|
|
|
for ( const auto& elem : arr->ref_arr )
|
|
{
|
|
BObject* bo = elem.get();
|
|
if ( bo == nullptr )
|
|
continue;
|
|
BObjectImp* imp = bo->impptr();
|
|
jsonArr.push_back( recurseE2J( imp ) );
|
|
}
|
|
return picojson::value( jsonArr );
|
|
}
|
|
else if ( v->isa( BObjectImp::OTStruct ) )
|
|
{
|
|
BStruct* bstruct = static_cast<BStruct*>( v );
|
|
picojson::object jsonObj;
|
|
for ( const auto& content : bstruct->contents() )
|
|
{
|
|
BObjectImp* imp = content.second->impptr();
|
|
jsonObj.insert( std::pair<std::string, picojson::value>( content.first, recurseE2J( imp ) ) );
|
|
}
|
|
return picojson::value( jsonObj );
|
|
}
|
|
else if ( v->isa( BObjectImp::OTDictionary ) )
|
|
{
|
|
BDictionary* cpropdict = static_cast<Bscript::BDictionary*>( v );
|
|
picojson::object jsonObj;
|
|
for ( const auto& content : cpropdict->contents() )
|
|
{
|
|
BObjectImp* imp = content.second->impptr();
|
|
jsonObj.insert( std::pair<std::string, picojson::value>( content.first->getStringRep(),
|
|
recurseE2J( imp ) ) );
|
|
}
|
|
return picojson::value( jsonObj );
|
|
}
|
|
return picojson::value();
|
|
}
|
|
Bscript::BObjectImp* BasicExecutorModule::mf_PackJSON()
|
|
{
|
|
BObjectImp* imp = exec.getParamImp( 0 );
|
|
return new String( recurseE2J( imp ).serialize() );
|
|
}
|
|
|
|
|
|
Bscript::BObjectImp* recurseJ2E( const picojson::value& v )
|
|
{
|
|
if ( v.is<std::string>() )
|
|
{
|
|
return new String( v.get<std::string>() );
|
|
}
|
|
else if ( v.is<double>() )
|
|
{
|
|
// Possible improvement: separate into BLong and Double
|
|
return new Double( v.get<double>() );
|
|
}
|
|
else if ( v.is<bool>() )
|
|
{
|
|
return new BBoolean( v.get<bool>() );
|
|
}
|
|
else if ( v.is<picojson::array>() )
|
|
{
|
|
std::unique_ptr<ObjArray> objarr( new ObjArray );
|
|
const picojson::array& arr = v.get<picojson::array>();
|
|
for ( const auto& elem : arr )
|
|
{
|
|
objarr->addElement( recurseJ2E( elem ) );
|
|
}
|
|
return objarr.release();
|
|
}
|
|
else if ( v.is<picojson::object>() )
|
|
{
|
|
std::unique_ptr<BStruct> objstruct( new BStruct );
|
|
for ( const auto& content : v.get<picojson::object>() )
|
|
{
|
|
objstruct->addMember( content.first.c_str(), recurseJ2E( content.second ) );
|
|
}
|
|
return objstruct.release();
|
|
}
|
|
else
|
|
return UninitObject::create();
|
|
}
|
|
|
|
Bscript::BObjectImp* BasicExecutorModule::mf_UnpackJSON()
|
|
{
|
|
const String* str;
|
|
|
|
if ( exec.getStringParam( 0, str ) )
|
|
{
|
|
picojson::value v;
|
|
std::string err = picojson::parse( v, str->data() );
|
|
if ( !err.empty() )
|
|
{
|
|
return new BError( err );
|
|
}
|
|
return recurseJ2E( v );
|
|
}
|
|
else
|
|
{
|
|
return new BError( "Invalid parameter type" );
|
|
}
|
|
}
|
|
|
|
Bscript::BObjectImp* BasicExecutorModule::mf_Boolean()
|
|
{
|
|
Bscript::BObjectImp* imp = exec.getParamImp( 0 );
|
|
if ( imp->isa( Bscript::BObjectImp::OTLong ) )
|
|
{
|
|
BLong* plong = static_cast<BLong*>( imp );
|
|
return new BBoolean( plong->value() != 0 );
|
|
}
|
|
else if ( imp->isa( Bscript::BObjectImp::OTBoolean ) )
|
|
{
|
|
return new BBoolean( *static_cast<BBoolean*>( imp ) );
|
|
}
|
|
else
|
|
{
|
|
return new BError( "Boolean() expects an Integer or Boolean" );
|
|
}
|
|
}
|
|
|
|
/*
|
|
Base64 encode/decode snippit by Rene Nyffenegger rene.nyffenegger@adp-gmbh.ch
|
|
Copyright (C) 2004-2008 Rene Nyffenegger
|
|
*/
|
|
Bscript::BObjectImp* BasicExecutorModule::mf_EncodeBase64()
|
|
{
|
|
std::string encoded_string = exec.paramAsString( 0 );
|
|
|
|
if ( encoded_string.empty() )
|
|
return new BError( "Invalid parameter type" );
|
|
|
|
unsigned int in_len = static_cast<unsigned int>( encoded_string.length() );
|
|
|
|
unsigned char const* bytes_to_encode =
|
|
reinterpret_cast<const unsigned char*>( encoded_string.c_str() );
|
|
std::string ret;
|
|
int i = 0;
|
|
int j = 0;
|
|
unsigned char char_array_3[3];
|
|
unsigned char char_array_4[4];
|
|
|
|
while ( in_len-- )
|
|
{
|
|
char_array_3[i++] = *( bytes_to_encode++ );
|
|
if ( i == 3 )
|
|
{
|
|
char_array_4[0] = ( char_array_3[0] & 0xfc ) >> 2;
|
|
char_array_4[1] = ( ( char_array_3[0] & 0x03 ) << 4 ) + ( ( char_array_3[1] & 0xf0 ) >> 4 );
|
|
char_array_4[2] = ( ( char_array_3[1] & 0x0f ) << 2 ) + ( ( char_array_3[2] & 0xc0 ) >> 6 );
|
|
char_array_4[3] = char_array_3[2] & 0x3f;
|
|
|
|
for ( i = 0; ( i < 4 ); i++ )
|
|
ret += base64_chars[char_array_4[i]];
|
|
i = 0;
|
|
}
|
|
}
|
|
|
|
if ( i )
|
|
{
|
|
for ( j = i; j < 3; j++ )
|
|
char_array_3[j] = '\0';
|
|
|
|
char_array_4[0] = ( char_array_3[0] & 0xfc ) >> 2;
|
|
char_array_4[1] = ( ( char_array_3[0] & 0x03 ) << 4 ) + ( ( char_array_3[1] & 0xf0 ) >> 4 );
|
|
char_array_4[2] = ( ( char_array_3[1] & 0x0f ) << 2 ) + ( ( char_array_3[2] & 0xc0 ) >> 6 );
|
|
char_array_4[3] = char_array_3[2] & 0x3f;
|
|
|
|
for ( j = 0; ( j < i + 1 ); j++ )
|
|
ret += base64_chars[char_array_4[j]];
|
|
|
|
while ( ( i++ < 3 ) )
|
|
ret += '=';
|
|
}
|
|
|
|
return new String( ret );
|
|
}
|
|
|
|
Bscript::BObjectImp* BasicExecutorModule::mf_DecodeBase64()
|
|
{
|
|
std::string encoded_string = exec.paramAsString( 0 );
|
|
|
|
if ( encoded_string.empty() )
|
|
return new BError( "Invalid parameter type" );
|
|
|
|
int in_len = static_cast<int>( encoded_string.size() );
|
|
int i = 0;
|
|
int j = 0;
|
|
int in_ = 0;
|
|
unsigned char char_array_4[4], char_array_3[3];
|
|
std::string ret;
|
|
|
|
while ( in_len-- && ( encoded_string[in_] != '=' ) && is_base64( encoded_string[in_] ) )
|
|
{
|
|
char_array_4[i++] = encoded_string[in_];
|
|
in_++;
|
|
if ( i == 4 )
|
|
{
|
|
for ( i = 0; i < 4; i++ )
|
|
char_array_4[i] = static_cast<u8>( base64_chars.find( char_array_4[i] ) );
|
|
|
|
char_array_3[0] = ( char_array_4[0] << 2 ) + ( ( char_array_4[1] & 0x30 ) >> 4 );
|
|
char_array_3[1] = ( ( char_array_4[1] & 0xf ) << 4 ) + ( ( char_array_4[2] & 0x3c ) >> 2 );
|
|
char_array_3[2] = ( ( char_array_4[2] & 0x3 ) << 6 ) + char_array_4[3];
|
|
|
|
for ( i = 0; ( i < 3 ); i++ )
|
|
ret += char_array_3[i];
|
|
i = 0;
|
|
}
|
|
}
|
|
|
|
if ( i )
|
|
{
|
|
for ( j = i; j < 4; j++ )
|
|
char_array_4[j] = 0;
|
|
|
|
for ( j = 0; j < 4; j++ )
|
|
char_array_4[j] = static_cast<u8>( base64_chars.find( char_array_4[j] ) );
|
|
|
|
char_array_3[0] = ( char_array_4[0] << 2 ) + ( ( char_array_4[1] & 0x30 ) >> 4 );
|
|
char_array_3[1] = ( ( char_array_4[1] & 0xf ) << 4 ) + ( ( char_array_4[2] & 0x3c ) >> 2 );
|
|
char_array_3[2] = ( ( char_array_4[2] & 0x3 ) << 6 ) + char_array_4[3];
|
|
|
|
for ( j = 0; ( j < i - 1 ); j++ )
|
|
ret += char_array_3[j];
|
|
}
|
|
|
|
return new String( ret );
|
|
}
|
|
} // namespace Module
|
|
} // namespace Pol
|