The Fidonet Squish module is able to read headers and texts of Fidonet echomail messages from Squish message bases according to FSP-1037 draft 3.
When you require()
the installed module, you get a constructor that uses the path to a Squish echo base as its parameter:
var Squish = require('fidonet-squish');
var echobase = Squish(basePath);
Names of echo base files are generated by appending lowercase extensions (.sql
, .sqi
, .sqd
) to the given path.
The constructed object has the following methods:
Asynchronously reads the .sql
file (Squish lastread storage) into memory and parses it, populating the variable lastreads
Asynchronously reads the .sqi
file (Squish index) into memory and parses that index, populating the object's .indexStructure
property with an array of objects with the following properties:
-
CRC
— Squish hash. -
offset
— the physical offset of the message's data in the.sqd
(header) file. -
MessageNum0
— a message's rebased (zero-based) internal number. Starts from0
(zero), i.e..indexStructure[0].MessageNum0 === 0
. Thebasemsgnum
value from the “Squish fixed header” (see below) should be added to generate the actual internal number of a message. Deleted messages leave gaps in that numbering (such as.indexStructure[i].MessageNum0 > i
and.indexStructure[i].MessageNum0 > .indexStructure[i-1].MessageNum0 + 1
) until the message base is packed by an echoprocessor.
Asynchronously reads the .sqd
file (Squish data) into memory, populating the object's .SQD
property with a raw Buffer. Then calls callback(error)
.
The data is cached. Subsequent calls to .readSQD
won't repeat the reading operation unless the object's .SQD
property is null
.
Returns .indexStructure.length
property (or undefined
when .indexStructure
is null
).
...
...
...
...
...
...
Return msgnum
for MsgId
Return hash of buffer
...
Works exactly as .numbersForMSGID
, but an array of messages' headers (instead of their numbers) is given to the callback: callback(error, headers)
.
Each of the headers (found for the given MSGID or MSGIDs) has the same properties as a result of .readHeader
. Each header is additionally given another property (MessageIndex
) that contains its number as found in .numbersForMSGID
. (Do not confuse it with JAM's internal MessageNumber
property of the same header object.)
Using the given message's number, finds out that message's parent in the tree of replies (i.e. the message that the given message replies to), calling .readHeader
and .readFixedHeaderInfoStruct
in the process. Then callback(error, parentNumber)
is called, where parentNumber === null
if the parent message cannot be found (for example, if the given message is not a reply).
Possible number values (of the given and the found number) start from (and including) 1
and go to (and including) .size()
without gaps. (The internal MessageNumber
values are used only internally in this method.)
Using the given message's number, finds out the number of its first child in the tree of replies (i.e. the first of the messages that reply to the given message), calling .readHeader
and .readFixedHeaderInfoStruct
in the process. Then callback(error, childNumber)
is called, where childNumber === null
if the given message has no replies.
Possible number values (of the given and the found number) start from (and including) 1
and go to (and including) .size()
without gaps. (The internal MessageNumber
values are used only internally in this method.)
Using the given message's number, finds out the number of its next sibling in the tree of replies (i.e. the next of the messages that reply to the given message's parent), calling .readHeader
and .readFixedHeaderInfoStruct
in the process. Then callback(error, siblingNumber)
is called, where siblingNumber === null
if such sibling message cannot be found (for example, if the given message is not a reply or if it's the last of the replies ever given to its parent message).
Possible number values (of the given and the found number) start from (and including) 1
and go to (and including) .size()
without gaps. (The internal MessageNumber
values are used only internally in this method.)
Using the given message's number, finds out the numbers of its children in the tree of replies (i.e. the messages that reply to the given message), calling .get1stChildNumber
and (probably) .getNextChildNumber
in the process. Then callback(error, childrenNumbers)
is called, where childrenNumbers
is an array (can be []
if the given message has no replies).
Possible number values (of the given and the found numbers) start from (and including) 1
and go to (and including) .size()
without gaps. (The internal MessageNumber
values are used only internally in this method.)
...
The module does not lock any files and does not create any “lock files” (flag files, semaphore files). The module's caller should control the access to the message base.
That's because Fidonet software uses different locking methods. For example, GoldED+ uses OS file locking (as seen in its source code) and HPT uses a lock file (the file's name is given on the LockFile
line in the HPT's config). It would complicate the module if it were the module's job to know what locking is necessary.