|
|
1.1 root 1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20: Synchronet Message Base Specification
21: Version 1.21
22: Updated 08/31/95
23:
24: Copyright 1995 Digital Dynamics
25:
26: PO Box 501
27: Yorba Linda, CA 92686
28:
29: Voice: 714-529-6328 BBS: 714-529-9525 V.32/V.32bis
30: FAX: 714-529-9721 714-529-9547 V.FC
31: Fido: 1:103/705 ftp: netcom.com /pub/sb/sbbs
32:
33: Table of Contents
34: =================
35: &&Contents
36:
37: Introduction....................................................@@INTRO___
38: Implementation Levels...........................................@@IMPLEVEL
39: Definitions.....................................................@@DEFINES_
40: Acronyms................................................@@ACRONYMS
41: Data Types..............................................@@DATATYPE
42: File Formats....................................................@@FILEFORM
43: Index.....................(*.SID).......................@@SID_FORM
44: Header....................(*.SHD).......................@@SHD_FORM
45: Header Allocation.........(*.SHA).......................@@SHA_FORM
46: Data......................(*.SDT).......................@@SDT_FORM
47: Data Allocation...........(*.SDA).......................@@SDA_FORM
48: CRC History...............(*.SCH).......................@@SCH_FORM
49: Header Field Types..............................................@@HFIELD_T
50: Data Field Types................................................@@DFIELD_T
51: Messsage Attributes.............................................@@ATTRBITS
52: Translation Types...............................................@@XLATTYPE
53: Agent Types.....................................................@@AGENTTYP
54: Network Types...................................................@@NETWORKS
55: Media Types.....................................................@@MEDIATYP
56: Message Storage Pseudo Code.....................................@@STORPCOD
57: Message Retrieval Pseudo Code...................................@@READPCOD
58: SMBUTIL.........................................................@@SMBUTIL_
59: CHKSMB..........................................................@@CHKSMB__
60: FIXSMB..........................................................@@FIXSMB__
61: SMBLIB (C library)..............................................@@SMBLIB__
62: Data Types and Constants..(SMBDEFS.H)...................@@SMBDEFS_
63: Global Variables..........(SMBVARS.C)...................@@SMBVARS_
64: Function Prototypes.......(SMBLIB.H)....................@@SMBLIB.H
65: Library Functions.........(SMBLIB.C)....................@@SMBLIB.C
66: Miscellaneous.............(CRC*.* and LZH.*)............@@SMB_MISC
67: SMBLIB Storage Example..........................................@@SMB_PUT_
68: SMBLIB Retrieval Example........................................@@SMB_GET_
69: SMBLIB Performance Issues.......................................@@PERFORM_
70: Bibliography....................................................@@BIBLIOGR
71: Implementations.................................................@@IMPLEMEN
72:
73: Introduction
74: ============
75: &&Introduction
76: $$INTRO___
77:
78: Q. What is SMB?
79:
80: A. SMB (Synchronet Message Base) is a technical specification for the storage
81: format of electronic mail messages. These e-mail messages may all be
82: contained in one database, or, more commonly, separated into catagorized
83: databases. These message databases (or message bases) are also referred to
84: as "sub-boards", "forums", "conferences", and "SIGs". The messages may be
85: directed to an individual person, sent to a group of individuals, or sent
86: to everyone who can read messages in that message base. Messages may be
87: created and read soley at one physical location, or imported from and
88: exported to a message network that may span continents. Message bases that
89: are connected to a message network are often called "echoes".
90:
91:
92: Q. Why SMB?
93:
94: A. The Synchronet Message Base is designed to store high volumes of messages
95: while maintaining optimum search, retrieval, and creation performance.
96: These messages are not limited to mere text. In addition to text, SMB
97: defines the storage of digitized sound, MIDI, graphics, fonts, animation,
98: as well as other multimedia data and triggers for localized multimedia.
99: SMB thrives on a multi-user environment where messages are being created,
100: read, modified, and deleted by multiple tasks simultaneously. With the
101: large message networks of today being the rule, rather than the exception,
102: and high volumes of messages being imported on a daily, sometimes hourly
103: basis, creation and deletion speed is of the utmost importance. This is
104: where SMB really shines. Being extensible enough to handle message formats
105: from networks of today and tomorrow, and fast enough to import more messages
106: that humanly readable, the SMB format will more than meet your message
107: storage needs.
108:
109:
110: Q. Why a specification?
111:
112: A. Message bases are often accessed and modified by a number of different
113: programs. Often these programs are developed by individuals or companies
114: other than the original designer of the message base format. This
115: specification is an attempt to aid developers in creating programs that
116: access or modify a message base stored in the SMB format.
117:
118:
119: Q. Who can use this specification?
120:
121: A. Anyone that has interest in the Synchronet Message Base format at either
122: an educational or professional level. Specifically, software developers
123: interested or currently involved in the development of message readers,
124: editors, echomail (toss/scan) programs, message transfer agents (MTAs),
125: network gateways, and bulletin board systems. Much of the information in
126: this specification is intended for those with preexisting programming
127: knowledge, so those with little or no programming experience may find it
128: hard to comprehend.
129:
130:
131: Q. What does the SMB specification include?
132:
133: A. The text you are reading is part of the SMB specification: a single text
134: document that defines the storage format of each of the six files of an
135: SMB format message base and how they are related to each other.
136:
137: Included with this specification is C source code to be used as an example
138: to programmers of how to access an SMB format message base and public domain
139: library functions (SMBLIB) that can be compiled and linked into programs
140: that access an SMB format message base developed by third parties. An SMB
141: utility program (SMBUTIL) is also included with C source code as an example
142: of how to use the SMBLIB functions.
143:
144:
145: Q. Where did the SMB specification come from?
146:
147: A. Digital Dynamics (southern California based software development company)
148: released "Synchronet Multinode BBS Software Version 1a" in June of 1992 as
149: one of the first BBS packages to be designed from the ground-up to operate
150: in a multinode environment with incredible speed and reliability, with a
151: large suite of multinode specific features and design innovations.
152:
153: The original message base format was designed with localized messaging and
154: low volume message networks in mind. By January of 1993, it was clear that
155: high volume message networks (FidoNet, RelayNet, Usenet, etc.) were the
156: preference of most BBS users and a new message base format was required to
157: allow for high volume message storage, improved storage, retrieval, and
158: maintenance performance, as well as lower storage space requirements.
159:
160: Rather than introduce another new message format, Digital Dynamics sought
161: to implement an existing public specification for a format that would meet
162: current and future message storage needs. More than a few specifications
163: were seriously considered at one time or another, but after careful
164: examination, design flaws and lack of extensibility eliminated them from the
165: long term plans of Digital Dynamics and Synchronet BBS Software. Thus began
166: the design of the "Synchronet Message Base" (SMB) format.
167:
168: At the request of many message related program developers, Digital Dynamics
169: created and released the SMB specification before the release of "Synchronet
170: Version 2.00" to allow lead-time on developing support programs for the new
171: format.
172:
173: Digital Dynamics strongly encourages developers of message related programs
174: (including software that directly competes with Synchronet or other Digital
175: Dynamics products) to implement support for SMB. Though this is a public
176: specification and Digital Dynamics encourages developer suggestions, it will
177: remain under the sole control of Digital Dynamics unless specifically stated
178: otherwise in a future revision of this specification.
179:
180: Digital Dynamics requests that any organizations that wish to adopt or
181: ratify this specification, in part or whole, notify Digital Dynamics through
182: any of the contact methods listed at the beginning of this document.
183:
184:
185: Q. How does SMB store messages?
186:
187: A. Each message base is stored in a set of binary files. This set consists
188: of between three and six files depending the storage method used. The base
189: filename (maximum of eight characters under DOS) is the same for all six
190: files of the same message base and unique amoung the filenames of other
191: message bases in the same directory. The six files each have a different
192: three character extension. The first character of the extension is always
193: the letter 'S' (for SMB), while the second and third characters define the
194: contents of the file.
195:
196: Two of the six files associated with each message base are not recreatable
197: and therefore are the most important when considering data integrity. These
198: two files are the data file (with a .SDT extension) and header file (.SHD
199: extension). Both of these files use 256 byte blocks and have associated
200: block allocation tables (stored in .SDA and .SHA respectively) so that
201: deleted message blocks may be used by new messages without creating odd
202: sized unused 'holes' in the files. The block allocation table files (.SDA
203: and .SHA) can be recreated with the information stored in the header (.SHD)
204: file. When using Hyper Allocation storage method, the allocation files (.SDA
205: and .SHA) are not used.
206:
207: For fast indexing, there is a small fixed length index file (with a .SID
208: extension). This file allows for the immediate location of message header
209: records based on sender's name or user number, recipient's name or user
210: number, subject, message number, or message attributes. This file can be
211: recreated with the data stored in the header (.SHD) file.
212:
213: The last file is an optional CRC history (.SCH) file. It contains 32-bit
214: CRCs of a configurable number of messages imported or created locally. This
215: is to help eliminate duplicate messages created by user or program error.
216: The CRC history file can be recreated with the combination of information
217: stored in the data (.SDT) and header (.SHD) files.
218:
219: Q. How fast do messages import into an SMB message base?
220:
221: A. This is a very important question for systems for that import large volumes
222: of messages. Of course, the answer depends on the storage format which you
223: are importing from, the average length of messages, the design of the
224: program which is peforming the import process, as well as the hardware and
225: system software being used. What's important is that SMB will allow the
226: fastest import process possible with any given combination of the above
227: factors.
228:
229: Since system storage capacity is rarely infinite, neither is the number
230: of messages which can be stored in a message base. System operators must
231: define the maximum number of messages to be stored in a message base, the
232: maximum age of the messages in that message base, or a combination of both.
233: When using the Self-packing storage method (defined later in this document),
234: the smaller the number of messages stored in a message base, the faster the
235: import process. The SMB format is flexible enough to support multiple levels
236: of import performance based on optimizations for storage space or speed.
237: Most system operators will almost invariably choose speed over space, but
238: which choices are available is determined by the importing program. This
239: specification defines three storage methods, from slowest to fastest:
240: Self-packing, Fast Allocation, and Hyper Allocation. Other options defined
241: in this specification may affect storage performance, including duplicate
242: message checking and message compression/encryption.
243:
244:
245: Q. How much storage is required for an SMB message base?
246:
247: A. The biggest factor in determining storage requirements for a message base
248: is the maximum number of messages to be stored in the base (defined by the
249: system operator) and the average size of each message. The minimum required
250: storage for a message base is 32 bytes plus 532 bytes per message (plus four
251: bytes per message if duplicate message checking is used and three bytes
252: per message if Self-packing or Fast Allocation storage methods are used).
253:
254: The SMB format was originally designed to be "self-packing", meaning purged
255: (deleted) message header and data blocks will be used automatically by new
256: messages. Relying solely on self-packing, an SMB format message base will
257: never "shrink" in size. This is not to say that it will continually "grow"
258: in size, but that without specific packing procedures, deleted message
259: blocks may remain unused for extended periods of time, meanwhile using some
260: amount of storage space that could be recovered using specific packing
261: procedures. The Fast Allocation and Hyper Allocation storage methods do not
262: use deleted message blocks for new messages so specific packing procedures
263: must be used if any messages are deleted and that storage space is to ever
264: be recovered.
265:
266: Limiting the maximum age of messages in an SMB message base is another way
267: to control the storage requirements. While maximum message age definition is
268: optional, the definition of the maximum number of messages is not.
269:
270: Q. How many messages can be stored per SMB message base?
271:
272: A. Without considering storage limitations or message data lengths greater than
273: 256, the theoretical maximum number of messages that can be stored in a
274: single SMB message base is 16.7 million. Considering the variable length
275: nature of message and header data, it is suggested that the system operator
276: allow no more than 1 million messages per base.
277:
278: To determine an estimated maximum number of messages for a message base
279: using the average message data length as a factor, use the following
280: formula:
281:
282: 4.2 billion divided by the average message length rounded up to be evenly
283: divisible by 256.
284:
285: If the average message data length is 1500 bytes, the estimated maximum
286: number of messages would be 2,734,375 (4.2 billion divided by 1536).
287:
288: Implementations of this format may be further limited by available system
289: memory.
290:
291: Implementation Levels
292: =====================
293: &&Implementation Levels
294: $$IMPLEVEL
295: The SMB format can be implemented to varying degrees between programs without
296: creating compatibilty issues. Rather than have developers specifically state
297: which features they have and have not implemented, we have defined seven levels
298: of implementation (represented by Roman numerals I through VII). For a program
299: or software package to meet an implementation level, it must have all of the
300: features listed for that level and all of those for each level below it. The
301: minimum suggested imlementation is level I. The SMBUTIL program included with
302: this specification is an example of a level I implementation with features
303: from some of the higher implementation levels.
304:
305: Level I
306: -------
307: The minimum suggested level of implementation. Messages contain merely ASCII
308: text displayable on an ANSI terminal. Messages can be added to the message
309: base and if the maximum number of messages is exceeded, messages are removed
310: or marked for deletion.
311:
312: Level II
313: --------
314: The addition of file attachments, multiple index/header entries per message
315: (multiple destinations), multiple text bodies for the separation of message
316: text and tag/origin lines (for example), forwarding, threading, and specific
317: FidoNet kludge header field support makes this level of implementation more
318: realistic for bulletin board system and EchoMail software implementation.
319:
320: Synchronet Multinode BBS Software v2.00 has a level II implementation of this
321: specification.
322:
323: Level III
324: ---------
325: This implementation adds support for translation strings defined later in this
326: document for data compression, encryption, escaping, and encoding. This level
327: is still limited to basic ASCII text and ANSI escape sequence entry and
328: retrieval.
329:
330: Synchronet Multinode BBS Software v2.10 has a level III implementation of this
331: specification.
332:
333: Level IV
334: --------
335: The storage and retrieval of embedded and attached images is added in this
336: level of implementation. Supported images are limited to single binary or text
337: data blocks that can be displayed or transferred to the user (automatically,
338: or by request) if their display and translation protocols define specific
339: support for the image type.
340:
341: Level V
342: -------
343: This level of implementation adds support for embedded and attached sound data.
344: This includes digitized sound and MIDI data. Supported sounds are limited to
345: single binary or text data blocks that can be played or transferred to the user
346: (automatically or by request) if their presentation and translation protocols
347: define specific support for the sound type.
348:
349: Level VI
350: --------
351: Localized sound and image data can be triggered by messages stored and
352: retrieved in an implementation of this level.
353:
354: Level VII
355: ---------
356: Complete multimedia support is reached in this implementation level with
357: support for embedded and attached animation, sound, and video data.
358:
359:
360: Definitions
361: ===========
362: &&Definitions
363: $$DEFINES_
364:
365: Control Characters
366: ------------------
367: When specifying control characters (ASCII 1 through 31), the caret symbol "^"
368: or the abreviation "ctrl-" followed by a character will be used to indicate the
369: value. ^A is equivalent to ASCII 1, ^B ASCII 2, etc. The case of the control
370: character is not significant (i.e. ^z and ^Z are equivalent). The control
371: character ^@ (ASCII 0) will be specified as NULL or 0.
372:
373:
374: Hexadecimal
375: -----------
376: Base sixteen numbering system which includes the digits 0-9 and A-F.
377: Hexadecimal numbers are represented in this document with a prefix of "0x" or
378: "\x" or a suffix of "h". Hexadecimal letter digits are not case sensitive
379: (i.e. the number 0xff is the same as 0xFF).
380:
381:
382: File dump
383: ---------
384: When example file dumps are displayed, the format is similar to that of the
385: output from the DOS DEBUG program. With the exception of the ASCII characters,
386: all numbers are in hexadecimal.
387:
388: Offset Byte values ASCII characters
389:
390: 000000 53 4D 42 1A 10 01 20 00 F4 01 00 00 F4 01 00 00 SMB... .�...�...
391: 000010 20 00 00 00 D0 07 00 00 D0 07 00 00 00 00 00 00 ...�...�.......
392:
393:
394: Bit values
395: ----------
396: Bit (or flag) values are represented in C notation as (1<<x) where x is the bit
397: number. (i.e. bit number 7 (1<<7) is the same as 0x80).
398:
399:
400: Word storage
401: ------------
402: All words (16-bit) and double words (32-bit) are stored in Intel 80x86 (little
403: endian) format with bytes stored from low to high (reverse of the Motorola
404: 680x0 word storage format).
405:
406: A 16-bit word with the value 1234h is stored as 34h 12h.
407:
408: Translation strings
409: -------------------
410: Translation strings (xlat variables) are arrays of words (16-bit) in the order
411: of the original storage translation. The last translation type is followed by a
412: 16-bit zero (defined later as XLAT_NONE). If there are no translations, then
413: the first and only element of the array is XLAT_NONE.
414:
415: If multiple translations are used, the translation order must be reversed
416: upon retrieval to obtain the proper data.
417:
418:
419: Local e-mail
420: ------------
421: When referring to the local e-mail message base of a Synchronet BBS, we are
422: referring specifically the message base with the name "MAIL" stored in the
423: "DATA" directory (e.g. \SBBS\DATA\MAIL).
424:
425: Messages stored in this message base are different in the following respects:
426:
427: The SMB_EMAIL status header attribute is set ON
428: Hyper Allocation storage method is not supported
429: The "To" and and "From" fields of the message indexes do NOT contain CRCs
430:
431: Acronyms:
432: ========
433: &&Definition of Acronyms
434: $$ACRONYMS
435:
436: ANSI American National Standards Institute
437: ASCII American Standard Code for Information Interchange
438: BBS Bulletin Board System
439: C The C programming language as defined by ANSI X3.159-1989
440: CR Carriage Return character (ASCII 13)
441: CRC Cyclic Redundancy Check
442: CRC-16 Standard 16-bit CRC using 1021h polynomial (seed 0)
443: CRC-32 Standard 32-bit CRC using EDB88320h polynomial (seed -1)
444: CRLF Carriage Return character followed by a Line Feed character
445: FSC FidoNet Standards Commitee (FTS proposal)
446: FTN FidoNet Technology Network
447: FTS FidoNet Technical Standard
448: LF Line Feed character (ASCII 10)
449: QWK Compressed message packet format for message reading/networking
450: RFC Request for Comments
451: SMB Synchronet Message Base
452: UT Universal Time (formerly called "Greenwhich Mean Time")
453:
454: Data types
455: ==========
456: &&Definition of Data Types
457: $$DATATYPE
458:
459: uchar Unsigned 8-bit value (0 through 255).
460: C example:
461:
462: #define uchar unsigned char
463:
464:
465: short Signed 16-bit value (-32768 through 32767).
466: "short" is a C keyword indicating "short int".
467:
468:
469: ushort Unsigned 16-bit value (0 through 65535).
470: C example:
471:
472: #define ushort unsigned short
473:
474:
475: ulong Unsigned 32-bit value (0 through 4294967295).
476: C example:
477:
478: #define ulong unsigned long
479:
480:
481: time_t Unsigned 32-bit value.
482: Seconds since 00:00 Jan 01 1970 (Unix format).
483: Used for all time/date storage in SMB as part of the when_t
484: data type. This time format will support dates through the year
485: 2105.
486: time_t is defined by ANSI C as a long (signed) which can
487: limit its date support to the year 2038 depending on the
488: library routines used.
489:
490:
491: ASCII String (aka character array) of 8-bit ASCII characters.
492: Characters with the bit 7 set (80h through FFh) represent
493: the IBM PC extended ASCII character set. When data or header
494: fields of this type are stored in the header, a NULL
495: terminator may or may not be present.
496: C example:
497:
498: uchar str[80];
499:
500:
501: ASCIIZ ASCII string with (non-optional) NULL terminator.
502: C example:
503:
504: uchar str[81];
505:
506: nulstr ASCII string immediately terminated by NULL.
507: C example:
508:
509: uchar *nulstr="";
510:
511:
512: undef Data buffer with undefined contents.
513: C example:
514:
515: uchar buf[BUF_LEN];
516:
517: when_t Date/Time stamp including time-zone adjustment information.
518: C example:
519:
520: typedef struct {
521:
522: time_t time; // Time stamp (in local time)
523: short zone; // Zone constant or Minutes (+/-) from UT
524:
525: } when_t;
526:
527: time:
528:
529: A time value of 0 is invalid and indicates an uninitialized
530: time stamp.
531:
532: Time stamps are always stored in universal time. i.e.
533: Regardless of what the local time zone is, Jan 1st 1994 00:00
534: will always be stored as 2D24BD00h.
535:
536: zone:
537:
538: If the zone is in the range -720 to +720, it represents the
539: number of minutes east or west of UT. Values in this range
540: should only be used for time zones not otherwise represented
541: here.
542:
543: If the zone is greater than 720 or less than -720, then the
544: following bits have special meaning:
545:
546: (1<<12) // Non-US time zone (east of UT)
547: (1<<13) // Non-US time zone (west of UT)
548: (1<<14) // U.S. time zone
549: (1<<15) // Daylight savings
550:
551: The lower 12 bits (0 through 11) contain the number of minutes
552: east or west of UT (not accounting for daylight savings).
553:
554: If the time zone is one specified in the U.S. Uniform Time Act,
555: the following values represent the zone:
556:
557: AST 0x40F0 // Atlantic (-04:00)
558: EST 0x412C // Eastern (-05:00)
559: CST 0x4168 // Central (-06:00)
560: MST 0x41A4 // Mountain (-07:00)
561: PST 0x41E0 // Pacific (-08:00)
562: YST 0x421C // Yukon (-09:00)
563: HST 0x4258 // Hawaii/Alaska (-10:00)
564: BST 0x4294 // Bering (-11:00)
565:
566: With bit 15 set, the following values represent the same zone
567: with the presence of daylight savings:
568:
569: ADT 0xC0F0 // Atlantic (-03:00)
570: EDT 0xC12C // Eastern (-04:00)
571: CDT 0xC168 // Central (-05:00)
572: MDT 0xC1A4 // Mountain (-06:00)
573: PDT 0xC1E0 // Pacific (-07:00)
574: YDT 0xC21C // Yukon (-08:00)
575: HDT 0xC258 // Hawaii/Alaska (-09:00)
576: BDT 0xC294 // Bering (-10:00)
577:
578: The following non-standard time zone specifications may also be
579: used:
580:
581: MID 0x2294 // Midway (-11:00)
582: VAN 0x21E0 // Vancouver (-08:00)
583: EDM 0x21A4 // Edmonton (-07:00)
584: WIN 0x2168 // Winnipeg (-06:00)
585: BOG 0x212C // Bogota (-05:00)
586: CAR 0x20F0 // Caracas (-04:00)
587: RIO 0x20B4 // Rio de Janeiro (-03:00)
588: FER 0x2078 // Fernando de Noronha (-02:00)
589: AZO 0x203C // Azores (-01:00)
590: LON 0x1000 // London (+00:00)
591: BER 0x103C // Berlin (+01:00)
592: ATH 0x1078 // Athens (+02:00)
593: MOS 0x10B4 // Moscow (+03:00)
594: DUB 0x10F0 // Dubai (+04:00)
595: KAB 0x110E // Kabul (+04:30)
596: KAR 0x112C // Karachi (+05:00)
597: BOM 0x114A // Bombay (+05:30)
598: KAT 0x1159 // Kathmandu (+05:45)
599: DHA 0x1168 // Dhaka (+06:00)
600: BAN 0x11A4 // Bangkok (+07:00)
601: HON 0x11E0 // Hong Kong (+08:00)
602: TOK 0x121C // Tokyo (+09:00)
603: SYD 0x1258 // Sydney (+10:00)
604: NOU 0x1294 // Noumea (+11:00)
605: WEL 0x12D0 // Wellington (+12:00)
606:
607: fidoaddr_t FidoNet address stored as four ushorts that represent the zone,
608: network, node, and point (in that order).
609: C example:
610:
611: typedef struct {
612:
613: ushort zone,
614: net,
615: node,
616: point;
617:
618: } fidoaddr_t;
619:
620:
621: typestr_t ASCIIZ string with ushort type prefix.
622: C example:
623:
624: typedef struct {
625:
626: ushort type; // Specifier for type of 'str'
627: uchar str[]; // ASCIIZ filename or other string data
628:
629: } typestr_t;
630:
631:
632: mattach_t File attachment information with type prefix, translation
633: string, and filename.
634: C example:
635:
636: typedef struct {
637:
638: ushort type; // Attachment type
639: ushort xlat[]; // Translations of data in attachment
640: uchar str[]; // ASCIIZ filename
641:
642: } mattach_t;
643:
644: vattach_t Video file attachment information with type, compression,
645: translation string, and filename.
646: C example:
647:
648: typedef struct {
649:
650: ushort type; // Attachment type
651: ushort comp; // Compression method
652: ushort xlat[]; // Translations of data in attachment
653: uchar str[]; // ASCIIZ filename
654:
655: } vattach_t;
656:
657: mtext_t Message text with translation string prefix.
658: C example:
659:
660: typedef struct {
661:
662: ushort xlat[]; // Translations of text
663: uchar text[]; // Actual text data
664:
665: } mtext_t;
666:
667:
668: ftext_t Formatted message text with translation string prefix and
669: format type.
670: C example:
671:
672: typedef struct {
673:
674: ushort type; // See Image Types for valid types
675: ushort xlat[]; // Translations of data
676: uchar data[]; // Actual formatted text data
677:
678: } ftext_t;
679:
680:
681: membed_t Embedded data with type prefix, translation string, and ASCIIZ
682: description.
683: C example:
684:
685: typedef struct {
686:
687: ushort type; // Specifier for type of 'dat'
688: ushort xlat[]; // Translations of embedded data
689: uchar name[]; // ASCIIZ char description of embedded data
690: uchar data[]; // Binary data
691:
692: } membed_t;
693:
694: vembed_t Embedded video data with type, compression method, translation
695: string, and ASCIIZ description.
696: C example:
697:
698: typedef struct {
699:
700: ushort type; // Specifier for type of 'dat'
701: ushort comp; // Compression method
702: ushort xlat[]; // Translations of embedded data
703: uchar name[]; // ASCIIZ char description of embedded data
704: uchar data[]; // Binary data
705:
706: } vembed_t;
707:
708: File formats
709: ============
710: &&File Formats
711: $$FILEFORM
712: &&Index (*.SID) File Format
713: $$SID_FORM
714:
715: Index File (*.SID)
716: ------------------
717: The index file for each message base contains one record per message in the
718: base. Each record is fixed length using the following format:
719:
720: Index Record:
721: ------------
722: C example:
723:
724: typedef struct {
725:
726: ushort to; // 16-bit CRC of recipient name (lower case) or user number
727: ushort from; // 16-bit CRC of sender name (lower case) or user number
728: ushort subj; // 16-bit CRC of title/subject (lower case)
729: ushort attr; // attributes (MSG_PRIVATE, MSG_READ, etc. flags)
730: ulong offset; // byte offset of message header in header file
731: ulong number; // message serial number (1 based)
732: time_t time; // import date/time stamp (Unix format)
733:
734: } idxrec_t;
735:
736:
737: Example file dump (16 messages starting with message number 15):
738: ---------------------------------------------------------------
739: 000000 36 4F 13 07 2A 77 00 00 20 00 00 00 0F 00 00 00 6O..*w.. .......
740: 000010 BE 62 76 2C 36 4F 46 0A 7F B2 00 00 20 01 00 00 �bv,6OF.�.. ...
741: 000020 10 00 00 00 C7 29 78 2C 36 4F 70 6F 46 FF 00 00 ....�)x,6OpoF�..
742: 000030 20 02 00 00 11 00 00 00 AD D3 7A 2C 70 6F 13 07 .......��z,po..
743: 000040 46 FF 00 00 20 03 00 00 12 00 00 00 D6 F8 7F 2C F�.. .......��,
744: 000050 36 4F E1 EA E7 E9 00 00 20 04 00 00 13 00 00 00 6O����.. .......
745: 000060 1E 7B 85 2C 37 0D 2E DF 4D 79 00 00 20 05 00 00 .{�,7..�My.. ...
746: 000070 14 00 00 00 5C E1 A1 2C 90 54 2D 5A 86 62 00 00 ....\�,�T-Z�b..
747: 000080 20 06 00 00 15 00 00 00 39 2E A2 2C 70 6F 1A 8B .......9.�,po.�
748: 000090 46 FF 00 00 20 07 00 00 16 00 00 00 D0 7B A8 2C F�.. .......�{�,
749: 0000A0 2E DF 1A 8B 4D 79 00 00 20 08 00 00 17 00 00 00 .�.�My.. .......
750: 0000B0 FF 7B A8 2C B4 D9 35 7C 23 B1 00 00 20 09 00 00 �{�,��5|#�.. ...
751: 0000C0 18 00 00 00 CE D4 BA 2C 36 4F BC D8 B2 E7 00 00 ....�Ժ,6O�ز�..
752: 0000D0 20 0A 00 00 19 00 00 00 14 5F C3 2C BA A8 4E B0 ........_�,��N�
753: 0000E0 67 76 00 00 20 0B 00 00 1A 00 00 00 6F 89 C3 2C gv.. .......o��,
754: 0000F0 36 4F 0C 01 19 9C 00 00 20 0C 00 00 1B 00 00 00 6O...�.. .......
755: 000100 F8 30 C6 2C 36 4F FA 48 0E 55 00 00 20 0D 00 00 �0�,6O�H.U.. ...
756: 000110 1C 00 00 00 6A 94 D3 2C 36 4F F1 CE CF A2 00 00 ....j��,6O��Ϣ..
757: 000120 20 0E 00 00 1D 00 00 00 53 DB D5 2C 8D A6 21 CE .......S��,��!�
758: 000130 F7 AB 00 00 20 0F 00 00 1E 00 00 00 31 29 DC 2C ��.. .......1)�,
759:
760:
761: Field descriptions:
762: ------------------
763: To:
764: The 'To' field is the CRC-16 of the name of the intended recipient agent of
765: this message or the intended recipient's user number. If the CRC is stored, the
766: text must be converted to lower case (A-Z changed to a-z) before the CRC is
767: calculated. If the message is forwarded to another agent, the original or new
768: index record must be changed to contain the CRC-16 of the new recipient name or
769: user number. This field must always contain the recipient user number for local
770: e-mail on a Synchronet BBS. Outbound netmail stored in the Synchronet local
771: e-mail message base will contain 0 in this field.
772:
773: From:
774: This field, similar to the 'To' field, contains the CRC-16 of the name of the
775: sending agent of this message or the sender's user number. If the CRC is
776: stored, the text must be converted to lower case (A-Z changed to a-z) before
777: the CRC is calculated. If the message is forwarded to another agent, the
778: original or new index record must be changed to contain the CRC-16 of the new
779: sender name or user number. If the message was imported into the local e-mail
780: message base on a Synchronet BBS via netmail, this field will contain 0.
781:
782: Subj:
783: The 'Subj' field contains the CRC-16 of the message's subject. The subject
784: must be converted to lower case (A-Z changed to a-z) and all preceeding
785: "re: "'s and "re:"'s removed before calculating the CRC-16.
786:
787: Attr:
788: This ushort is a bit field of the specific attributes for this message.
789: It is a clone of the 'attr' element of the msghdr_t structure.
790:
791: Offset:
792: This ulong is the offset (in bytes) in the header file for this message's
793: header record.
794:
795: Number:
796: This ulong is the serial number of this message. Valid values are 1 through
797: 0xffffffff. No two index records in the same message base may have the same
798: message number. All index records must have sequential, but not necessarily
799: consequetive, message numbers.
800:
801: Time:
802: This field is the date/time stamp the message was imported to or posted in
803: the message base. It is a clone of the 'when_imported.time' element of the
804: msghdr_t structure.
805:
806: Header File (*.SHD)
807: ===================
808: &&Header File (*.SHD) Format
809: $$SHD_FORM
810:
811: Each SMB header file is made up of two distinct sections: base header records
812: and message header records (usually the bulk of the file).
813:
814: Base Header Records:
815: -------------------
816: Base header records are blocks of data that apply to the entire message base
817: and are of variable length. This specification defines only one base header
818: record, the "Status info" (smbstatus_t) record. This status info record must be
819: the first base header record in the file and must be modified if additional
820: base header records are added.
821:
822: Additional header records allow other developers to store configuration and
823: status information particular to their application needs. It also allows for
824: future header record definitions as part of this specification without causing
825: backward compatibility issues.
826:
827: Each base header record contains a fixed length portion (smbhdr_t) and an
828: optional variable length portion.
829:
830: Whenever a base header record is read or updated (written), it must first
831: be successfully locked and subsequently unlocked.
832:
833: The first base header record (Status Info) is used as a semaphore when writing
834: to the message index (.SID) file and, when using the Hyper Allocation storage
835: method, writing to the message data (.SDT) file. This record must be
836: succesfully locked before writing and subsequently unlocked. This is to insure
837: that multiple applications simultaneously writing to the same message base
838: does result in corrrupted data.
839:
840:
841: Message Header Records:
842: ----------------------
843: Following the last base header record is the first message header record. Each
844: header record is stored in one or more 256 byte blocks. There must be exactly
845: one active message header record for every index record in the index file.
846: (Note: This does not include deleted message headers that have not been
847: overwritten by a new message header).
848:
849: Each message header record contains a fixed length portion (msghdr_t), a list
850: of zero or more fixed length data fields (dfield_t), and a list of three or
851: more variable length header fields (hfield_t).
852:
853: The value of the data stored in the zero or more unused bytes of the last
854: header record block have an undefined value, though whenever possible
855: developers should initialize to binary zero for human readability.
856:
857: Whenever a message header record is read or updated (written), it must first
858: be successfully locked and subsequently unlocked.
859:
860: Base Header Record (Fixed Portion):
861: ----------------------------------
862: C example:
863:
864: typedef struct {
865:
866: uchar id[4]; // text or binary unique hdr ID
867: ushort version; // version number (initially 100h for 1.00)
868: ushort length; // length including this struct
869:
870: } smbhdr_t;
871:
872:
873: Base Header Record Field Descriptions:
874: -------------------------------------
875: Id:
876: This is a four byte unique ID identifying the type of the base header record.
877: The bytes may contain any value, but printable ASCII characters are preferred.
878: The only ID defined in this specification is "SMB^Z" used by the Status Info
879: base header record.
880:
881: Version:
882: This is a version number of the base header record type. Base header records
883: of different versions may have different formats or contain different
884: information. This is to aid the application in determining if the record
885: is pertinent and if so, to what degree. The Status Info base header record
886: uses this version field to define the version of the format for the entire
887: message base (currently 0x121 for version 1.21).
888:
889: Length:
890: This is entire length in bytes of this header record (including both fixed
891: and variable portions).
892:
893:
894: Base Header #1 (Status info) Record (Variable Portion):
895: ------------------------------------------------------
896: C example:
897:
898: typedef struct {
899:
900: ulong last_msg; // last message number posted or imported
901: ulong total_msgs; // total messages currently in message base
902: ulong header_offset; // byte offset to first header record
903: ulong max_crcs; // Maximum number of CRCs to keep in history
904: ulong max_msgs; // Maximum number of messages to keep in base
905: ushort max_age; // Maximum age of messages (days) to keep in base
906: ushort attr; // Attribute bits
907:
908: } smbstatus_t;
909:
910: Base Header #1 (Status Info) Record (Variable Portion) Field Descriptions:
911: -------------------------------------------------------------------------
912: Last_msg:
913: This is the serial number of the last message imported or posted into this
914: message base. The index, header, and data records for this message may possibly
915: not exist (due to deletion). This field is used for determining the message
916: number to give to a new message being imported or posted into this message
917: base. This field must be updated for every message added to the message base.
918:
919: Total_msgs:
920: This is the total number of active messages currently in the message base.
921: This number should match the number of records in the index (.SID) file
922: and active header records in the header (.SHD) file. This field must be
923: updated whenever a message is added to or removed from the message base.
924:
925: Header_offset:
926: This is the byte offset to the first message header record. It is useful
927: for skipping all the base header records and going directly to the first
928: message header record.
929:
930: Max_crcs:
931: This is the maximum number of message CRCs to store in the CRC history (.SCH)
932: file for duplicate message checking. If this field contains 0, then duplicate
933: message checking is disabled.
934:
935: Max_msgs:
936: This is the preferred maximum number of messages to keep in this message
937: base as specified by the system operator. It is used by maintenance programs
938: that trim the message base down by removing old messages. This field should
939: be ignored by applications importing or posting messages allowing them to
940: exceed this maximum at will.
941:
942: Max_age:
943: This field is the maximum age (in days) of messages to keep in the message
944: base. It is used by maintenance programs to purge out-dated messages from
945: the message base.
946:
947: Attr:
948: This is a bit field containing specific attributes (or flags) that may define
949: the way messages are stored or retrieved from the this message base. The
950: following attributes are defined:
951:
952: SMB_EMAIL (1<<0)
953:
954: Indicates the message base is specifically for messages to or from local
955: users. When this bit is set, the idxrec.to and idxrec.from fields will
956: contain the user numbers (or 0 for non-user destination/source) instead of
957: the CRC-16 of the agent name.
958:
959: SMB_HYPERALLOC (1<<1)
960:
961: Indicates the message base uses the Hyper Allocation storage method. This
962: bit should not be cleared by an application without first deleting all the
963: messages in the message base. This is due to the fact the Hyper Allocation
964: is not downward compatible with the Self-packing and Fast Allocation
965: storage methods.
966:
967: When used with Synchronet BBS software, a message base must NOT have both of
968: the above attributes set. The only message base that should have the SMB_EMAIL
969: attribute set is the DATA\MAIL message base.
970:
971:
972: Base Header #1 (Status info) Record Contents:
973: --------------------------------------------
974: smbhdr.id="SMB\x1a"; // SMB^Z
975: smbhdr.version=0x121; // v1.21
976: smbhdr.length=sizeof(smbhdr_t)+sizeof(smbstatus_t); smbstatus_t status;
977:
978:
979: Additional Base Headers:
980: -----------------------
981: Additional headers from developers must have initial 8 bytes in smbhdr_t
982: format, length must include size of smbhdr_t, and header_offset of smbstatus_t
983: must be changed to include the size of the additional header(s).
984:
985:
986: Example file dump (base header portion only):
987: --------------------------------------------
988: 000000 53 4D 42 1A 20 01 20 00 F4 01 00 00 F4 01 00 00 SMB. . .�...�...
989: 000010 20 00 00 00 D0 07 00 00 D0 07 00 00 00 00 00 00 ...�...�.......
990:
991:
992: Message Header Record (Fixed portion):
993: -------------------------------------
994: C example:
995:
996: typedef struct {
997:
998: uchar id[4]; // SHD^Z (same for all types and versions)
999: ushort type; // Message type (this is the definition of type 0)
1000: ushort version; // Version of type (initially 100h for 1.00)
1001: ushort length; // Total length of fixed portion + all fields
1002: ushort attr; // Attributes (bit field) (duplicated in SID)
1003: ulong auxattr; // Auxillary attributes (bit field)
1004: ulong netattr; // Network attributes (bit field)
1005: when_t when_written; // Date/Time message was originally created
1006: when_t when_imported; // Date/Time message was imported (locally)
1007: ulong number; // Message number (unique, not necessarily seq.)
1008: ulong thread_orig; // Original message number in thread
1009: ulong thread_next; // Next message in thread
1010: ulong thread_first; // Number of first reply to this message
1011: uchar reserved[16]; // 16 reserved bytes for future use
1012: ulong offset; // Offset for buffer into data file (0 or mod 256)
1013: ushort total_dfields; // Total number of data fields
1014:
1015: } msghdr_t;
1016:
1017: typedef struct {
1018:
1019: ushort type; // See "Data Field Types" values
1020: ulong offset; // Offset into buffer
1021: ulong length; // Length of data field in buffer
1022:
1023: } dfield_t;
1024:
1025: typedef struct {
1026:
1027: ushort type; // See "Header Field Types" for values
1028: ushort length; // Length of buffer
1029: uchar dat[length];
1030:
1031: } hfield_t;
1032:
1033: Example file dump (one header record, both fixed and variable length portions):
1034: ------------------------------------------------------------------------------
1035: 000020 53 48 44 1A 00 00 20 01 F5 00 00 00 00 00 00 00 SHD... .�.......
1036: 000030 00 00 00 00 46 DB F7 2C 00 00 7D D7 29 2D 00 00 ....F��,..}�)-..
1037: 000040 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
1038: 000050 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
1039: 000060 00 00 00 00 02 00 00 00 00 00 00 00 4A 01 00 00 ............J...
1040: 000070 02 00 4A 01 00 00 53 00 00 00 00 00 13 00 4D 61 ..J...S.......Ma
1041: 000080 72 69 61 6E 6E 65 20 4D 6F 6E 74 67 6F 6D 65 72 rianne Montgomer
1042: 000090 79 30 00 0C 00 43 61 72 6F 6C 20 47 61 69 73 65 y0...Carol Gaise
1043: 0000A0 72 60 00 07 00 46 61 72 6E 68 61 6D A4 00 14 00 r`...Farnham�...
1044: 0000B0 31 3A 31 33 38 2F 31 30 32 2E 30 20 32 63 66 38 1:138/102.0 2cf8
1045: 0000C0 30 35 37 36 A5 00 14 00 31 3A 33 34 33 2F 31 30 0576�...1:343/10
1046: 0000D0 30 2E 30 20 32 63 66 33 62 39 30 61 A3 00 23 00 0.0 2cf3b90a�.#.
1047: 0000E0 31 33 38 2F 31 30 32 20 31 20 32 37 30 2F 31 30 138/102 1 270/10
1048: 0000F0 31 20 32 30 39 2F 32 30 39 20 31 30 33 2F 30 20 1 209/209 103/0
1049: 000100 33 35 35 02 00 02 00 02 00 03 00 08 00 01 00 8A 355............�
1050: 000110 00 66 00 00 00 00 00 00 00 00 00 00 00 00 00 00 .f..............
1051:
1052: Contents of example header:
1053: --------------------------
1054: id SHD^Z
1055: type 0000h
1056: version 0120h
1057: length 245
1058: attr 0000h
1059: auxattr 00000000h
1060: netattr 00000000h
1061: when_written Sat Nov 27 17:57:10 1993
1062: when_imported Tue Jan 04 15:54:21 1994
1063: number 1
1064: thread_orig 0
1065: thread_next 0
1066: thread_first 0
1067: reserved[16]
1068: offset 0
1069: total_dfields 2
1070:
1071: dfield[0].type 00h
1072: dfield[0].offset 0
1073: dfield[0].length 330
1074: dfield[1].type 02h
1075: dfield[1].offset 330
1076: dfield[1].length 83
1077:
1078: hfield[0].type 00h
1079: hfield[0].length 19
1080: hfield[0]_dat Marianne Montgomery
1081: hfield[1].type 30h
1082: hfield[1].length 12
1083: hfield[1]_dat Carol Gaiser
1084: hfield[2].type 60h
1085: hfield[2].length 7
1086: hfield[2]_dat Farnham
1087: hfield[3].type A4h
1088: hfield[3].length 20
1089: hfield[3]_dat 1:138/102.0 2cf80576
1090: hfield[4].type A5h
1091: hfield[4].length 20
1092: hfield[4]_dat 1:343/100.0 2cf3b90a
1093: hfield[5].type A3h
1094: hfield[5].length 35
1095: hfield[5]_dat 138/102 1 270/101 209/209 103/0 355
1096: hfield[6].type 02h
1097: hfield[6].length 2
1098: hfield[6]_dat 02 00
1099: hfield[7].type 03h
1100: hfield[7].length 8
1101: hfield[7]_dat 01 00 8A 00 66 00 00 00
1102:
1103: Fixed Portion Field descriptions:
1104: --------------------------------
1105: Id:
1106: This field (regardless of the header type or version) must always contain the
1107: the string "SHD^Z". This is to aid in the restoration of a corrupted header
1108: file and give a visual indication of the beginning of a new header record when
1109: viewing dumps of the header file.
1110:
1111: Type:
1112: This is the message header type. Only one type is currently defined by this
1113: specification (type 0). Any and all future header types will have the first
1114: 4 fields (10 bytes) in the same format of type 0. This allows other types
1115: (with different lengths) to be skipped because the 4th field (length) will
1116: always be in the same position.
1117:
1118: Version:
1119: This is the version of this header type. This specification defines version
1120: 1.21 of message header type 0 (stored as 121h).
1121:
1122: Length:
1123: This is the total length of this message header record (including both fixed
1124: and variable length portions, but NOT including unused block space).
1125:
1126: Attr:
1127: This is a bit field (16-bit) containing basic message attributes (flags) for
1128: this message. An exact duplicate of this field is stored in the index file as
1129: well. They must always match.
1130:
1131: Auxattr:
1132: This is a bit field (32-bit) containing the auxillary attributes (flags) for
1133: this message. The attributes stored in this variable are more specific in
1134: nature and less critical than those in the Attr field.
1135:
1136: Netattr:
1137: This is a bit field (32-bit) containing the network attributes (flags) for this
1138: message. The attributes stored in this variable are related solely to message
1139: networking.
1140:
1141: When_written:
1142: This is the date and time when the message was originally created.
1143:
1144: When_imported:
1145: This is the date and time when the message was posted on or imported into the
1146: local message system.
1147:
1148: Number:
1149: This is the message's unique serial number (from 1 to FFFFFFFFh). This field
1150: is duplicated in the index file. They must always match.
1151:
1152: Thread_orig:
1153: If this message is a reply, then this field contains the number of the original
1154: message that was replied to. If this message was not a reply, this field will
1155: contain the value 0.
1156:
1157: Thread_next:
1158: If this message is a reply, and there are later replies to that message
1159: (the message number contained in the Thread_orig field), then this field will
1160: contain the number of the next reply in the chain. If this message is the only
1161: reply to the orignal message, this field will contain the value 0.
1162:
1163: Thread_first:
1164: If there are any replies to this message (after it has been posted), this field
1165: will contain the number of the first reply to this message. If there are no
1166: replies to this message, this field will contain the value 0.
1167:
1168: Reserved:
1169: Unused bytes, reserved for future definition in the message header type 0
1170: specification.
1171:
1172: Offset:
1173: The byte offset into the data file, specifying the start of the buffer for
1174: all data associated with this message. This value must be either 0 or modula
1175: 256. When retrieving the actual data portion of data fields, the physical
1176: offset into the file will be the offset of the message data buffer (this field)
1177: plus the offset of the individual data field (msghdr_t.offset+dfield_t.offset).
1178:
1179: Total_dfields:
1180: This field contains the total number of data fields associated with this
1181: message. The value of this field must match the actual number of data fields
1182: stored in the header (dfield_t data types following the fixed portion of the
1183: message header).
1184:
1185:
1186: Variable Portion Field descriptions:
1187: -----------------------------------
1188: See the Header Field Type and Data Field Type sections for the descriptions
1189: of the values contained in these fields.
1190:
1191: Message Header Block Allocation (*.SHA)
1192: =======================================
1193: &&Header Allocation File (*.SHA) Format
1194: $$SHA_FORM
1195:
1196: If this message base uses the Hyper Allocation storage method (the
1197: SMB_HYPERALLOC bit is set in the smbstatus_t.attr field), then this file is
1198: not created or used.
1199:
1200: This file contains no header or signature data. Each byte (uchar) in the file
1201: specifies the allocation state of the corresponding 256 byte block in the
1202: header (*.SHD) file. A value of 0 indicates a free header block, and a value of
1203: 1 indicates an allocated block. Other non-zero values are undefined.
1204:
1205: This file must always be opened DENY ALL (non-shareable).
1206:
1207: Message Data (*.SDT)
1208: ====================
1209: &&Data File (*.SDT) Format
1210: $$SDT_FORM
1211:
1212: This file contains no header or signature data. It contains the text and other
1213: embedded data for the messages in a single message base. The data for each
1214: message always begins on a 256 byte block boundary. The data in the unused
1215: portion of a data block is undefined, but should be initialized to NULL
1216: whenever possible.
1217:
1218: This file must always be opened DENY NONE (shareable).
1219:
1220: Data fields of type TEXT_BODY and TEXT_TAIL must have all trailing white space
1221: and control characters removed (i.e. the last character of the data record
1222: must be in the range 21h to FFh). The only exception to this rule, is if the
1223: TEXT_BODY is terminated with multiple contiguous CRLFs, only the last CRLF
1224: should be removed. A CRLF should always be appended to the text data when it is
1225: displayed.
1226:
1227: When reading from this file, it is a good idea to make sure the message header
1228: for the data being read is currently locked (though no single message header
1229: should be locked for extended durations of time). This will insure that no
1230: other application will write to this portion of the file while it's being
1231: read (read from disk, not displayed).
1232:
1233: When using the Hyper Allocation storage method, the Status Info message base
1234: header must be successfully locked before writing to this file and subsequently
1235: unlocked.
1236:
1237: Message Data Block Allocation (*.SDA)
1238: =====================================
1239: &&Data Allocation File (*.SDA) Format
1240: $$SDA_FORM
1241:
1242: If this message base uses the Hyper Allocation storage method (the
1243: SMB_HYPERALLOC bit is set in the smbstatus_t.attr field), then this file is
1244: not created or used.
1245:
1246: This file contains no header or signature data. Each word (ushort) in the file
1247: specifies the allocation state of the corresponding 256 byte block in the data
1248: (*.SDT) file. A value of 0 indicates a free block, and a non-zero value
1249: indicates the number of message header records associated with this message
1250: data (most often 1). Each block can be used by up to 65,535 header records.
1251:
1252: This file must always be opened DENY ALL (non-shareable).
1253:
1254: CRC history for duplicate message checking (*.SCH)
1255: ==================================================
1256: &&CRC History File (*.SCH) Format
1257: $$SCH_FORM
1258:
1259: This file is optional and contains no header or signature data. Each long word
1260: (ulong) in the file contains a CRC-32 of previously posted/imported messages.
1261: These CRCs can be used to check a candidate message for posting/import to be
1262: sure the message isn't a duplicate created by human or program error. The
1263: maximum number of CRCs to store is defined in the first message base header
1264: record (smbstatus_t.max_crcs).
1265:
1266: The CRC is calculated on the first TEXT_BODY data field before any translations
1267: are applied (e.g. encoding, compression, encryption).
1268:
1269: This file must always be opened DENY ALL (non-shareable).
1270:
1271: Header Field Types:
1272: ==================
1273: &&Header Field Types
1274: $$HFIELD_T
1275:
1276: These are the defined valid values for hfield_t.type:
1277:
1278: Name : SENDER
1279: Value : 00h
1280: Data : ASCII
1281: Multiple : Yes, order significant
1282: Required : Yes
1283: Summary : Name of agent that sent this message
1284:
1285: If blank (0 length or nulstr), assumed "Anonymous". If multiple SENDER fields
1286: exist, then the message has been forwarded and the order of the fields in the
1287: record must match the forwarding order (chronologically). When forwarding a
1288: message, the original SENDER field should be left intact and new SENDER,
1289: FORWARDED, and RECIPIENT fields added to the end of the record.
1290:
1291: Name : SENDERAGENT
1292: Value : 01h
1293: Data : ushort
1294: Multiple : Yes, order significant
1295: Required : No
1296: Default : AGENT_PERSON or previous SENDERAGENT if exists
1297: Summary : Type of agent that sent this message
1298:
1299: If multiple SENDER fields exist, then the message has been forwarded. If any of the
1300: forwarding agents is of a type other than AGENT_PERSON, then this field must
1301: follow that SENDER field to specify the agent type.
1302:
1303: Name : SENDERNETTYPE
1304: Value : 02h
1305: Data : ushort
1306: Multiple : Yes, order significant
1307: Required : No
1308: Default : NET_NONE or previous SENDERNETTYPE if exists
1309: Summary : Type of network message was sent from
1310:
1311: If multiple SENDERNETADDR fields are included, a SENDERNETTYPE field should be
1312: included before each to determine what data type the address is stored in.
1313:
1314: Name : SENDERNETADDR
1315: Value : 03h
1316: Data : undef
1317: Multiple : Yes, order significant
1318: Required : No
1319: Default : Previous SENDERNETADDR if exists
1320: Summary : Network address for agent that sent this message
1321:
1322: The SENDERNETTYPE field indicates the data type of this field. If the
1323: SENDERNETTYPE is of type NET_INTERNET, the local-part of the Internet
1324: address is optional. If the local-part separator character ('@') is omitted,
1325: the SENDER field is assumed to be the local-part of the address.
1326:
1327: Name : SENDEREXT
1328: Value : 04h
1329: Data : ASCII
1330: Multiple : Yes, order significant
1331: Required : No
1332: Default : Previous SENDEREXT if exists
1333: Summary : Extension of sending agent
1334:
1335: This field is useful for storing the sending agent's extension, when the
1336: agent's extension binds more tightly than the agent's name.
1337:
1338: For example, Synchronet Multinode BBS Software stores local e-mail with the
1339: sending and receiving agent's user numbers stored as their respective
1340: extensions. This is done so that if a user name changes for some reason,
1341: messages will not "disappear" from the user's mail box.
1342:
1343: If the SMB_EMAIL status header attribute is set, then the "From" field in the
1344: index must contain the binary value of this field rather than the CRC-16 of the
1345: SENDER (name) field.
1346:
1347: Name : SENDERPOS
1348: Value : 05h
1349: Data : ASCII
1350: Multiple : Yes, order significant
1351: Required : No
1352: Default : Previous SENDERPOS if exists
1353: Summary : Position of sending agent
1354:
1355: Primarily for documentary purposes, this field contains the position of the
1356: sending agent (i.e. President, Sysop, C.E.O., MIS Director, etc).
1357:
1358: It can also be useful for getting a message or reply to the intended
1359: recipient when the agent name is not located or is unknown, but the position
1360: of the agent is known and specified.
1361:
1362: Name : SENDERORG
1363: Value : 06h
1364: Data : ASCII
1365: Multiple : Yes, order significant
1366: Required : No
1367: Default : Previous SENDERORG if exists
1368: Summary : Organization name of sending agent
1369:
1370: Primarily for documentary purposes, this field contains the organization to
1371: which the sending agent belongs (i.e. Microsoft, Joe's BBS, SoCal User's Group,
1372: etc).
1373:
1374: Name : AUTHOR
1375: Value : 10h
1376: Data : ASCII
1377: Multiple : Yes
1378: Required : No
1379: Default : First SENDER
1380: Summary : Name of agent that created this message
1381:
1382: This field can only be added by the process that originally creates the
1383: message. It should not be included if same as first SENDER field. If multiple
1384: AUTHOR fields exist, then the message was created by multiple agents and is
1385: considered valid. The order of multiple AUTHOR fields in the record is not
1386: significant.
1387:
1388: Name : AUTHORAGENT
1389: Value : 11h
1390: Data : ushort
1391: Multiple : Yes, order significant
1392: Required : No
1393: Default : SENDERAGENT or previous AUTHORAGENT if exists
1394: Summary : Type of agent that created this message
1395:
1396: This field can only be added by the process that originally creates the
1397: message. It should not be included if same as first SENDERAGENT field. If
1398: multiple AUTHOR fields exist, then the message was created by multiple agents
1399: and if the agent type for any of the authors is other than AGENT_PERSON, an
1400: AUTHORAGENT field must follow to specify the agent type.
1401:
1402: Name : AUTHORNETTYPE
1403: Value : 12h
1404: Data : ushort
1405: Multiple : Yes, order significant
1406: Required : No
1407: Default : SENDERNETTYPE or previous AUTHORNETTYPE if exists
1408: Summary : Type of network this author is member of
1409:
1410: Name : AUTHORNETADDR
1411: Value : 13h
1412: Data : undef
1413: Multiple : Yes, order significant
1414: Required : No
1415: Default : SENDERNETADDR or previous AUTHORNETADDR if exists
1416: Summary : Network address of this author
1417:
1418: Name : AUTHOREXT
1419: Value : 14h
1420: Data : ASCII
1421: Multiple : Yes, order significant
1422: Required : No
1423: Default : SENDEREXT or previous AUTHOREXT if exists
1424: Summary : Extension of this author
1425:
1426: Name : AUTHORPOS
1427: Value : 15h
1428: Data : ASCII
1429: Multiple : Yes, order significant
1430: Required : No
1431: Default : SENDERPOS or previous AUTHORPOS if exists
1432: Summary : Position of this author
1433:
1434: Name : AUTHORORG
1435: Value : 16h
1436: Data : ASCII
1437: Multiple : Yes, order significant
1438: Required : No
1439: Default : SENDERORG or previous AUTHORORG if exists
1440: Summary : Organization this author belongs to
1441:
1442: Name : REPLYTO
1443: Value : 20h
1444: Data : ASCII
1445: Multiple : Yes, but only last is valid
1446: Required : No
1447: Default : SENDER
1448: Summary : Name of agent that replies should go to
1449:
1450: Name : REPLYTOAGENT
1451: Value : 21h
1452: Data : ushort
1453: Multiple : Yes, but only last is valid
1454: Required : No
1455: Default : SENDERAGENT
1456: Summary : Type of agent that replies should go to
1457:
1458: Name : REPLYTONETTYPE
1459: Value : 22h
1460: Data : ushort
1461: Multiple : Yes, but only last is valid
1462: Required : No
1463: Default : SENDERNETTYPE
1464: Summary : Type of network that replies should go to
1465:
1466: Name : REPLYTONETADDR
1467: Value : 23h
1468: Data : undef
1469: Multiple : Yes, but only last is valid
1470: Required : No
1471: Default : SENDERNETADDR
1472: Summary : Network address that replies should go to
1473:
1474: Name : REPLYTOEXT
1475: Value : 24h
1476: Data : ASCII
1477: Multiple : Yes, but only last is valid
1478: Required : No
1479: Default : SENDEREXT
1480: Summary : Extension of agent that replies should go to
1481:
1482: Name : REPLYTOPOS
1483: Value : 25h
1484: Data : ASCII
1485: Multiple : Yes, but only last is valid
1486: Required : No
1487: Default : SENDERPOS
1488: Summary : Position of agent that replies should go to
1489:
1490: Name : REPLYTOORG
1491: Value : 26h
1492: Data : ASCII
1493: Multiple : Yes, but only last is valid
1494: Required : No
1495: Default : SENDERORG
1496: Summary : Organization of agent that replies should go to
1497:
1498: Name : RECIPIENT
1499: Value : 30h
1500: Data : ASCII
1501: Multiple : Yes, order significant
1502: Required : Yes
1503: Default : "All"
1504: Summary : Name of agent to receive this message
1505:
1506: If multiple RECIPIENT fields exist, the message has been forwarded and for each
1507: additional RECIPIENT field (after the initial RECIPIENT), there should be a
1508: FORWARDED field. The order of the RECIPIENT fields in the record must match the
1509: order in which the message was sent and forwarded (chronologically).
1510:
1511: Name : RECIPIENTAGENT
1512: Value : 31h
1513: Data : ushort
1514: Multiple : Yes, order significant
1515: Required : No
1516: Default : AGENT_PERSON or previous RECIPIENTAGENT if exists
1517: Summary : Type of agent to receive this message
1518:
1519: If multiple RECIPIENT fields exist, the message has been forwarded. If any of
1520: the recipient agents are of a type other than AGENT_PERSON, this field must
1521: follow the RECIPIENT field to specify the agent type.
1522:
1523: Name : RECIPIENTNETTYPE
1524: Value : 32h
1525: Data : ushort
1526: Multiple : Yes, order significant
1527: Required : No
1528: Default : NET_NONE or previous RECIPIENTNETTYPE if exists
1529: Summary : Type of network to receive this message
1530:
1531: Name : RECIPIENTNETADDR
1532: Value : 33h
1533: Data : undef
1534: Multiple : Yes, order significant
1535: Required : No
1536: Default : Previous RECIPIENTNETADDR if exists
1537: Summary : Address of network to receive this message
1538:
1539: Name : RECIPIENTEXT
1540: Value : 34h
1541: Data : ASCII
1542: Multiple : Yes, order significant
1543: Required : No
1544: Default : Previous RECIPIENTEXT if exists
1545: Summary : Extension of agent to receive this message
1546:
1547: If SMB_EMAIL status header attribute is set, then the "To" field in the index
1548: must contain the binary value of this field rather than the CRC-16 of the
1549: RECIPIENT (name) field. This is the case specifically with the local e-mail
1550: message base on a Synchronet BBS.
1551:
1552: Name : RECIPIENTPOS
1553: Value : 35h
1554: Data : ASCII
1555: Multiple : Yes, order significant
1556: Required : No
1557: Default : Previous RECIPIENTPOS if exists
1558: Summary : Position of agent to receive this message
1559:
1560: Name : RECIPIENTORG
1561: Value : 36h
1562: Data : ASCII
1563: Multiple : Yes, order significant
1564: Required : No
1565: Default : Previous RECIPIENTORG if exists
1566: Summary : Type of agent to receive this message
1567:
1568: Name : FORWARDTO
1569: Value : 40h
1570: Data : ASCII
1571: Multiple : Yes, order significant
1572: Required : No
1573: Summary : Name of agent this message is to be forwarded to
1574:
1575: Name : FORWARDTOAGENT
1576: Value : 41h
1577: Data : ushort
1578: Multiple : Yes, order significant
1579: Required : No
1580: Default : RECIPIENTAGENT or previous FORWARDTOAGENT if exists
1581: Summary : Type of agent this message is to be forwarded to
1582:
1583: Name : FORWARDTONETTYPE
1584: Value : 42h
1585: Data : ushort
1586: Multiple : Yes, order significant
1587: Required : No
1588: Default : RECIPIENTNETTYPE or previous FORWARDTONETTYPE if exists
1589: Summary : Type of network this message is to be forwarded to
1590:
1591: Name : FORWARDTONETADDR
1592: Value : 43h
1593: Data : undef
1594: Multiple : Yes, order significant
1595: Required : No
1596: Default : RECIPIENTNETADDR or previous FORWARDTONETADDR if exists
1597: Summary : Network address this message is to be forwarded to
1598:
1599: Name : FORWARDTOEXT
1600: Value : 44h
1601: Data : ASCII
1602: Multiple : Yes, order significant
1603: Required : No
1604: Default : RECIPIENTEXT or previous FORWARDTOEXT if exists
1605: Summary : Extension of agent this message is to be forwarded to
1606:
1607: Name : FORWARDTOPOS
1608: Value : 45h
1609: Data : ASCII
1610: Multiple : Yes, order significant
1611: Required : No
1612: Default : RECIPIENTPOS or previous FORWARDTOPOS if exists
1613: Summary : Position of agent this message is to be forwarded to
1614:
1615: Name : FORWARDTOORG
1616: Value : 46h
1617: Data : ASCII
1618: Multiple : Yes, order significant
1619: Required : No
1620: Default : RECIPIENTORG or previous FORWARDTOORG if exists
1621: Summary : Organization of agent this message is to be forwarded to
1622:
1623: Name : FORWARDED
1624: Value : 48h
1625: Data : when_t
1626: Multiple : Yes, order significant
1627: Required : Yes, if forwarded
1628: Summary : Date/Time this message was forwarded to another agent
1629:
1630: Name : RECEIVEDBY
1631: Value : 50h
1632: Data : ASCII
1633: Multiple : Yes, order significant
1634: Required : Yes, if receiving agent is other than RECIPIENT
1635: Summary : Name of agent that received this message
1636:
1637: Name : RECEIVEDBYAGENT
1638: Value : 51h
1639: Data : ushort
1640: Multiple : Yes, order significant
1641: Required : No
1642: Default : RECIPIENTAGENT or previous RECEIVEDBYAGENT if exists
1643: Summary : Type of agent that received this message
1644:
1645: Name : RECEIVEDBYNETTYPE
1646: Value : 52h
1647: Data : ushort
1648: Multiple : Yes, order significant
1649: Required : No
1650: Default : RECIPIENTNETTYPE or previous RECEIVEDBYNETTYPE if exists
1651: Summary : Type of network that received this message
1652:
1653: Name : RECEIVEDBYNETADDR
1654: Value : 53h
1655: Data : undef
1656: Multiple : Yes, order significant
1657: Required : No
1658: Default : RECIPIENTNETADDR or previous RECEIVEDBYNETADDR if exists
1659: Summary : Network address that received this message
1660:
1661: Name : RECEIVEDBYEXT
1662: Value : 54h
1663: Data : ASCII
1664: Multiple : Yes, order significant
1665: Required : No
1666: Default : RECIPIENTEXT or previous RECEIVEDBYEXT if exists
1667: Summary : Extension of agent that received this message
1668:
1669: Name : RECEIVEDBYPOS
1670: Value : 55h
1671: Data : ASCII
1672: Multiple : Yes, order significant
1673: Required : No
1674: Default : RECIPIENTPOS or previous RECEIVEDBYPOS if exists
1675: Summary : Position of agent that received this message
1676:
1677: Name : RECEIVEDBYORG
1678: Value : 56h
1679: Data : ASCII
1680: Multiple : Yes, order significant
1681: Required : No
1682: Default : RECIPIENTORG or previous RECEIVEDBYORG if exists
1683: Summary : Organization of agent that received this message
1684:
1685: Name : RECEIVED
1686: Value : 58h
1687: Data : when_t
1688: Multiple : Yes, order significant
1689: Required : Yes, if received
1690: Default : NULL
1691: Summary : Date/Time this message was received
1692:
1693: Name : SUBJECT
1694: Value : 60h
1695: Data : ASCII
1696: Multiple : No
1697: Required : Yes, but may be blank (0 length or nulstr)
1698: Summary : Subject/title of message
1699:
1700: Name : SUMMARY
1701: Value : 61h
1702: Data : ASCII
1703: Multiple : No
1704: Required : No
1705: Summary : Summary of message contents, created by AUTHOR
1706:
1707: Name : COMMENT
1708: Value : 62h
1709: Data : ASCII
1710: Multiple : Yes
1711: Required : No
1712: Summary : Comment about this message, created by SENDER
1713:
1714: This field is useful for adding notes to a message when forwarding to a new
1715: recipient.
1716:
1717: Name : CARBONCOPY
1718: Value : 63h
1719: Data : ASCII
1720: Multiple : Yes
1721: Required : No
1722: Summary : List of agents this message was also sent to
1723:
1724: This field is optional and only for the use of notifying the recipient of who
1725: else received the message.
1726:
1727: Name : GROUP
1728: Value : 64h
1729: Data : ASCII
1730: Multiple : Yes
1731: Required : No
1732: Summary : Name of group of users to receive message on recipient system
1733:
1734: This field is used when sending to a group name across a network, where the
1735: group can be expanded into multiple header records for each agent on the
1736: destination system.
1737:
1738: Name : EXPIRATION
1739: Value : 65h
1740: Data : when_t
1741: Multiple : No
1742: Required : No
1743: Summary : Date/Time that this message will expire
1744:
1745: Name : PRIORITY
1746: Value : 66h
1747: Data : ulong
1748: Multiple : No
1749: Required : No
1750: Default : 0
1751: Summary : Message priority (0 is lowest, FFFFFFFFh is highest)
1752:
1753: Name : FILEATTACH
1754: Value : 70h
1755: Data : ASCII
1756: Multiple : Yes
1757: Required : No
1758: Summary : Name/file specification of attached file(s)
1759:
1760: Name of attached file(s). Wildcards allowed. MSG_FILEATTACH attribute must be
1761: set. If the MSG_FILEATTACH attribute is set but this field is not included,
1762: the SUBJECT field is assumed to be the filename(s).
1763:
1764: Name : DESTFILE
1765: Value : 71h
1766: Data : ASCII
1767: Multiple : Yes, order significant
1768: Required : No
1769: Summary : Destination name for attached file(s)
1770:
1771: Wildcards allowed. FILEATTACH field must also be included.
1772:
1773: Name : FILEATTACHLIST
1774: Value : 72h
1775: Data : ASCII
1776: Multiple : Yes
1777: Required : No
1778: Summary : Name of ASCII list of attached filenames
1779:
1780: Wildcards not allowed in ASCII list filename. Wildcards allowed in ASCII list.
1781: MSG_FILEATTACH attribute must be set.
1782:
1783: Name : DESTFILELIST
1784: Value : 73h
1785: Data : ASCII
1786: Multiple : Yes, order significant
1787: Required : No
1788: Summary : Name of ASCII list of destination filenames
1789:
1790: Wildcards not allowed in ASCII list filename. Wildcards allowed in ASCII list.
1791:
1792: Name : FILEREQUEST
1793: Value : 74h
1794: Data : ASCII
1795: Multiple : Yes
1796: Required : No
1797: Summary : Name of requested file
1798:
1799: Wildcards allowed. MSG_FILEREQUEST attribute must be set
1800:
1801: Name : FILEPASSWORD
1802: Value : 75h
1803: Data : ASCII
1804: Multiple : Yes, order significant
1805: Required : No
1806: Summary : Password for FILEREQUEST
1807:
1808: Name : FILEREQUESTLIST
1809: Value : 76h
1810: Data : ASCII
1811: Multiple : Yes
1812: Required : No
1813: Summary : Name of ASCII list of filenames to request
1814:
1815: Wildcards allowed.
1816:
1817: Name : FILEPASSWORDLIST
1818: Value : 77h
1819: Data : ASCII
1820: Multiple : Yes, order significant
1821: Required : No
1822: Summary : Name of ASCII list of passwords for FILEREQUESTLIST
1823:
1824: Name : IMAGEATTACH
1825: Value : 80h
1826: Data : mattach_t
1827: Multiple : Yes, order significant
1828: Required : No
1829: Summary : Type and filename of attached image file for display
1830:
1831: MSG_FILEATTACH attribute must be set. See Image Types for valid
1832: mattach_t.type values.
1833:
1834: Name : ANIMATTACH
1835: Value : 81h
1836: Data : mattach_t
1837: Multiple : Yes, order significant
1838: Required : No
1839: Summary : Type and filename of attached graphical animation file for display
1840:
1841: MSG_FILEATTACH attribute must be set. See Animation Types for valid
1842: mattach_t.type values.
1843:
1844: Name : FONTATTACH
1845: Value : 82h
1846: Data : mattach_t
1847: Multiple : Yes, order significant
1848: Required : No
1849: Summary : Type and filename of attached font definition file
1850:
1851: MSG_FILEATTACH attribute must be set. See Font Types for valid mattach_t.type
1852: values.
1853:
1854: Name : SOUNDATTACH
1855: Value : 83h
1856: Data : mattach_t
1857: Multiple : Yes, order significant
1858: Required : No
1859: Summary : Type and filename of attached sound file for playback
1860:
1861: MSG_FILEATTACH attribute must be set. See Sound Types for valid mattach_t.type
1862: values.
1863:
1864: Name : PRESENTATTACH
1865: Value : 84h
1866: Data : mattach_t
1867: Multiple : Yes, order significant
1868: Required : No
1869: Summary : Type and filename of attached presentation definition file
1870:
1871: MSG_FILEATTACH attribute must be set. See Present Types for valid
1872: mattach_t.type values.
1873:
1874: Name : VIDEOATTACH
1875: Value : 85h
1876: Data : vattach_t
1877: Multiple : Yes, order significant
1878: Required : No
1879: Summary : Type and filename of attached interleaved video/sound file
1880:
1881: MSG_FILEATTACH attribute must be set. See Video Types for valid
1882: vattach_t.type values and Video Compression Types for valid vattach_t.comp
1883: values.
1884:
1885: Name : APPDATAATTACH
1886: Value : 86h
1887: Data : mattach_t
1888: Multiple : Yes, order significant
1889: Required : No
1890: Summary : Name of attached application data file for process/display
1891:
1892: MSG_FILEATTACH attribute must be set. See Application Data Types for valid
1893: mattach_t.type values.
1894:
1895: Name : IMAGETRIGGER
1896: Value : 90h
1897: Data : typestr_t
1898: Multiple : Yes, order significant
1899: Required : No
1900: Summary : Type and filename of image file to trigger for display
1901:
1902: See Image Types for valid typestr_t.type values.
1903:
1904: Name : ANIMTRIGGER
1905: Value : 91h
1906: Data : typestr_t
1907: Multiple : Yes, order significant
1908: Required : No
1909: Summary : Type and filename of animation file to trigger for display
1910:
1911: See Animation Types for valid typestr_t.type values.
1912:
1913: Name : FONTTRIGGER
1914: Value : 92h
1915: Data : typestr_t
1916: Multiple : Yes, order significant
1917: Required : No
1918: Summary : Type and filename of font definition file to trigger
1919:
1920: See Font Types for valid typestr_t.type values.
1921:
1922: Name : SOUNDTRIGGER
1923: Value : 93h
1924: Data : typestr_t
1925: Multiple : Yes, order significant
1926: Required : No
1927: Summary : Type and filename of sound file to trigger for playback
1928:
1929: See Sound Types for valid typestr_t.type values.
1930:
1931: Name : PRESENTTRIGGER
1932: Value : 94h
1933: Data : typestr_t
1934: Multiple : Yes, order significant
1935: Required : No
1936: Summary : Type and filename of presentation definition file to trigger
1937:
1938: See Present Types for valid typestr_t.type values.
1939:
1940: Name : VIDEOTRIGGER
1941: Value : 95h
1942: Data : typestr_t
1943: Multiple : Yes, order significant
1944: Required : No
1945: Summary : Type and filename of interleaved video/sound file to trigger
1946:
1947: See Video Types for valid typestr_t.type values.
1948:
1949: Name : APPDATATRIGGER
1950: Value : 96h
1951: Data : typestr_t
1952: Multiple : Yes, order significant
1953: Required : No
1954: Summary : Type and filename of application data file to trigger
1955:
1956: See Application Data Types for valid typestr_t.type values.
1957:
1958: Name : FIDOCTRL
1959: Value : A0h
1960: Data : ASCII
1961: Multiple : Yes, order significant
1962: Required : No
1963: Format : keyword ":" [" "] appdata
1964: Summary : FTS/FSC-compliant control information line
1965:
1966: Any FidoNet FTS/FSC-compliant control information ("kludge") line that
1967: does not have an equivalent representation here. All data not unique to the
1968: actual control line, including leading and trailing white space, Ctrl-A (01h)
1969: character and terminating CR must be ommited. Defined in FTS-0001.
1970:
1971: Name : FIDOAREA
1972: Value : A1h
1973: Data : ASCII
1974: Multiple : No
1975: Required : No
1976: Summary : FTN EchoMail conference name.
1977:
1978: Defined in FTS-0004.
1979:
1980: Name : FIDOSEENBY
1981: Value : A2h
1982: Data : ASCII
1983: Multiple : Yes, order significant
1984: Required : No
1985: Format : net"/"node [" "[net"/"]node] [...]
1986: Summary : Used to store two-dimensional (net/node) SEEN-BY information
1987:
1988: Often used in FTN EchoMail environments. Only the actual SEEN-BY data is stored
1989: and SEEN-BY: is stripped along with any leading and trailing white space
1990: characters. Defined in FTS-0004.
1991:
1992: Name : FIDOPATH
1993: Value : A3h
1994: Data : ASCII
1995: Multiple : Yes, order significant
1996: Required : No
1997: Format : net"/"node [" "[net"/"]node] [...]
1998: Summary : Used to store two-dimensional (net/node)
1999:
2000: Defined in FTS-0004. ^aPATH: is stripped along with any leading and trailing
2001: white space characters.
2002:
2003: Name : FIDOMSGID
2004: Value : A4h
2005: Data : ASCII
2006: Multiple : No
2007: Required : No
2008: Format : origaddr " " serialno
2009: Summary : MSGID field as specified in FTS-0009.
2010:
2011: Name : FIDOREPLYID
2012: Value : A5h
2013: Data : ASCII
2014: Multiple : No
2015: Required : No
2016: Format : origaddr " " serialno
2017: Summary : REPLY field as specified in FTS-0009.
2018:
2019: Name : FIDOPID
2020: Value : A6h
2021: Data : ASCII
2022: Multiple : No
2023: Required : No
2024: Format : pID " " version [" "serialno]
2025: Summary : Indentification string of program that created this message
2026:
2027: Defined FSC-0046. "^aPID:" and any white space is not included.
2028:
2029: Name : FIDOFLAGS
2030: Value : A7h
2031: Data : ASCII
2032: Multiple : Yes
2033: Required : No
2034: Summary : Used to store the FTN FLAGS kludge information
2035:
2036: Note that all FLAG options that have binary representation in the message
2037: header must be removed from the FLAGS string prior to storing it. Only the
2038: actual flags option string is stored and ^aFLAGS is stripped along with any
2039: leading and trailing white space characters. Defined in FSC-0053.
2040:
2041: Name : RFC822HEADER
2042: Value : B0h
2043: Data : ASCII
2044: Multiple : Yes, order significant
2045: Required : No
2046: Format : field-name ":" [field-body] [CRLF]
2047: Summary : Undefined RFC-822 header field
2048:
2049: Internet Message storage format, that does not have an equivalent
2050: representation here. Folded header fields are allowed. Terminating CRLF may be
2051: ommited.
2052:
2053: Name : RFC822MSGID
2054: Value : B1h
2055: Data : ASCII
2056: Multiple : No
2057: Required : No
2058: Format : "<" addr-spec ">"
2059: Summary : Message-ID field as specified in RFC-822.
2060:
2061: Name : RFC822REPLYID
2062: Value : B2h
2063: Data : ASCII
2064: Multiple : No
2065: Required : No
2066: Format : "<" addr-spec ">"
2067: Summary : In-Reply-To field as specified in RFC-822.
2068:
2069: Name : UNKNOWN
2070: Value : F0h
2071: Data : undef
2072: Multiple : Yes
2073: Required : No
2074: Summary : Undefined header field of undefined type
2075:
2076: This field is useful for retaining binary header fields (that do not have an
2077: equivalent representation here) between message storage formats.
2078:
2079: Name : UNKNOWNASCII
2080: Value : F1h
2081: Data : ASCII
2082: Multiple : Yes
2083: Required : No
2084: Summary : Undefined header field of type ASCII
2085:
2086: This field is useful for retaining ASCII header fields (that do not have an
2087: equivalent representation here) between message storage formats.
2088:
2089: Name : UNUSED
2090: Value : FFh
2091: Data : undef
2092: Multiple : Yes
2093: Required : No
2094: Summary : Unused (deleted) header field
2095:
2096: The data contained in this header field is of an unknown type and should not be
2097: processed.
2098:
2099:
2100: Note:
2101: ----
2102: Specifically, not defined are the values F000h through FFFFh. These values
2103: are to be used for user or system defined header fields. Digital Dynamics
2104: requests that any developers or organizations that wish to have additional
2105: header fields added to this specification notify Digital Dynamics through any
2106: of the contact methods listed at the beginning of this document.
2107:
2108: Data Field Types:
2109: ================
2110: &&Data Field Types
2111: $$DFIELD_T
2112:
2113: These are the defined valid values for dfield_t.type:
2114:
2115:
2116: Val Name Data Description
2117: --- ---- ---- -----------
2118: 00h TEXT_BODY mtext_t Displayable text (body of message).
2119: Included in duplicate message checking.
2120: All terminating white space and control
2121: characters are to be truncated from data
2122: (except when multiple contiguous CRLFs
2123: terminate the text, only the last CRLF
2124: is removed).
2125:
2126: 01h TEXT_SOUL mtext_t Non-displayed text.
2127: Not normally displayed. Not necessarily
2128: displayable.
2129: Included in duplicate message checking.
2130:
2131: 02h TEXT_TAIL mtext_t Displayable text (tag/tear/origin lines,
2132: etc).
2133: Not included in duplicate message checking.
2134: All terminating white space and control
2135: characters are to be truncated from data.
2136:
2137: 03h TEXT_WING mtext_t Non-displayed text.
2138: Not normally displayed. Not necessarily
2139: displayable.
2140: Not included in duplicate message checking.
2141:
2142: 10h FTEXT_BODY ftext_t Formatted equivalent of TEXT_BODY to be
2143: displayed in place of TEXT_BODY if format
2144: is supported. See Image Types for valid
2145: values of ftext_t.type.
2146:
2147: 12h FTEXT_TAIL ftext_t Formatted equivalent of TEXT_TAIL to be
2148: displayed in place of TEXT_TAIL if format
2149: is supported. See Image Types for valid
2150: values of ftext_t.type.
2151:
2152: 20h IMAGEEMBED membed_t Type and data of embedded raster image file
2153: for display.
2154: See Image Types for valid membed.type
2155: values.
2156:
2157: 21h ANIMEMBED membed_t Type and data of embedded graphical
2158: animation file for display.
2159: See Animation Types for valid membed.type
2160: values.
2161:
2162: 22h FONTEMBED membed_t Type and data of embedded font definition
2163: file. See Font Types for valid
2164: membed_t.type values.
2165:
2166: 23h SOUNDEMBED membed_t Type and data of embedded sound file for
2167: playback.
2168: See Sound Types for valid membed_t.type
2169: values.
2170:
2171: 24h PRESENTEMBED membed_t Type and data of embedded presentation
2172: definition file.
2173: See Present Types for valid membed_t.type
2174: values.
2175:
2176: 25h VIDEOEMBED vembed_t Type and data of embedded video/sound file
2177: for playback.
2178: See Video Types for valid vembed_t.type
2179: values.
2180: See Video Compression Types for valid
2181: vembed_t.comp values.
2182:
2183: 26h APPDATAEMBED membed_t Type and data of embedded application data
2184: file for process/display.
2185: See Application Data Types for valid
2186: membed_t.type values.
2187:
2188: FFh UNUSED undef Space allocated for future update/expansion
2189:
2190:
2191: Specifically, not defined are the values F000h through FFFFh. These values
2192: are to be used for user or system defined data fields. Digital Dynamics
2193: requests that any developers or organizations that wish to have additional
2194: data fields added to this specification notify Digital Dynamics through any
2195: of the contact methods listed at the beginning of this document.
2196:
2197:
2198: Message Attributes:
2199: ------------------
2200: &&Message Attributes
2201: $$ATTRBITS
2202:
2203: These are the bit values for idxrec_t.attr and msghdr_t.attr:
2204:
2205: MSG_PRIVATE (1<<0) // Private
2206: MSG_READ (1<<1) // Read by addressee
2207: MSG_PERMANENT (1<<2) // Permanent
2208: MSG_LOCKED (1<<3) // Msg is locked, no editing possible
2209: MSG_DELETE (1<<4) // Msg is marked for deletion
2210: MSG_ANONYMOUS (1<<5) // Anonymous author
2211: MSG_KILLREAD (1<<6) // Delete message after it has been read
2212: MSG_MODERATED (1<<7) // This message must be validated before export
2213: MSG_VALIDATED (1<<8) // This message has been validated by a moderator
2214:
2215:
2216: Auxillary Attributes:
2217: --------------------
2218: These are the bit values for msghdr_t.auxattr:
2219:
2220: MSG_FILEREQUEST (1<<0) // File request
2221: MSG_FILEATTACH (1<<1) // File(s) attached to Msg
2222: MSG_TRUNCFILE (1<<2) // Truncate file(s) when sent
2223: MSG_KILLFILE (1<<3) // Delete file(s) when sent
2224: MSG_RECEIPTREQ (1<<4) // Return receipt requested
2225: MSG_CONFIRMREQ (1<<5) // Confirmation receipt requested
2226: MSG_NODISP (1<<6) // Msg may not be displayed to user
2227:
2228:
2229: Network Attributes:
2230: ------------------
2231: These are the bit values for msghdr_t.netattr:
2232:
2233: MSG_LOCAL (1<<0) // Msg created locally
2234: MSG_INTRANSIT (1<<1) // Msg is in-transit
2235: MSG_SENT (1<<2) // Sent to remote
2236: MSG_KILLSENT (1<<3) // Kill when sent
2237: MSG_ARCHIVESENT (1<<4) // Archive when sent
2238: MSG_HOLD (1<<5) // Hold for pick-up
2239: MSG_CRASH (1<<6) // Crash
2240: MSG_IMMEDIATE (1<<7) // Send Msg now, ignore restrictions
2241: MSG_DIRECT (1<<8) // Send directly to destination
2242: MSG_GATE (1<<9) // Send via gateway
2243: MSG_ORPHAN (1<<10) // Unknown destination
2244: MSG_FPU (1<<11) // Force pickup
2245: MSG_TYPELOCAL (1<<12) // Msg is for local use only
2246: MSG_TYPEECHO (1<<13) // Msg is for conference distribution
2247: MSG_TYPENET (1<<14) // Msg is direct network mail
2248:
2249: Translation Types:
2250: -----------------
2251: &&Translation Types
2252: $$XLATTYPE
2253:
2254: Definition for values of *.xlat[x]:
2255:
2256: XLAT_NONE 0 // No translation/End of translation list
2257: XLAT_LF2CRLF 1 // Expand sole LF to CRLF
2258: XLAT_ESCAPED 2 // 7-bit ASCII escaping for ctrl and 8-bit data
2259: XLAT_HUFFMAN 3 // Static and adaptive Huffman coding compression
2260: XLAT_LZW 4 // LZW (Lempel-Ziv-Welch) encoding for compression
2261: // Terry Welch, IEEE Computer Vol 17, No 6
2262: // June 1984, pp 8-19
2263: XLAT_LZC 5 // LZC (modified LZW) encoding for compression
2264: // Unix compress program
2265: XLAT_RLE 6 // Run length encoding compression
2266: XLAT_IMPLODE 7 // Implode compression (PKZIP v1.x)
2267: XLAT_SHRINK 8 // Shrink compression (PKZIP v1.x)
2268: XLAT_LZH 9 // LZH dynamic Huffman coding
2269: // Haruyasu Yoshizaki, LHarc
2270: // November, 1988
2271:
2272: Agent Types:
2273: -----------
2274: &&Agent Types
2275: $$AGENTTYP
2276:
2277: AGENT_PERSON 0 // To or from person
2278: AGENT_PROCESS 1 // Unknown process, identified by agent name
2279:
2280: Agent types E000h through EFFFh are reserved for Synchronet process types
2281: (defined specifically by Digital Dynamics).
2282:
2283: Note:
2284: ----
2285: Specifically not defined are agent types F000h through FFFFh. These values
2286: are to be used for user or system defined agent types. Digital Dynamics
2287: requests that any developers or organizations that wish to have additional
2288: agent types added to this specification notify Digital Dynamics through any
2289: of the contact methods listed at the beginning of this document.
2290:
2291: Network Types:
2292: -------------
2293: &&Network Types
2294: $$NETWORKS
2295:
2296: // Net Type Address Format
2297: // -----------------------------------
2298: NET_NONE 0 // Locally created none
2299: NET_UNKNOWN 1 // Unknown undef
2300: NET_FIDO 2 // FTN network fidoaddr_t
2301: NET_POSTLINK 3 // PostLink network none
2302: NET_QWK 4 // QWK based network ASCII
2303: NET_INTERNET 5 // The Internet ASCII
2304: NET_WWIV 6 // WWIV based network ulong
2305: NET_MHS 7 // MHS network ASCII
2306:
2307:
2308: Media Types:
2309: ===========
2310: &&Media Types
2311: $$MEDIATYP
2312:
2313: Image Types:
2314: -----------
2315:
2316: IMAGE_UNKNOWN 0x00 // Use image signature header to determine format
2317: IMAGE_ASC 0x01 // ASCII text/IBM extended ASCII graphics
2318: IMAGE_ANS 0x02 // ANSI X3.64 terminal escape sequences
2319: IMAGE_AVT 0x03 // AVATAR terminal escape sequences
2320: IMAGE_LVI 0x04 // LVI terminal escape sequences
2321: IMAGE_GIF 0x05 // Compuserve Graphics Interchange Format (GIF)
2322: IMAGE_TIF 0x06 // Tagged Image Format (AKA TIFF)
2323: IMAGE_JPG 0x07 // Joint Photographers Electronics Group (JPEG)
2324: IMAGE_T16 0x08 // TrueVision 16-bit bitmap (TGA)
2325: IMAGE_T24 0x09 // TrueVision 24-bit bitmap (TGA)
2326: IMAGE_T32 0x0a // TrueVision 32-bit bitmpa (TGA)
2327: IMAGE_PCX 0x0b // ZSoft PaintBrush graphics
2328: IMAGE_BMP 0x0c // Windows bitmap
2329: IMAGE_RLE 0x0d // Windows bitmap (compressed)
2330: IMAGE_DIB 0x0e // Display independant bitmap
2331: IMAGE_PCD 0x0f // Kodak PhotoCD
2332: IMAGE_G3F 0x10 // Group 3 FAX
2333: IMAGE_EPS 0x11 // Ecapsulated PostScript
2334: IMAGE_RTF 0x12 // Rich text format
2335: IMAGE_RIP 0x13 // Remote Imaging Protocol Script (RIPscrip)
2336: IMAGE_NAP 0x14 // NAPLPS
2337: IMAGE_CDR 0x15 // Corel Draw!
2338: IMAGE_CGM 0x16 // Computer graphics metafile
2339: IMAGE_WMF 0x17 // Windows metafile
2340: IMAGE_DFX 0x18 // Autodesk AutoCAD
2341: IMAGE_IFF 0x19 // Amiga Interchange File Format
2342: IMAGE_HTM 0x20 // HyperText Markup Language (MTML) Document
2343: IMAGE_OS2 0x21 // OS/2 bitmap (BMP)
2344:
2345: Animation Types:
2346: ---------------
2347:
2348: ANIM_UNKNOWN 0 // Use file signature header to determine format
2349: ANIM_FLI 1 // Autodesk animator
2350: ANIM_FLC 2 // Autodesk
2351: ANIM_GL 3 // Grasprt
2352: ANIM_IFF 4 // Amiga Interchange File Format
2353:
2354:
2355: Video Types:
2356: -----------
2357:
2358: VIDEO_UNKNOWN 0 // Use file signature header to determine format
2359: VIDEO_QTIME 1 // Apple Quick-time
2360: VIDEO_FQTIME 2 // Apple Flattened Quick-time
2361: VIDEO_AVI 3 // Windows Auto/Video Interleave
2362: VIDEO_ULT 4 // OS/2 Ultimotion
2363:
2364: Video Compression Types:
2365: -----------------------
2366:
2367: VCOMP_UNKNOWN 0 // Use file signature header to determine codec
2368: VCOMP_RLE 1 // Apple animation
2369: VCOMP_SMC 2 // Apple graphics
2370: VCOMP_RPZA 3 // Apple video
2371: VCOMP_KLIC 4 // Captain crunch
2372: VCOMP_CVID 5 // CinePak
2373: VCOMP_RT21 6 // Intel indeo R2
2374: VCOMP_IV31 7 // Intel indeo R3
2375: VCOMP_YVU9 8 // Intel YVU9
2376: VCOMP_JPEG 9 // JPEG
2377: VCOMP_MRLE 10 // Microsoft RLE
2378: VCOMP_MSVC 11 // Microsoft video 1
2379:
2380:
2381: Font Types:
2382: ----------
2383:
2384: FONT_UNKNOWN 0 // Use file signature header to determine format
2385: FONT_TTF 1 // Windows TrueType
2386: FONT_PFB 2 // PostScript Type 1 Font Binary
2387: FONT_PFM 3 // PostScript Type 1 Font Metric
2388: FONT_AMIGA 4 // Amiga Bitmapped
2389: FONT_AGFA 5 // CompuGraphic Fonts
2390:
2391:
2392: Sound Types:
2393: -----------
2394:
2395: SOUND_UNKNOWN 0 // Use file signature header to determine format
2396: SOUND_MOD 1 // MOD format
2397: SOUND_VOC 2 // Sound Blaster VOC format
2398: SOUND_WAV 3 // Windows 3.1 WAV RIFF format
2399: SOUND_MID 4 // MIDI format
2400: SOUND_GMID 5 // General MIDI format (standardized patches)
2401: SOUND_SMP 6 // Turtle Beach SampleVision format
2402: SOUND_SF 7 // IRCAM format
2403: SOUND_AU 8 // Sun Microsystems AU format
2404: SOUND_IFF 9 // Amiga Interchange File Format
2405:
2406: Application Data Types:
2407: ----------------------
2408:
2409: APPDATA_UNKNOWN 0 // Use file signature header to determine format
2410: APPDATA_WORDPERFECT 1 // WordPerfect Document
2411: APPDATA_WKS 2 // Lotus 123 Worksheet (?)
2412: APPDATA_WK1 3 // Lotus 123 Worksheet rev 1
2413: APPDATA_WK2 4 // Lotus 123 Worksheet rev 2
2414: APPDATA_WK3 5 // Lotus 123 Worksheet rev 3
2415: APPDATA_DBF 6 // dBase III data file
2416: APPDATA_PDX 7 // Paradox data file
2417: APPDATA_EXCEL 8 // Excel data file
2418: APPDATA_QUATRO 9 // Borland Quatro Pro file
2419: APPDATA_WORD 10 // Microsoft Word
2420:
2421: Message Storage Pseudo Code
2422: ===========================
2423: &&Message Storage Pseudo Code
2424: $$STORPCOD
2425:
2426: The following is a "C like" pseudo code listing example of adding a message to
2427: an SMB message base. SMBLIB contains C functions to do most of the following
2428: operations. We are supplying this pseudo code as a general definition of the
2429: order of required operations in writing to the message base. Many details have
2430: been left out to simplify the code and to demonstrate only the basic
2431: principles.
2432:
2433: shd = open ( MSGBASE.SHD , READ/WRITE/DENY_NONE )
2434: sdt = open ( MSGBASE.SDT , READ/WRITE/DENY_NONE )
2435: sid = open ( MSGBASE.SDT , READ/WRITE/DENY_NONE )
2436:
2437: lock ( shd , smbhdr )
2438: read ( shd , smbstatus )
2439:
2440: if ( smbstatus.attr & SMB_HYPERALLOC )
2441: msg.hdr.offset = filelength ( sdt )
2442:
2443: else {
2444: number_of_blocks = length_of_message_data / SDT_BLOCK_LEN
2445: if ( length_of_message_data % SDT_BLOCK_LEN ) /* unevenly divisible */
2446: number_of_blocks = number_of_blocks + 1
2447:
2448: sda = open ( MSGBASE.SDA , READ/WRITE/DENY_ALL )
2449:
2450: if ( fast_allocation_mode )
2451: seek ( sda , END_OF_FILE )
2452:
2453: else {
2454: seek ( sda , BEGINNING_OF_FILE )
2455: while ( not end_of_file ( sda ) ) {
2456: read ( sda , allocated , number_of_blocks * 2 )
2457: if ( allocated = 0 ) {
2458: seek_backwards ( sda , number_of_blocks * 2 )
2459: break
2460: }
2461: }
2462: }
2463:
2464: msg.hdr.offset = ( current_position ( sda ) / 2 ) * SDT_BLOCK_LEN
2465:
2466: allocated = 1
2467:
2468: write ( sda , allocated , number_of_blocks * 2 )
2469:
2470: close ( sda )
2471: }
2472:
2473: seek ( sdt , msg.hdr.offset )
2474:
2475: write ( sdt , message_data )
2476:
2477: if ( smbstatus.attr & SMB_HYPERALLOC )
2478: msg.idx.offset = filelength ( shd )
2479:
2480: else {
2481: number_of_blocks = length_of_message_header / SHD_BLOCK_LEN
2482: if ( length_of_message_header % SHD_BLOCK_LEN ) /* unevenly divisible */
2483: number_of_blocks = number_of_blocks + 1
2484:
2485: sha = open ( MSGBASE.SHA , READ/WRITE/DENY_ALL )
2486:
2487: if ( fast_allocation_mode )
2488: seek ( sha , END_OF_FILE )
2489:
2490: else {
2491: seek ( sha , BEGINNING_OF_FILE )
2492: while ( not end_of_file ( sha ) ) {
2493: read ( sha , allocated , number_of_blocks )
2494: if ( allocated = 0 ) {
2495: seek_backwards ( sha , number_of_blocks )
2496: break
2497: }
2498: }
2499: }
2500:
2501: msg.idx.offset = ( current_position ( sha ) * SHD_BLOCK_LEN )
2502: msg.idx.offset = msg.idx.offset + smbstatus.header_offset
2503:
2504: allocated = 1
2505:
2506: write ( sha , allocated , number_of_blocks )
2507:
2508: close ( sha )
2509: }
2510:
2511: seek ( shd , msg.idx.offset )
2512:
2513: msg.hdr.number = smbstatus.last_msg+1
2514:
2515: write ( shd , msg.hdr )
2516:
2517: smbstatus.total_msgs = smbstatus.total_msgs + 1
2518: smbstatus.last_msg = msg.hdr.number
2519:
2520: write ( shd , smbstatus )
2521:
2522: write ( sid , msg.idx )
2523:
2524: unlock ( shd , smbstatus )
2525:
2526: Message Retrieval Pseudo Code
2527: =============================
2528: &&Message Retrieval Pseudo Code
2529: $$READPCOD
2530:
2531: shd = open ( MSGBASE.SHD , READ/WRITE/DENY_NONE )
2532: sdt = open ( MSGBASE.SDT , READ/WRITE/DENY_NONE )
2533: sid = open ( MSGBASE.SDT , READ/WRITE/DENY_NONE )
2534:
2535: read ( sid , msg.idx )
2536:
2537: seek ( shd , msg.idx.offset )
2538:
2539: lock ( shd , msg.hdr )
2540:
2541: read ( shd , msg.hdr )
2542:
2543: seek ( sdt , msg.hdr.offset )
2544:
2545: read ( sdt , msg.hdr.data_length )
2546:
2547: unlock ( shd , msg.hdr )
2548:
2549: SMBUTIL
2550: =======
2551: &&SMBUTIL
2552: $$SMBUTIL_
2553:
2554: SMBUTIL is a utility that can perform various functions on an SMB message base.
2555: The primary purpose of SMBUTIL is as an example to C programmers of how to use
2556: the SMBLIB functions to access and modify an SMB message base. The complete C
2557: source code for SMBUTIL is included and functions from it can be used or
2558: modified by developers at their own discretion. The following files make up
2559: SMBUTIL:
2560:
2561: SMBUTIL.EXE Compiled and linked for 16-bit DOS (ready to run)
2562: SMBUTIL.C C functions
2563: SMBUTIL.H C definitions and variable prototypes
2564: SMBUTIL.WAT Makefile for Watcom C/C++ (type wmake -f smbutil.wat)
2565: SMBUTIL.BOR Makefile for Borland C/C++ (type make -f smbutil.bor)
2566:
2567: The usage syntax is as follows:
2568:
2569: SMBUTIL [/opts] cmd smb_filespec.shd
2570:
2571: where cmd is one or more of the following:
2572:
2573: l[n] = list msgs starting at number n
2574: r[n] = read msgs starting at number n
2575: v[n] = view msg headers starting at number n
2576: k[n] = kill (delete) n msgs
2577: i<f> = import from text file f
2578: s = display msg base status
2579: c = change msg base status
2580: m = maintain msg base - delete old msgs and msgs over max
2581: p[k] = pack msg base (k specifies minimum packable Kbytes)
2582:
2583: where opts is one or more of the following:
2584:
2585: a = always (force) packing
2586: z<n> = set time zone (n=min +/- from UT or 'EST','EDT','CST',etc)
2587:
2588: and smb_filespec is the base filename or file specification (wildcards) for the
2589: message base. If wildcards are used, the ".SHD" extension must be specified.
2590:
2591: An example command line:
2592:
2593: SMBUTIL MP C:\SBBS\DATA\SUBS\*.SHD
2594:
2595: would maintain and pack all the message bases found in the C:\SBBS\DATA\SUBS
2596: directory.
2597:
2598: CHKSMB
2599: ======
2600: &&CHKSMB
2601: $$CHKSMB__
2602:
2603: CHKSMB is a utility that performs a comprehensive analysis of a message base
2604: to find any possible errors and calculate the number of packable bytes. It does
2605: not "fix" a message base if any errors are found, it only reports the specific
2606: errors (and exits with a non-zero error level). If any errors are reported,
2607: packing the message base with SMBUTIL may rebuild the damaged files. If that
2608: doesn't work, then use FIXSMB as a last resort.
2609:
2610: C source code for CHKSMB is also included as an example to programmers of how
2611: to use SMBLIB functions.
2612:
2613: The usage syntax is as follows:
2614:
2615: CHKSMB [/opts] smb_filespec.shd
2616:
2617: where opts is one or more of the following:
2618:
2619: q = quiet mode (no beeps)
2620: s = stop after an errored message base (for use with wildcards)
2621: p = pause after an errored message base (wait for key press)
2622: t = don't check for unsupported translation strings (faster)
2623: e = display extended information on corrupted messages
2624:
2625: An example command line:
2626:
2627: CHKSMB /QP C:\SBBS\DATA\SUBS\*.SHD
2628:
2629: would check all the message bases in the C:\SBBS\DATA\SUBS directory, without
2630: beeping on errors, and pausing after an errored message base.
2631:
2632: FIXSMB
2633: ======
2634: &&FIXSMB
2635: $$FIXSMB__
2636:
2637: FIXSMB is a utility that will rebuild the index and allocation files for a
2638: message base. Since the message headers are not necessarily stored
2639: sequentially, the order of the messages in the index may be changed when the
2640: index is rebuilt. Messages are also re-numbered, so only use this program if
2641: the index is corrupted and the messages are extremely important.
2642:
2643: C source code for FIXSMB is also included as an example to programmers of how
2644: to use SMBLIB functions.
2645:
2646: The usage syntax is as follows:
2647:
2648: FIXSMB [/M] smb_file
2649:
2650: An example command line:
2651:
2652: FIXSMB \SBBS\DATA\MAIL
2653:
2654: Only use the "/M" command line switch if fixing an older Synchronet e-mail
2655: message base (created with SBBS v2.1 or earlier). Once the SMB_EMAIL status
2656: attr is set ("SMBUTIL S" will report a status attr of 1), the "/M" is not
2657: required.
2658:
2659: SMBLIB
2660: ======
2661: &&SMBLIB
2662: $$SMBLIB__
2663:
2664: SMBLIB is a library of C functions for accessing and storing messages in an
2665: SMB format message base. It can eliminate much of the development time for
2666: developers that wish to use the library in whole or in part, or use the
2667: functions as examples for their own message base function library. The library
2668: consists of the following files:
2669:
2670: SMBDEFS.H Constant definitions, macros, and data types
2671: SMBLIB.H Library constants and function prototypes
2672: SMBLIB.C Function definitions
2673: SMBVARS.C Global variable definitions (doubles as declaration file)
2674:
2675: For developers to use this library with their program, they must include the
2676: "SMBLIB.H" header file at the top of each C file that uses any of the library
2677: functions, global variables, data types, macros, and constants. This can be
2678: done by simply adding the following line to each .C file:
2679:
2680: #include "smblib.h"
2681:
2682: If SMBLIB.H is included, there is no need to include SMBDEFS.H or SMBVARS.C.
2683:
2684: To link the library functions and variables with a main program, the files
2685: SMBVARS.OBJ and SMBLIB.OBJ must be linked with the main program .OBJ files.
2686: If the operating system is DOS, be sure that all .OBJ files are compiled for
2687: the same memory model.
2688:
2689: Example MAKEFILEs for compiling and linking SMBUTIL with Borland C/C++
2690: (SMBUTIL.BOR) and Watcom C/C++ (SMBUTIL.WAT) are included.
2691:
2692: SMBDEFS.H
2693: =========
2694: &&SMBDEFS.H
2695: $$SMBDEFS_
2696:
2697: The SMBDEFS.H file contains important constant definitions and data types (also
2698: defined in this document). If ever this document and SMBDEFS.H are inconsistent
2699: with each other, then SMBDEFS.H is to be considered correct and this document
2700: in error. If such a discrepency is found, please notifiy Digital Dynamics so it
2701: can be corrected in a future revision of the specification.
2702:
2703: Most notable of the data types is a structure called smbmsg_t (not defined
2704: in this document). It contains the fixed and variable portions of a message's
2705: header record as well as convenience pointers to the sender's name
2706: (smbmsg_t.to), recipient's name (smbmsg_t.from), network addresses, and more.
2707: If multiple SENDER header fields are included (for example), then smbmsg_t.to
2708: will point to the last SENDER header field in the header record. Convenience
2709: pointers for other data items work in the same fasion if multiple header fields
2710: of the same type exist in the header record.
2711:
2712: Variables of the smbmsg_t data type (and pointers to variables of smbmsg_t
2713: type) are used as arguments to many of the SMBLIB functions.
2714:
2715: SMBVARS.C
2716: =========
2717: &&SMBVARS.C
2718: $$SMBVARS_
2719:
2720: The SMBVARS.C file contains definitions of the global variables used by the
2721: SMBLIB functions. It is a fairly small file since there are a small number of
2722: global variables (by design). This file is used for both definitions and
2723: declarations, so no "extern" declarations need to be made in developers source
2724: code as long as SMBVARS.C or (preferably) SMBLIB.H is included in the source
2725: code.
2726:
2727: SMBLIB.H
2728: =======
2729: &&SMBLIB.H
2730: $$SMBLIB.H
2731:
2732: The SMBLIB.H file contains prototypes of all the functions in the SMBLIB.C
2733: file. It is necessary to include this file in C source code if any of the
2734: SMBLIB functions are used. The following C source line will include this file:
2735:
2736: #include "smblib.h"
2737:
2738: and should be placed near the top of all C source files that use SMBLIB
2739: functions, variables, constants, or data types.
2740:
2741: Function prototypes are necessary for compilers to know the correct calling
2742: syntax of a function and detect incorrect usage. Prototypes are also useful
2743: as a quick reference for programmers as to the correct calling syntax of a
2744: specific function.
2745:
2746: SMBLIB.C
2747: =======
2748: &&SMBLIB.C
2749: $$SMBLIB.C
2750:
2751: The SMBLIB.C file contains the actual SMBLIB library functions. This source
2752: file is not a stand alone program, but instead must be compiled and linked
2753: with a main source file to create the executable program.
2754:
2755: The functions in this file are organized in a logical order, but their order
2756: is actually irrelevant to the compiling, linking, and execution of the
2757: resulting program.
2758:
2759: A comment block preceeds each function, explaining what the function does,
2760: how the passed parameters are used, and what the return code (if any)
2761: indicates. A more detailed explanation of each function is included here:
2762:
2763: int smb_open(int retry_time)
2764: ----------------------------
2765: The smb_open() function must be called before the message base is accessed
2766: (read from or written to). The parameter, retry_time, is the maximum number
2767: of seconds to wait while retrying to lock the message base header. If
2768: retry_time is 0, then the message base header is not locked or read (this is
2769: called "Fast Open" and should only be used when speed is more important than
2770: checking for compatibility and validity upon opening). The global variable
2771: smb_file must be initialized with the path and base filename of the message
2772: base. This function returns 0 on success, 1 if the .SDT file could not be
2773: opened, 2 if the .SHD file could not be opened, and 3 if the .SID file could
2774: not be opened. If the message base header could not be locked, this function
2775: returns -1. If the message base ID is incorrect, it returns -2. And if the
2776: message base is of an incompatible version, it returns -3.
2777:
2778: The errno global variable (standard of most C libraries) will most likely
2779: contain the error code for open failure.
2780:
2781: int smb_open_da(int retry_time)
2782: -------------------------------
2783: The smb_open_da() function is used to open the data block allocation file for
2784: writing messages to a message base. The parameter, retry_time, is the maximum
2785: number of seconds to wait while retrying to open the file. This function
2786: returns 0 on success. -1 is returned if an open error other than "Access
2787: Denied" is returned from the operating system, and the global variable errno
2788: will contain the error code. -2 is returned if the retry_time has been
2789: reached, and -3 is returned if the file descriptor could not be converted to
2790: a stream by the fdopen() function.
2791:
2792: fclose(sda_fp) should be called immediately after all necessary file access
2793: has been completed.
2794:
2795: This function is not used with the Hyper Allocation storage method.
2796:
2797: int smb_open_ha(int retry_time)
2798: -------------------------------
2799: The smb_open_ha() function is used to open the header block allocation file for
2800: writing messages to a message base. The parameter, retry_time, is the maximum
2801: number of seconds to wait while retrying to open the file. This function
2802: returns 0 on success. -1 is returned if an open error other than "Access
2803: Denied" is returned from the operating system, and the global variable errno
2804: will contain the error code. -2 is returned if the retry_time has been
2805: reached, and -3 is returned if the file descriptor could not be converted to
2806: a stream by the fdopen() function.
2807:
2808: fclose(sha_fp) should be called immediately after all necessary file access
2809: has been completed.
2810:
2811: This function is not used with the Hyper Allocation storage method.
2812:
2813: int smb_create(ulong max_crcs, ulong max_msgs, ushort max_age, ushort attr
2814: ,int retry_time)
2815: --------------------------------------------------------------------------
2816: The smb_create() function is used to create a new message base or reset an
2817: existing message base. The parameters max_crcs, max_msgs, max_age, and attr
2818: are used to set the initial status of the message base status header. The
2819: parameter, retry_time is the maximum number of seconds to wait while retrying
2820: to lock the message base header. This functions returns 0 on success or 1 if
2821: the message base header could not be locked.
2822:
2823: int smb_trunchdr(int retry_time)
2824: --------------------------------
2825: The smb_trunchdr() function is used to truncate the header file when packing
2826: the message base and writing the new header information back to the header
2827: file. The parameter, retry_time is the maximum number of seconds to wait while
2828: retrying to truncate the header file. Returns 0 on success, -1 if error was
2829: other than "Access Denied", or -2 if retry_time reached.
2830:
2831: int smb_locksmbhdr(int retry_time)
2832: ----------------------------------
2833: The smb_locksmbhdr() function is used to lock the first message base (status)
2834: header. The parameter, retry_time is the number of seconds to wait while
2835: retrying to lock the header. The smb_unlocksmbhdr() function should always be
2836: used to unlock the header after accessing the message base header (usually
2837: with smb_getstatus() and/or smb_putstatus()). Returns 0 if successful, -1 if
2838: unsuccessful.
2839:
2840: int smb_unlocksmbhdr()
2841: ----------------------
2842: The smb_unlocksmbhdr() function is used to unlock a previously locked message
2843: base header (using smb_lockmsghdr()). Returns 0 on success, non-zero on
2844: failure.
2845:
2846: int smb_getstatus(smbstatus_t *hdr)
2847: -----------------------------------
2848: The smb_getstatus() function is used to read the status message base header
2849: into the hdr structure. Returns 0 on success, 1 on failure.
2850:
2851: int smb_putstatus(smbstatus_t hdr)
2852: ----------------------------------
2853: The smb_putstatus() function is used to write the status information to the
2854: first message base header. The parameter hdr, contains the status information
2855: to be written. Returns 0 on success, 1 on failure.
2856:
2857: int smb_getmsgidx(smbmsg_t *msg)
2858: --------------------------------
2859: The smb_getmsgidx() function is used to get the byte offset for a specific
2860: message header in the message header file based on the message base index.
2861:
2862: If msg->hdr.number is non-zero when this function is called, then the index
2863: will be searched for this message number. If the message number is found in
2864: the index, the msg->idx.offset is set to the byte offset of the message header
2865: record in the header file and msg->offset is set to the record offset of the
2866: index record in the index file, and the function returns 0. If the message
2867: number is not found in the index, the function returns 1.
2868:
2869: If msg->hdr.number is zero, msg->idx.offset and msg->idx.number are obtained
2870: from the index record at record offset msg->offset. If msg->offset is an
2871: invalid record offset when this function is called, the function returns 1.
2872: Otherwise, the function returns 0.
2873:
2874: int smb_getlastidx(idxrec_t *idx)
2875: ---------------------------------
2876: Reads the last index record of the currently open message base into the
2877: idxrec_t structure pointed to by idx. Returns 0 if successful, -1 if the index
2878: is empty or unopened, or -2 if the record can't be read.
2879:
2880: int smb_getmsghdrlen(smbmsg_t msg)
2881: ----------------------------------
2882: The smb_getmsghdrlen() function is used to calculate the total length of
2883: message header msg including both fixed and variable length portions. This
2884: function returns the length of the header record in bytes.
2885:
2886: long smb_getmsgdatlen(smbmsg_t msg)
2887: -----------------------------------
2888: The smb_getmsgdatlen() function is used to calculate the total length of the
2889: data for message msg. This function returns the length of all data fields
2890: combined.
2891:
2892: int smb_lockmsghdr(smbmsg_t msg, int retry_time)
2893: ------------------------------------------------
2894: The smb_lockmsghdr() function is used to lock the header record for message
2895: msg. The parameter retry_time is the maximum number of seconds to wait while
2896: retrying to lock the header. Returns 0 on success, -1 on failure. The function
2897: smb_unlockmsghdr() should immediately be called after accessing the message
2898: header (usually with smb_getmsghdr() or smb_putmsghdr()).
2899:
2900: int smb_getmsghdr(smbmsg_t *msg)
2901: --------------------------------
2902: The function smb_getmsghdr() is used to read the header record for message
2903: msg. msg->idx.offset must be initialized to the byte offset of the header
2904: record in the header file before this function is called. The function
2905: smb_freemsgmem() must be called to free the memory allocated by this function
2906: for the header and data felds. This function returns 0 on success, -1 if
2907: the fixed portion of the message header record could not be read, -2 if the
2908: message header ID was incorrect, -3 if memory could not be allocated, -4
2909: if a data field could not be read, -5 if the fixed length portion of a header
2910: field could not be read, -6 if the variable length portion of a header field
2911: could not be read, -7 if one or more of the mandatory header fields (SENDER,
2912: RECIPIENT, or SUBJECT) are missing, -8 if total_dfields extends beyond the
2913: end of the header record, or -9 if incompatible header version.
2914:
2915: Several convenience pointers in the msg structure are initialized by this
2916: function to point to the last occurance of the SENDER (msg->from), RECIPIENT
2917: (msg->to), SUBJECT (msg->subj), etc.
2918:
2919: int smb_unlockmsghdr(smbmsg_t msg)
2920: ----------------------------------
2921: The smb_unlockmsghdr() function is used to unlock a previously locked message
2922: header (with smb_lockmsghdr()). This function returns 0 on success, non-zero
2923: on failure.
2924:
2925: int smb_addcrc(ulong max_crcs, ulong crc, int retry_time)
2926: ---------------------------------------------------------
2927: The smb_addcrc() function is used to add a CRC-32 to the CRC history file
2928: for a message base, automatically checking for duplicates. The parameter
2929: max_crcs should be the max_crcs defined in the status header of the message
2930: base. The parameter crc, is the CRC-32 of the TEXT_BODY and TEXT_SOUL data
2931: fields for the message. The parameter retry_time is the maximum number of
2932: seconds to wait when retrying to open the CRC history file.
2933:
2934: This function returns -1 if there was an open error, -2 if the retry_time
2935: was reached, -3 if there was a memory allocation error, 1 if the CRC already
2936: exists in the CRC history file (indicating a duplicate message), or 0 on
2937: success (and no duplicate).
2938:
2939: int smb_hfield(smbmsg_t *msg, ushort type, ushort length, void *data)
2940: ---------------------------------------------------------------------
2941: The smb_hfield() function is used to add a header field to the structure msg.
2942: The parameters type, length, and data, must be specified according to the
2943: header field values listed in this specification. This function returns 0
2944: on success, non-zero on memory allocation error. The function smb_freemsgmem()
2945: must be called to free the memory allocated by this function.
2946:
2947: int smb_dfield(smbmsg_t *msg, ushort type, ulong length)
2948: --------------------------------------------------------
2949: The smb_dfield() function is used to add a data field to the structure msg.
2950: The parameters type and length must be specified according to the data field
2951: values listed in this specification. This function returns 0 on success,
2952: non-zero on memory allocation error. The function smb_freemsgmem() must be
2953: called to free the memory allocated by this function.
2954:
2955: int smb_addmsghdr(smbmsg_t *msg,smbstatus_t *status,int storage,int retry_time)
2956: -------------------------------------------------------------------------------
2957: The smb_addmsghdr() function is used to add a new message header to the message
2958: header file and update the index file. The msg and status structures are
2959: updated to reflect the new total messages, last message number, etc. The
2960: storage parameter is used to indicate the storage method to use (either
2961: SMB_SELFPACK, SMB_FASTALLOC, or SMB_HYPERALLOC). If the storage type is
2962: SMB_SELFPACK, the header block allocation file will be searched for unused
2963: block(s) to store this header. If the storage type is SMB_FASTALLOC or
2964: SMB_HYPERALLOC, the header is stored at the end of the header file. Returns 0
2965: on success, non-zero on failure. The parameter retry_time is the maximum number
2966: of seconds to wait while retrying to lock and open files.
2967:
2968: int smb_putmsg(smbmsg_t msg)
2969: ----------------------------
2970: The smb_putmsg() function calls both the smb_putmsghdr() and smb_putmsgidx()
2971: functions to write the header and index elements of a message to the
2972: appropriate files. Returns 0 on success, non-zero on failure.
2973:
2974: int smb_putmsgidx(smbmsg_t msg)
2975: -------------------------------
2976: The smb_putmsgidx() function is used to store a message index in the message
2977: index file. The message index can be for a new message or an existing
2978: message. Returns 0 on success, non-zero on failure.
2979:
2980: int smb_putmsghdr(smbmsg_t msg)
2981: -------------------------------
2982: The smb_putmsghdr() function is used to store a message header in the message
2983: header file. The message header can be for a new message or an existing
2984: message. Returns 0 on success, non-zero on failure.
2985:
2986: void smb_freemsgmem(smbmsg_t msg)
2987: ---------------------------------
2988: Frees allocated memory for the header and data fields in the msg structure.
2989: This function must be called to free the memory allocated by the functions
2990: smb_hfield(), smb_dfield(), and smb_getmsghdr().
2991:
2992: long smb_hdrblocks(ulong length)
2993: --------------------------------
2994: The smb_hdrblocks() function is used to calculate the number of blocks
2995: required to store a message header of length size (in bytes). This function
2996: returns the number of blocks required.
2997:
2998: long smb_datblocks(ulong length)
2999: --------------------------------
3000: The smb_datblocks() function is used to calculate the number of blocks
3001: required to store message data of length size (in byte). This function returns
3002: the number of blocks required.
3003:
3004: long smb_allochdr(ulong length)
3005: -------------------------------
3006: The smb_allochdr() function is used to search for free blocks to store a
3007: message header of length bytes and mark the free blocks as allocated in the
3008: header allocation file. This function returns the byte offset to the header
3009: record or a negative number on error. The function smb_open_ha() should be
3010: called prior to calling this function and fclose(sha_fp) should be called
3011: after. The function is called from smb_addmsghdr(), so you probably have no
3012: need to call this function directly.
3013:
3014: long smb_fallochdr(ulong length)
3015: --------------------------------
3016: The smb_fallochdr() function works exactly the same as the smb_allochdr()
3017: function except it is much faster because the header allocation file is not
3018: searched for free blocks. The function is called from smb_addmsghdr(), so you
3019: probably have no need to call this function directly.
3020:
3021: long smb_hallochdr(ulong header_offset)
3022: ---------------------------------------
3023: This smb_hallochdr() functions works exactly the same as the smb_fallochdr()
3024: function except the status.header_offset is passed as the argument and the
3025: header allocation (.SHA) file is not updated so smb_open_ha() need not be
3026: called. The function is called from smb_addmsghdr(), so you probably have no
3027: need to call this function directly.
3028:
3029: long smb_allocdat(ulong length, ushort headers)
3030: -----------------------------------------------
3031: The smb_allocdat() function is used to search for free blocks to store length
3032: amount of data for a message. The parameter headers, indicates the number of
3033: message headers that are associated with this data. Normally, the headers
3034: parameter will be 1, unless this message is part of a mass mailing. The offset
3035: to the allocated data blocks is returned, or a negative value on error. The
3036: function smb_open_da() should be called prior to calling this function and
3037: fclose(sda_fp) should be called after.
3038:
3039: long smb_fallocdat(ulong length, ushort headers)
3040: ------------------------------------------------
3041: The smb_fallocdat() function works exactly the same as the smb_allocdat()
3042: function except it is much faster because the data allocation file is not
3043: searched for free blocks.
3044:
3045: long smb_hallocdat()
3046: --------------------
3047: The smb_hallocdat() function works exactly the same as the smb_hallocdat()
3048: function except no argument is passed and the data allocation file (.SDA) is
3049: not updated so smb_open_da() need not be called.
3050:
3051: int smb_incdat(ulong offset, ulong length, ushort headers)
3052: ----------------------------------------------------------
3053: The smb_incdat() function is used to increment the header counter in the data
3054: allocation file for the data starting at the byte offset and length size in
3055: bytes. The parameter headers, indicates the number of headers to add to the
3056: current allocation value in the data allocation file. Returns 0 on success,
3057: non-zero on failure.
3058:
3059: int smb_freemsg(smbmsg_t msg, smbstatus_t status)
3060: -------------------------------------------------
3061: The smb_freemsg() function is used to free the disk space allocated for the
3062: header and data fields of the message msg. Returns 0 on success, non-zero on
3063: failure. The parameter, status, must be the current status from the message
3064: base header for this message base.
3065:
3066: int smb_freemsgdat(ulong offset, ulong length, ushort headers)
3067: --------------------------------------------------------------
3068: The smb_freemsgdat() function is used to decrement the data block allocation
3069: records in the data allocation file associated with the data in the data file
3070: by the value of the headers parameter (normally 1). The parameter offset
3071: indicates the byte offset to the beginning of the message data in the data
3072: file and the parameter length is the total length of the message data.
3073: Returns 0 on success, non-zero on failure.
3074:
3075: int smb_freemsghdr(ulong offset, ulong length)
3076: ----------------------------------------------
3077: The smb_freemsghdr() function is used to set the header block allocation
3078: records in the header allocation file to 0 (indicated non-allocated block).
3079: The parameter offset indicates the byte offset to the beginning of the header
3080: record being freed and the parameter length indicates the total length of the
3081: header record. Returns 0 on success, non-zero on failure.
3082:
3083: int smb_stack(int op)
3084: ---------------------
3085: The smb_stack() function is used to save and restore message base information
3086: so that multiple message bases can be open simultaneously. The stack can
3087: save up to 4 message bases (allowing 5 simultaneously open message bases).
3088: The stack is a "last in, first out" storage area for open message bases.
3089: If the op parameter is SMB_STACK_PUSH, smb_stack() will save (push) the current
3090: message base onto the stack. Calling smb_stack(SMB_STACK_POP) will restore
3091: (pop) the most recently pushed message base off the stack. Calling
3092: smb_stack(SMB_STACK_XCHNG) will exchange the most recently pushed message base
3093: and the current message base (replacing the top of the stack with the current
3094: message base).
3095:
3096: void smb_close()
3097: ----------------
3098: Closes the header, data, and index files for the currently open message base.
3099:
3100:
3101: Miscellaneous SMBLIB Files
3102: ==========================
3103: &&Miscellaneous SMBLIB Files
3104: $$SMB_MISC
3105:
3106: CRC32.H C header file for CRC-32 calculations
3107: -----------------------------------------------------
3108: This file contains a static 32-bit CRC table (crc32tbl[]) and a macro (ucrc32)
3109: that uses this table to calculate 32-bit CRCs one byte at a time.
3110:
3111: Example:
3112:
3113: ulong crc=0xffffffff;
3114:
3115: for(i=0;i<length;i++)
3116: crc=ucrc32(buf[i],crc);
3117: crc=~crc;
3118:
3119:
3120: CRC16.C C functions for 16-bit CRC calculations
3121: -------------------------------------------------------
3122: This file contains a function (ucrc16), to calculate 16-bit CRCs one byte at a
3123: time and a function (crc16) that uses the ucrc16() function to calculate the
3124: 16-bit CRC of an ASCIIZ character string.
3125:
3126: Example:
3127:
3128: ushort crc;
3129:
3130: crc=crc16("Text");
3131:
3132: LZH.H Function prototypes for LZH.C
3133: ---------------------------------------------
3134: This file contains function prototypes for the two most important functions
3135: in LZH.C, lzh_encode() and lzh_decode().
3136:
3137: Example:
3138:
3139: uchar str[256],lzh[512];
3140: long length;
3141:
3142: strcpy(str,"This is a string of text");
3143: length=lzh_encode(str,strlen(str),lzh);
3144: lzh_decode(lzh,length,str);
3145:
3146:
3147: LZH.C C functions for LZH encoding (compression/decompression)
3148: ------------------------------------------------------------------------
3149: This file contains the functions for encoding and decoding LZH compressed
3150: data. If the macro LZH_DYNAMIC_BUF is defined when this file is compiled,
3151: temporary buffers will be dynamically allocated as opposed to static. This
3152: may be slower than the static buffer method, but frees the allocated memory
3153: after encoding or decoding. If free memory for your application is an issue,
3154: then define this macro when compiling this file.
3155:
3156: Example (Borland C):
3157:
3158: bcc -c -DLZH_DYNAMIC_BUF lzh
3159:
3160: Example (Watcom C):
3161:
3162: wcc -dLZH_DYNAMIC_BUF lzh
3163:
3164: SMBLIB Storage Example
3165: ======================
3166: &&SMBLIB Storage Example
3167: $$SMB_PUT_
3168:
3169: #include "smblib.h"
3170: #include "crc16.c"
3171:
3172: int main(void)
3173: {
3174: char str[256] // General purpose string
3175: ,*msg_text="Hello, world!" // Message text
3176: ,nul_buf[SDT_BLOCK_LEN]={0} // NULL initialized buffer
3177: ;
3178: int i // General purpose integer
3179: ,storage=SMB_SELFPACK // Default storage method
3180: ,retry=10 // Retry for opening/locking files
3181: ;
3182: ushort max_age=0 // Default maximum age of messages
3183: ,xlat=XLAT_NONE // Translation string
3184: ,tzone=PST // Time zone
3185: ,copies=1 // Number of copies of this msg
3186: ;
3187: ulong max_msgs=500 // Default max number of msgs
3188: ,max_crcs=0 // Default max crcs
3189: ,length // Length of msg text
3190: ,offset // Offset to msg text in data file
3191: ;
3192: smbmsg_t msg; // Message structure
3193: smbstatus_t status; // Message base status record
3194:
3195: strcpy(smb_file,"MSGBASE"); // We'll use "MSGBASE" for the name
3196: if((i=smb_open(retry))!=0) { // Can't open!?!
3197: printf("smb_open returned %d\n",i);
3198: return(1); }
3199:
3200: if(!filelength(fileno(shd_fp))) // Message base not created yet
3201: smb_create(max_crcs // Create with default settings
3202: ,max_msgs
3203: ,max_age
3204: ,storage==SMB_HYPERALLOC
3205: ? SMB_HYPERALLOC : 0 // SMB_EMAIL if this was e-mail
3206: ,retry
3207: );
3208:
3209: if((i=smb_locksmbhdr(retry))!=0) { // Can't lock status base header
3210: printf("smb_locksmbhdr returned %d\n",i);
3211: smb_close();
3212: return(1); }
3213:
3214: if((i=smb_getstatus(&status))!=0) { // Can't read status base header
3215: smb_unlocksmbhdr();
3216: smb_close();
3217: printf("smb_getstatus returned %d\n",i);
3218: return(1); }
3219:
3220: if(status.attr&SMB_HYPERALLOC)
3221: storage=SMB_HYPERALLOC;
3222: else
3223: storage=SMB_SELFPACK;
3224:
3225: length=strlen(msg_text); // Get length of message
3226: length+=sizeof(xlat); // Add length of xlat string
3227:
3228: if(storage==SMB_HYPERALLOC) // Allocate space for message text
3229: offset=smb_hallocdat();
3230: else {
3231: if((i=smb_open_da(retry))!=0) {
3232: smb_unlocksmbhdr();
3233: printf("smb_open_da returned %d\n",i);
3234: smb_close();
3235: return(1); }
3236: if(storage==SMB_FASTALLOC)
3237: offset=smb_fallocdat(length,copies);
3238: else
3239: offset=smb_allocdat(length,copies);
3240: fclose(sda_fp); }
3241:
3242: fseek(sdt_fp,offset,SEEK_SET); // Seek to beginning of data block
3243: fwrite(&xlat,sizeof(xlat),1,sdt_fp); // Write xlat string
3244: fwrite(msg_text,strlen(msg_text),1,sdt_fp); // Write message text
3245: fwrite(nul_buf,SDT_BLOCK_LEN-length // Write NULLs out to end of block
3246: ,1,sdt_fp);
3247: fflush(sdt_fp); // Flush output buffer
3248: smb_unlocksmbhdr(); // Unlock status base header
3249:
3250: memset(&msg,0,sizeof(smbmsg_t)); // Initialize header to NULL
3251: memcpy(msg.hdr.id,"SHD\x1a",4); // Always set to SHD^Z
3252: msg.hdr.version=SMB_VERSION;
3253: msg.hdr.when_written.time=time(NULL);
3254: msg.hdr.when_written.zone=tzone;
3255: msg.hdr.when_imported.time=time(NULL);
3256: msg.hdr.when_imported.zone=tzone;
3257: msg.hdr.offset=offset;
3258:
3259: strcpy(str,"All"); // Send message to "All"
3260: if((i=smb_hfield(&msg,RECIPIENT,strlen(str),str))!=0) {
3261: printf("smb_hfield returned %d\n",i);
3262: smb_freemsgdat(offset,length,copies);
3263: smb_close();
3264: return(1); }
3265: strlwr(str); // If this were e-mail, idx.to
3266: msg.idx.to=crc16(str); // would be the "to" user number
3267:
3268: strcpy(str,"Sysop"); // Send message from "Sysop"
3269: if((i=smb_hfield(&msg,SENDER,strlen(str),str))!=0) {
3270: printf("smb_hfield returned %d\n",i);
3271: smb_freemsgdat(offset,length,copies);
3272: smb_freemsgmem(msg);
3273: smb_close();
3274: return(1); }
3275: strlwr(str); // If this were e-mail, idx.from
3276: msg.idx.from=crc16(str); // would be the "from" user number
3277:
3278: strcpy(str,"This is a test"); // Set the message subject/title
3279: if((i=smb_hfield(&msg,SUBJECT,strlen(str),str))!=0) {
3280: printf("smb_hfield returned %d\n",i);
3281: smb_freemsgdat(offset,length,copies);
3282: smb_freemsgmem(msg);
3283: smb_close();
3284: return(1); }
3285: strlwr(str);
3286: msg.idx.subj=crc16(str);
3287:
3288: if((i=smb_dfield(&msg,TEXT_BODY,length))!=0) {
3289: printf("smb_dfield returned %d\n",i);
3290: smb_freemsgdat(offset,length,copies);
3291: smb_freemsgmem(msg);
3292: smb_close();
3293: return(1); }
3294:
3295: if((i=smb_addmsghdr(&msg,&status,storage,retry))!=0) {
3296: printf("smb_addmsghdr returned %d\n",i);
3297: smb_freemsgdat(offset,length,copies);
3298: smb_freemsgmem(msg);
3299: smb_close();
3300: return(1); }
3301:
3302: smb_freemsgmem(msg); // Unnecessary if exiting main()
3303: smb_close(); // Unnecessary if exiting main()
3304: return(0);
3305: }
3306:
3307: SMBLIB Retrieval Example
3308: ========================
3309: &&SMBLIB Retrieval Example
3310: $$SMB_GET_
3311:
3312: #include "smblib.h"
3313:
3314: int main(void)
3315: {
3316: char ch; // General purpose character
3317: int i, // General purpose integer
3318: retry=10; // Retry for opening/locking files
3319: ushort xlat; // Translation string
3320: ulong l; // General purpose long integer
3321: smbmsg_t msg; // Message structure
3322:
3323: strcpy(smb_file,"MSGBASE"); // We'll use "MSGBASE" for the name
3324: if((i=smb_open(retry))!=0) { // Can't open!?!
3325: printf("smb_open returned %d\n",i);
3326: return(1); }
3327:
3328: if(!filelength(fileno(shd_fp))) { // Message base not created yet
3329: printf("Empty\n");
3330: smb_close();
3331: return(0); }
3332:
3333: for(msg.offset=0;!ferror(sid_fp);msg.offset++) {
3334:
3335: fseek(sid_fp,msg.offset*sizeof(idxrec_t),SEEK_SET);
3336: if(!fread(&msg.idx,1,sizeof(idxrec_t),sid_fp))
3337: break;
3338:
3339: if((i=smb_lockmsghdr(msg,retry))!=0) {
3340: printf("smb_lockmsghdr returned %d\n",i);
3341: break; }
3342: if((i=smb_getmsghdr(&msg))!=0) {
3343: smb_unlockmsghdr(msg);
3344: printf("smb_getmsghdr returned %d\n",i);
3345: break; }
3346: if((i=smb_unlockmsghdr(msg))!=0) {
3347: smb_freemsgmem(msg);
3348: printf("smb_unlockmsghdr returned %d\n",i);
3349: break; }
3350:
3351: printf("Subj : %s\n",msg.subj);
3352: printf("To : %s\n",msg.to);
3353: printf("From : %s\n",msg.from);
3354: printf("Date : %s\n",ctime((time_t *)&msg.hdr.when_written.time));
3355:
3356: for(i=0;i<msg.hdr.total_dfields;i++)
3357: switch(msg.dfield[i].type) {
3358: case TEXT_BODY: // Only show BODY and TAIL data fields
3359: case TEXT_TAIL:
3360: fseek(sdt_fp,msg.hdr.offset+msg.dfield[i].offset
3361: ,SEEK_SET);
3362: fread(&xlat,sizeof(xlat),1,sdt_fp);
3363: if(xlat!=XLAT_NONE) // No translations supported
3364: continue;
3365: for(l=sizeof(xlat);l<msg.dfield[i].length;l++) {
3366: ch=fgetc(sdt_fp);
3367: if(ch)
3368: putchar(ch); }
3369: printf("\n");
3370: break; }
3371: printf("\n");
3372:
3373: smb_freemsgmem(msg); } // Free memory allocated by smb_getmsghdr()
3374:
3375: smb_close();
3376: return(0);
3377: }
3378:
3379: SMBLIB Performance Issues
3380: =========================
3381: &&SMBLIB Performance Issues
3382: $$PERFORM_
3383:
3384: Since importing messages is the usually the most time consuming task likely
3385: undertaken by an SMB application, it is also the most susceptable to design
3386: issues that effect performance.
3387:
3388: Opening and Closing
3389: -------------------
3390: When importing multiple messages for a single message base, it appears logical
3391: to open the message base, import all the messages, then close it. This indeed
3392: is preferred over opening and closing the message base for each message.
3393:
3394: When importing multiple messages for possibly non-consecutive message bases,
3395: developers may easily make the mistake of opening and closing the message base
3396: for each message. This is not necessary and can considerably hinder the
3397: import performance. The easiest solution is to only close the message base and
3398: open a new one if the next message to be imported is not for the same message
3399: base as the previously imported message. Example:
3400:
3401: smb_file[0]=0;
3402: for(i=0;i<total_messages_to_be_imported;i++) {
3403: if(stricmp(get_messagebase_for_this_message(i),smb_file)) {
3404: if(smb_file[0]) /* We've already opened one */
3405: smb_close();
3406: strcpy(smb_file,get_messagebase_for_this_message(i));
3407: smb_open(10); }
3408: /* Import this message */
3409: }
3410: if(smb_file[0])
3411: smb_close();
3412:
3413: A more advanced method is to keep multiple message bases open at the same time.
3414: Due to the likely limitation of total file handles on the system, it is
3415: suggested to keep the number of simultaneously open message bases at or below
3416: 3. SMBLIB includes the function smb_stack() to easily "push" and "pop" message
3417: bases without closing them (push is the equivalent to "save" and pop is the
3418: equivalent to "restore"). The downside of this function is that you cannot
3419: access message bases on the stack without actually popping them off (in reverse
3420: of the order they were pushed). You can however "exchange" the current message
3421: base with the message base on the top of the stack (most recently pushed).
3422: To intelligently juggle more than two open message bases, the developer should
3423: create their own equivalent of the smb_stack() function so they can access the
3424: message bases on the stack without popping them off. An example of keeping a
3425: maximum of two message bases open using smb_stack():
3426:
3427: char last_messagebase[128],new_messagebase[128];
3428:
3429: smb_file[0]=0;
3430: last_messagebase[0]=0;
3431: for(i=0;i<total_messages_to_be_imported;i++) {
3432: strcpy(new_messagebase,get_messagebase_for_this_message(i));
3433: if(stricmp(new_messagebase,smb_file)) { /* Not current message base */
3434: if(smb_file[0]) { /* We've already opened one */
3435: if(!stricmp(new_messagebase,last_messagebase)) { /* Same as last */
3436: strcpy(last_messagebase,smb_file);
3437: smb_stack(SMB_STACK_XCHNG); } /* Retore previous base */
3438: else {
3439: if(last_messagebase[0]) {
3440: smb_stack(SMB_STACK_XCHNG);
3441: smb_close();
3442: strcpy(last_messagebase,new_messagebase); }
3443: else {
3444: strcpy(last_messagebase,smb_file);
3445: smb_stack(SMB_STACK_PUSH); } /* Save current base */
3446: strcpy(smb_file,new_messagebase);
3447: smb_open(10); } }
3448: else {
3449: strcpy(smb_file,new_messagebase);
3450: smb_open(10); } }
3451: /* Import this message */
3452: }
3453: if(smb_file[0])
3454: smb_close();
3455: if(last_messagebase[0]) {
3456: smb_stack(SMB_STACK_POP);
3457: smb_close(); }
3458:
3459: The second example would be of negligible performance gain over the first
3460: example (6 open operations versus 7) if the messages to import were in the
3461: following order:
3462:
3463: msg[0] --> msgbase[0] // 0 opened
3464: msg[1] --> msgbase[1] // 0 pushed 1 opened
3465: msg[2] --> msgbase[1]
3466: msg[3] --> msgbase[2] // 1 closed 0 popped 0 closed 2 opened
3467: msg[4] --> msgbase[0] // 2 pushed 0 opened
3468: msg[5] --> msgbase[2] // 0 pushed 2 popped (exchanged)
3469: msg[6] --> msgbase[3] // 2 closed 0 popped 0 closed 3 opened
3470: msg[7] --> msgbase[0] // 3 pushed 0 opened
3471:
3472: The second example would be of significant performance gain over the first
3473: example (4 open operations versus 8) if the messages to import were in the
3474: following order:
3475:
3476: msg[0] --> msgbase[0] // 0 opened
3477: msg[1] --> msgbase[1] // 0 pushed 1 opened
3478: msg[2] --> msgbase[0] // 1 pushed 0 popped (exchanged)
3479: msg[3] --> msgbase[1] // 0 pushed 1 popped (exchanged)
3480: msg[4] --> msgbase[0] // 1 pushed 0 popped (exchanged)
3481: msg[5] --> msgbase[2] // 0 pushed 1 popped (exchanged) 1 closed 2 opened
3482: msg[6] --> msgbase[3] // 2 pushed 0 popped (exchanged) 0 closed 3 opened
3483: msg[7] --> msgbase[2] // 3 pushed 2 popped (exchanged)
3484:
3485: More advanced use of "stack-like" message base file handle storage can easily
3486: reduce the number of open operations, therefore increasing import performance
3487: under more adverse message base ordering conditions.
3488:
3489: Compression
3490: -----------
3491: If any message data compression features are offered by the application, it
3492: is important the the application not unnecessarily compress data that will
3493: not save any storage space. While this may seem an obvious statement, please
3494: review the following pseudo-code example:
3495:
3496: if ( message_data_length < SDT_BLOCK_LEN )
3497: // Store uncompressed data
3498: else {
3499: // Compress data
3500: if ( ( compressed_data_length / SDT_BLOCK_LEN )
3501: < ( message_data_length / SDT_BLOCK_LEN ) ) // Saves a block or more
3502: // Store compressed data
3503: else
3504: // Store uncompressed data
3505: }
3506:
3507: Since the SMB format stores message data in fixed length blocks, there is no
3508: point in storing a message in compressed format if it requires the same number
3509: of blocks as the uncompressed format (i.e. a message that is two blocks in
3510: length in uncompressed format and only a block and a half in length when
3511: compressed should not be stored in compressed format since it still requires
3512: two full blocks of storage). It is important to note that in the above example,
3513: the length of the data translation string was not taken into account in
3514: determining the number of required blocks. Also, the smb_datblocks() function
3515: is normally used in determing the number of required blocks to store a given
3516: data length and it is a little more involved than simply dividing the length of
3517: the data by SDT_BLOCK_LEN.
3518:
3519:
3520: Bibliography
3521: ============
3522: &&Bibliography
3523: $$BIBLIOGR
3524:
3525: Title : The C Programming Language
3526: Publisher : Prentice Hall
3527: Author : Brian W. Kernighan and Dennis M. Ritchie
3528:
3529: Document : ARPANET Request for Comments (RFC) #822
3530: Title : Standard for the Format of ARPA Internet text messages
3531: Publisher : SRI International
3532: Author : David H. Crocker, University of Delaware
3533:
3534: Document : FTS-0001
3535: Publisher : FSC
3536: Author : Randy Bush, Pacific Systems Group
3537:
3538: Document : FTS-0004
3539: Title : EchoMail Specification
3540: Publisher : FSC
3541: Author : Bob Hartman
3542:
3543: Document : FTS-0009
3544: Title : A standard for unique message identifiers and reply chain linkage
3545: Publisher : FSC
3546: Author : Jim Nutt
3547:
3548: Document : FSC-00046
3549: Title : A Product Idenfifier for FidoNet Message Handlers
3550: Publisher : FSC
3551: Author : Joaquim H. Homrighausen
3552:
3553: Document : FSC-00053
3554: Title : Specifications for the ^aFLAGS field
3555: Publisher : FSC
3556: Author : Joaquim H. Homrighausen
3557:
3558:
3559: Implementations
3560: ===============
3561: &&Implementations
3562: $$IMPLEMEN
3563:
3564: Product : Synchronet Multinode BBS Software
3565: Developer : Digital Dynamics
3566: Level : III
3567: Version : 2.20
3568:
3569: Product : Synchronet/FidoNet Import/Export Utility (SBBSFIDO)
3570: Developer : Digital Dynamics
3571: Level : III
3572: Version : 2.23
3573:
3574: Product : Synchronet UTI (Universal Text Interface) Driver
3575: Developer : Digital Dynamics
3576: Level : III
3577: Version : 2.23
3578:
3579: Product : SBBSecho FidoNet Packet Tosser for Synchronet
3580: Developer : Digital Dynamics
3581: Level : III
3582: Version : 1.11
3583:
3584: Product : NetXpress Internet UUCP for Synchronet
3585: Developer : Merlin Systems
3586: Level : II
3587: Version : 1.50
3588:
3589: Product : InterEcho FidoNet Packet Tosser
3590: Developer : InterMail Sales Inc
3591: Level : II
3592: Version : 1.11
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.