Added FS.MemoryFilesystem

This commit is contained in:
2025-01-03 05:54:27 -06:00
parent 82bf80ba06
commit f0a7c77134
16 changed files with 1105 additions and 991 deletions

View File

@ -19,558 +19,8 @@
namespace Tesses::CrossLang
{
#if defined(CROSSLANG_ENABLE_MBED)
static void my_debug(void *ctx, int level,
const char *file, int line,
const char *str)
{
((void) level);
fprintf(stderr, "%s:%04d: %s", file, line, str);
fflush(stderr);
}
class TlsClientStream {
GCList* ls;
TCallable* read;
TCallable* write;
TCallable* close;
TByteArray* readBuffer;
TByteArray* writeBuffer;
mbedtls_entropy_context entropy;
mbedtls_ctr_drbg_context ctr_drbg;
mbedtls_ssl_context ssl;
mbedtls_ssl_config conf;
mbedtls_x509_crt cachain;
static int strm_send(void* ctx,const unsigned char* buf,size_t len)
{
TlsClientStream* strm = static_cast<TlsClientStream*>(ctx);
strm->writeBuffer->data.resize(len);
memcpy(strm->writeBuffer->data.data(),buf,len);
auto res = strm->write->Call(*strm->ls,{strm->writeBuffer});
if(std::holds_alternative<int64_t>(res))
{
auto num = std::get<int64_t>(res);
return (int)num;
}
return -1;
}
static int strm_recv(void* ctx,unsigned char* buf,size_t len)
{
TlsClientStream* strm = static_cast<TlsClientStream*>(ctx);
strm->readBuffer->data.resize(len);
auto res = strm->read->Call(*strm->ls,{strm->readBuffer});
if(std::holds_alternative<int64_t>(res))
{
auto num = std::get<int64_t>(res);
if(num < 0) return (int)num;
size_t read = (size_t)num;
if(read > len) read = len;
memcpy(buf,strm->readBuffer->data.data(), read);
return read;
}
return -1;
//return (int)strm->Read((uint8_t*)buf,len);
}
public:
void Close()
{
close->Call(*ls,{});
}
bool success=false;
bool isDoneReading = false;
int64_t Read(uint8_t* buffer, size_t len)
{
if(isDoneReading) return 0;
int64_t r = (int64_t)mbedtls_ssl_read(&ssl,buffer,len);
if(r == 0) isDoneReading=true;
if(r == -30848)
{
isDoneReading = true;
return 0;
}
return r;
}
int64_t Write(uint8_t* buffer, size_t len)
{
return (int64_t)mbedtls_ssl_write(&ssl,buffer,len);
}
TlsClientStream(GC* gc,std::string domain,std::string chain,bool verify, TCallable* read, TCallable* write, TCallable* close)
{
ls = new GCList(gc);
ls->Add(read);
ls->Add(write);
ls->Add(close);
this->read = read;
this->write = write;
this->close = close;
readBuffer = TByteArray::Create(ls);
writeBuffer = TByteArray::Create(ls);
mbedtls_ssl_init(&ssl);
mbedtls_ssl_config_init(&conf);
mbedtls_x509_crt_init(&cachain);
mbedtls_ctr_drbg_init(&ctr_drbg);
mbedtls_entropy_init(&entropy);
const char* pers = "CrossLangTLS";
int ret=0;
#if defined(MBEDTLS_USE_PSA_CRYPTO)
psa_status_t status = psa_crypto_init();
if (status != PSA_SUCCESS) {
mbedtls_fprintf(stderr, "Failed to initialize PSA Crypto implementation: %d\n",
(int) status);
return;
}
#endif
if ((ret = mbedtls_ctr_drbg_seed(&ctr_drbg, mbedtls_entropy_func, &entropy,
(const unsigned char *) pers,
strlen(pers))) != 0)
{
printf("FAILED mbedtls_ctr_drbg_seed\n");
return;
}
if(ret != 0) { printf("FAILED mbedtls_x509_crt_parse cert %i\n",ret); return;}
ret = mbedtls_x509_crt_parse(&cachain, (const unsigned char *) chain.c_str(),
chain.size()+1);
if(ret != 0) {printf("FAILED mbedtls_x509_crt_parse chain %i\n",ret); return;}
if((ret = mbedtls_ssl_config_defaults(&conf,
MBEDTLS_SSL_IS_CLIENT,
MBEDTLS_SSL_TRANSPORT_STREAM,
MBEDTLS_SSL_PRESET_DEFAULT)) != 0)
{
char buffer[100];
mbedtls_strerror(ret,buffer,sizeof(buffer));
printf("FAILED mbedtls_ssl_conf_defaults %s\n",buffer);
return;
}
mbedtls_ssl_conf_rng(&conf, mbedtls_ctr_drbg_random, &ctr_drbg);
mbedtls_ssl_conf_dbg(&conf,my_debug,stdout);
/* #if defined(MBEDTLS_SSL_CACHE_C)
mbedtls_ssl_conf_session_cache(&conf, &cache,
mbedtls_ssl_cache_get,
mbedtls_ssl_cache_set);
#endif*/
mbedtls_ssl_conf_authmode(&conf, verify ? MBEDTLS_SSL_VERIFY_REQUIRED: MBEDTLS_SSL_VERIFY_OPTIONAL);
mbedtls_ssl_conf_ca_chain(&conf, &cachain, NULL);
mbedtls_ssl_set_bio(&ssl, static_cast<void*>(this),strm_send,strm_recv, NULL);
if((ret=mbedtls_ssl_setup(&ssl,&conf) != 0))
{
printf("FAILED mbedtls_ssl_setup %i\n",ret);
return;
}
if((ret=mbedtls_ssl_set_hostname(&ssl,domain.c_str()) != 0))
{
printf("FAILED mbedtls_ssl_set_hostname %i\n",ret);
return;
}
if((ret = mbedtls_ssl_handshake(&ssl)) != 0)
{
char buffer[100];
mbedtls_strerror(ret,buffer,sizeof(buffer));
printf("FAILED mbedtls_ssl_handshake %s\n",buffer);
return;
}
uint32_t flags;
if ((flags = mbedtls_ssl_get_verify_result(&ssl)) != 0) {
#if !defined(MBEDTLS_X509_REMOVE_INFO)
char vrfy_buf[512];
#endif
#if !defined(MBEDTLS_X509_REMOVE_INFO)
mbedtls_x509_crt_verify_info(vrfy_buf, sizeof(vrfy_buf), " ! ", flags);
#endif
if(verify)
return;
}
success=true;
}
~TlsClientStream()
{
mbedtls_ctr_drbg_free(&ctr_drbg);
mbedtls_entropy_free(&entropy);
mbedtls_ssl_config_free(&conf);
#if defined(MBEDTLS_USE_PSA_CRYPTO)
mbedtls_psa_crypto_free();
#endif /* MBEDTLS_USE_PSA_CRYPTO */
delete ls;
}
};
class TlsServerStream {
GCList* ls;
TCallable* read;
TCallable* write;
TCallable* close;
TByteArray* readBuffer;
TByteArray* writeBuffer;
mbedtls_entropy_context entropy;
mbedtls_ctr_drbg_context ctr_drbg;
mbedtls_ssl_context ssl;
mbedtls_ssl_config conf;
mbedtls_x509_crt srvcert;
mbedtls_x509_crt cachain;
mbedtls_pk_context pkey;
static int strm_send(void* ctx,const unsigned char* buf,size_t len)
{
TlsServerStream* strm = static_cast<TlsServerStream*>(ctx);
strm->writeBuffer->data.resize(len);
memcpy(strm->writeBuffer->data.data(),buf,len);
auto res = strm->write->Call(*strm->ls,{strm->writeBuffer});
if(std::holds_alternative<int64_t>(res))
{
auto num = std::get<int64_t>(res);
return (int)num;
}
return -1;
}
static int strm_recv(void* ctx,unsigned char* buf,size_t len)
{
TlsServerStream* strm = static_cast<TlsServerStream*>(ctx);
strm->readBuffer->data.resize(len);
auto res = strm->read->Call(*strm->ls,{strm->readBuffer});
if(std::holds_alternative<int64_t>(res))
{
auto num = std::get<int64_t>(res);
if(num < 0) return num;
size_t read = (size_t)num;
if(read > len) read = len;
memcpy(buf,strm->readBuffer->data.data(), read);
return read;
}
return -1;
//return (int)strm->Read((uint8_t*)buf,len);
}
public:
void Close()
{
close->Call(*ls,{});
}
bool success=false;
bool isDoneReading =false;
int64_t Read(uint8_t* buffer, size_t len)
{
if(isDoneReading) return 0;
int64_t r = (int64_t)mbedtls_ssl_read(&ssl,buffer,len);
if(r == 0) isDoneReading=true;
if(r == -30848)
{
isDoneReading = true;
return 0;
}
return r;
}
int64_t Write(uint8_t* buffer, size_t len)
{
return mbedtls_ssl_write(&ssl,buffer,len);
}
TlsServerStream(GC* gc,std::string cert, std::string chain, std::string privkey, TCallable* read, TCallable* write, TCallable* close)
{
ls = new GCList(gc);
ls->Add(read);
ls->Add(write);
ls->Add(close);
readBuffer = TByteArray::Create(ls);
writeBuffer = TByteArray::Create(ls);
this->read = read;
this->write = write;
this->close = close;
mbedtls_ssl_init(&ssl);
mbedtls_ssl_config_init(&conf);
mbedtls_x509_crt_init(&srvcert);
mbedtls_x509_crt_init(&cachain);
mbedtls_ctr_drbg_init(&ctr_drbg);
mbedtls_entropy_init(&entropy);
mbedtls_pk_init(&pkey);
const char* pers = "CrossLangTLS";
int ret=0;
#if defined(MBEDTLS_USE_PSA_CRYPTO)
psa_status_t status = psa_crypto_init();
if (status != PSA_SUCCESS) {
mbedtls_fprintf(stderr, "Failed to initialize PSA Crypto implementation: %d\n",
(int) status);
return;
}
#endif
if ((ret = mbedtls_ctr_drbg_seed(&ctr_drbg, mbedtls_entropy_func, &entropy,
(const unsigned char *) pers,
strlen(pers))) != 0)
{
printf("FAILED mbedtls_ctr_drbg_seed\n");
return;
}
ret = mbedtls_x509_crt_parse(&srvcert, (const unsigned char *) cert.c_str(),
cert.size()+1);
if(ret != 0) { printf("FAILED mbedtls_x509_crt_parse cert %i\n",ret); return;}
ret = mbedtls_x509_crt_parse(&cachain, (const unsigned char *) chain.c_str(),
chain.size()+1);
if(ret != 0) {printf("FAILED mbedtls_x509_crt_parse chain %i\n",ret); return;}
ret = mbedtls_pk_parse_key(&pkey, (const unsigned char *) privkey.c_str(),
privkey.size()+1, NULL, 0);
if(ret != 0) {printf("FAILED mbedtls_pk_parse_key %i\n",ret); return;}
if((ret = mbedtls_ssl_config_defaults(&conf,
MBEDTLS_SSL_IS_SERVER,
MBEDTLS_SSL_TRANSPORT_STREAM,
MBEDTLS_SSL_PRESET_DEFAULT)) != 0)
{
char buffer[100];
mbedtls_strerror(ret,buffer,sizeof(buffer));
printf("FAILED mbedtls_ssl_conf_defaults %s\n",buffer);
return;
}
mbedtls_ssl_conf_rng(&conf, mbedtls_ctr_drbg_random, &ctr_drbg);
/* #if defined(MBEDTLS_SSL_CACHE_C)
mbedtls_ssl_conf_session_cache(&conf, &cache,
mbedtls_ssl_cache_get,
mbedtls_ssl_cache_set);
#endif*/
mbedtls_ssl_conf_own_cert(&conf,&srvcert,&pkey);
mbedtls_ssl_conf_ca_chain(&conf, &cachain, NULL);
mbedtls_ssl_set_bio(&ssl, static_cast<void*>(this),strm_send,strm_recv, NULL);
if((ret=mbedtls_ssl_setup(&ssl,&conf) != 0))
{
printf("FAILED mbedtls_ssl_setup %i\n",ret);
return;
}
if((ret = mbedtls_ssl_handshake(&ssl)) != 0)
{
char buffer[100];
mbedtls_strerror(ret,buffer,sizeof(buffer));
printf("FAILED mbedtls_ssl_handshake %s\n",buffer);
return;
}
success=true;
}
~TlsServerStream()
{
mbedtls_x509_crt_free(&srvcert);
mbedtls_pk_free(&pkey);
mbedtls_ctr_drbg_free(&ctr_drbg);
mbedtls_entropy_free(&entropy);
mbedtls_ssl_config_free(&conf);
#if defined(MBEDTLS_USE_PSA_CRYPTO)
mbedtls_psa_crypto_free();
#endif /* MBEDTLS_USE_PSA_CRYPTO */
delete ls;
}
};
static TObject Crypto_TlsClient(GCList& ls, std::vector<TObject> args)
{
//TlsServerStream(GC* gc,std::string domain, std::string chain, bool verify, TCallable* read, TCallable* write, TCallable* close)
if(args.size() == 6 && std::holds_alternative<std::string>(args[0]) && std::holds_alternative<std::string>(args[1]) && std::holds_alternative<bool>(args[2]) && std::holds_alternative<THeapObjectHolder>(args[3]) && std::holds_alternative<THeapObjectHolder>(args[4]) && std::holds_alternative<THeapObjectHolder>(args[5]))
{
std::string domain = std::get<std::string>(args[0]);
std::string chain = std::get<std::string>(args[1]);
bool verify = std::get<bool>(args[2]);
TCallable* read = dynamic_cast<TCallable*>(std::get<THeapObjectHolder>(args[3]).obj);
TCallable* write = dynamic_cast<TCallable*>(std::get<THeapObjectHolder>(args[4]).obj);
TCallable* close = dynamic_cast<TCallable*>(std::get<THeapObjectHolder>(args[5]).obj);
if(read != nullptr && write != nullptr && close != nullptr)
{
auto serverStream = new TlsClientStream(ls.GetGC(),domain,chain,verify,read,write,close);
if(!serverStream->success)
{
serverStream->Close();
delete serverStream;
return nullptr;
}
TNative* native = TNative::Create(ls,static_cast<void*>(serverStream),[](void* ptr)->void {
if(ptr == nullptr) return;
TlsClientStream* strm = static_cast<TlsClientStream*>(ptr);
strm->Close();
delete strm;
});
TDictionary* dict = TDictionary::Create(ls);
ls.GetGC()->BarrierBegin();
dict->SetValue("_native",native);
ls.GetGC()->BarrierEnd();
dict->DeclareFunction(ls.GetGC(),"Read","Read data from Tls Connection",{"buffer","offset","length"},[native](GCList& ls2, std::vector<TObject> args2)->TObject {
if(args2.size() == 3 && std::holds_alternative<THeapObjectHolder>(args2[0]) && std::holds_alternative<int64_t>(args2[1]) && std::holds_alternative<int64_t>(args2[2]))
{
auto byteArray = dynamic_cast<TByteArray*>(std::get<THeapObjectHolder>(args2[0]).obj);
size_t offset = (size_t)std::get<int64_t>(args2[1]);
size_t length = (size_t)std::get<int64_t>(args2[2]);
if(!native->GetDestroyed() && byteArray != nullptr && ((offset + length) <= byteArray->data.size()))
{
auto strm = static_cast<TlsClientStream*>(native->GetPointer());
return strm->Read(byteArray->data.data()+offset, length);
}
}
return Undefined();
});
dict->DeclareFunction(ls.GetGC(),"Write","Write data to Tls Connection",{"buffer","offset","length"},[native](GCList& ls2, std::vector<TObject> args2)->TObject {
if(args2.size() == 3 && std::holds_alternative<THeapObjectHolder>(args2[0]) && std::holds_alternative<int64_t>(args2[1]) && std::holds_alternative<int64_t>(args2[2]))
{
auto byteArray = dynamic_cast<TByteArray*>(std::get<THeapObjectHolder>(args2[0]).obj);
size_t offset = (size_t)std::get<int64_t>(args2[1]);
size_t length = (size_t)std::get<int64_t>(args2[2]);
if(!native->GetDestroyed() && byteArray != nullptr && ((offset + length) <= byteArray->data.size()))
{
auto strm = static_cast<TlsClientStream*>(native->GetPointer());
return strm->Write(byteArray->data.data()+offset, length);
}
}
return Undefined();
});
dict->DeclareFunction(ls.GetGC(),"Close","Close Tls Connection",{},[native](GCList& ls2, std::vector<TObject> args2)->TObject {
if(!native->GetDestroyed())
{
native->Destroy();
}
return Undefined();
});
return dict;
}
}
return Undefined();
}
static TObject Crypto_TlsServer(GCList& ls, std::vector<TObject> args)
{
//TlsServerStream(GC* gc,std::string cert, std::string chain, std::string privkey, TCallable* read, TCallable* write, TCallable* close)
if(args.size() == 6 && std::holds_alternative<std::string>(args[0]) && std::holds_alternative<std::string>(args[1]) && std::holds_alternative<std::string>(args[2]) && std::holds_alternative<THeapObjectHolder>(args[3]) && std::holds_alternative<THeapObjectHolder>(args[4]) && std::holds_alternative<THeapObjectHolder>(args[5]))
{
std::string cert = std::get<std::string>(args[0]);
std::string chain = std::get<std::string>(args[1]);
std::string privkey = std::get<std::string>(args[2]);
TCallable* read = dynamic_cast<TCallable*>(std::get<THeapObjectHolder>(args[3]).obj);
TCallable* write = dynamic_cast<TCallable*>(std::get<THeapObjectHolder>(args[4]).obj);
TCallable* close = dynamic_cast<TCallable*>(std::get<THeapObjectHolder>(args[5]).obj);
if(read != nullptr && write != nullptr && close != nullptr)
{
auto serverStream = new TlsServerStream(ls.GetGC(),cert,chain,privkey,read,write,close);
if(!serverStream->success)
{
serverStream->Close();
delete serverStream;
return nullptr;
}
TNative* native = TNative::Create(ls,static_cast<void*>(serverStream),[](void* ptr)->void {
if(ptr == nullptr) return;
TlsServerStream* strm = static_cast<TlsServerStream*>(ptr);
strm->Close();
delete strm;
});
TDictionary* dict = TDictionary::Create(ls);
ls.GetGC()->BarrierBegin();
dict->SetValue("_native",native);
ls.GetGC()->BarrierEnd();
dict->DeclareFunction(ls.GetGC(),"Read","Read data from Tls Connection",{"buffer","offset","length"},[native](GCList& ls2, std::vector<TObject> args2)->TObject {
if(args2.size() == 3 && std::holds_alternative<THeapObjectHolder>(args2[0]) && std::holds_alternative<int64_t>(args2[1]) && std::holds_alternative<int64_t>(args2[2]))
{
auto byteArray = dynamic_cast<TByteArray*>(std::get<THeapObjectHolder>(args2[0]).obj);
size_t offset = (size_t)std::get<int64_t>(args2[1]);
size_t length = (size_t)std::get<int64_t>(args2[2]);
if(!native->GetDestroyed() && byteArray != nullptr && ((offset + length) <= byteArray->data.size()))
{
auto strm = static_cast<TlsServerStream*>(native->GetPointer());
return strm->Read(byteArray->data.data()+offset, length);
}
}
return Undefined();
});
dict->DeclareFunction(ls.GetGC(),"Write","Write data to Tls Connection",{"buffer","offset","length"},[native](GCList& ls2, std::vector<TObject> args2)->TObject {
if(args2.size() == 3 && std::holds_alternative<THeapObjectHolder>(args2[0]) && std::holds_alternative<int64_t>(args2[1]) && std::holds_alternative<int64_t>(args2[2]))
{
auto byteArray = dynamic_cast<TByteArray*>(std::get<THeapObjectHolder>(args2[0]).obj);
size_t offset = (size_t)std::get<int64_t>(args2[1]);
size_t length = (size_t)std::get<int64_t>(args2[2]);
if(!native->GetDestroyed() && byteArray != nullptr && ((offset + length) <= byteArray->data.size()))
{
auto strm = static_cast<TlsServerStream*>(native->GetPointer());
return strm->Write(byteArray->data.data()+offset, length);
}
}
return Undefined();
});
dict->DeclareFunction(ls.GetGC(),"Close","Close Tls Connection",{},[native](GCList& ls2, std::vector<TObject> args2)->TObject {
if(!native->GetDestroyed())
{
native->Destroy();
}
return Undefined();
});
return dict;
}
}
return Undefined();
}
static TObject Crypto_Sha1(GCList& ls, std::vector<TObject> args)
{
@ -750,6 +200,60 @@ namespace Tesses::CrossLang
return dict;
}
static TObject Crypto_Base64Encode(GCList& ls, std::vector<TObject> args)
{
TByteArray* byteArray;
int64_t offset;
int64_t length;
if(GetArgumentHeap(args,0,byteArray) && GetArgument(args,1,offset) && GetArgument(args,2,length))
{
std::string str={};
size_t olen;
size_t off = (size_t)offset;
size_t len = (size_t)length;
len = std::min(std::min(byteArray->data.size(),len-off),len);
if(len > 0)
{
mbedtls_base64_encode((uint8_t*)str.data(), 0, &olen, byteArray->data.data()+offset,len);
str.resize(olen);
if(mbedtls_base64_encode((uint8_t*)str.data(), olen, &olen, byteArray->data.data()+offset,len)==0)
{
return str;
}
}
return "";
}
}
static TObject Crypto_Base64Decode(GCList& ls, std::vector<TObject> args)
{
std::string str;
if(GetArgument(args,0,str))
{
size_t olen;
TByteArray* bArray = TByteArray::Create(ls);
mbedtls_base64_decode(bArray->data.data(), 0, &olen, (const uint8_t*)str.data(),str.size());
str.resize(olen);
if(mbedtls_base64_decode(bArray->data.data(), olen, &olen, (const uint8_t*)str.data(),str.size())==0)
{
return str;
}
}
}
#endif
void TStd::RegisterCrypto(GC* gc,TRootEnvironment* env)
{
@ -759,14 +263,10 @@ namespace Tesses::CrossLang
GCList ls(gc);
TDictionary* dict = TDictionary::Create(ls);
//dict->DeclareFunction(gc, "Decode","Deserialize Json",{"Json string"},Json_Decode);
//dict->DeclareFunction(gc, "Encode","Serialize Json",{"any","$indent"},Json_Encode);
dict->DeclareFunction(gc, "Sha1","Sha1 Algorithm (needed for WebSocket handshake/BitTorrent etc) (don't use unless you have no other choice)",{},Crypto_Sha1);
dict->DeclareFunction(gc, "Sha256","Sha256 Algorithm",{"$is224"},Crypto_Sha256);
dict->DeclareFunction(gc, "Sha512","Sha512 Algorithm",{"$is384"},Crypto_Sha512);
dict->DeclareFunction(gc, "TlsClient", "Create TLS client for HTTPS client",{"domain","chain","verify","read","write","close"},Crypto_TlsClient);
dict->DeclareFunction(gc, "TlsServer", "Create TLS server for HTTPS server",{"cert","chain","privkey","read","write","close"},Crypto_TlsServer);
dict->DeclareFunction(gc, "Base64Encode","Sha512 Algorithm",{"data"},Crypto_Base64Encode);
gc->BarrierBegin();
env->DeclareVariable("Crypto", dict);
gc->BarrierEnd();

View File

@ -8,7 +8,6 @@ namespace Tesses::CrossLang
TDictionary* dict;
dict->items.begin();
if(args.size() == 1 && std::holds_alternative<THeapObjectHolder>(args[0]))
{
auto item = dynamic_cast<TDictionary*>(std::get<THeapObjectHolder>(args[0]).obj);

View File

@ -35,6 +35,10 @@ namespace Tesses::CrossLang
}
return nullptr;
}
static TObject FS_CreateMemoryFilesystem(GCList& ls, std::vector<TObject> args)
{
return TVFSHeapObject::Create(ls, new Tesses::Framework::Filesystem::MemoryFilesystem());
}
static TObject FS_CreateFilesystem(GCList& ls, std::vector<TObject> args)
{
@ -71,6 +75,41 @@ namespace Tesses::CrossLang
}
return nullptr;
}
static TObject FS_CreateArchive(GCList& ls, std::vector<TObject> args)
{
TVFSHeapObject* vfs;
TStreamHeapObject* strm;
std::string name;
std::string version;
std::string info;
TVMVersion version2;
if(GetArgumentHeap(args,0,vfs) && GetArgumentHeap(args,1,strm) && GetArgument(args,2,name) && GetArgument(args,3,version) && GetArgument(args,4,info) && TVMVersion::TryParse(version,version2))
{
CrossArchiveCreate(vfs->vfs,strm->stream,name,version2,info);
}
return nullptr;
}
static TObject FS_ExtractArchive(GCList& ls, std::vector<TObject> args)
{
TVFSHeapObject* vfs;
TStreamHeapObject* strm;
if(GetArgumentHeap(args,0,strm) && GetArgumentHeap(args,1,vfs))
{
auto res = CrossArchiveExtract(strm->stream,vfs->vfs);
TDictionary* dict = TDictionary::Create(ls);
ls.GetGC()->BarrierBegin();
dict->SetValue("Name",res.first.first);
dict->SetValue("Version",res.first.second.ToString());
dict->SetValue("Info",res.second);
ls.GetGC()->BarrierEnd();
return dict;
}
return nullptr;
}
void TStd::RegisterIO(GC* gc,TRootEnvironment* env,bool enableLocalFilesystem)
{
@ -93,6 +132,10 @@ namespace Tesses::CrossLang
dict->DeclareFunction(gc, "MemoryStream","Create a memory stream",{"writable"}, FS_MemoryStream);
dict->DeclareFunction(gc, "CreateStream","Create stream", {"strm"},FS_CreateStream);
dict->DeclareFunction(gc, "CreateFilesystem","Create filesystem", {"fs"},FS_CreateFilesystem);
dict->DeclareFunction(gc, "CreateMemoryFilesystem","Create in memory filesystem", {},FS_CreateMemoryFilesystem);
dict->DeclareFunction(gc, "CreateArchive", "Create a crvm archive",{"fs","strm","name","version","info"},FS_CreateArchive);
dict->DeclareFunction(gc,"ExtractArchive", "Extract a crvm archive",{"strm","vfs"},FS_ExtractArchive);
env->DeclareVariable("FS", dict);
gc->BarrierEnd();
}

View File

@ -12,6 +12,31 @@ namespace Tesses::CrossLang
{
#if defined(CROSSLANG_ENABLE_JSON)
static bool IsValidForJson(TObject v)
{
if(std::holds_alternative<std::nullptr_t>(v)) return true;
if(std::holds_alternative<int64_t>(v)) return true;
if(std::holds_alternative<double>(v)) return true;
if(std::holds_alternative<bool>(v)) return true;
if(std::holds_alternative<std::string>(v)) return true;
if(std::holds_alternative<THeapObjectHolder>(v))
{
auto res = std::get<THeapObjectHolder>(v);
auto ls = dynamic_cast<TList*>(res.obj);
auto dict = dynamic_cast<TDictionary*>(res.obj);
if(ls != nullptr) return true;
if(dict != nullptr) return true;
}
return false;
}
static json_t* JsonSerialize(TObject v)
{
if(std::holds_alternative<std::nullptr_t>(v)) return json_null();
@ -34,7 +59,9 @@ namespace Tesses::CrossLang
json_t* items=json_array();
for(int64_t i = 0; i < ls->Count(); i++)
{
json_array_append_new(items,JsonSerialize(ls->Get(i)));
auto val = ls->Get(i);
if(IsValidForJson(val))
json_array_append_new(items,JsonSerialize(val));
}
return items;
}
@ -44,6 +71,7 @@ namespace Tesses::CrossLang
json_t* obj = json_object();
for(auto item : dict->items)
{
if(IsValidForJson(item.second))
json_object_setn_new(obj, item.first.c_str(), item.first.size(),JsonSerialize(item.second));
}
return obj;

View File

@ -329,6 +329,14 @@ namespace Tesses::CrossLang
}
return Undefined();
}
static TObject Net_HtmlEncode(GCList& ls, std::vector<TObject> args)
{
if(args.size() == 1 && std::holds_alternative<std::string>(args[0]))
{
return HttpUtils::HtmlEncode(std::get<std::string>(args[0]));
}
return Undefined();
}
static TObject Net_UrlEncode(GCList& ls, std::vector<TObject> args)
{
if(args.size() == 1 && std::holds_alternative<std::string>(args[0]))
@ -530,6 +538,8 @@ namespace Tesses::CrossLang
TDictionary* dict = TDictionary::Create(ls);
TDictionary* http = TDictionary::Create(ls);
http->DeclareFunction(gc, "HtmlEncode","Html encode",{"param"}, Net_HtmlEncode);
http->DeclareFunction(gc, "UrlEncode","Url encode query param",{"param"}, Net_UrlEncode);
http->DeclareFunction(gc, "UrlDecode","Url decode query param",{"param"}, Net_UrlDecode);
http->DeclareFunction(gc, "UrlPathEncode","Url encode path",{"path"}, Net_UrlPathEncode);