• src/sbbs3/js_filebase.cpp

    From Rob Swindell (on Windows 11)@VERT to Git commit to main/sbbs/master on Thu May 14 02:49:16 2026
    https://gitlab.synchro.net/main/sbbs/-/commit/1767046fd69fbcda29d09372
    Modified Files:
    src/sbbs3/js_filebase.cpp
    Log Message:
    js_filebase: initialize SMB_FILE_DIRECTORY for fresh ad-hoc (is_path) bases

    For an is_path FileBase, js_open() called smb_open() directly instead
    of smb_open_dir(). smb_open_dir() initializes a fresh file base by
    setting status.attr = SMB_FILE_DIRECTORY (and any dir-specific limits)
    then calling smb_create() to write the SMB header to disk. Plain
    smb_open() does neither — it just opens the .shd file (creating an
    empty one if absent) and reads existing status only if the file is
    already big enough.

    Without SMB_FILE_DIRECTORY in status.attr, smb_idxreclen() (smblib.c)
    returns sizeof(idxrec_t) (smaller, msg-style) instead of
    sizeof(fileidxrec_t). That meant smb_addfile() wrote a corrupted
    .sid index — small msg records where the rest of FileBase expects
    file records — and loadfilenames(), iterating the index using sizeof(fileidxrec_t), saw garbage / zero records. Net effect: add()
    returned true, but get(), get_list(), and get_names() never found the
    added file.

    Reproducer:
    var fb = new FileBase(system.temp_dir + "x", true);
    fb.open();
    fb.add({name: "f.dat", desc: "d", from: "u"});
    fb.get("f.dat"); // -> null
    fb.get_list().length; // -> 0

    Fix: when js_open()'s !dirnum_is_valid (is_path) branch is taken and
    smb_open() succeeds against an empty .shd, set status.attr =
    SMB_FILE_DIRECTORY and call smb_create() — mirroring smb_open_dir()'s first-time-init for ad-hoc bases. Like the savemsg/votemsg fix in
    e5ddda76d, this is a latent bug exposed when 93b4d946c added the
    is_path constructor option.

    ---
    ■ Synchronet ■ Vertrauen ■ Home of Synchronet ■ [vert/cvs/bbs].synchro.net
  • From Rob Swindell (on Debian Linux)@VERT to Git commit to main/sbbs/master on Mon Sep 21 22:21:21 2026
    https://gitlab.synchro.net/main/sbbs/-/commit/5185eec5a6d9d53581014588
    Modified Files:
    src/sbbs3/js_filebase.cpp
    Log Message:
    FileBase.update(): don't destroy stored text the caller didn't supply

    A file object with no 'extdesc' or 'auxdata' property meant "write NULL
    over whatever is stored", because those two live in the message data
    blocks and the changed-text path removes and re-adds the record. Every
    other property already means "leave it alone" when absent, since parse_file_properties() only writes a header field when the property
    exists on the object.

    So a script that reads a record and hands the object back silently
    dropped both: rehashfiles.js, updatefiles.js, readdfiles.js and
    testbuild.js all fetch below the detail level of the text they then
    overwrite, and fileman.js drops auxdata whenever a sysop edits an
    extended description.

    Load the record at file_detail_auxdata, as renew() already does, so the
    stored values are there to keep, and fall back to them when the caller
    supplied none. An empty string still clears, so either one can still
    be removed deliberately.

    Extract the DIZ only when use_diz_always was requested or the file has
    no extended description to keep. It used to replace a hand-edited
    description with the archive's FILE_ID.DIZ whenever the caller simply
    did not mention the extended description.

    Compare the loaded auxdata with trailing whitespace trimmed, as the
    extended description already was, so handing back identical auxdata no
    longer reads as a change and no longer forces a remove and re-add.

    Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

    ---
    ■ Synchronet ■ Vertrauen ■ Home of Synchronet ■ [vert/cvs/bbs].synchro.net