|
|
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.