Add global music player, invoicing/payment system, account subpages, mail account admin, and the qualityiron.vegas Jet 2.0 port

Jet interpreter (Tag.cpp, __call.cpp, __imap*.cpp/h, __smtpsend.cpp/h,
__imapemptyfolder.cpp/h - new): assorted parser/tag fixes found across
this work - a stray literal-tag-in-comment and backslash-quote parser
corruption class, a dangling-pointer fix, a __call.cpp fd leak, IMAP
folder-management tags, multi-account/per-host IMAP support, and a
smtpsend Message-ID fix.

barant.com site (jetc/barant-site/):
- A site-wide persistent music player (header band, playlist/queue,
  stereo FFT EQ, session-persisted state) fed by new library/
  ianslibrary/music song-list subpages.
- /account split into info/phones/invoices subpages; a full invoicing
  and Square payment system (create/edit/copy/pay/email invoice);
  admin invoice management and mail-account management subpages.
- /services split into overview/hosting/siptrunking/documents
  subpages, retiring the old standalone pages.
- SIPPHONE.tag: a Jet 2.0 WebRTC softphone tag.
- main.css/spa.js/email.js: the SPA loading indicator, the music
  player band styling, and assorted fixes accumulated alongside this
  work.

qualityiron-site/: the qualityiron.vegas job/contractor/customer/
document management app, ported from its original Jet 1.4 codebase to
Jet 2.0 as barant.coms APIServers second multi-tenant site.

wcwc/wcwc.jet: the WCWC site Jet source (wcwc.jtc build output not
included).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
Brad ArantandClaude Sonnet 5 committed 2026-10-06 17:42:01 +00:00
1 parent 905fbafa5a
commit b8f7793773
406 files changed
+15803 -587

No files matched your search

+73 -26
View File
@@ -7,13 +7,15 @@
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <cerrno>
#include <cstring>
#include <filesystem>
namespace jet {
__call::__call(coreutils::ZString &in, coreutils::MString &parentOut, Global &global, Tag *parent, Tag *local) : Tag(in, parentOut, global, parent, local) {
if(hasContainer && keywordDefined("input"))
throw coreutils::Exception("call tag cannot have both input keyword and have a container.");
throw coreutils::Exception("call tag cannot have both input keyword and have a container.");
if(!keywordDefined("pgm"))
throw coreutils::Exception("pgm keyword must be specified.");
for(ix = 0; ix < 50; ++ix)
@@ -35,48 +37,93 @@ namespace jet {
} else
break;
}
pipe(fdo);
// pipe()/fork() both used to go unchecked here - on failure (most
// realistically pipe() hitting the process's open-file-descriptor
// limit, see below) fdo[] is left holding whatever garbage was
// already on the stack/in this member array, and every use of it
// after this point (close(), read(), and - for a failed fork() -
// waitpid(-1, ...), which has the special POSIX meaning "wait for
// ANY child" rather than "wait for none") operates on that garbage
// or on an unrelated process instead of safely no-oping. That's a
// real, confirmed mechanism for exactly the kind of sporadic
// memory corruption this codebase has seen: closing/reading a
// stale fd that coincidentally matches another subsystem's live
// socket, or reaping a concurrent request's own child out from
// under it.
if(pipe(fdo) != 0)
throw coreutils::Exception("call: pipe() failed - " + std::string(strerror(errno)), __FILE__, __LINE__, 500);
pid = fork();
if(pid < 0) {
close(fdo[0]);
close(fdo[1]);
throw coreutils::Exception("call: fork() failed - " + std::string(strerror(errno)), __FILE__, __LINE__, 500);
}
if(pid == 0) {
close(fdo[0]);
dup2(fdo[1], 1);
if(hasContainer) {
pipe(fdi);
if(fork() == 0) {
close(fdi[0]);
write(fdi[1], container.getData(), container.getLength());
close(fdi[1]);
exit(0);
if(hasContainer) {
if(pipe(fdi) == 0) {
pid_t innerPid = fork();
if(innerPid == 0) {
close(fdi[0]);
write(fdi[1], container.getData(), container.getLength());
close(fdi[1]);
_exit(0);
} else if(innerPid > 0) {
close(fdi[1]);
dup2(fdi[0], 0);
close(fdi[0]);
} else {
close(fdi[0]);
close(fdi[1]);
}
}
close(fdi[1]);
dup2(fdi[0], 0);
} else if(keywordDefined("input")) {
coreutils::MString input(resolveKeyword("input"));
pipe(fdi);
if(fork() == 0) {
close(fdi[0]);
write(fdi[1], input.getData(), input.getLength());
close(fdi[1]);
exit(0);
if(pipe(fdi) == 0) {
pid_t innerPid = fork();
if(innerPid == 0) {
close(fdi[0]);
write(fdi[1], input.getData(), input.getLength());
close(fdi[1]);
_exit(0);
} else if(innerPid > 0) {
close(fdi[1]);
dup2(fdi[0], 0);
close(fdi[0]);
} else {
close(fdi[0]);
close(fdi[1]);
}
}
close(fdi[1]);
dup2(fdi[0], 0);
}
rc = execvpe(argv[0], argv, global.envp);
close(fdo[1]);
exit(errno);
_exit(errno);
}
close(fdo[1]);
if(keywordDefined("name")) {
coreutils::MString value;
value.read(fdo[0]);
storeVariable(resolveKeyword("name"), value, resolveKeyword("scope"));
} else
out.read(fdo[0]);
} else
out.read(fdo[0]);
// fdo[0] (the read end, still open in this - the parent - process)
// was never closed here before, leaking one file descriptor on
// every single <call> invocation for the life of the process.
// Harmless-looking for an occasional <call>, but <call> is used
// throughout this codebase (jq/curl parsing, mailcreate, this
// session's own per-line-item JS-escaping on the invoice editor,
// which alone can issue a double-digit number of calls per page
// load) - repeated, routine use was slowly accumulating leaked
// fds for as long as this process stayed up, eventually hitting
// the real open-files limit and turning into exactly the pipe()
// failures (and the undefined behavior above) this fix addresses.
close(fdo[0]);
waitpid(pid, &status, 0);
if(keywordDefined("error")) {
if(keywordDefined("error")) {
global.variables[resolveKeyword("error")] = (status >> 8 & 255);
}
}
}
}