pax_global_header00006660000000000000000000000064114164213550014514gustar00rootroot0000000000000052 comment=0f66465b4f93cd436b6da19ecad7b05c9133620d jamnntpd-1.2/000077500000000000000000000000001141642135500131715ustar00rootroot00000000000000jamnntpd-1.2/HOWTO000066400000000000000000000127661141642135500140300ustar00rootroot00000000000000So you finally decided to take a look at that JamNNTPd package you've heard so much about? And after you've unpacked it, you have absolutely no clue about what to do with it? Well, then you've decided to read the right textfile. I did very much the same, half a year ago. It wasn't until I got a permanent connection to the internet that I realized what I could do with this package. If you *don't* have a permanent connection to the internet, you can stop reading here, and just delete the entire package. Well, on second thought maybe not -- a local installation of JamNNTPd and your favourite news reader will probably be a better combination for reading and writing fidonet echoes than most others you will find, so stay with us. What is it? ========== JamNNTPd is for 'news://...' what Apache, IIS &al are for 'http://...', i.e. it's a server program that lets any user from internet reach your JAM message base with any news reader they happen to have installed. So how do you go about making JamNNTPd work? Well, this is a case study from my setup. I use WinXP as front-end against internet, and have (of course!) the built-in firewall enabled. I have several 'mshome.net' workstations connected to the internet via ICS, and on one of these I decided to setup and run JamNNTPd. What do I do first? ================== The first thing you should do, after you've unpacked the zip-file, is to edit the four config files, jamnntpd.groups, *.users, *.allow and *.xlat to suit your setup. The help-texts in those files should be selfexplanatory. Then what? ========= Then you have to open up a port in your firewall to allow outside, as well as inside (usually yourself) callers to reach your JamNNTPd newsserver. The default port for a newsserver is 119, so this is a good choice for incoming from internet, and 5000 is usually a good one for outgoing to your local network. Settings for the WinXP firewall can be reached from right-clicking on your internet connection icon in 'Settings'->'Network and Dial-up Connections' and then click your way to 'Properties'->'Advanced'->'Settings'. Add a new porthole, lets call it JamNNTPd, with 119, 5000, TCP and the local name of the workstation where you installed the JamNNTPd server (localhost will do fine if you installed JamNNTPd on the workstation that your firewall is located on). Now all you have to do is 'Win-R cmd' and do a 'cd' to the proper directory and give the command 'jamnntpd' and you're up and running! Remember that even if your outside callers must use port 119, you yourself, from inside the firewall, must use port 5000 to connect to your own newsserver. So that's it, then? ================== Once you've made sure it's working, you can start finetuning your setup. First of all, Ctrl-C stops the server. :) Then you may remember that the server does not need to be restarted whenever you edit one of the four config files. Thirdly, even if the defaults usually is a good choice, if you want a conservative, fidonettish look&feel from your JamNNTPd newsserver, you might be interested in knowing how I start it: jm.bat ------ @jamnntpd.exe -notearline -smartquote -noreplyaddr -m 10 -echomailjam r:\sem\fdxit6.60 ------ As some of you might guess from the above, I still rely on a FrontDoor node to take care of most of the things, such as tossing and scanning echomail. 'fdxit6.60' is a semaphore file that tells my FrontDoor node 6 to exit with errorlevel 60. That is my major toss&scan event. I use CrashMail II (from the JamNNTPd author) to toss&scan my JAM areas, since my old squishmail can't handle JAM. Can I let anybody in? ==================== In fidonet, we have a very strict policy about real-names and proper authentication of users, before they are allowed to write anything in any of our echoes. So, if you setup fidonet echoes, you must make sure your users are authenticated before they are allowed to write anything. Reading is, of course, perfectly OK even for anonymous visitors. Proper authenticating is also handled by JamNNTPd, based on how you setup your *.users and *.allow files. Normally you probably will have a *.allow that only has one line: '* ABCDE A' ... meaning you let everybody read in your A, B, C, D and E groups but only write in A (for anonymous). In *.users you can add more groups, that only authenticated users may read or write: # Syntax: # # # sysop password ABISTX ABISTX # # I=international # S=Swedish # T=beta-test # X=private # user1 password1 AIST AIST user2 password2 ABIST ABIST user3 password3 ABIST ABIS user4 password4 AIST ABST user5 password5 AIST AI guest guest AIST A Well, sysop could just as well have used * for both groups. Poor user 4 is not allowed to read B groups but can write (probably not a very good idea), and user5 is not trusted with writing in Swedish-only echoes. Furthermore, you can add a real-name for any user listed here (more about that in the main doc). Then all you have to do, is inform your users to set up their news reader to "always request authentication to this server" and to have configured it with the proper nick, true-name and password. It may interest them to know, that what they enter in the "Organisation:" field ends up in the origin line, unless you use one of the options, described in the main doc, to use a fixed origin line of your choice. ----- Bj”rn Felten, news://felten.yi.org or fidonet 2:203/208 jamnntpd-1.2/History.txt000066400000000000000000000115161141642135500153770ustar00rootroot00000000000000 Changes in version 1.2 - Make From addresses into valid RFC 5322 addresses. - JamNNTPd traditionally has used Fidonet-style addresses in the From header. This breaks RFC 5322 and causes some e-mail software (Alpine, Opera) not to display the sender address properly. This patch changes the From header to use a valid RFC 5322 syntax, albeit not a valid Internet e-mail address. Changes in version 1.1 - Ported to OS/2 Changes in version 1.0 - Added support for netmail and local areas (see examples/jamnntpd.groups) - Added support for cancel messages - It is now possible to read configuration options from a file using the new -config option. If JamNNTPd is started without any command-line arguments at all, it will read configuration options from the file jamnntpd.config if it is present. A config file with the default options can be created with the -create option. - Introduced the -readorigin switch that makes JamNNTPd read addresses from the origin line instead of the JAM headers. - "To: name" can be used on the first line of posted messages to set an alternative recipient name. - Added partial support for the LIST NEWSGROUPS command so that JamNNTPd also works with Lynx. - JamNNTPd no longer adds an empty REPLY kludge if to MSGID was found. - Fixed -smartquote so that incorrect initials are not inserted. - Fixed broken backspace quoting on From line. - "jamnntpd -h" is more helpful. - Error messages were cleaned up a bit. - The Windows version now tries to display error messages instead of Winsock error codes. Only works on newer versions of Windows. - Makechs now hopefully compiles without errors on *BSD. - Cleaned up the build process a bit. Changes in version 0.61 - Fixed a bug that would cause JamNNTPd to crash when a JAM messagebase couldn't be opened. - Fixed a bug that would cause JamNNTPd to crash when a default charset had been specified in jamnntpd.groups. (Thanks Viktor!) Changes in version 0.6 - Configurable charset handling based on CHS files in the GoldED+ format. - Greatly improved MIME-handling. JamNNTPd now handles both quoted-printable and base64 in both headers and message body when posting messages. Message headers containing non-ascii characters are encoded when displayed unless the -noencode option is used. - Now supports "quoting" with backslash as described in RFC-822. - JamNNTPd can now create an echomail.jam file that contains a list of all posted messages. The echomail.jam file can also be used as a semaphore. - A new -origin switch can be used to override the Organization line for the origin. - Support for TZUTC/TZUTCINFO kludges. JamNNTPd now creates a TZUTC kludge unless the -notzutc option is used. Thanks to Peter Karlsson for the patch. - Better parsing of configuration files. You can now use quotes for strings containing space characters. "" means an empty string. - It is now possible to override the From name on posts from authenticated users. It is also possible to specify a suffix that is added to the From name of all unauthenticated users using the -guestsuffix option. - Access groups are now case-insensitive. In addition, "*" now means all groups and "-" means no groups. - The -smartquote option no longer removes initial space characters from quoted text and inserts incorrect initials. - Fixed broken response code of NEWGROUPS command. - The LIST ACTIVE and LIST OVERVIEW.FMT commands are now also supported. - JamNNTPd now displays an X-Comment-To header line. - The signature delimiter "-- " is no longer reflowed when posting with format=flowed. Fixed display problems with long lines without spaces and format=flowed. - All characters <32 are removed in the output of the XOVER command to prevent problems. - Increased the maximum size for posts from 10 000 bytes to 20 000 bytes. - JamNNTPd no longer crashes when an area cannot be opened. - JamNNTPd no longer crashes when trying to display messages with blank JAMSFLD_FTSKLUDGE fields in the XOVER command. - The body text of posts that started with a blank line were lost in previous versions. This has now been fixed. - Upgraded JAMLIB to version 1.3.2. - Other minor fixes and improvements. Changes in version 0.5 - Superfluous space characters are now removed when lines are joined when posting using format=flowed. - Implemented quote reformatting (-smartquote switch) - Changed % to $ in Message-Id and References line. - XOVER didn't work in groups with only one message. Fixed. - JAMLIB is now included in the JamNNTPd archive and no longer needs to be downloaded separately. - Simplified the compilation process. Now "make linux" or "make win32" in the src directory is enough. Changes in version 0.4 - First public release jamnntpd-1.2/ReadMe.txt000066400000000000000000000365011141642135500150740ustar00rootroot00000000000000 JamNNTPd 1.2 Copyright 2003-2005, Johan Billing (billing@df.lth.se) Copyright 2009, Peter Krefting (peter@softwolves.pp.se) Copyright 2008, 2010, Robert James Clay (jame@rocasa.us) 2010-07-11 1. Introduction =============== JamNNTPd is an attempt to merge dying fidonet technology with modern Usenet newsreaders. Basically, JamNNTPd is NNTP server that allows newsreaders to access a JAM messagebase. (If you didn't understand a word of this, you probably don't want to use JamNNTPd anyway). JamNNTPd can be used with both Linux and Windows. An executable binary is only suppplied for Windows, Linux users need to compile JamNNTPd themselves. 2. Copyright ============ The copyright of JamNNTPd belongs to Johan Billing. Permission to use, copy and distribute JamNNTPd is granted provided that this copyright notice is included. Permission to modify JamNNTPd is granted. Distributing modified versions of JamNNTPd is allowed provided that the documentation clearly states that it is a modified version. Parts of JamNNTPd may be freely used in other projects as long as credit is given. JamNNTPd uses JAMLIB for reading and modifying JAM messagebases. JAMLIB is copyright 1996 Björn Stenberg and is released under the GNU Lesser General Public License (see included file src/jamlib/LICENSE). 3. Security =========== I cannot guarantee that there are no security leaks in JamNNTPd. If you decide to use it, you do it on your own risk. If you use JamNNTPd under Linux, you should avoid running it with root privileges. 4. Using JamNNTPd ================= 4.1 Configuration options ------------------------- The behaviour of JamNNTPd can be configured using the configuration options specified below. These can be given to JamNNTPd in two ways: 1) As commandline arguments 2) In a configuration file (see -config command). The preceding dash (-) is optional when an option is given in a file, it will be added if missing. A configuration file with the default settings can be created with the -create option. If JamNNTPd is run without any commandline arguments at all, it will attempt to read options from a file called "jamnntpd.config" if present. Under Linux, JamNNTPd will look for this file in the "/etc" directory and under Windows in the current directory. It is not necessary to specify any configuration options at all unless when fine-tuning JamNNTPd, the default have been designed to be sensible. General options: -port or -p Set the port where JamNNTPd listens for connections. The default is 5000. -max or -m The maximum allowed number of connections at one time. The default is 5. -groups or -g -allow or -a -users or -u -xlat or -x Use these to override the default locations of the config files. -logfile or -l Use this to override the default location of the log file. -noecholog Disables echoing of log messages to the console window. -debug If this option is used, JamNNTPd will print all sent and received text to the console window. Useful for testing. Options for displaying messages: -readorigin Get address from the Origin line instead of the OADDRESS field of the JAM message header. This option makes JamNNTPd slower, but may be useful if your tosser does not set the OADDRESS field. -noencode JamNNTPd by default MIME-encodes headers with non-ascii characters. If you use this option, JamNNTPd will instead send the headers as plain 8-bit text. -strictnetmail Makes JamNNTPd use strict article counters for netmail messages. Normally JamNNTPd uses article counters that include all messages, not only those that the user is allowed to read. That behaviour is much faster, but may cause your newsreader to indicate the presence of new messages in the netmail area even when there are only messages for other users. Using this option will make JamNNTPd slower, but speed seems to be acceptable for small netmail areas with up to 1000 messages. Users will never be allowed to actually read netmail messages of other users even when this option is not used. -def_flowed on/off -def_showto on/off Sets the default of the flowed and showto settings (if no default is specified on the commandline, both will be on by default) flowed: If flowed is on, JamNNTPd will use format=flowed (section 6.5), otherwise it will wrap long lines to a fixed width. showto: Since there is no receiver for news messages, JamNNTPd can display the receiver name as a part of the sender name. With this option, this behaviour can be turned on or off. These can be modified by the user by logging in with parameters (section 4.4) Options for posting messages: -nostripre JamNNTPd normally strips "Re:" from subject lines of followups. Use this option if you want to retain the "Re:". -notearline JamNNTPd normally puts the information from the X-Newsreader or User-Agent header field in the tearline of posted messages. This option disables this behaviour and leaves the tearline blank. -noreplyaddr JamNNTPd normally adds a REPLYADDR kludge with the e-mail address of the sender in posted messages. Use this option if you don't want REPLYADDR kludges. See also see section 6.4 below. -notzutc JamNNTPd normally writes the timezone into a TZUTC kludge when a message is posted. You can use this option if you don't want to create TZUTC kludges. -nocancel Disallows the cancelling (deleting) of messages by the users. If allowed, users can only cancel messages from one of their "realnames" and only if the message has not yet been sent. -smartquote The quoting style of most newsreaders is different from traditional fidonet software. If you enable this option, JamNNTPd will try to change any quoted lines to fidonet style. This means that it will try to insert the initials of the person you reply to before the '>' character and also that it will try to compound multiple generations of quotes, i.e. "AA> BB>" will be changed into "BB>>". Reformatting quotes in this way means that the user who posts a message will no longer have final say over the final content of the message since it will be changed after he or she sends it to JamNNTPd. Since this in principle is a bad thing even if quoted text will look a lot better after reformatting, this option is turned off by default. -origin Normally JamNNTPd uses the text found in the Organization header line as the Origin line text in posted messages. You can use this switch to override the Organization line and set your own origin for all posted messages. -guestsuffix If desired, JamNNTPd can add a suffix to posts from unauthenticated users. To activate that feature, specify the suffix here. Example: -guestsuffix " [GUEST]". -echomailjam If you specify a filename here, JamNNTPd will write a line to this file with the messagebase and message number for each message that is posted. The file follows the ECHOMAIL.JAM format supported by some tossers. Options for configuration files: -config Read options from the specified configuration file. -create Create a configuration file with the default settings. 4.2 Access rights ----------------- Access rights in JamNNTPd is based on access groups. Every newsgroup in JamNNTPd belongs to an acess group. Access groups are named using one letter, typically A to Z (access groups are case-insensitive). In the configuration files, you can use "*" for "all groups" and "-" for "no groups". When a user connects to the server, he/she gets access to two set of access groups. The first set of groups are for read access and the second set of groups are for post access. Users are only allowed to read newsgroups that belong to an access group they have read access to and are only allowed to post to newsgroups belong to an access group that they have post access to. The default access groups for users are configured in the "allow" file. A user might get access to additional access groups if he/she logs in to the server using the AUTHINFO command. The groups associated with a user are defined in the "users" file. 4.3 Configuration files ----------------------- JamNNTPd uses four configuration files: 1) In the "groups" file, the JAM areas that JamNNTPd should provide as newsgroups are configured. 2) In the "allow" file, the IP numbers that are allowed to use the server are listed. Here you also set the default access rights for users before they log in. 3) In the "users" file, you can list users that should be given access to additional groups if they log in. 4) In the "xlat" file, you can configure translation between the different character sets used in your JAM messagebase and your newsreader. The format of these files can be seen in the example configuration files. You do not need to restart JamNNTPd if you change them since they are read every time a new connection to the server is made. 4.4 Logging in with parameters ------------------------------ Since it is likely that all users will not prefer the same settings for the flowed and showto options (see section 4.1), these can be modified by the user by logging in with parameters. If you want to set these options, login using a login name of this format: username/option1=on,option2=off If you want to set options without logging in, just omit the user name and enter anything as your password. Examples: billing/showto=off billing/flowed=on,showto=on /flowed=off 5. Compilation ============== JamNNTPd should compile with most compilers. I use gcc under Linux and MinGW under Windows. To compile JamNNTPd, go to the src directory and type either "make linux" or "make win32" depending on what platform you are compiling JamNNTPd on. After a successful compilation, you will find a file called "jamnntpd" or "jamnntpd.exe" in the src directory. 6. Compatibility ================ 6.1 The NNTP protocol --------------------- JamNNTPd supports most of the basic NNTP protocol as specified in RFC-977. The commands IHAVE, NEWGROUPS and NEWNEWS are not implemented, but at least give valid response codes if a newsreader tries to use them. JamNNTPd also supports the XOVER and AUTHINFO commands as specified in RFC-2980. XOVER never sends information about the line counts and byte counts of messages. 6.2 Format of news messages --------------------------- JamNNTPd probably breaks the RFC-1036 specification on some minor points, but seems to work well enough with most newsreaders. MIME is supported. Headers with non-ascii characters are encoded using quoted-printable or base64 unless disabled with -noencode. Message bodies are always sent as 7bit or 8bit. The charset is always set to "us-ascii" if a message does not contain non-ascii characters. Posted messages can either be in plain text (8bit or 7bit) or encoded with quoted-printable of base64. Posted messages are only accepted if they are in the format text/plain (i. e. HTML and multipart messages will be rejected). Crossposted messages will be rejected. Messages longer than 20 000 bytes will also be rejected. 6.3 MSGID / Message-ID ---------------------- JamNNTPd does not present the MSGIDs found in the JAM messagebase as Message-IDs to the newsreader, but rather uses its own dummy Message-IDs instead. The references line in followups will be replaced by the proper REPLY line. 6.4 REPLYADDR ------------- When a message is posted to a JAM messagebase, JamNNTPd converts the original from address to a REPLYADDR kludge. According to FSC-0035, REPLYADDR kludges should be accompanied by a REPLYTO line. JamNNTPd does not create a REPLYTO line, but this should not be a major problem. If you want to disable the REPLYADDR kludge altogether, use the -noreplyaddr option. 6.5 format=flowed ----------------- A recent extension to MIME (RFC-2646) specifies a format for "flowed" text, i. e. text that only has line breaks between paragraphs and not after every line. This format is more well-suited for fidonet messages than the traditional format since fidonet has always used "flowed" text. JamNNTPd uses format=flowed unless disabled with the -def_flowed switch or with login parameters, and it is preferable to use a newsreader that also supports this format. Unfortunately, only few newsreaders support this format today. JamNNTPd will also work with other newsreaders, but messages will look slightly worse both on the NNTP and fidonet side. 6.6 Character set translation ----------------------------- JamNNTPd has good support for character sets. The character set translation is configured in the "xlat" file and uses CHS files in the GoldED+ format for the actual translation. Extended CHS files with 256 character translations are supported and a character may be translated to up to four characters. 6.7 Netmail ----------- JamNNTPd now also supports netmail. In netmail areas, users can only read messages to or from one of the names configured in the jamnntpd.users file. Replies to netmails are handled transparently and the name and address of the recipient are taken from the original message. When a user wants to write a new netmail, the name and address of the recipient are specified on the first line of the new message using this format: To: name,address Example: To: Johan Billing, 2:15/87 A To: line can also be used to specify an alternative recipient in both netmail and echomail areas. 6.8 Tested newsreaders ---------------------- JamNNTPd has been found to work with the following newsreaders: Mozilla 1.4.1 Outlook Express 6.00.2800.1106 KNode 0.7.2 Xnews 5.04.25 40tude Dialog 2.0.7.1 Forte Free Agent 1.93/32.576 Lynx 2.8.5 Of these, only Mozilla seems to support format=flowed. 7. How to create additional *.chs files ======================================= The *.chs files in the "xlat" and "unicode/xlat" directories are character set translation tables in the GoldED+ format. The files were created from mappings files found at this URL: http://www.unicode.org/Public/MAPPINGS/ Fallback sequences for characters that don't exist in the target charset were taken from Markus Kuhn's transliteration tables found at the URL below: http://www.cl.cam.ac.uk/~mgk25/download/transtab.tar.gz If you want to create additional translation tables, you can easily do so with the supplied utility "makechs". Syntax for makechs: makechs [] is the fidonet name of the charset you want to convert from. is the fidonet name of the charset you want to convert to. is the Unicode mappings file for the source charset. is the Unicode mappings file for the destination charset. If you don't supply a mappings file, makechs will instead create a chs file that converts the source charset to utf-8. The output of makechs is written to the console and needs to be redirected to the desired file. Examples: makechs IBMPC LATIN-1 map/cp437.txt map/8859-1.txt >437_iso.chs makechs IBMPC UTF-8 map/cp437.txt >437_utf.chs Mappings files for all imaginable character sets can be found at the Unicode site above. jamnntpd-1.2/ReadMe_hpt.txt000066400000000000000000000021061141642135500157410ustar00rootroot00000000000000Some notes on using JamNNTPd with the hpt tosser from the Husky project: * The fidoconfig2jamnntpd.pl script found on the JamNNTPd homepage can be used to convert your area configuration to a jamnntpd.groups file. * If you want JamNNTPd to display the From address correctly, you need to run it with the -readorigin switch. * When hpt creates JAM messagebases, it does not create the lastread (*.jlr) file. JamNNTPd will not be able to open an area unless all four JAM files are present. The checkgroups.pl script from the JamNNTPd homepage can be used to create missing *.jlr files. * Do NOT pack your messagebase with "hpt pack". When hpt packs a messagebase, it will also renumber it. This will cause the article numbers in JamNNTPd to change which will confuse most newsreaders. * JamNNTPd can optionally create an echomail.jam files with the paths to messagebases with messages to export. This file can not be used to tell hpt what areas to scan, but it can be converted to an echotoss.log file for hpt with the echomailjam2hpt.pl script. jamnntpd-1.2/examples/000077500000000000000000000000001141642135500150075ustar00rootroot00000000000000jamnntpd-1.2/examples/jamnntpd.allow000066400000000000000000000007601141642135500176650ustar00rootroot00000000000000# Allowed IP numbers for JamNNTPd # # Syntax: # # # # "*" can be used as a wildcard. Everything after "*" is ignored, i. e. # 127.0.*.1 is equivalent to 127.0.*. Just write "*" alone on a line to # allow all IP numbbers. # # If no access groups are configured, users connecting from that IP will # not be able to access any newsgroups unless they log in. # # "*" means "all groups" and "-" means "no groups". # 127.0.0.1 AX A jamnntpd-1.2/examples/jamnntpd.groups000066400000000000000000000025121141642135500200630ustar00rootroot00000000000000# Groups configuration for JamNNTPd # # Syntax: # # [] [-nochrs] # # The tagname is the name of the group. If you enter a '!' character in front # of the tagname, the area will be treated as a netmail area and users can # only read messages to or from their realname(s). If you enter a '$' in # front of the tagname, the area will be treated as a local area which means # that posted messages will have no address, no tearline and no origin line. # # The default charset (optional) is the assumed charset when no CHRS or # CODEPAGE line is found. If the default chrs begins with a "!" character, # the "force" mode is activated for that group. In "force" mode, the # specified charset is used regardless of the contents of the CHRS and # CODEPAGE lines and messages can only be posted in charsets that can # be translated to the forced character set. # # If -nochrs is specified, no CHRS will be created when messages are # posted in this area. !NETMAIL A 2:205/454.77 c:\fido\areas\NETMAIL R20_TEKNISKT_RASERI A 2:205/454.77 c:\fido\areas\R20_TEKNISKT_RASERI R20_AMIGA A 2:205/454.77 c:\fido\areas\R20_AMIGA LATIN-1 RU.COMP.HUMOR A 2:205/454.77 c:\fido\areas\RU.COMP.HUMOR !CP866 $LOCAL A 2:205/454.77 c:\fido\areas\LOCAL jamnntpd-1.2/examples/jamnntpd.users000066400000000000000000000021641141642135500177100ustar00rootroot00000000000000# User configuration file for JamNNTd # # Syntax: # # [] # # "*" means "all groups" and "-" means "no groups". # # Optionally, you can also specify one or more "real" names for the user. # Multiple names are separated by a comma. It is necessary to supply # realnames if you want to use JamNNTPd with netmail as users can only read # netmails to or from one of these names. It is possible to use the "?" # and "*" wildcards in the realnames. # # It it also only possible for a user to cancel messages that were written # by a name that matches their realnames. # # When a user posts a message, the first realname is used as the from name # unless it contains wildcards. If the first realname contains wildcards or # if no realnames are supplied, the from name is taken from the From: header # line of the posted message. # # If you use non-ascii characters in the realname, they should be in the # character set used on the NNTP side, most often iso-8859-1. billing password AX AX "Johan Billing,Billing,Johan" palinuris vulgaris AX AX "Palle Kuling" jamnntpd-1.2/examples/jamnntpd.xlat000066400000000000000000000050331141642135500175150ustar00rootroot00000000000000# Charset configuration for JamNNTPd # # If you want to disable charset translation, uncomment the following two lines # and remove the rest of the file. # #read * unknown-8bit #post * "" # This is the directory where the *.chs files will be found chsdir /home/fido/jamnntpd/xlat # Charset translations when reading messages # The charset specified with "defaultread" is the charset JamNNTPd will use # when no charset was specified in the CHRS and CODEPAGE lines. If you enter # the character "!" before the charset, the "force" mode is activated. In # "force" mode, the specified charset is used regardless of the contents of # the CHRS and CODEPAGE lines and messages can only be posted in charsets # that can be translated to the forced character set. Example: !CP866 # # You can enter group-specific default charsets in jamnntpd.groups. defaultread IBMPC # Syntax: read [,] [] [-keepsoftcr] # # Here you can configure the charset translations to be used when reading # messages. CHRS and CODEPAGE are taken from the respective kludge lines. # If you omit the xlat file, no actual charset translation will take place. # # The "-keepsoftcr" option can be used to prevent JamNNTPd from removing the # Soft-CR character (0x8d) as it is used in some character sets like CP866. read CP437 iso-8859-1 437_iso.chs read CP850 iso-8859-1 850_iso.chs read CP865 iso-8859-1 865_iso.chs read CP866 koi8-r 866_koi.chs -keepsoftcr read LATIN-1 iso-8859-1 # readalias can be used to configure aliases for charsets readalias IBMPC,850 CP850 readalias IBMPC,865 CP865 readalias IBMPC,866 CP866 readalias IBMPC CP437 # Charset translations when posting messages # The charset specified with "defaultpost" is the charset JamNNTPd will use # when no charset was specified. defaultpost iso-8859-1 # Syntax: post [,] # # Here you can configure the charset translations to be used when posting # messages. If you don't want to create CHRS kludges, enter "" as CHRS. # You should have "read" translations set up for all charsets you accept or # the receiver name of the posts might not be translated properly. post iso-8859-1 IBMPC iso_437.chs post koi8-r CP866 koi_866.chs # postalias can be used to configure aliases for charsets # # windows-1252 and iso-8859-15 are not exactly the same as iso-8859-1, but # close enough for most people. postalias windows-1252 iso-8859-1 postalias iso-8859-15 iso-8859-1 postalias us-ascii iso-8859-1 jamnntpd-1.2/src/000077500000000000000000000000001141642135500137605ustar00rootroot00000000000000jamnntpd-1.2/src/Makefile000066400000000000000000000017141141642135500154230ustar00rootroot00000000000000# type either "make linux", "make win32" or "make os2" to compile MAKE = make help: @echo You can use this Makefile in the following ways: @echo make linux ............ Make Linux binaries @echo make win32 ............ Make Win32 binaries @echo make os2 ............ Make OS/2 binaries (EMX) @echo make cleanlinux ....... Remove object files under Linux @echo make cleanwin32 ....... Remove object files under Win32 @echo make cleanos2 ......... Remove object files under OS/2 (EMX) linux : $(MAKE) -C jamlib -f Makefile.linux $(MAKE) -f Makefile.linux win32 : $(MAKE) -C jamlib -f Makefile.win32 $(MAKE) -f Makefile.win32 os2 : $(MAKE) -C jamlib -f Makefile.os2 $(MAKE) -f Makefile.os2 cleanlinux : $(MAKE) -C jamlib -f Makefile.linux clean $(MAKE) -f Makefile.linux clean cleanwin32 : $(MAKE) -C jamlib -f Makefile.win32 clean $(MAKE) -f Makefile.win32 clean cleanos2 : $(MAKE) -C jamlib -f Makefile.os2 clean $(MAKE) -f Makefile.os2 clean jamnntpd-1.2/src/Makefile.linux000066400000000000000000000022231141642135500165550ustar00rootroot00000000000000# Makefile for Linux # General PLATFORMDEF = -DPLATFORM_LINUX EXESUFFIX = CC = gcc $(DEFS) -Wall RM = rm -f STRIP = strip OBJS = main.o nntpserv.o os_linux.o sockio.o groups.o misc.o xlat.o allow.o login.o mime.o targets: jamnntpd$(EXESUFFIX) makechs$(EXESUFFIX) makechs$(EXESUFFIX): makechs.c $(CC) $(PLATFORMDEF) makechs.c -o makechs $(STRIP) makechs$(EXESUFFIX) jamnntpd$(EXESUFFIX): $(OBJS) $(CC) -o jamnntpd$(EXESUFFIX) $(OBJS) jamlib/jamlib.a -lpthread $(STRIP) jamnntpd$(EXESUFFIX) nntpserv.o : nntpserv.c $(CC) $(PLATFORMDEF) -c nntpserv.c -o nntpserv.o os_linux.o : os_linux.c $(CC) $(PLATFORMDEF) -c os_linux.c -o os_linux.o main.o : main.c $(CC) $(PLATFORMDEF) -c main.c -o main.o sockio.o : sockio.c $(CC) $(PLATFORMDEF) -c sockio.c -o sockio.o groups.o : groups.c $(CC) $(PLATFORMDEF) -c groups.c -o groups.o misc.o : misc.c $(CC) $(PLATFORMDEF) -c misc.c -o misc.o xlat.o : xlat.c $(CC) $(PLATFORMDEF) -c xlat.c -o xlat.o allow.o : allow.c $(CC) $(PLATFORMDEF) -c allow.c -o allow.o login.o : login.c $(CC) $(PLATFORMDEF) -c login.c -o login.o mime.o : mime.c $(CC) $(PLATFORMDEF) -c mime.c -o mime.o clean : $(RM) *.o jamnntpd-1.2/src/Makefile.os2000066400000000000000000000022451141642135500161250ustar00rootroot00000000000000# Makefile for OS/2 (EMX) # General PLATFORMDEF = -DPLATFORM_OS2 EXESUFFIX = .exe CC = gcc $(DEFS) -Wall -Zmt RM = del STRIP = emxbind -s OBJS = main.o nntpserv.o os_os2.o sockio.o groups.o misc.o xlat.o allow.o login.o mime.o targets: jamnntpd$(EXESUFFIX) makechs$(EXESUFFIX) makechs$(EXESUFFIX): makechs.c $(CC) $(PLATFORMDEF) makechs.c -o makechs$(EXESUFFIX) $(STRIP) makechs$(EXESUFFIX) jamnntpd$(EXESUFFIX): $(OBJS) $(CC) -o jamnntpd$(EXESUFFIX) $(OBJS) jamlib/jamlib.a -lsocket $(STRIP) jamnntpd$(EXESUFFIX) nntpserv.o : nntpserv.c $(CC) $(PLATFORMDEF) -c nntpserv.c -o nntpserv.o os_os2.o : os_os2.c $(CC) $(PLATFORMDEF) -c os_os2.c -o os_os2.o main.o : main.c $(CC) $(PLATFORMDEF) -c main.c -o main.o sockio.o : sockio.c $(CC) $(PLATFORMDEF) -c sockio.c -o sockio.o groups.o : groups.c $(CC) $(PLATFORMDEF) -c groups.c -o groups.o misc.o : misc.c $(CC) $(PLATFORMDEF) -c misc.c -o misc.o xlat.o : xlat.c $(CC) $(PLATFORMDEF) -c xlat.c -o xlat.o allow.o : allow.c $(CC) $(PLATFORMDEF) -c allow.c -o allow.o login.o : login.c $(CC) $(PLATFORMDEF) -c login.c -o login.o mime.o : mime.c $(CC) $(PLATFORMDEF) -c mime.c -o mime.o clean : $(RM) *.o jamnntpd-1.2/src/Makefile.win32000066400000000000000000000022521141642135500163620ustar00rootroot00000000000000# Makefile for Linux # General PLATFORMDEF = -DPLATFORM_WIN32 EXESUFFIX = .exe CC = gcc $(DEFS) -Wall RM = del STRIP = strip OBJS = main.o nntpserv.o os_win32.o sockio.o groups.o misc.o xlat.o allow.o login.o mime.o targets: jamnntpd$(EXESUFFIX) makechs$(EXESUFFIX) makechs$(EXESUFFIX) : makechs.c $(CC) $(PLATFORMDEF) makechs.c -o makechs$(EXESUFFIX) $(STRIP) makechs$(EXESUFFIX) jamnntpd$(EXESUFFIX) : $(OBJS) $(CC) -o jamnntpd$(EXESUFFIX) $(OBJS) jamlib/jamlib.a -lwsock32 $(STRIP) jamnntpd$(EXESUFFIX) nntpserv.o : nntpserv.c $(CC) $(PLATFORMDEF) -c nntpserv.c -o nntpserv.o os_win32.o : os_win32.c $(CC) $(PLATFORMDEF) -c os_win32.c -o os_win32.o main.o : main.c $(CC) $(PLATFORMDEF) -c main.c -o main.o sockio.o : sockio.c $(CC) $(PLATFORMDEF) -c sockio.c -o sockio.o groups.o : groups.c $(CC) $(PLATFORMDEF) -c groups.c -o groups.o misc.o : misc.c $(CC) $(PLATFORMDEF) -c misc.c -o misc.o xlat.o : xlat.c $(CC) $(PLATFORMDEF) -c xlat.c -o xlat.o allow.o : allow.c $(CC) $(PLATFORMDEF) -c allow.c -o allow.o login.o : login.c $(CC) $(PLATFORMDEF) -c login.c -o login.o mime.o : mime.c $(CC) $(PLATFORMDEF) -c mime.c -o mime.o clean : $(RM) *.o jamnntpd-1.2/src/allow.c000066400000000000000000000021211141642135500152360ustar00rootroot00000000000000#include "nntpserv.h" bool checkallow(struct var *var,uchar *ip) { FILE *fp; uchar s[1000],cfgip[100],cfgreadgroups[50],cfgpostgroups[50]; int res1,res2,res3; ulong pos,line; if(!(fp=fopen(cfg_allowfile,"r"))) { os_logwrite("(%s) Can't read allow file %s",var->clientid,cfg_allowfile); return(FALSE); } line=0; while(fgets(s,999,fp)) { line++; strip(s); pos=0; if(s[0]!=0 && s[0]!='#') { res1=getcfgword(s,&pos,cfgip,100); res2=getcfgword(s,&pos,cfgreadgroups,50); res3=getcfgword(s,&pos,cfgpostgroups,50); if(res1) { if(matchpattern(cfgip,ip)) { if(res2) strcpy(var->readgroups,cfgreadgroups); if(res3) strcpy(var->postgroups,cfgpostgroups); fclose(fp); return(TRUE); } } else { os_logwrite("(%s) Syntax error on line %lu in %s, skipping line",var->clientid,line,cfg_allowfile); } } } fclose(fp); return(FALSE); } jamnntpd-1.2/src/allow.h000066400000000000000000000000551141642135500152470ustar00rootroot00000000000000bool checkallow(struct var *var,uchar *str); jamnntpd-1.2/src/groups.c000066400000000000000000000054711141642135500154520ustar00rootroot00000000000000#include "nntpserv.h" bool readgroups(struct var *var) { FILE *fp; uchar s[1000],tagname[100],group[2],aka[40],jampath[100],option[100]; bool res1,res2,res3,res4; ulong pos,line; struct group *newgroup,*lastgroup; if(!(fp=fopen(cfg_groupsfile,"r"))) { os_logwrite("(%s) Failed to read group configuration file %s",var->clientid,cfg_groupsfile); return(FALSE); } lastgroup=NULL; var->firstgroup=NULL; line=0; while(fgets(s,999,fp)) { line++; strip(s); pos=0; if(s[0]!=0 && s[0]!='#') { res1=getcfgword(s,&pos,tagname,100); res2=getcfgword(s,&pos,group,2); res3=getcfgword(s,&pos,aka,40); res4=getcfgword(s,&pos,jampath,100); if(res1 && res2 && res3 && res4) { if(!(newgroup=(struct group *)malloc(sizeof(struct group)))) { fclose(fp); return(FALSE); } newgroup->next=NULL; if(!var->firstgroup) var->firstgroup=newgroup; if(lastgroup) lastgroup->next=newgroup; lastgroup=newgroup; newgroup->netmail=FALSE; newgroup->local=FALSE; if(tagname[0] == '!') { newgroup->netmail=TRUE; strcpy(newgroup->tagname,&tagname[1]); } else if(tagname[0] == '$') { newgroup->local=TRUE; strcpy(newgroup->tagname,&tagname[1]); } else { strcpy(newgroup->tagname,tagname); } newgroup->group=group[0]; strcpy(newgroup->aka,aka); strcpy(newgroup->jampath,jampath); newgroup->nochrs=FALSE; newgroup->defaultchrs[0]=0; while(getcfgword(s,&pos,option,100)) { if(stricmp(option,"-nochrs")==0) { newgroup->nochrs=TRUE; } else if(option[0] != '-' && newgroup->defaultchrs[0] == 0) { mystrncpy(newgroup->defaultchrs,option,20); } else { os_logwrite("(%s) Warning: Unknown option %s on line %lu in %s",var->clientid,option,line,cfg_groupsfile); } } } else { os_logwrite("(%s) Syntax error on line %lu in %s, skipping line",var->clientid,line,cfg_groupsfile); } } } fclose(fp); if(!var->firstgroup) { os_logwrite("(%s) No groups configured",var->clientid); return(FALSE); } return(TRUE); } void freegroups(struct var *var) { freelist(var->firstgroup); var->firstgroup=NULL; } jamnntpd-1.2/src/groups.h000066400000000000000000000004111141642135500154440ustar00rootroot00000000000000struct group { struct group *next; uchar tagname[100]; uchar group; uchar jampath[100]; uchar aka[40]; uchar defaultchrs[20]; bool netmail; bool local; bool nochrs; }; bool readgroups(struct var *var); void freegroups(struct var *var); jamnntpd-1.2/src/jamlib/000077500000000000000000000000001141642135500152165ustar00rootroot00000000000000jamnntpd-1.2/src/jamlib/LICENSE000066400000000000000000000634761141642135500162430ustar00rootroot00000000000000 GNU LESSER GENERAL PUBLIC LICENSE Version 2.1, February 1999 Copyright (C) 1991, 1999 Free Software Foundation, Inc. 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. [This is the first released version of the Lesser GPL. It also counts as the successor of the GNU Library Public License, version 2, hence the version number 2.1.] Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public Licenses are intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This license, the Lesser General Public License, applies to some specially designated software packages--typically libraries--of the Free Software Foundation and other authors who decide to use it. You can use it too, but we suggest you first think carefully about whether this license or the ordinary General Public License is the better strategy to use in any particular case, based on the explanations below. When we speak of free software, we are referring to freedom of use, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish); that you receive source code or can get it if you want it; that you can change the software and use pieces of it in new free programs; and that you are informed that you can do these things. To protect your rights, we need to make restrictions that forbid distributors to deny you these rights or to ask you to surrender these rights. These restrictions translate to certain responsibilities for you if you distribute copies of the library or if you modify it. For example, if you distribute copies of the library, whether gratis or for a fee, you must give the recipients all the rights that we gave you. You must make sure that they, too, receive or can get the source code. If you link other code with the library, you must provide complete object files to the recipients, so that they can relink them with the library after making changes to the library and recompiling it. And you must show them these terms so they know their rights. We protect your rights with a two-step method: (1) we copyright the library, and (2) we offer you this license, which gives you legal permission to copy, distribute and/or modify the library. To protect each distributor, we want to make it very clear that there is no warranty for the free library. Also, if the library is modified by someone else and passed on, the recipients should know that what they have is not the original version, so that the original author's reputation will not be affected by problems that might be introduced by others. Finally, software patents pose a constant threat to the existence of any free program. We wish to make sure that a company cannot effectively restrict the users of a free program by obtaining a restrictive license from a patent holder. Therefore, we insist that any patent license obtained for a version of the library must be consistent with the full freedom of use specified in this license. Most GNU software, including some libraries, is covered by the ordinary GNU General Public License. This license, the GNU Lesser General Public License, applies to certain designated libraries, and is quite different from the ordinary General Public License. We use this license for certain libraries in order to permit linking those libraries into non-free programs. When a program is linked with a library, whether statically or using a shared library, the combination of the two is legally speaking a combined work, a derivative of the original library. The ordinary General Public License therefore permits such linking only if the entire combination fits its criteria of freedom. The Lesser General Public License permits more lax criteria for linking other code with the library. We call this license the "Lesser" General Public License because it does Less to protect the user's freedom than the ordinary General Public License. It also provides other free software developers Less of an advantage over competing non-free programs. These disadvantages are the reason we use the ordinary General Public License for many libraries. However, the Lesser license provides advantages in certain special circumstances. For example, on rare occasions, there may be a special need to encourage the widest possible use of a certain library, so that it becomes a de-facto standard. To achieve this, non-free programs must be allowed to use the library. A more frequent case is that a free library does the same job as widely used non-free libraries. In this case, there is little to gain by limiting the free library to free software only, so we use the Lesser General Public License. In other cases, permission to use a particular library in non-free programs enables a greater number of people to use a large body of free software. For example, permission to use the GNU C Library in non-free programs enables many more people to use the whole GNU operating system, as well as its variant, the GNU/Linux operating system. Although the Lesser General Public License is Less protective of the users' freedom, it does ensure that the user of a program that is linked with the Library has the freedom and the wherewithal to run that program using a modified version of the Library. The precise terms and conditions for copying, distribution and modification follow. Pay close attention to the difference between a "work based on the library" and a "work that uses the library". The former contains code derived from the library, whereas the latter must be combined with the library in order to run. GNU LESSER GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License Agreement applies to any software library or other program which contains a notice placed by the copyright holder or other authorized party saying it may be distributed under the terms of this Lesser General Public License (also called "this License"). Each licensee is addressed as "you". A "library" means a collection of software functions and/or data prepared so as to be conveniently linked with application programs (which use some of those functions and data) to form executables. The "Library", below, refers to any such software library or work which has been distributed under these terms. A "work based on the Library" means either the Library or any derivative work under copyright law: that is to say, a work containing the Library or a portion of it, either verbatim or with modifications and/or translated straightforwardly into another language. (Hereinafter, translation is included without limitation in the term "modification".) "Source code" for a work means the preferred form of the work for making modifications to it. For a library, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the library. Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running a program using the Library is not restricted, and output from such a program is covered only if its contents constitute a work based on the Library (independent of the use of the Library in a tool for writing it). Whether that is true depends on what the Library does and what the program that uses the Library does. 1. You may copy and distribute verbatim copies of the Library's complete source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and distribute a copy of this License along with the Library. You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. 2. You may modify your copy or copies of the Library or any portion of it, thus forming a work based on the Library, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: a) The modified work must itself be a software library. b) You must cause the files modified to carry prominent notices stating that you changed the files and the date of any change. c) You must cause the whole of the work to be licensed at no charge to all third parties under the terms of this License. d) If a facility in the modified Library refers to a function or a table of data to be supplied by an application program that uses the facility, other than as an argument passed when the facility is invoked, then you must make a good faith effort to ensure that, in the event an application does not supply such function or table, the facility still operates, and performs whatever part of its purpose remains meaningful. (For example, a function in a library to compute square roots has a purpose that is entirely well-defined independent of the application. Therefore, Subsection 2d requires that any application-supplied function or table used by this function must be optional: if the application does not supply it, the square root function must still compute square roots.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Library, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Library, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Library. In addition, mere aggregation of another work not based on the Library with the Library (or with a work based on the Library) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may opt to apply the terms of the ordinary GNU General Public License instead of this License to a given copy of the Library. To do this, you must alter all the notices that refer to this License, so that they refer to the ordinary GNU General Public License, version 2, instead of to this License. (If a newer version than version 2 of the ordinary GNU General Public License has appeared, then you can specify that version instead if you wish.) Do not make any other change in these notices. Once this change is made in a given copy, it is irreversible for that copy, so the ordinary GNU General Public License applies to all subsequent copies and derivative works made from that copy. This option is useful when you wish to copy part of the code of the Library into a program that is not a library. 4. You may copy and distribute the Library (or a portion or derivative of it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange. If distribution of object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place satisfies the requirement to distribute the source code, even though third parties are not compelled to copy the source along with the object code. 5. A program that contains no derivative of any portion of the Library, but is designed to work with the Library by being compiled or linked with it, is called a "work that uses the Library". Such a work, in isolation, is not a derivative work of the Library, and therefore falls outside the scope of this License. However, linking a "work that uses the Library" with the Library creates an executable that is a derivative of the Library (because it contains portions of the Library), rather than a "work that uses the library". The executable is therefore covered by this License. Section 6 states terms for distribution of such executables. When a "work that uses the Library" uses material from a header file that is part of the Library, the object code for the work may be a derivative work of the Library even though the source code is not. Whether this is true is especially significant if the work can be linked without the Library, or if the work is itself a library. The threshold for this to be true is not precisely defined by law. If such an object file uses only numerical parameters, data structure layouts and accessors, and small macros and small inline functions (ten lines or less in length), then the use of the object file is unrestricted, regardless of whether it is legally a derivative work. (Executables containing this object code plus portions of the Library will still fall under Section 6.) Otherwise, if the work is a derivative of the Library, you may distribute the object code for the work under the terms of Section 6. Any executables containing that work also fall under Section 6, whether or not they are linked directly with the Library itself. 6. As an exception to the Sections above, you may also combine or link a "work that uses the Library" with the Library to produce a work containing portions of the Library, and distribute that work under terms of your choice, provided that the terms permit modification of the work for the customer's own use and reverse engineering for debugging such modifications. You must give prominent notice with each copy of the work that the Library is used in it and that the Library and its use are covered by this License. You must supply a copy of this License. If the work during execution displays copyright notices, you must include the copyright notice for the Library among them, as well as a reference directing the user to the copy of this License. Also, you must do one of these things: a) Accompany the work with the complete corresponding machine-readable source code for the Library including whatever changes were used in the work (which must be distributed under Sections 1 and 2 above); and, if the work is an executable linked with the Library, with the complete machine-readable "work that uses the Library", as object code and/or source code, so that the user can modify the Library and then relink to produce a modified executable containing the modified Library. (It is understood that the user who changes the contents of definitions files in the Library will not necessarily be able to recompile the application to use the modified definitions.) b) Use a suitable shared library mechanism for linking with the Library. A suitable mechanism is one that (1) uses at run time a copy of the library already present on the user's computer system, rather than copying library functions into the executable, and (2) will operate properly with a modified version of the library, if the user installs one, as long as the modified version is interface-compatible with the version that the work was made with. c) Accompany the work with a written offer, valid for at least three years, to give the same user the materials specified in Subsection 6a, above, for a charge no more than the cost of performing this distribution. d) If distribution of the work is made by offering access to copy from a designated place, offer equivalent access to copy the above specified materials from the same place. e) Verify that the user has already received a copy of these materials or that you have already sent this user a copy. For an executable, the required form of the "work that uses the Library" must include any data and utility programs needed for reproducing the executable from it. However, as a special exception, the materials to be distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. It may happen that this requirement contradicts the license restrictions of other proprietary libraries that do not normally accompany the operating system. Such a contradiction means you cannot use both them and the Library together in an executable that you distribute. 7. You may place library facilities that are a work based on the Library side-by-side in a single library together with other library facilities not covered by this License, and distribute such a combined library, provided that the separate distribution of the work based on the Library and of the other library facilities is otherwise permitted, and provided that you do these two things: a) Accompany the combined library with a copy of the same work based on the Library, uncombined with any other library facilities. This must be distributed under the terms of the Sections above. b) Give prominent notice with the combined library of the fact that part of it is a work based on the Library, and explaining where to find the accompanying uncombined form of the same work. 8. You may not copy, modify, sublicense, link with, or distribute the Library except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense, link with, or distribute the Library is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. 9. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Library or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Library (or any work based on the Library), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Library or works based on it. 10. Each time you redistribute the Library (or any work based on the Library), the recipient automatically receives a license from the original licensor to copy, distribute, link with or modify the Library subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties with this License. 11. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Library at all. For example, if a patent license would not permit royalty-free redistribution of the Library by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Library. If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply, and the section as a whole is intended to apply in other circumstances. It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. 12. If the distribution and/or use of the Library is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Library under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. 13. The Free Software Foundation may publish revised and/or new versions of the Lesser General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Library specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Library does not specify a license version number, you may choose any version ever published by the Free Software Foundation. 14. If you wish to incorporate parts of the Library into other free programs whose distribution conditions are incompatible with these, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. NO WARRANTY 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS How to Apply These Terms to Your New Libraries If you develop a new library, and you want it to be of the greatest possible use to the public, we recommend making it free software that everyone can redistribute and change. You can do so by permitting redistribution under these terms (or, alternatively, under the terms of the ordinary General Public License). To apply these terms, attach the following notices to the library. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Also add information on how to contact you by electronic and paper mail. You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the library, if necessary. Here is a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the library `Frob' (a library for tweaking knobs) written by James Random Hacker. , 1 April 1990 Ty Coon, President of Vice That's all there is to it! jamnntpd-1.2/src/jamlib/Makefile.linux000066400000000000000000000010471141642135500200160ustar00rootroot00000000000000CC = gcc -D__LINUX__ -Wall AR = ar -ru RM = rm -f OBJS = crc32.o mbase.o message.o lastread.o subpack.o structrw.o jamlib.a : $(OBJS) $(AR) jamlib.a $(OBJS) crc32.o: crc32.c jam.h $(CC) -c crc32.c -o crc32.o mbase.o: mbase.c jam.h $(CC) -c mbase.c -o mbase.o message.o: message.c jam.h $(CC) -c message.c -o message.o lastread.o: lastread.c jam.h $(CC) -c lastread.c -o lastread.o subpack.o: subpack.c jam.h $(CC) -c subpack.c -o subpack.o structrw.o: structrw.c jam.h $(CC) -c structrw.c -o structrw.o clean: $(RM) *.o *.a jamnntpd-1.2/src/jamlib/Makefile.os2000066400000000000000000000010721141642135500173600ustar00rootroot00000000000000CC = gcc -Wall -D__OS2__ -DINCL_DOSPROCESS -Zmt AR = ar -ru RM = del OBJS = crc32.o mbase.o message.o lastread.o subpack.o structrw.o jamlib.a: $(OBJS) $(AR) jamlib.a $(OBJS) crc32.o: crc32.c jam.h $(CC) -c crc32.c -o crc32.o mbase.o: mbase.c jam.h $(CC) -c mbase.c -o mbase.o message.o: message.c jam.h $(CC) -c message.c -o message.o lastread.o: lastread.c jam.h $(CC) -c lastread.c -o lastread.o subpack.o: subpack.c jam.h $(CC) -c subpack.c -o subpack.o structrw.o: structrw.c jam.h $(CC) -c structrw.c -o structrw.o clean: $(RM) *.o *.a jamnntpd-1.2/src/jamlib/Makefile.win32000066400000000000000000000010311141642135500176120ustar00rootroot00000000000000CC = gcc -Wall AR = ar -ru RM = del OBJS = crc32.o mbase.o message.o lastread.o subpack.o structrw.o jamlib.a : $(OBJS) $(AR) jamlib.a $(OBJS) crc32.o: crc32.c jam.h $(CC) -c crc32.c -o crc32.o mbase.o: mbase.c jam.h $(CC) -c mbase.c -o mbase.o message.o: message.c jam.h $(CC) -c message.c -o message.o lastread.o: lastread.c jam.h $(CC) -c lastread.c -o lastread.o subpack.o: subpack.c jam.h $(CC) -c subpack.c -o subpack.o structrw.o: structrw.c jam.h $(CC) -c structrw.c -o structrw.o clean: $(RM) *.o *.a jamnntpd-1.2/src/jamlib/crc32.c000066400000000000000000000106341141642135500163020ustar00rootroot00000000000000/* Crc32 - CRC32-calculation for JAM Copyright (C) 2000 Johan Billing This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Changes made by Johan Billing 2003-10-22 - Fixed comparison between signed and unsigned variable in JAM_Crc32() */ #include "jam.h" ulong crc32tab[] = { /* CRC polynomial 0xedb88320 */ 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f, 0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988, 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, 0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7, 0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9, 0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172, 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, 0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59, 0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423, 0xcfba9599, 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924, 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190, 0x01db7106, 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433, 0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01, 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e, 0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950, 0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65, 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0, 0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa, 0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f, 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a, 0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683, 0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1, 0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb, 0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc, 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, 0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b, 0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55, 0x316e8eef, 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236, 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe, 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d, 0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713, 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38, 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242, 0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777, 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45, 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2, 0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc, 0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9, 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693, 0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94, 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d }; /*********************************************************************** ** ** JAM_Crc32 - Calculates CRC-32 ** ***********************************************************************/ ulong JAM_Crc32(uchar *Buffer_PC, ulong Length_I) { ulong Crc_I; ulong c; Crc_I=0xffffffff; for(c=0;c < Length_I; c++) Crc_I=(Crc_I>>8) ^ crc32tab[(uchar)Crc_I ^ tolower(Buffer_PC[c])]; return(Crc_I); } jamnntpd-1.2/src/jamlib/jam.h000066400000000000000000000253341141642135500161450ustar00rootroot00000000000000/* JAMLIB - A JAM subroutine library Copyright (C) 1999 Björn Stenberg This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Changes made by Johan Billing 2000-04-16: - Added #defines for JAM_NO_MESSAGE and JAM_CORRUPT_MSG - Added #ifndef linux around typedefs for ushort and ulong - Added prototype for JAM_AddEmptyMessage() Backported changes from JAMLIB 1.4.7 made by Johan Billing 2003-10-26 - Added prototype for JAM_DeleteMessage() */ /*********************************************************************** ** ** JAM Definitions ** ***********************************************************************/ #ifndef __JAM_H__ #define __JAM_H__ #include #include #include #ifndef linux typedef unsigned short ushort; /* must be 16 bits wide */ typedef unsigned long ulong; /* must be 32 bits wide */ #endif typedef unsigned char uchar; /* must be 8 bits wide */ /* ** Error codes */ #define JAM_BAD_PARAM 1 /* one or more parameters are wrong */ #define JAM_IO_ERROR 2 /* i/o error. check JAM_Errno() for details */ #define JAM_LOCK_FAILED 3 /* lock could not be set */ #define JAM_NOT_LOCKED 4 /* the message base was not locked before writing */ #define JAM_NO_MEMORY 5 /* out of memory! */ #define JAM_NO_USER 6 /* user not found */ #define JAM_NO_MESSAGE 7 /* message has been deleted */ #define JAM_CORRUPT_MSG 8 /* message header is corrupt */ /* ** CRC definitions */ #define JAM_NO_CRC 0xffffffff /* ** File extensions */ #define EXT_HDRFILE ".jhr" #define EXT_TXTFILE ".jdt" #define EXT_IDXFILE ".jdx" #define EXT_LRDFILE ".jlr" /* ** Revision level and header signature */ #define CURRENTREVLEV 1 #define HEADERSIGNATURE "JAM\0" /* ** Header file information block, stored first in all .JHR files */ typedef struct { uchar Signature[4]; /* followed by */ ulong DateCreated; /* Creation date */ ulong ModCounter; /* Last processed counter */ ulong ActiveMsgs; /* Number of active (not deleted) msgs */ ulong PasswordCRC; /* CRC-32 of password to access */ ulong BaseMsgNum; /* Lowest message number in index file */ uchar RSRVD[1000]; /* Reserved space */ } s_JamBaseHeader; /* ** Message status bits */ #define MSG_LOCAL 0x00000001L /* Msg created locally */ #define MSG_INTRANSIT 0x00000002L /* Msg is in-transit */ #define MSG_PRIVATE 0x00000004L /* Private */ #define MSG_READ 0x00000008L /* Read by addressee */ #define MSG_SENT 0x00000010L /* Sent to remote */ #define MSG_KILLSENT 0x00000020L /* Kill when sent */ #define MSG_ARCHIVESENT 0x00000040L /* Archive when sent */ #define MSG_HOLD 0x00000080L /* Hold for pick-up */ #define MSG_CRASH 0x00000100L /* Crash */ #define MSG_IMMEDIATE 0x00000200L /* Send Msg now, ignore restrictions */ #define MSG_DIRECT 0x00000400L /* Send directly to destination */ #define MSG_GATE 0x00000800L /* Send via gateway */ #define MSG_FILEREQUEST 0x00001000L /* File request */ #define MSG_FILEATTACH 0x00002000L /* File(s) attached to Msg */ #define MSG_TRUNCFILE 0x00004000L /* Truncate file(s) when sent */ #define MSG_KILLFILE 0x00008000L /* Delete file(s) when sent */ #define MSG_RECEIPTREQ 0x00010000L /* Return receipt requested */ #define MSG_CONFIRMREQ 0x00020000L /* Confirmation receipt requested */ #define MSG_ORPHAN 0x00040000L /* Unknown destination */ #define MSG_ENCRYPT 0x00080000L /* Msg text is encrypted */ #define MSG_COMPRESS 0x00100000L /* Msg text is compressed */ #define MSG_ESCAPED 0x00200000L /* Msg text is seven bit ASCII */ #define MSG_FPU 0x00400000L /* Force pickup */ #define MSG_TYPELOCAL 0x00800000L /* Msg is for local use only (no export) */ #define MSG_TYPEECHO 0x01000000L /* Msg is for conference distribution */ #define MSG_TYPENET 0x02000000L /* Msg is direct network mail */ #define MSG_NODISP 0x20000000L /* Msg may not be displayed to user */ #define MSG_LOCKED 0x40000000L /* Msg is locked, no editing possible */ #define MSG_DELETED 0x80000000L /* Msg is deleted */ /* ** Message header */ typedef struct { uchar Signature[4]; /* followed by */ ushort Revision; /* CURRENTREVLEV */ ushort ReservedWord; /* Reserved */ ulong SubfieldLen; /* Length of Subfields */ ulong TimesRead; /* Number of times message read */ ulong MsgIdCRC; /* CRC-32 of MSGID line */ ulong ReplyCRC; /* CRC-32 of REPLY line */ ulong ReplyTo; /* This msg is a reply to.. */ ulong Reply1st; /* First reply to this msg */ ulong ReplyNext; /* Next msg in reply chain */ ulong DateWritten; /* When msg was written */ ulong DateReceived; /* When msg was received/read */ ulong DateProcessed; /* When msg was processed by packer */ ulong MsgNum; /* Message number (1-based) */ ulong Attribute; /* Msg attribute, see "Status bits" */ ulong Attribute2; /* Reserved for future use */ ulong TxtOffset; /* Offset of text in text file */ ulong TxtLen; /* Length of message text */ ulong PasswordCRC; /* CRC-32 of password to access msg */ ulong Cost; /* Cost of message */ } s_JamMsgHeader; /* ** Message header Subfield types */ #define JAMSFLD_OADDRESS 0 #define JAMSFLD_DADDRESS 1 #define JAMSFLD_SENDERNAME 2 #define JAMSFLD_RECVRNAME 3 #define JAMSFLD_MSGID 4 #define JAMSFLD_REPLYID 5 #define JAMSFLD_SUBJECT 6 #define JAMSFLD_PID 7 #define JAMSFLD_TRACE 8 #define JAMSFLD_ENCLFILE 9 #define JAMSFLD_ENCLFWALIAS 10 #define JAMSFLD_ENCLFREQ 11 #define JAMSFLD_ENCLFILEWC 12 #define JAMSFLD_ENCLINDFILE 13 #define JAMSFLD_EMBINDAT 1000 #define JAMSFLD_FTSKLUDGE 2000 #define JAMSFLD_SEENBY2D 2001 #define JAMSFLD_PATH2D 2002 #define JAMSFLD_FLAGS 2003 #define JAMSFLD_TZUTCINFO 2004 #define JAMSFLD_UNKNOWN 0xffff /* ** Message header Subfield */ typedef struct { ushort LoID; /* Field ID, 0 - 0xffff */ ushort HiID; /* Reserved for future use */ ulong DatLen; /* Length of buffer that follows */ uchar* Buffer; /* DatLen bytes of data */ } s_JamSubfield; typedef struct { ushort LoID; /* Field ID, 0 - 0xffff */ ushort HiID; /* Reserved for future use */ ulong DatLen; /* Length of buffer that follows */ } s_JamSaveSubfield; /* ** Message index record */ typedef struct { ulong UserCRC; /* CRC-32 of destination username */ ulong HdrOffset; /* Offset of header in .JHR file */ } s_JamIndex; /* ** Lastread structure, one per user */ typedef struct { ulong UserCRC; /* CRC-32 of user name (lowercase) */ ulong UserID; /* Unique UserID */ ulong LastReadMsg; /* Last read message number */ ulong HighReadMsg; /* Highest read message number */ } s_JamLastRead; /* ** JAMLIB message base handle */ typedef struct { FILE* HdrFile_PS; /* File handle for .JHR file */ FILE* TxtFile_PS; /* File handle for .JDT file */ FILE* IdxFile_PS; /* File handle for .JDX file */ FILE* LrdFile_PS; /* File handle for .JLR file */ int Errno_I; /* last i/o error */ int Locked_I; /* is area locked? */ ulong LastUserPos_I; /* last position of lastread record */ ulong LastUserId_I; /* userid for the last read lastread record */ } s_JamBase; /* ** JAMLIB subfield packet */ typedef struct { s_JamSubfield** Fields; ulong NumFields; ulong NumAlloc; } s_JamSubPacket; /* ** JAMLIB function declarations */ /* mbase.c */ int JAM_OpenMB ( uchar* Basename_PC, s_JamBase** NewArea_PPS ); int JAM_CloseMB ( s_JamBase* Area_PS ); int JAM_CreateMB ( uchar* Basename_PC, ulong BaseMsg_I, s_JamBase** NewArea_PPS ); int JAM_RemoveMB ( s_JamBase* Area_PS, uchar* Basename_PC ); int JAM_LockMB ( s_JamBase* Area_PS, int Timeout_I ); int JAM_UnlockMB ( s_JamBase* Area_PS ); int JAM_ReadMBHeader ( s_JamBase* Area_PS, s_JamBaseHeader* Header_PS ); int JAM_WriteMBHeader ( s_JamBase* Area_PS, s_JamBaseHeader* Header_PS ); int JAM_FindUser ( s_JamBase* Area_PS, ulong UserCrc_I, ulong StartMsg_I, ulong* MsgNo_PI ); int JAM_GetMBSize ( s_JamBase* Area_PS, ulong* Messages_PI ); /* message.c */ int JAM_ReadMsgHeader ( s_JamBase* Area_PS, ulong MsgNo_I, s_JamMsgHeader* Header_PS, s_JamSubPacket** SubfieldPack_PPS ); int JAM_ReadMsgText ( s_JamBase* Area_PS, ulong Offset_I, ulong Length_I, uchar* Buffer_PC ); int JAM_AddMessage ( s_JamBase* Area_PS, s_JamMsgHeader* Header_PS, s_JamSubPacket* SubPack_PS, uchar* Text_PC, ulong TextLen_I ); int JAM_AddEmptyMessage ( s_JamBase* Area_PS ); int JAM_DeleteMessage ( s_JamBase* Base_PS, ulong MsgNo_I ); int JAM_ChangeMsgHeader ( s_JamBase* Area_PS, ulong MsgNo_I, s_JamMsgHeader* Header_PS ); int JAM_ClearMsgHeader ( s_JamMsgHeader* Header_PS ); int JAM_Errno ( s_JamBase* Area_PS ); /* lastread.c */ int JAM_ReadLastRead ( s_JamBase* Area_PS, ulong User_I, s_JamLastRead* Record_PS ); int JAM_WriteLastRead ( s_JamBase* Area_PS, ulong User_I, s_JamLastRead* Record_PS ); /* subpacket.c */ s_JamSubPacket* JAM_NewSubPacket ( void ); int JAM_DelSubPacket ( s_JamSubPacket* SubPack_PS ); s_JamSubfield* JAM_GetSubfield ( s_JamSubPacket* SubPack_PS ); s_JamSubfield* JAM_GetSubfield_R ( s_JamSubPacket* SubPack_PS , ulong* Count_PI); int JAM_PutSubfield ( s_JamSubPacket* SubPack_PS, s_JamSubfield* Field_PS ); /* crc32.c */ ulong JAM_Crc32 ( uchar* Buffer_PC, ulong Length_I ); #endif jamnntpd-1.2/src/jamlib/jamlib.doc000066400000000000000000001270471141642135500171560ustar00rootroot00000000000000 JAMLIB A JAM subroutine library by Björn Stenberg modifications by Johan Billing version 1.3.2 2004-07-10 GENERAL ======= History ------- JAMLIB 1.0 was originally released by Björn Stenberg 1996-03-06. Since the original license did not permit modification of the library, Johan Billing contacted Björn Stenberg and asked him to change the license. Björn Stenberg agreed to change the license to the GNU Lesser General Public License 1999-12-21 (see the accompanying file LICENSE). After that, some minor additions and bug fixes were made by Johan Billing and JAMLIB 1.1 was released under the new license. Changes in 1.3.2: * Updated the Win32-specific parts of the code to make it compatible with newer versions of MinGW (tested with 3.1.0-1). Changes in 1.3.1: * Backported the following bugfixes and improvements from JAMLIB 1.4.7 while retaining the platform-independence and high portability of the early versions of JAMLIB. - JAMLIB now uses calloc() instead of malloc() followed by memset() - JAM_OpenMB() and JAM_CreateMB() will set (*NewArea_PPS) to NULL if calloc() failed - JAM_CreateMB() no longer attempts indefinitely to lock the newly created messagebase. If the first attempt fails, it will return an error. - jam_Lock() now sets Base_PS->Errno under Linux - JAM_NewSubPacket() and JAM_PutSubField() would give memory leaks under conditions of low memory conditions. Fixed. - JAM_ReadMsgHeader() would give memory leaks on failure. Fixed. - Added JAM_DeleteMessage() Big thanks to Sir Raorn (and others?) for finding and fixing these bugs! * JAM_CreateMB() would never unlock or close the newly created messagebase upon failure. Fixed. * Improved handling of ActiveMsgs counter. JAM_AddMessage() now only increases ActiveMsgs if the added message does not have MSG_DELETED set. JAM_ChangeMsgHeader() decreases ActiveMsgs if MSG_DELETED is set and the message wasn't already deleted. JAM_DeleteMessage() now only decreases ActiveMsgs if the message wasn't already deleted. * Updated the documentation to reflect the need to free() memory after JAM_CloseMB() and failed calls to JAM_OpenMB() and JAM_CreateMB(). * Eliminated compiler warnings Changes in 1.3: * JAM_AddMessage() would fail when trying to add an empty message to the messagebase under Linux. Fixed. Changes in 1.2: * Since JAM_GetSubField() is not reentrant and cannot be used in multi-threaded applications, JAM_GetSubField_R() was added as a replacement for cases where a reentrant function is needed. Changes in 1.1: * Added support for Win32 and Linux * Added JAM_AddEmptyMessage() * Rewrote the Makefiles * Rewrote the CRC32 routine * Fixed broken JAM_FindUser() * Fixed broken JAM_GetSubfield() * Changed JAM_OpenMB so that files are opened in binary mode. This is necessary to use JAMLIB under Windows. * Improved JAM_ReadMsgHeader() to give the error JAM_NO_MESSAGE if the message no longer exists in the messagebase and JAM_CORRUPT_MSG if the subfields of the message have been corrupted. * Improved portability by changing JAMLIB so that it no longer reads and writes stuctures directly using fread() and fwrite(). * Improved ANSI-C compatibilty by no longer including the non-ANSI header file memory.h and using feof() to check for EOF instead of errno == EPASTEOF. * Added an #ifdef so that ushort and ulong are no longer defined in jam.h when compiling under Linux. These are normally already defined in the standard header files. License ------- JAMLIB - A JAM subroutine library Copyright (C) 1999 Björn Stenberg This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Description ----------- These are a collection of subroutines that encapsulate much of the format-specific and tedious details of the JAM message base format. The idea is that application programmers by using these routines can concentrate on the more high-level issues of their programs instead of worrying about their JAM routines. I [Björn Stenberg] wrote these routines primarily because I needed them myself. I was trying to implement JAM support in my FrexxLink BBS system and was frustrated by the poor level of documentation supplied in the JAMAPI archive distributed by the JAM authors. Finally, I dove into the JAMAPI source code in a desperate attempt at finding out how to use it. To my despair, I discovered that the JAMAPI is targeted at a very low level. I would need to implement a lot of JAM-handling code into my own program. This library is an attempt to do two things: Firstly, provide an, at least sparingly, _documented_ API, allowing application programmers to easily implement JAM into their programs. Secondly, raise the level of functionality above that of the original JAMAPI package, so that the application programmer does not have to learn and understand all the internals of the JAM message base format to implement support for it. I have not succeded completely on any of the two points, of course. Documentation can never be too good, and there are still a few things about JAM you must know in order to use it. But I think I have made it somewhat easier than perhaps was the case before. References ---------- If you are extra curious about the JAM message format, I suggest you get a hold of an archive called JAMAPI.ARJ. That archive contains a file called JAM.DOC which is the file I have used as reference for the development of these routines. Credits ------- All original code except for the CRC32 routine was written by Björn Stenberg. The CRC32 code was rewritten by Johan Billing for JAMLIB 1.1 to replace the original CRC32 code whose origin and copyright was unclear. The jam.h header file is a compilation of the best from the various header files in the JAMAPI package with some of additions by Björn Stenberg as well. Additions and modifications by Johan Billing. The JAM message base proposal is: JAM(mbp) - Copyright 1993 Joaquim Homrighausen, Andrew Milner, Mats Birch, Mats Wallin. ALL RIGHTS RESERVED Contact Information ------------------- For questions about JAMLIB, please contact: Johan Billing E-mail: billing@df.lth.se If you wish to contact Björn Stenberg, his current e-mail address (as of 1999-12-21) is bjorn@haxx.nu. THE LIBRARY =========== The Source Code --------------- I made a point of making this library as system independant as I could. Only one function needs to be altered when porting this to another system: The file locking. ANSI C does not include file locking so there is not much I can do about it. The choice of C over C++ is a part of this philosophy aswell. More systems have C compilers than C++ compilers, and more people know C than C++. Also, converting this library to a C++ class should be fairly simple. If you do, send me a copy. I use some naming conventions throughout the code and in the examples. These are invented by myself as a reaction to the stunningly ugly and hard-to-read Hungarian Notation promoted by some people. The rules of my notation are simple: * All library-global identifiers are prefixed with 'JAM_'. All file-global identifiers are prefixed with 'jam_'. Local identifiers do not have prefixes. * All variables have a suffix describing their basic type. Suffixes used in this library are: _I - integer (int Example_I) _C - character (char Example_C) _S - struct (struct Example_S) _P - pointer (void* Example_P) _A - array Suffixes are then combined, to show the correct type: _PI - pointer to integer (int* Example_PI) _PC - pointer to char (char* Example_PC) _AC - array of char (char Example_AC[x]) _PPS - pointer to pointer to struct (struct** Example_PPS) * Functions do not have suffixes The whole idea is that it is quicker to read and comprehend a variable called 'Text_PC' than one called 'pszText'. We read from left to right, and thus the most important information - the name - should be the leftmost data in the word. The variable type is additional information and is therefore added to the end where it does not disturb the reader. The Functions ------------- The library is divided into five groups: * Message base functions * Message functions * Subfield functions * LastRead functions * Miscellanous functions -------------------------------------------------------------------------- Message base functions ---------------------- These functions handle JAM message bases, by opening, locking, scanning etc the contents of a message base. These are fairly straight-forward and simple routines that you should have little, if any, trouble with. A message base is identified by a message base handle, which is obtained from either JAM_OpenMB() och JAM_CreateMB(). All functions that read or write from the message base take this handle as parameter, to know which message base to use. ================================ JAM_OpenMB - Open a message base ================================ Syntax int JAM_OpenMB( uchar* Basename_PC, t_JamBase** NewBase_PPS ); Description Opens a message base. Only one message base can be open at a time. Parameters Basename_PC The path and base filename of the message base. "Base filename" means the filename without the JAM-specific extension. NewBase_PPS A pointer to a message base handle where the new message base handle will be written. On error you must free() this memory if (*NewBase_PPS) not NULL. Returns 0 if successful JAM_IO_ERROR if an I/O error occured. see JAM_Errno() JAM_BAD_PARAM if NewBas_PPS is NULL Example { int Result_I; Result_I = JAM_OpenMB( "c:\\jam\\mybase", &Base_PS ); if ( Result_I ) printf("JAM_OpenMB returned %d.\n", Result_I ); } ================================ JAM_CloseMB - Close message base ================================ Syntax int JAM_CloseMB( Base_PS ); Description Unlocks (if locked) and closes the currently open message base. Parameters Base_PS The message base to close. Note, that you must free() this memory by yourself. Returns 0 if successful JAM_IO_ERROR if an I/O error occured. see JAM_Errno() JAM_LOCK_FAILED if the message base could not be unlocked Example { int Result_I; Result_I = JAM_CloseMB( Base_PS ); if ( Result_I ) printf("JAM_CloseMB returned %d.\n", Result_I ); } ======================================== JAM_CreateMB - Create a new message base ======================================== Syntax int JAM_CreateMB( uchar* Basename_PC, ulong BaseMsg_I, s_JamBase** NewBase_PPS ); Description Creates the necessary files for a new message base and writes a new message base header. If the message base already exists, its contents are destroyed. Parameters Basename_PC The path and base filename of the new message base. BaseMsg_I The base message number (first message #) for the new message base. This number is used when calculating new messages' unique message number. It should not be set to 0. NewBase_PPS A pointer to a message base handle where the new message base handle will be written. On error you must free() this memory if (*NewBase_PPS) not NULL. Returns 0 if successful JAM_IO_ERROR if an I/O error occured. see JAM_Errno() JAM_BAD_PARAM if BaseMsg_I is 0 or NewBase_PPS is NULL Example { int Result_I; Result_I = JAM_CreateMB( "c:\\jam\\mybase", 1, &Base_PS ); if ( Result_I ) printf("JAM_CreateMB returned %d.\n", Result_I ); } ==================================== JAM_RemoveMB - Remove a message base ==================================== Syntax int JAM_RemoveMB( ErrorBase_PS, uchar* Basename_PC ); Description Deletes all files associated with a message base. No checking is done as to whether the message base is currently open or not. Parameters ErrorBase_PS The message base in which to store the I/O error, if any. This parameter does *NOT* specify the message to be removed, it is only used for error tracking purposes. If an i/o error occurs when removing the message base files, this message base handler will simply hold the error code. Basename_PC The path and base filename of the message base to remove. Returns 0 if successful JAM_IO_ERROR if an I/O error occured. see JAM_Errno() JAM_BAD_PARAM if ErrorBase_PS is NULL Example { int Result_I; Result_I = JAM_RemoveMB( Base_PS, "c:\\jam\\mybase" ); if ( Result_I ) { printf("JAM_RemoveMB returned %d.\n", Result_I ); if ( Result_I == JAM_IO_ERROR ) printf( "i/o error %d\n", JAM_Errno( ErrorBase_PS ) ); } } =================================================== JAM_LockMB - Lock message base for exclusive access =================================================== Syntax int JAM_LockMB( t_JamBase* Base_PS ); Description Locks the currently open message base so that no other programs may modify it. The message base should be locked for only small periods of time, or the performance of tossers and other software may be affected. Parameters Base_PS The message base to lock Returns 0 if successful JAM_IO_ERROR if an I/O error occured. see JAM_Errno() JAM_LOCK_FAILED if the message base is currently locked by another process JAM_BAD_PARAM if Base_PS is NULL Example { int Result_I; while ( 1 ) { Result_I = JAM_LockMB( Base_PS ); if ( Result_I ) { if ( Result_I == JAM_LOCK_FAILED ) /* base locked by someone else, wait for unlock */ sleep( 1 ); else { /* error */ printf("JAM_LockMB returned %d.\n", Result_I ); return -1; } } } } ================================== JAM_UnlockMB - Unlock message base ================================== Syntax int JAM_UnlockMB( s_JamBase* Base_PS ); Description Unlocks message base, allowing other programs to modify it. Parameters Base_PS The message base to unlock Returns 0 if successful JAM_IO_ERROR if an I/O error occured. see JAM_Errno() JAM_BAD_PARAM if Base_PS is NULL Example { int Result_I; Result_I = JAM_UnlockMB( Base_PS ); if ( Result_I ) printf("JAM_UnlockMB returned %d.\n", Result_I ); } =========================================== JAM_ReadMBHeader - Read message base header =========================================== Syntax int JAM_ReadMBHeader( s_JamBase* Base_PS, s_JamBaseHeader* Header_PS ); Description Reads the message base header from the start of the JAM header file. Parameters Base_PS The message base to use Header_PS A pointer to a base header structure where the base header will be stored. Returns 0 if successful JAM_BAD_PARAM if Base_PS or Header_PS is NULL JAM_IO_ERROR if an I/O error occured. see JAM_Errno() Example { s_JamBaseHeader BaseHeader_S; int Result_I; Result_I = JAM_ReadMBHeader( Base_PS, &BaseHeader_S ); if ( Result_I ) printf("JAM_ReadMBHeader returned %d.\n", Result_I ); } ============================================= JAM_WriteMBHeader - Write message base header ============================================= Syntax int JAM_WriteMBHeader( s_JamBase* Base_PS, s_JamBaseHeader* Header_PS ); Description Increases the ModCounter field by one, resets the header signature and writes the message base header to the start of the JAM header file. Parameters Base_PS The message base to use Header_PS A pointer to the base header to be stored Returns 0 if successful JAM_BAD_PARAM if Base_PS or Header_PS is NULL JAM_IO_ERROR if an I/O error occured. see JAM_Errno() JAM_NOT_LOCKED if the message base is not locked Example { s_JamBaseHeader BaseHeader_S; int Result_I; /* modify header here */ Result_I = JAM_WriteMBHeader( &BaseHeader_S ); if ( Result_I ) printf("JAM_WriteMBHeader returned %d.\n", Result_I ); } ===================================== JAM_FindUser - Find message to a user ===================================== Syntax int JAM_FindUser( s_JamBase* Base_PS, ulong UserCrc_I, ulong StartMsg_I, ulong* MsgNo_PI ); Description Scans the message base looking for a message written to a specific user. Parameters Base_PS The message base to use UserCrc_I The CRC32 value for the searched name StartMsg_I The first message number to look at. This value is not the message's unique number, but rather the absolute position of the message in the message base. Message 0 therefore means the first message. MsgNo_PI A pointer to a variable where the message number for the found message will be stored. This number is the absolute message position in the message base. Message 0 means the first message. Returns 0 if a message was found JAM_NO_USER if no message was found JAM_IO_ERROR if an I/O error occured. see JAM_Errno() Example { uchar Name_AC[32]; int Result_I; ulong Crc_I; ulong Msg_I; strcpy( Name_AC, "Bjorn Stenberg" ); Crc_I = JAM_Crc32( Name_AC, strlen( Name_AC ) ); Result_I = JAM_FindUser( Base_PS, Crc_I, 0, &Msg_I ); switch ( Result_I ) { case JAM_NO_USER: printf("No message for me.\n"); break; case JAM_IO_ERROR: printf("IO error %d\n", JAM_Errno() ); break; } } ========================================================== JAM_GetMBSize - Get the number of messages in message base ========================================================== Syntax int JAM_GetMBSize( s_JamBase* Base_PS, ulong* Messages_PI ); Description Finds out the number of messages (deleted and undeleted) in the message base. Parameters Base_PS The message base to use Messages_PI A pointer to a variable where the number of messages will be stored. Returns 0 if successful JAM_IO_ERROR if an I/O error occured. see JAM_Errno() Example { int Result_I; ulong Size_I; Result_I = JAM_GetMBSize( Base_PS, &Size_I ); if ( Result_I ) printf("JAM_GetMBSize returned %d.\n", Result_I ); } -------------------------------------------------------------------------- Message functions ----------------- These functions handle individual JAM messages. A JAM message contains of three parts: * Message Header * Message Header Subfields * Message Text The message header is a simple C structure and the message text is a simple text buffer. The subfields, however, are a bit more tricky. These contain everything that is not covered by the header, including the TO, FROM, SUBJECT fields, origin and destination network adresses etc. There can be an unlimited number of subfields to a message. In this routine library the subfields are encapsulated by a 'subfield packet', which is handled by its own set of routines. See a later section of this document for an explanation of those. ============================================================= JAM_ReadMsgHeader - Read a message's header and its subfields ============================================================= Syntax int JAM_ReadMsgHeader( s_JamBase* Base_PS, ulong MsgNo_I, s_JamMsgHeader* Header_PS, s_JamSubPacket** Subfields_PPS ); Description Reads a message header and (optionally) the message header subfields. Parameters Base_PS The message base to use MsgNo_I The message number, i.e. the absolute position of the message in the message base. Message 0 is the first message. Header_PS A pointer to a message header structure where the message header will be stored. Subfields_PPS A pointer to a subpacket pointer, where the subfield packet handle will be stored. If this parameter is NULL, no subfields are read. Returns 0 if successful JAM_IO_ERROR if an I/O error occured. see JAM_Errno() JAM_NO_MEMORY if a memory allocation failed JAM_NO_MESSAGE if message has been removed JAM_CORRUPT_MSG if message subfields are corrupted Example { s_JamMsgHeader Header_S; s_JamSubPacket* SubPack_PS int Result_I; Result_I = JAM_ReadMsgHeader( 0, &Header_S, &SubPack_PS ); if ( Result_I ) printf("JAM_ReadMsgHeader returned %d.\n", Result_I ); } ======================================= JAM_ReadMsgText - Read a message's text ======================================= Syntax int JAM_ReadMsgText( s_JamBase* Base_PS, ulong Offset_I, ulong Length_I, uchar* Buffer_PC ); Description Reads the body text associated with a message. Parameters Base_PS The message base to use Offset_I The text position in the text file. This information is stored in the message header. Length_I The text length. This information is stored in the message header. Buffer_PC A pointer to where the text should be stored. Returns 0 if successful JAM_IO_ERROR if an I/O error occured. see JAM_Errno() Example { s_JamMsgHeader Header_S; uchar* Buffer_PC; int Result_I; /* read msg header */ Result_I = JAM_ReadMsgHeader( Base_PS, 0, &Header_S, &SubPack_PS ); if ( Result_I ) { printf("JAM_ReadMsgHeader returned %d.\n", Result_I ); return; } /* allocate buffer text */ Buffer_PC = (uchar*) malloc( Header_S.TxtLen ); if ( !Buffer_PC ) { printf("malloc failed.\n"); return; } /* read text */ Result_I = JAM_ReadMsgText( Base_PS, Header_S.TxtOffset, Header_S.TxtLen, Buffer_PC ); if ( Result_I ) printf("JAM_ReadMsgText returned %d.\n", Result_I ); free( Buffer_PC ); } ============================================== JAM_AddMessage - Add a message to message base ============================================== Syntax int JAM_AddMessage( s_JamBase* Base_PS, s_JamMsgHeader* Header_PS, s_JamSubPacket* SubPack_PS, uchar* Text_PC, ulong TextLen_I ); Description Adds a message to the message base. Fully automatic. Parameters Base_PS The message base to use Header_PS A pointer to the message header struct. The function will set the following header fields: Signature, Revision, TxtOffset, TxtLen, SubfieldLen and MsgNum. Whatever you set these fields to will be overwritten. SubPack_PS A subfield packet handler, containing all subfields for the message. Text_PC A pointer to the first byte of the message text. TextLen_I The length of the message text, excluding any zero termination characters. Returns 0 if successful JAM_IO_ERROR if an I/O error occured. see JAM_Errno() JAM_NOT_LOCKED if the message base is not locked Example { s_JamSubPacket* SubPacket_PS; s_JamSubfield Subfield_S; s_JamMsgHeader Header_S; uchar Text_AC[64]; uchar Field_AC[64]; /* ** Fix message header */ JAM_ClearMsgHeader( &Header_S ); Header_S.DateWritten = time(NULL); /* ** Create subfield packet */ SubPacket_PS = JAM_NewSubPacket(); if ( !SubPacket_PS ) { printf("JAM_NewSubPacket returned NULL.\n" ); return; } /* set up subfield 1 */ strcpy( Field_AC, "This is field #1" ); Subfield_S.LoID = JAMSFLD_SENDERNAME; Subfield_S.HiID = 0; Subfield_S.DatLen = strlen( Field_AC ); Subfield_S.Buffer = Field_AC; JAM_PutSubfield( SubPacket_PS, &Subfield_S ); /* set up subfield 2 */ strcpy( Field_AC, "This is field #2" ); Subfield_S.LoID = JAMSFLD_RECVRNAME; Subfield_S.HiID = 0; Subfield_S.DatLen = strlen( Field_AC ); Subfield_S.Buffer = Field_AC; JAM_PutSubfield( SubPacket_PS, &Subfield_S ); /* ** Add message */ strcpy( Text_AC, "Hello world!\nThis is a test."); /* [lock the message base] */ Result_I = JAM_AddMessage( Base_PS, &Header_S, SubPacket_PS, Text_AC, strlen( Text_AC ) ); if ( Result_I ) { printf("JAM_AddMessage returned %d.\n", Result_I ); return; } /* [unlock the message base] */ JAM_DelSubPacket( SubPacket_PS ); } ================================================================= JAM_AddEmptyMessage - Add a empty message entry to a message base ================================================================= Syntax int JAM_AddEmptyMessage( s_JamBase* Base_PS); Description Adds an empty message header to the message base. Useful when writing a messagebase maintenance utility. Parameters Base_PS The message base to use Returns 0 if successful JAM_IO_ERROR if an I/O error occured. see JAM_Errno() JAM_NOT_LOCKED if the message base is not locked Example none =============================================== JAM_ChangeMsgHeader - Change a message's header =============================================== Syntax int JAM_ChangeMsgHeader( s_JamBase* Base_PS, ulong MsgNo_I, s_JamMsgHeader* Header_PS ); Description Writes over an old message header with a new one. Only the header - not the subfields - can be changed due to the subfields' dynamic size. NOTE! Use this function with caution. It is easy to corrupt a message by giving it an incorrect header. Parameters Base_PS The message base to use MsgNo_I The absolute message number. Message #0 is the first in the message base. Header_PS A pointer to the header structure to write. Returns 0 if successful JAM_IO_ERROR if an I/O error occured. see JAM_Errno() JAM_NOT_LOCKED if the message base is not locked Example { s_JamMsgHeader Header_S; int Result_I; /* [lock the message base] */ Result_I = JAM_ReadMsgHeader( Base_PS, 0, &Header_S, NULL ); if ( Result_I ) printf("JAM_ReadMsgHeader returned %d.\n", Result_I ); Header_S.TimesRead++; Result_I = JAM_ChangeMsgHeader( Base_PS, 0, &Header_S ); if ( Result_I ) printf("JAM_ChangeMsgHeader returned %d.\n", Result_I ); /* [unlock the message base] */ } ===================================================== JAM_ClearMsgHeader - Clear a message header structure ===================================================== Syntax int JAM_ClearMsgHeader( s_JamMsgHeader* Header_PS ); Description Clears a message header structure and prepares it for use. This includes setting the Signature field and the Revision field to their correct values, and setting the CRC fields to JAM_NO_CRC. Parameters Header_PS A pointer to the structure to prepare. Returns 0 if successful JAM_BAD_PARAM if Header_PS is NULL =================================================== JAM_DeleteMessage - Delete message from messagebase =================================================== Syntax int JAM_DeleteMessage( s_JamBase* Base_PS, ulong MsgNo_I ); Description Deletes message from messagebase by setting HdrOffset and UserCRC in index to 0xFFFFFFFF. ActiveMsgs in base header also updated. Parameters Base_PS The message base to use MsgNo_I The absolute message number. Message #0 is the first in the message base. Returns 0 if successful JAM_IO_ERROR if an I/O error occured. see JAM_Errno() JAM_NOT_LOCKED if the message base is not locked Example none -------------------------------------------------------------------------- Subfield packet functions ------------------------- As described earlier, a subfield is a part of the message header. Due to the complexity of the different network types in use, it is not feasible to try and cram all data into one header struct. Therefore, JAM uses a fairly small header struct and instead marks all additional data fields as 'subfields'. In order to make life a little more easy, I have used the concept of a container for all subfields. I call it a 'Subfield Packet'. It is identified by a struct pointer, and should be looked upon as a file or a list that you manipulate via the following four functions: =============================================== JAM_NewSubPacket - Create a new subfield packet =============================================== Syntax s_JamSubPacket* JAM_NewSubPacket( void ); Description Creates a new, empty, subfield packet. Parameters None Returns The subpacket handle, if successful, or NULL if a memory allocation failed. Example { s_JamSubPacket* SubPacket_PS; SubPacket_PS = JAM_NewSubPacket(); if ( !SubPacket_PS ) { printf("JAM_NewSubPacket returned NULL.\n" ); return; } } =========================================== JAM_DelSubPacket - Delete a subfield packet =========================================== Syntax int JAM_DelSubPacket( s_JamSubPacket* SubPack_PS ); Description Frees all memory used by a subfield packet. All subfields in the packet will be lost and the packet handle will not be valid any more. Parameters SubPack_PS The subfield packet to delete Returns 0 if successful JAM_BAD_PARAM if SubPack_PS is NULL. Example { s_JamSubPacket* SubPacket_PS; SubPacket_PS = JAM_NewSubPacket(); if ( !SubPacket_PS ) { printf("JAM_NewSubPacket returned NULL.\n" ); return; } SubPacket_PS = JAM_DelSubPacket(); if ( !SubPacket_PS ) { printf("JAM_DelSubPacket returned NULL.\n" ); return; } } ======================================================================= JAM_GetSubfield - Get a subfield from a subfield packet (not reentrant) ======================================================================= Syntax s_JamSubfield* JAM_GetSubfield( s_JamSubPacket* SubPack_PS ); Description Returns a pointer to the first/next subfield struct in the subfield packet. WARNING: This function is not reentrant and should not be used in multi-threaded applications unless you know what you are doing. Use JAM_GetSubfield_R instead when a reentrant function is needed. Parameter SubPack_PS The subfield packet to use. If this parameter is NULL, the next subfield from the subfield packet previously scanned will be returned. Returns A pointer to a subfield, if successful, or NULL if there are no more subfields in the packet. Example { s_JamSubPacket* SubPack_PS; s_JamSubfield* Subfield_PS; s_JamMsgHeader Header_S; int Result_I; Result_I = JAM_ReadMsgHeader( 0, &Header_S, &SubPack_PS ); if ( Result_I ) printf("JAM_ReadMsgHeader returned %d.\n", Result_I ); for ( Subfield_PS = JAM_GetSubfield( SubPack_PS ); Subfield_PS; Subfield_PS = JAM_GetSubfield( NULL ) ) printf("Subfield id %d\n", Subfield_PS->LoID ); JAM_DelSubPacket( SubPack_PS ); } ===================================================================== JAM_GetSubfield_R - Get a subfield from a subfield packet (reentrant) ===================================================================== Syntax s_JamSubfield* JAM_GetSubfield( s_JamSubPacket* SubPack_PS, ulong* Count_PI ); Description Returns a pointer to the first/next subfield struct in the subfield packet. This function is a reentrant replacement for JAM_GetSubfield. Parameter SubPack_PS The subfield packet to use. Count_PI Pointer to a variable that contains the number of the subfield to retrieve. The variable should be set to zero the first time the function is called and is then automatically increased by the function for any subsequent calls. Returns A pointer to a subfield, if successful, or NULL if there are no more subfields in the packet. Example { s_JamSubPacket* SubPack_PS; s_JamSubfield* Subfield_PS; s_JamMsgHeader Header_S; ulong Count_I; int Result_I; Result_I = JAM_ReadMsgHeader( 0, &Header_S, &SubPack_PS ); if ( Result_I ) printf("JAM_ReadMsgHeader returned %d.\n", Result_I ); Count_I = 0; while( ( Subfield_PS = JAM_GetSubfield_R( SubPack_PS , &Count_I ) ) ) printf("Subfield id %d\n", Subfield_PS->LoID ); JAM_DelSubPacket( SubPack_PS ); } ======================================================= JAM_PutSubfield - Put a subfield into a subfield packet ======================================================= Syntax int JAM_PutSubfield( s_JamSubPacket* SubPack_PS, s_JamSubfield* Subfield_PS ); Description Puts a subfield into a subfield packet. The subfield is copied before being put into the subfield packet. Parameters SubPack_PS The subfield packet to add to Subfield_PS The subfield to put in the packet Returns 0 if successful JAM_NO_MEMORY if a memory allocation failed Example { s_JamSubPacket* SubPacket_PS; s_JamSubfield Subfield_S; uchar Field_AC[64]; SubPacket_PS = JAM_NewSubPacket(); if ( !SubPacket_PS ) { printf("JAM_NewSubPacket returned NULL.\n" ); return; } /* set up subfield 1 */ strcpy( Field_AC, "This is field #1" ); Subfield_S.LoID = JAMSFLD_SENDERNAME; Subfield_S.HiID = 0; Subfield_S.DatLen = strlen( Field_AC ); Subfield_S.Buffer = Field_AC; JAM_PutSubfield( SubPacket_PS, &Subfield_S ); /* set up subfield 2 */ strcpy( Field_AC, "This is field #2" ); Subfield_S.LoID = JAMSFLD_RECVRNAME; Subfield_S.HiID = 0; Subfield_S.DatLen = strlen( Field_AC ); Subfield_S.Buffer = Field_AC; JAM_PutSubfield( SubPacket_PS, &Subfield_S ); JAM_DelSubPacket( SubPacket_PS ); } -------------------------------------------------------------------------- LastRead functions ------------------ JAM implements the often-used concept of high water marking for remembering which user read how many messages in each area. Personally I think this concept stinks, since it does not store *which* messages a user has read, only the number of the highest message he has read. But since it's a part of JAM and it's fairly straightforward and easy, I've implemented two support functions for it. I would, however, strongly recommend all BBS programmers to use proper message mapping systems instead, so your users can read their messages in whatever order they wish. ========================================= JAM_ReadLastRead - Read a lastread record ========================================= Syntax int JAM_ReadLastRead( s_JamBase* Base_PS, ulong User_I, s_JamLastRead* Record_PS ); Description Reads a lastread record from the lastread file. Parameter Base_PS The message base to use User_I A system-unique user number. Record_PS A pointer to the lastread struct where the record will be stored. Returns 0 if successful JAM_BAD_PARAM if Record_PS is NULL JAM_IO_ERROR if an I/O error occured. see JAM_Errno() JAM_NO_USER if the user number was not found Example { int Result_I; s_JamLastRead LastRead_S; Result_I = JAM_ReadLastRead( Base_PS, 4711, &LastRead_S ); if ( Result_I ) printf("JAM_ReadLastRead returned %d\n", Result_I ); } =========================================== JAM_WriteLastRead - Write a lastread record =========================================== Syntax int JAM_WriteLastRead( s_JamBase* Base_PS, ulong User_I, s_JamLastRead* Record_PS ); Description Writes a lastread record to the lastread file. If the user number could not be found, the record will be appended to the end of the file. Parameter Base_PS The message base to use User_I A system-unique user number Record_PS A pointer to the lastread struct to be written Returns 0 if successful JAM_BAD_PARAM if Record_PS is NULL JAM_IO_ERROR if an I/O error occured. see JAM_Errno() Example { int Result_I; s_JamLastRead LastRead_S; Result_I = JAM_WriteLastRead( Base_PS, 4711, &LastRead_S ); if ( Result_I ) printf("JAM_WriteLastRead returned %d\n", Result_I ); } -------------------------------------------------------------------------- Miscellanous functions ---------------------- ============================================== JAM_Crc32 - Calculate CRC32 on a block of data ============================================== Syntax ulong JAM_Crc32( uchar* Buffer_PC, ulong Length_I ); Description Calculates the Crc32 value for a block of data. All ASCII characters are converted to lowercase before calculating the CRC (the input data is unchanged). Parameters Buffer_PC A pointer to the first byte of the data block Length_I The number of bytes in the data block Returns The Crc32 value Example { ulong Crc_I; uchar Text_AC[32]; strcpy( Text_AC, "Hello world!\n"); Crc_I = JAM_Crc32( Text_AC, strlen( Text_AC ) ); } ============================= JAM_Errno - Specify I/O error ============================= Syntax int JAM_Errno( s_JamBase* Base_PS ); Description When any of these library routines return JAM_IO_ERROR, you can call this function to find out exactly what went wrong. Parameters Base_PS The message base to use Returns Standard 'errno' values, as the C compiler generated them, or if the I/O error was system specific, the return code is (10000 + system status code). Examples { int Result_I; uchar Text_AC[10]; /* generate an I/O error */ Result_I = JAM_ReadMsgText( 0xffffffff, 10, Text_AC ); if ( Result_I ) { errno = JAM_Errno( Base_PS ); perror("JAM i/o error"); } } jamnntpd-1.2/src/jamlib/lastread.c000066400000000000000000000107541141642135500171700ustar00rootroot00000000000000/* JAMLIB - A JAM subroutine library Copyright (C) 1999 Björn Stenberg This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Changes made by Johan Billing 2000-04-16: - Changed source to use feof() instead of errno == EPASTEOF - Changed source to use structrw to read and write structures */ /*********************************************************************** ** ** LASTREAD.C -- Lastread pointer handling ** ** Author: Bj”rn Stenberg (bjorn.stenberg@sth.frontec.se) ** ***********************************************************************/ #include #include #include "jam.h" #include "structrw.h" /*********************************************************************** ** ** File global variables ** ***********************************************************************/ /*********************************************************************** ** ** JAM_ReadLastRead - Read LastRead record ** ***********************************************************************/ int JAM_ReadLastRead( s_JamBase* Base_PS, ulong User_I, s_JamLastRead* Record_PS ) { s_JamLastRead Record_S; int Pos_I; if (!Record_PS) return JAM_BAD_PARAM; if ( fseek( Base_PS->LrdFile_PS, 0, SEEK_SET ) ) { Base_PS->Errno_I = errno; return JAM_IO_ERROR; } for ( Pos_I = 0; ; Pos_I++ ) { if ( 1 > freadjamlastread(Base_PS->LrdFile_PS,&Record_S) ) { if ( feof(Base_PS->LrdFile_PS) ) return JAM_NO_USER; Base_PS->Errno_I = errno; return JAM_IO_ERROR; } if ( Record_S.UserID == User_I ) { Base_PS->LastUserPos_I = Pos_I; Base_PS->LastUserId_I = User_I; *Record_PS = Record_S; return 0; } } return 0; } /*********************************************************************** ** ** JAM_WriteLastRead - Write LastRead record ** ***********************************************************************/ int JAM_WriteLastRead( s_JamBase* Base_PS, ulong User_I, s_JamLastRead* Record_PS ) { s_JamLastRead Record_S; int Pos_I; if (!Record_PS) return JAM_BAD_PARAM; /* if the last read is stored */ if ( User_I == Base_PS->LastUserId_I ) { Pos_I = Base_PS->LastUserPos_I * sizeof( s_JamLastRead ); if ( fseek( Base_PS->LrdFile_PS, Pos_I, SEEK_SET ) ) { Base_PS->Errno_I = errno; return JAM_IO_ERROR; } /* be safe, check it */ if ( 1 > freadjamlastread(Base_PS->LrdFile_PS,&Record_S) ) { Base_PS->Errno_I = errno; return JAM_IO_ERROR; } /* is it where we expected it to be? */ if ( User_I == Record_S.UserID ) { if ( fseek( Base_PS->LrdFile_PS, Pos_I, SEEK_SET ) ) { Base_PS->Errno_I = errno; return JAM_IO_ERROR; } if ( 1 > fwritejamlastread(Base_PS->LrdFile_PS,Record_PS) ) { Base_PS->Errno_I = errno; return JAM_IO_ERROR; } fflush(Base_PS -> LrdFile_PS); return 0; } } /* no last position, or position incorrect */ if ( fseek( Base_PS->LrdFile_PS, 0, SEEK_SET ) ) { Base_PS->Errno_I = errno; return JAM_IO_ERROR; } for ( Pos_I = 0; ; Pos_I++ ) { if ( 1 > freadjamlastread(Base_PS->LrdFile_PS,&Record_S) ) { if ( feof(Base_PS->LrdFile_PS) ) { /* user not in file, append a new record */ if ( fseek( Base_PS->LrdFile_PS, 0, SEEK_END ) ) { Base_PS->Errno_I = errno; return JAM_IO_ERROR; } break; } Base_PS->Errno_I = errno; return JAM_IO_ERROR; } /* found the user? */ if ( Record_S.UserID == User_I ) { if ( fseek( Base_PS->LrdFile_PS, Pos_I * sizeof(s_JamLastRead), SEEK_SET ) ) { Base_PS->Errno_I = errno; return JAM_IO_ERROR; } break; } } if ( 1 > fwritejamlastread(Base_PS->LrdFile_PS,Record_PS) ) { Base_PS->Errno_I = errno; return JAM_IO_ERROR; } fflush( Base_PS->LrdFile_PS ); return 0; } jamnntpd-1.2/src/jamlib/mbase.c000066400000000000000000000355501141642135500164610ustar00rootroot00000000000000/* JAMLIB - A JAM subroutine library Copyright (C) 1999 Björn Stenberg This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Changes made by Johan Billing 2000-04-16: - Added support for Win32 and Linux - Changed JAM_OpenMB to open files in binary mode - Changed source to use feof() instead of errno == EPASTEOF - Changed source to use structrw to read and write structures - Fixed broken JAM_FindUser() - #includes string.h and stdlib.h instead of memory.h Backported changes from JAMLIB 1.4.7 made by Johan Billing 2003-10-26 - Now uses calloc instead of malloc/memset - (*NewArea_PPS) will be set to zero even if calloc() failed in JAM_OpenMB() and JAM_CreateMB() - JAM_CreateMB() no longer attempts to forever to lock the newly created messagebase. If the first attempt fails, it will return an error. - jam_Lock() now sets Base_PS->Errno under Linux Other changes made by Johan Billing 2003-10-26 - Fixed comparison between signed and unsigned variable in JAM_GetMBSize() - JAM_CreateMB() would not unlock and close the newly created messagebase upon failure. Changes made by Johan Billing 2004-07-10 - Updated the Win32-specific parts of the code to make it compatible with newer versions of MinGW (tested with 3.1.0-1): * Now uses Sleep() instead of sleep() * Changed _LK_UNLOCK to _LK_UNLCK in jam_Lock() */ /*********************************************************************** ** ** MBASE.C -- Message base handling ** ** Author: Bj”rn Stenberg (bjorn.stenberg@sth.frontec.se) ** ***********************************************************************/ #include #include #include #include #include #include "jam.h" #include "structrw.h" #if defined( __OS2__ ) #include /* ANSI C does not include file locking :-( */ #endif #if defined( __WIN32__ ) #include #include #include #if !defined( _LK_UNLCK ) && defined ( _LK_UNLOCK ) #define _LK_UNLCK _LK_UNLOCK /* For backwards compatibility */ #endif #endif #if defined( __LINUX__ ) #include #include #endif #define OS_ERROR_OFFSET 10000 #if defined( __OS2__ ) #define JAM_Sleep( _x_ ) DosSleep( _x_*1000 ) #endif #if defined( __WIN32__ ) #define JAM_Sleep(x) Sleep(x*1000) #endif #if defined( __LINUX__ ) #define JAM_Sleep(x) sleep(x) #endif /*************************************<********************************** ** ** File-global functions ** ***********************************************************************/ int jam_Open( s_JamBase* Base_PS, uchar* Filename_PC, char* Mode_PC ); int jam_Lock( s_JamBase* Base_PS, int DoLock_I ); /*********************************************************************** ** ** JAM_OpenMB - Open message base ** ***********************************************************************/ int JAM_OpenMB( uchar* Basename_PC, s_JamBase** NewArea_PPS ) { s_JamBase* Base_PS; int Status_I; if ( !NewArea_PPS ) return JAM_BAD_PARAM; *NewArea_PPS = NULL; Base_PS = (s_JamBase*) calloc( 1, sizeof( s_JamBase ) ); if (!Base_PS) return JAM_NO_MEMORY; *NewArea_PPS = Base_PS; Status_I = jam_Open( Base_PS, Basename_PC, "r+b" ); if ( Status_I ) { return Status_I; } return 0; } /*********************************************************************** ** ** JAM_CreateMB - Create a new message base ** ***********************************************************************/ int JAM_CreateMB( uchar* Basename_PC, ulong BaseMsg_I, s_JamBase** NewArea_PPS ) { s_JamBaseHeader Base_S; int Status_I; s_JamBase* Base_PS; if ( !NewArea_PPS || !BaseMsg_I ) return JAM_BAD_PARAM; *NewArea_PPS = NULL; Base_PS = (s_JamBase*) calloc( 1, sizeof( s_JamBase ) ); if (!Base_PS) return JAM_NO_MEMORY; *NewArea_PPS = Base_PS; Status_I = jam_Open( Base_PS, Basename_PC, "w+b" ); if ( Status_I ) return Status_I; Base_S.DateCreated = time(NULL); Base_S.ModCounter = 0; Base_S.ActiveMsgs = 0; Base_S.PasswordCRC = 0xffffffff; Base_S.BaseMsgNum = BaseMsg_I; memset( &Base_S.RSRVD, 0, sizeof( Base_S.RSRVD ) ); Status_I = JAM_LockMB( Base_PS, 0 ); /* If the new base cannot be locked directly, something is seriously wrong */ if ( Status_I ) { JAM_CloseMB(Base_PS); return Status_I; } Status_I = JAM_WriteMBHeader( Base_PS, &Base_S ); if ( Status_I ) { JAM_UnlockMB( Base_PS ); JAM_CloseMB(Base_PS); return Status_I; } JAM_UnlockMB( Base_PS ); return 0; } /*********************************************************************** ** ** JAM_CloseMB - Close message base ** ***********************************************************************/ int JAM_CloseMB( s_JamBase* Base_PS ) { if ( Base_PS->Locked_I ) { int Status_I = JAM_UnlockMB( Base_PS ); if ( Status_I ) return Status_I; } if ( Base_PS->HdrFile_PS ) { fclose( Base_PS->HdrFile_PS ); Base_PS->HdrFile_PS = NULL; fclose( Base_PS->TxtFile_PS ); Base_PS->TxtFile_PS = NULL; fclose( Base_PS->IdxFile_PS ); Base_PS->IdxFile_PS = NULL; fclose( Base_PS->LrdFile_PS ); Base_PS->LrdFile_PS = NULL; } Base_PS->Locked_I = 0; return 0; } /*********************************************************************** ** ** JAM_RemoveMB - Remove a message base ** ***********************************************************************/ int JAM_RemoveMB( s_JamBase* Base_PS, uchar* Basename_PC ) { uchar Filename_AC[250]; int Status_AI[4]; /* .JHR file */ sprintf( Filename_AC, "%s%s", Basename_PC, EXT_HDRFILE ); Status_AI[0] = remove( Filename_AC ); if ( Status_AI[0] ) Base_PS->Errno_I = errno; /* .JDT file */ sprintf( Filename_AC, "%s%s", Basename_PC, EXT_TXTFILE ); Status_AI[1] = remove( Filename_AC ); if ( Status_AI[1] ) Base_PS->Errno_I = errno; /* .JDX file */ sprintf( Filename_AC, "%s%s", Basename_PC, EXT_IDXFILE ); Status_AI[2] = remove( Filename_AC ); if ( Status_AI[2] ) Base_PS->Errno_I = errno; /* .JLR file */ sprintf( Filename_AC, "%s%s", Basename_PC, EXT_LRDFILE ); Status_AI[3] = remove( Filename_AC ); if ( Status_AI[3] ) Base_PS->Errno_I = errno; if (Status_AI[0] || Status_AI[1] || Status_AI[2] || Status_AI[3]) return JAM_IO_ERROR; return 0; } /*********************************************************************** ** ** JAM_GetMBSize - Get the number of messages in message base ** ***********************************************************************/ int JAM_GetMBSize( s_JamBase* Base_PS, ulong* Messages_PI ) { long Offset_I; /* go to end of index file */ if ( fseek( Base_PS->IdxFile_PS, 0, SEEK_END ) ) { Base_PS->Errno_I = errno; return JAM_IO_ERROR; } Offset_I = ftell( Base_PS->IdxFile_PS ); if ( Offset_I == -1 ) { Base_PS->Errno_I = errno; return JAM_IO_ERROR; } *Messages_PI = Offset_I / sizeof( s_JamIndex ); return 0; } /*********************************************************************** ** ** JAM_LockMB - Lock message base ** ***********************************************************************/ int JAM_LockMB( s_JamBase* Base_PS, int Timeout_I ) { if ( Base_PS->Locked_I ) return 0; switch ( Timeout_I ) { /* unlimited timeout */ case -1: while ( jam_Lock( Base_PS, 1 ) == JAM_LOCK_FAILED ) JAM_Sleep( 1 ); return 0; /* no timeout */ case 0: return jam_Lock( Base_PS, 1 ); /* X seconds timeout */ default: { time_t Time_I = time(NULL) + Timeout_I; while ( time(NULL) < Time_I ) { int Result_I; Result_I = jam_Lock( Base_PS, 1 ); if ( Result_I == JAM_LOCK_FAILED ) JAM_Sleep( 1 ); else return Result_I; } return JAM_LOCK_FAILED; } } } /*********************************************************************** ** ** JAM_UnlockMB - Flush all writes and unlock message base ** ***********************************************************************/ int JAM_UnlockMB( s_JamBase* Base_PS ) { fflush( Base_PS->HdrFile_PS ); fflush( Base_PS->TxtFile_PS ); fflush( Base_PS->IdxFile_PS ); fflush( Base_PS->LrdFile_PS ); return jam_Lock( Base_PS, 0 ); } /*********************************************************************** ** ** JAM_ReadMBHeader - Read message base header ** ***********************************************************************/ int JAM_ReadMBHeader( s_JamBase* Base_PS, s_JamBaseHeader* Header_PS ) { if ( !Header_PS || !Base_PS ) return JAM_BAD_PARAM; if ( fseek( Base_PS->HdrFile_PS, 0, SEEK_SET ) ) { Base_PS->Errno_I = errno; return JAM_IO_ERROR; } if ( 1 > freadjambaseheader(Base_PS->HdrFile_PS,Header_PS) ) { Base_PS->Errno_I = errno; return JAM_IO_ERROR; } return 0; } /*********************************************************************** ** ** JAM_WriteMBHeader - Write message base header ** ***********************************************************************/ int JAM_WriteMBHeader( s_JamBase* Base_PS, s_JamBaseHeader* Header_PS ) { if ( !Header_PS || !Base_PS ) return JAM_BAD_PARAM; if ( !Base_PS->Locked_I ) return JAM_NOT_LOCKED; if ( fseek( Base_PS->HdrFile_PS, 0, SEEK_SET ) ) { Base_PS->Errno_I = errno; return JAM_IO_ERROR; } /* ensure header looks right */ memcpy( Header_PS->Signature, HEADERSIGNATURE, 4 ); Header_PS->ModCounter++; if ( 1 > fwritejambaseheader(Base_PS->HdrFile_PS,Header_PS) ) { Base_PS->Errno_I = errno; return JAM_IO_ERROR; } fflush( Base_PS->HdrFile_PS ); return 0; } /*********************************************************************** ** ** JAM_FindUser - Scan scan file for messages to a user ** ***********************************************************************/ int JAM_FindUser( s_JamBase* Base_PS, ulong UserCrc_I, ulong StartMsg_I, ulong* MsgNo_PI ) { ulong MsgNo_I; /* go to start message */ if ( fseek( Base_PS->IdxFile_PS, StartMsg_I * sizeof( s_JamIndex ), SEEK_SET ) ) { Base_PS->Errno_I = errno; return JAM_IO_ERROR; } /* scan file */ for ( MsgNo_I = StartMsg_I; ; MsgNo_I++ ) { s_JamIndex Index_S; if ( 1 > freadjamindex(Base_PS->IdxFile_PS,&Index_S) ) { if ( feof(Base_PS->IdxFile_PS) ) return JAM_NO_USER; Base_PS->Errno_I = errno; return JAM_IO_ERROR; } if ( Index_S.UserCRC == UserCrc_I ) break; } *MsgNo_PI = MsgNo_I; return 0; } /*********************************************************************** ** ** jam_Lock - Lock/unlock a message base ** ***********************************************************************/ int jam_Lock( s_JamBase* Base_PS, int DoLock_I ) { #if defined(__OS2__) FILELOCK Area_S; APIRET Status_I; ULONG Timeout_I = 0; int Handle_I; Handle_I = fileno( Base_PS->HdrFile_PS ); if ( Handle_I == -1 ) { Base_PS->Errno_I = errno; return JAM_IO_ERROR; } Area_S.lOffset = 0; Area_S.lRange = 1; if ( DoLock_I ) Status_I = DosSetFileLocks( Handle_I, NULL, &Area_S, Timeout_I, 0 ); else Status_I = DosSetFileLocks( Handle_I, &Area_S, NULL, Timeout_I, 0 ); if ( Status_I ) { if ( 232 == Status_I ) return JAM_LOCK_FAILED; Base_PS->Errno_I = Status_I + OS_ERROR_OFFSET; return JAM_IO_ERROR; } if ( DoLock_I ) Base_PS->Locked_I = 1; else Base_PS->Locked_I = 0; return 0; #elif defined(__WIN32__) int Handle_I,Status_I; fseek(Base_PS->HdrFile_PS,0,SEEK_SET); /* Lock from start of file */ Handle_I = fileno( Base_PS->HdrFile_PS ); if ( Handle_I == -1 ) { Base_PS->Errno_I = errno; return JAM_IO_ERROR; } if ( DoLock_I ) Status_I = _locking(Handle_I,_LK_NBLCK,1); else Status_I = _locking(Handle_I,_LK_UNLCK,1); if ( Status_I ) return JAM_LOCK_FAILED; if ( DoLock_I ) Base_PS->Locked_I = 1; else Base_PS->Locked_I = 0; return 0; #elif defined(__LINUX__) int Handle_I,Status_I; struct flock fl; fseek(Base_PS->HdrFile_PS,0,SEEK_SET); /* Lock from start of file */ Handle_I = fileno( Base_PS->HdrFile_PS ); if ( Handle_I == -1 ) { Base_PS->Errno_I = errno; return JAM_IO_ERROR; } if(DoLock_I) fl.l_type=F_WRLCK; else fl.l_type=F_UNLCK; fl.l_whence=SEEK_SET; fl.l_start=0; fl.l_len=1; fl.l_pid=getpid(); Status_I=fcntl(Handle_I,F_SETLK,&fl); if ( Status_I ) { Base_PS->Errno_I = errno; return JAM_LOCK_FAILED; } if ( DoLock_I ) Base_PS->Locked_I = 1; else Base_PS->Locked_I = 0; return 0; #else #error Unsupported platform #endif } /*********************************************************************** ** ** jam_Open - Open/create message base files ** ***********************************************************************/ int jam_Open( s_JamBase* Base_PS, uchar* Basename_PC, char* Mode_PC ) { uchar Filename_AC[250]; /* .JHR file */ sprintf( Filename_AC, "%s%s", Basename_PC, EXT_HDRFILE ); Base_PS->HdrFile_PS = fopen( Filename_AC, Mode_PC ); if (!Base_PS->HdrFile_PS) { Base_PS->Errno_I = errno; return JAM_IO_ERROR; } /* .JDT file */ sprintf( Filename_AC, "%s%s", Basename_PC, EXT_TXTFILE ); Base_PS->TxtFile_PS = fopen( Filename_AC, Mode_PC ); if (!Base_PS->TxtFile_PS) { Base_PS->Errno_I = errno; fclose( Base_PS->HdrFile_PS ); Base_PS->HdrFile_PS = NULL; return JAM_IO_ERROR; } /* .JDX file */ sprintf( Filename_AC, "%s%s", Basename_PC, EXT_IDXFILE ); Base_PS->IdxFile_PS = fopen( Filename_AC, Mode_PC ); if (!Base_PS->IdxFile_PS) { Base_PS->Errno_I = errno; fclose( Base_PS->HdrFile_PS ); Base_PS->HdrFile_PS = NULL; fclose( Base_PS->TxtFile_PS ); Base_PS->TxtFile_PS = NULL; return JAM_IO_ERROR; } /* .JLR file */ sprintf( Filename_AC, "%s%s", Basename_PC, EXT_LRDFILE ); Base_PS->LrdFile_PS = fopen( Filename_AC, Mode_PC ); if (!Base_PS->LrdFile_PS) { Base_PS->Errno_I = errno; fclose( Base_PS->HdrFile_PS ); Base_PS->HdrFile_PS = NULL; fclose( Base_PS->TxtFile_PS ); Base_PS->TxtFile_PS = NULL; fclose( Base_PS->IdxFile_PS ); Base_PS->IdxFile_PS = NULL; return JAM_IO_ERROR; } return 0; } jamnntpd-1.2/src/jamlib/message.c000066400000000000000000000401211141642135500170040ustar00rootroot00000000000000/* JAMLIB - A JAM subroutine library Copyright (C) 1999 Björn Stenberg This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Changes made by Johan Billing 2000-04-16: - Changed source to use feof() instead of errno == EPASTEOF - Changed source to use structrw to read and write structures - Added JAM_AddEmptyMessage() - Added error messages JAM_NO_MESSAGE and JAM_CORRUPT_MSG for JAM_ReadMsgHeader() - #includes stdlib.h instead of malloc.h and memory.h - Fixed a bug that caused JAM_AddMessage() to fail when trying to add an empty message to the messagebase under Linux. Backported changes from JAMLIB 1.4.7 made by Johan Billing 2003-10-26 - Fixed memory leaks that would occur if JAM_ReadMsgHeader() failed - Added JAM_DeleteMessage() Other changes made by Johan Billing 2003-10-26 - Fixed comparison between signed and unsigned variable in JAM_AddMessage() - Improved handling of ActiveMsgs counter. JAM_AddMessage() now only increases ActiveMsgs if the added message does not have MSG_DELETED set. JAM_ChangeMsgHeader() decreases ActiveMsgs if MSG_DELETED is set and the message wasn't already deleted. JAM_DeleteMessage() now only decreases ActiveMsgs if the message wasn't already deleted. */ /*********************************************************************** ** ** Message.C -- Message handling ** ** Author: Bj”rn Stenberg (bjorn.stenberg@sth.frontec.se) ** ***********************************************************************/ #include #include #include #include #include "jam.h" #include "structrw.h" /*********************************************************************** ** ** JAM_ReadMsgHeader - Read message header ** ***********************************************************************/ int JAM_ReadMsgHeader( s_JamBase* Base_PS, ulong MsgNo_I, s_JamMsgHeader* Header_PS, s_JamSubPacket** SubfieldPack_PPS ) { s_JamIndex Index_S; if ( !Base_PS || !Header_PS ) return JAM_BAD_PARAM; /* find index record */ if ( fseek( Base_PS->IdxFile_PS, MsgNo_I * sizeof( s_JamIndex ), SEEK_SET ) ) { Base_PS->Errno_I = errno; return JAM_IO_ERROR; } /* read index record */ if ( 1 > freadjamindex(Base_PS->IdxFile_PS,&Index_S) ) { Base_PS->Errno_I = errno; return JAM_IO_ERROR; } /* message is not there */ if(Index_S.HdrOffset == 0xffffffff && Index_S.UserCRC == 0xffffffff) { return JAM_NO_MESSAGE; } /* find header */ if ( fseek( Base_PS->HdrFile_PS, Index_S.HdrOffset, SEEK_SET ) ) { Base_PS->Errno_I = errno; return JAM_IO_ERROR; } /* read header */ if ( 1 > freadjammsgheader(Base_PS->HdrFile_PS,Header_PS) ) { Base_PS->Errno_I = errno; return JAM_IO_ERROR; } /* are Subfields requested? */ if ( SubfieldPack_PPS && Header_PS->SubfieldLen ) { s_JamSubPacket* SubPacket_PS; s_JamSubfield Subfield_S; char* Buf_PC; char* Ptr_PC; char* Roof_PC; int BufSize_I = Header_PS->SubfieldLen; Buf_PC = (void*) malloc( BufSize_I ); if ( !Buf_PC ) return JAM_NO_MEMORY; /* read all subfields */ if ( 1 > fread( Buf_PC, BufSize_I, 1, Base_PS->HdrFile_PS ) ) { Base_PS->Errno_I = errno; free (Buf_PC); return JAM_IO_ERROR; } SubPacket_PS = JAM_NewSubPacket(); if ( !SubPacket_PS ) { free (Buf_PC); return JAM_NO_MEMORY; } Roof_PC = Buf_PC + BufSize_I; /* cut out the subfields */ for ( Ptr_PC = Buf_PC; Ptr_PC < Roof_PC; Ptr_PC += Subfield_S.DatLen + SIZE_JAMSAVESUBFIELD ) { int Status_I; getjamsubfield(Ptr_PC,&Subfield_S); if((char *)Subfield_S.Buffer + Subfield_S.DatLen > Roof_PC) { JAM_DelSubPacket( SubPacket_PS ); free (Buf_PC); return JAM_CORRUPT_MSG; } Status_I = JAM_PutSubfield( SubPacket_PS, &Subfield_S ); if ( Status_I ) { JAM_DelSubPacket( SubPacket_PS ); free (Buf_PC); return Status_I; } } free( Buf_PC ); *SubfieldPack_PPS = SubPacket_PS; } else if ( SubfieldPack_PPS ) /* fields requested but none found */ /* return an empty packet */ *SubfieldPack_PPS = JAM_NewSubPacket(); return 0; } /*********************************************************************** ** ** JAM_ReadMsgText - Read message text ** ***********************************************************************/ int JAM_ReadMsgText( s_JamBase* Base_PS, ulong Offset_I, ulong Length_I, uchar* Buffer_PC ) { if ( !Base_PS || !Buffer_PC ) return JAM_BAD_PARAM; if ( !Length_I ) return 0; if ( fseek( Base_PS->TxtFile_PS, Offset_I, SEEK_SET ) ) { Base_PS->Errno_I = errno; return JAM_IO_ERROR; } if ( 1 > fread( Buffer_PC, Length_I, 1, Base_PS->TxtFile_PS ) ) { Base_PS->Errno_I = errno; return JAM_IO_ERROR; } return 0; } /*********************************************************************** ** ** JAM_ChangeMsgHeader - Change a message header ** ***********************************************************************/ int JAM_ChangeMsgHeader( s_JamBase* Base_PS, ulong MsgNo_I, s_JamMsgHeader* Header_PS ) { s_JamBaseHeader BaseHeader_S; s_JamMsgHeader OldHeader_S; s_JamIndex Index_S; int Status_I; if ( !Base_PS ) return JAM_BAD_PARAM; if ( !Base_PS->Locked_I ) return JAM_NOT_LOCKED; /* read message base header */ Status_I = JAM_ReadMBHeader( Base_PS, &BaseHeader_S ); if ( Status_I ) return Status_I; /* find index record */ if ( fseek( Base_PS->IdxFile_PS, MsgNo_I * sizeof( s_JamIndex ), SEEK_SET ) ) { Base_PS->Errno_I = errno; return JAM_IO_ERROR; } /* read index record */ if ( 1 > freadjamindex(Base_PS->IdxFile_PS,&Index_S) ) { Base_PS->Errno_I = errno; return JAM_IO_ERROR; } /* find header */ if ( fseek( Base_PS->HdrFile_PS, Index_S.HdrOffset, SEEK_SET ) ) { Base_PS->Errno_I = errno; return JAM_IO_ERROR; } /* read old message header */ if ( 1 > freadjammsgheader( Base_PS->HdrFile_PS, &OldHeader_S ) ) { Base_PS->Errno_I = errno; return JAM_IO_ERROR; } /* find header */ if ( fseek( Base_PS->HdrFile_PS, Index_S.HdrOffset, SEEK_SET ) ) { Base_PS->Errno_I = errno; return JAM_IO_ERROR; } /* write header */ if ( 1 > fwritejammsgheader(Base_PS->HdrFile_PS,Header_PS) ) { Base_PS->Errno_I = errno; return JAM_IO_ERROR; } if( ( Header_PS->Attribute & MSG_DELETED ) && !(OldHeader_S.Attribute & MSG_DELETED) ) { /* message is deleted now but wasn't before */ BaseHeader_S.ActiveMsgs--; } Status_I = JAM_WriteMBHeader( Base_PS, &BaseHeader_S ); if ( Status_I ) return Status_I; return 0; } /*********************************************************************** ** ** JAM_AddMessage - Add a message to a message base ** ***********************************************************************/ int JAM_AddMessage( s_JamBase* Base_PS, s_JamMsgHeader* Header_PS, s_JamSubPacket* SubPack_PS, uchar* Text_PC, ulong TextLen_I ) { s_JamBaseHeader BaseHeader_S; s_JamIndex Index_S; long Offset_I; int Status_I; ulong TotLen_I; if ( !Base_PS ) return JAM_BAD_PARAM; if ( !Base_PS->Locked_I ) return JAM_NOT_LOCKED; /* read message base header */ Status_I = JAM_ReadMBHeader( Base_PS, &BaseHeader_S ); if ( Status_I ) return Status_I; /* ** Add text if any */ Header_PS->TxtOffset = 0; Header_PS->TxtLen = 0; if(Text_PC && TextLen_I!=0) { /* go to end of text file */ if ( fseek( Base_PS->TxtFile_PS, 0, SEEK_END ) ) { Base_PS->Errno_I = errno; return JAM_IO_ERROR; } /* store text offset (for header) */ Offset_I = ftell( Base_PS->TxtFile_PS ); if ( Offset_I == -1 ) { Base_PS->Errno_I = errno; return JAM_IO_ERROR; } Header_PS->TxtOffset = Offset_I; Header_PS->TxtLen = TextLen_I; /* write text */ if ( 1 > fwrite( Text_PC, TextLen_I, 1, Base_PS->TxtFile_PS ) ) { Base_PS->Errno_I = errno; return JAM_IO_ERROR; } } /* ** Add header */ /* go to end of header file */ if ( fseek( Base_PS->HdrFile_PS, 0, SEEK_END ) ) { Base_PS->Errno_I = errno; return JAM_IO_ERROR; } /* calculate the size of all Subfields */ TotLen_I = 0; if ( SubPack_PS ) { s_JamSubfield* Subfield_PS; for ( Subfield_PS = JAM_GetSubfield( SubPack_PS ); Subfield_PS; Subfield_PS = JAM_GetSubfield( NULL ) ) TotLen_I += sizeof( s_JamSaveSubfield ) + Subfield_PS->DatLen; } Header_PS->SubfieldLen = TotLen_I; /* go to end of index file */ if ( fseek( Base_PS->IdxFile_PS, 0, SEEK_END ) ) { Base_PS->Errno_I = errno; return JAM_IO_ERROR; } /* find out new message number (for message header) */ Offset_I = ftell( Base_PS->IdxFile_PS ); if ( Offset_I == -1 ) { Base_PS->Errno_I = errno; return JAM_IO_ERROR; } /* update header */ Header_PS->MsgNum = Offset_I / sizeof( s_JamIndex ) + BaseHeader_S.BaseMsgNum; memcpy( Header_PS->Signature, HEADERSIGNATURE, 4 ); Header_PS->Revision = CURRENTREVLEV; /* go to end of header file */ if ( fseek( Base_PS->HdrFile_PS, 0, SEEK_END ) ) { Base_PS->Errno_I = errno; return JAM_IO_ERROR; } /* find out new header offset (for index record) */ Offset_I = ftell( Base_PS->HdrFile_PS ); if ( Offset_I == -1 ) { Base_PS->Errno_I = errno; return JAM_IO_ERROR; } Index_S.HdrOffset = Offset_I; /* write new header */ if ( 1 > fwritejammsgheader(Base_PS->HdrFile_PS,Header_PS) ) { Base_PS->Errno_I = errno; return JAM_IO_ERROR; } /* write Subfields */ if ( SubPack_PS ) { s_JamSubfield* Subfield_PS; uchar User_AC[101]; /* clear username */ User_AC[0] = 0; for ( Subfield_PS = JAM_GetSubfield( SubPack_PS ); Subfield_PS; Subfield_PS = JAM_GetSubfield( NULL ) ) { /* first, save Subfield header */ if ( 1 > fwritejamsavesubfield(Base_PS->HdrFile_PS,(s_JamSaveSubfield *)Subfield_PS) ) { Base_PS->Errno_I = errno; return JAM_IO_ERROR; } /* then, save Subfield data if any*/ if(Subfield_PS->DatLen) { if ( 1 > fwrite( Subfield_PS->Buffer, Subfield_PS->DatLen, 1, Base_PS->HdrFile_PS ) ) { Base_PS->Errno_I = errno; return JAM_IO_ERROR; } } /* store username for index file */ if ( Subfield_PS->LoID == JAMSFLD_RECVRNAME ) { memcpy( User_AC, Subfield_PS->Buffer, Subfield_PS->DatLen ); User_AC[ Subfield_PS->DatLen ] = 0; } } /* update index record */ if ( User_AC[0] ) Index_S.UserCRC = JAM_Crc32( User_AC, strlen( User_AC ) ); else Index_S.UserCRC = JAM_NO_CRC; } else /* update index record */ Index_S.UserCRC = JAM_NO_CRC; /* ** Add index */ /* write index record */ if ( 1 > fwritejamindex(Base_PS->IdxFile_PS,&Index_S) ) { Base_PS->Errno_I = errno; return JAM_IO_ERROR; } if(!(Header_PS->Attribute & MSG_DELETED)) BaseHeader_S.ActiveMsgs++; /* Only increase ActiveMsgs if MSG_DELETED not set */ /* write message base header */ Status_I = JAM_WriteMBHeader( Base_PS, &BaseHeader_S ); if ( Status_I ) return Status_I; return 0; } /*********************************************************************** ** ** JAM_AddEmptyMessage - Add a empty message entry to a message base ** ***********************************************************************/ int JAM_AddEmptyMessage( s_JamBase* Base_PS) { s_JamIndex Index_S; if ( !Base_PS ) return JAM_BAD_PARAM; if ( !Base_PS->Locked_I ) return JAM_NOT_LOCKED; /* go to end of index file */ if ( fseek( Base_PS->IdxFile_PS, 0, SEEK_END ) ) { Base_PS->Errno_I = errno; return JAM_IO_ERROR; } /* ** Add index */ Index_S.HdrOffset = 0xffffffff; Index_S.UserCRC = 0xffffffff; /* write index record */ if ( 1 > fwritejamindex(Base_PS->IdxFile_PS,&Index_S) ) { Base_PS->Errno_I = errno; return JAM_IO_ERROR; } return 0; } /*********************************************************************** ** ** JAM_DeleteMessage - Delete message from messagebase ** ***********************************************************************/ int JAM_DeleteMessage( s_JamBase* Base_PS, ulong MsgNo_I ) { s_JamBaseHeader BaseHeader_S; s_JamMsgHeader Header_S; s_JamIndex Index_S; int Status_I; ulong OldAttribute_I; if ( !Base_PS ) return JAM_BAD_PARAM; if ( !Base_PS->Locked_I ) return JAM_NOT_LOCKED; /* read message base header */ Status_I = JAM_ReadMBHeader( Base_PS, &BaseHeader_S ); if ( Status_I ) return Status_I; /* find index record */ if ( fseek( Base_PS->IdxFile_PS, MsgNo_I * sizeof( s_JamIndex ), SEEK_SET ) ) { Base_PS->Errno_I = errno; return JAM_IO_ERROR; } /* read index record */ if ( 1 > freadjamindex( Base_PS->IdxFile_PS, &Index_S ) ) { Base_PS->Errno_I = errno; return JAM_IO_ERROR; } /* message is not there */ if(Index_S.HdrOffset == 0xffffffff && Index_S.UserCRC == 0xffffffff) { return JAM_NO_MESSAGE; } /* find header */ if ( fseek( Base_PS->HdrFile_PS, Index_S.HdrOffset, SEEK_SET ) ) { Base_PS->Errno_I = errno; return JAM_IO_ERROR; } /* read header */ if ( 1 > freadjammsgheader( Base_PS->HdrFile_PS, &Header_S ) ) { Base_PS->Errno_I = errno; return JAM_IO_ERROR; } OldAttribute_I = Header_S.Attribute; Header_S.Attribute |= MSG_DELETED; /* find header */ if ( fseek( Base_PS->HdrFile_PS, Index_S.HdrOffset, SEEK_SET ) ) { Base_PS->Errno_I = errno; return JAM_IO_ERROR; } /* write header */ if ( 1 > fwritejammsgheader( Base_PS->HdrFile_PS, &Header_S ) ) { Base_PS->Errno_I = errno; return JAM_IO_ERROR; } /* find index record */ if ( fseek( Base_PS->IdxFile_PS, MsgNo_I * sizeof( s_JamIndex ), SEEK_SET ) ) { Base_PS->Errno_I = errno; return JAM_IO_ERROR; } Index_S.HdrOffset = 0xffffffff; Index_S.UserCRC = 0xffffffff; /* write index record */ if ( 1 > fwritejamindex(Base_PS->IdxFile_PS,&Index_S) ) { Base_PS->Errno_I = errno; return JAM_IO_ERROR; } if(!(OldAttribute_I & MSG_DELETED)) BaseHeader_S.ActiveMsgs--; /* decrease ActiveMsgs if the message wasn't already deleted */ /* write message base header */ Status_I = JAM_WriteMBHeader( Base_PS, &BaseHeader_S ); if ( Status_I ) return Status_I; return 0; } /*********************************************************************** ** ** JAM_Errno - Report the latest C library error code ** ***********************************************************************/ int JAM_Errno( s_JamBase* Base_PS ) { return Base_PS->Errno_I; } /*********************************************************************** ** ** JAM_ClearMsgHeader - Clear a message header ** ***********************************************************************/ int JAM_ClearMsgHeader( s_JamMsgHeader* Header_PS ) { if (!Header_PS) return JAM_BAD_PARAM; memset( Header_PS, 0, sizeof( s_JamMsgHeader ) ); memcpy( Header_PS->Signature, HEADERSIGNATURE, 4 ); Header_PS->Revision = CURRENTREVLEV; Header_PS->MsgIdCRC = JAM_NO_CRC; Header_PS->ReplyCRC = JAM_NO_CRC; Header_PS->PasswordCRC = JAM_NO_CRC; return 0; } jamnntpd-1.2/src/jamlib/structrw.c000066400000000000000000000206761141642135500172720ustar00rootroot00000000000000/* structrw - Platform-independent reading and writing of JAM structs Copyright (C) 1999 Johan Billing This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Changes made by Johan Billing 2003-10-22 - Added #include */ #include #include #include "jam.h" #include "structrw.h" ushort jamgetuword(uchar *buf,ulong offset) { return (ushort) buf[offset]+ buf[offset+1]*256; } void jamputuword(uchar *buf,ulong offset,ushort num) { buf[offset]=num%256; buf[offset+1]=num/256; } void jamputulong(uchar *buf,ulong offset,ulong num) { buf[offset]=num%256; buf[offset+1]=(num / 256) % 256; buf[offset+2]=(num / 256 / 256) % 256; buf[offset+3]=(num / 256 / 256 / 256) % 256; } ulong jamgetulong(uchar *buf,ulong offset) { return (ulong) buf[offset]+ buf[offset+1]*256+ buf[offset+2]*256*256+ buf[offset+3]*256*256*256; } int freadjambaseheader(FILE *fp,s_JamBaseHeader *s_JamBaseHeader) { uchar buf[SIZE_JAMBASEHEADER]; if(fread(buf,SIZE_JAMBASEHEADER,1,fp) != 1) return 0; memcpy(s_JamBaseHeader->Signature,&buf[JAMBASEHEADER_SIGNATURE],4); s_JamBaseHeader->DateCreated = jamgetulong(buf,JAMBASEHEADER_DATECREATED); s_JamBaseHeader->ModCounter = jamgetulong(buf,JAMBASEHEADER_MODCOUNTER); s_JamBaseHeader->ActiveMsgs = jamgetulong(buf,JAMBASEHEADER_ACTIVEMSGS); s_JamBaseHeader->PasswordCRC = jamgetulong(buf,JAMBASEHEADER_PASSWORDCRC); s_JamBaseHeader->BaseMsgNum = jamgetulong(buf,JAMBASEHEADER_BASEMSGNUM); memcpy(s_JamBaseHeader->RSRVD,&buf[JAMBASEHEADER_RSRVD],1000); return 1; } int fwritejambaseheader(FILE *fp,s_JamBaseHeader *s_JamBaseHeader) { uchar buf[SIZE_JAMBASEHEADER]; memcpy(&buf[JAMBASEHEADER_SIGNATURE],s_JamBaseHeader->Signature,4); jamputulong(buf,JAMBASEHEADER_DATECREATED, s_JamBaseHeader->DateCreated); jamputulong(buf,JAMBASEHEADER_MODCOUNTER, s_JamBaseHeader->ModCounter); jamputulong(buf,JAMBASEHEADER_ACTIVEMSGS, s_JamBaseHeader->ActiveMsgs); jamputulong(buf,JAMBASEHEADER_PASSWORDCRC, s_JamBaseHeader->PasswordCRC ); jamputulong(buf,JAMBASEHEADER_BASEMSGNUM, s_JamBaseHeader->BaseMsgNum); memcpy(&buf[JAMBASEHEADER_RSRVD],s_JamBaseHeader->RSRVD,1000); if(fwrite(buf,SIZE_JAMBASEHEADER,1,fp) != 1) return 0; return 1; } int freadjammsgheader(FILE *fp,s_JamMsgHeader *s_JamMsgHeader) { uchar buf[SIZE_JAMMSGHEADER]; if(fread(buf,SIZE_JAMMSGHEADER,1,fp) != 1) return 0; memcpy(s_JamMsgHeader->Signature,&buf[JAMMSGHEADER_SIGNATURE],4); s_JamMsgHeader->Revision = jamgetuword(buf,JAMMSGHEADER_REVISION); s_JamMsgHeader->ReservedWord = jamgetuword(buf,JAMMSGHEADER_RESERVEDWORD); s_JamMsgHeader->SubfieldLen = jamgetulong(buf,JAMMSGHEADER_SUBFIELDLEN); s_JamMsgHeader->TimesRead = jamgetulong(buf,JAMMSGHEADER_TIMESREAD); s_JamMsgHeader->MsgIdCRC = jamgetulong(buf,JAMMSGHEADER_MSGIDCRC); s_JamMsgHeader->ReplyCRC = jamgetulong(buf,JAMMSGHEADER_REPLYCRC); s_JamMsgHeader->ReplyTo = jamgetulong(buf,JAMMSGHEADER_REPLYTO); s_JamMsgHeader->Reply1st = jamgetulong(buf,JAMMSGHEADER_REPLY1ST); s_JamMsgHeader->ReplyNext = jamgetulong(buf,JAMMSGHEADER_REPLYNEXT); s_JamMsgHeader->DateWritten = jamgetulong(buf,JAMMSGHEADER_DATEWRITTEN); s_JamMsgHeader->DateReceived = jamgetulong(buf,JAMMSGHEADER_DATERECEIVED); s_JamMsgHeader->DateProcessed = jamgetulong(buf,JAMMSGHEADER_DATEPROCESSED); s_JamMsgHeader->MsgNum = jamgetulong(buf,JAMMSGHEADER_MSGNUM); s_JamMsgHeader->Attribute = jamgetulong(buf,JAMMSGHEADER_ATTRIBUTE); s_JamMsgHeader->Attribute2 = jamgetulong(buf,JAMMSGHEADER_ATTRIBUTE2); s_JamMsgHeader->TxtOffset = jamgetulong(buf,JAMMSGHEADER_TXTOFFSET); s_JamMsgHeader->TxtLen = jamgetulong(buf,JAMMSGHEADER_TXTLEN); s_JamMsgHeader->PasswordCRC = jamgetulong(buf,JAMMSGHEADER_PASSWORDCRC); s_JamMsgHeader->Cost = jamgetulong(buf,JAMMSGHEADER_COST); return 1; } int fwritejammsgheader(FILE *fp,s_JamMsgHeader *s_JamMsgHeader) { uchar buf[SIZE_JAMMSGHEADER]; memcpy(&buf[JAMMSGHEADER_SIGNATURE],s_JamMsgHeader->Signature,4); jamputuword(buf,JAMMSGHEADER_REVISION, s_JamMsgHeader->Revision); jamputuword(buf,JAMMSGHEADER_RESERVEDWORD, s_JamMsgHeader->ReservedWord); jamputulong(buf,JAMMSGHEADER_SUBFIELDLEN, s_JamMsgHeader->SubfieldLen); jamputulong(buf,JAMMSGHEADER_TIMESREAD, s_JamMsgHeader->TimesRead); jamputulong(buf,JAMMSGHEADER_MSGIDCRC, s_JamMsgHeader->MsgIdCRC); jamputulong(buf,JAMMSGHEADER_REPLYCRC, s_JamMsgHeader->ReplyCRC ); jamputulong(buf,JAMMSGHEADER_REPLYTO, s_JamMsgHeader->ReplyTo); jamputulong(buf,JAMMSGHEADER_REPLY1ST, s_JamMsgHeader->Reply1st); jamputulong(buf,JAMMSGHEADER_REPLYNEXT, s_JamMsgHeader->ReplyNext); jamputulong(buf,JAMMSGHEADER_DATEWRITTEN, s_JamMsgHeader->DateWritten); jamputulong(buf,JAMMSGHEADER_DATERECEIVED, s_JamMsgHeader->DateReceived ); jamputulong(buf,JAMMSGHEADER_DATEPROCESSED, s_JamMsgHeader->DateProcessed); jamputulong(buf,JAMMSGHEADER_MSGNUM, s_JamMsgHeader->MsgNum); jamputulong(buf,JAMMSGHEADER_ATTRIBUTE, s_JamMsgHeader->Attribute); jamputulong(buf,JAMMSGHEADER_ATTRIBUTE2, s_JamMsgHeader->Attribute2); jamputulong(buf,JAMMSGHEADER_TXTOFFSET, s_JamMsgHeader->TxtOffset); jamputulong(buf,JAMMSGHEADER_TXTLEN, s_JamMsgHeader->TxtLen); jamputulong(buf,JAMMSGHEADER_PASSWORDCRC, s_JamMsgHeader->PasswordCRC); jamputulong(buf,JAMMSGHEADER_COST, s_JamMsgHeader->Cost); if(fwrite(buf,SIZE_JAMMSGHEADER,1,fp) != 1) return 0; return 1; } int freadjamindex(FILE *fp,s_JamIndex *s_JamIndex) { uchar buf[SIZE_JAMINDEX]; if(fread(buf,SIZE_JAMINDEX,1,fp) != 1) return 0; s_JamIndex->UserCRC = jamgetulong(buf,JAMINDEX_USERCRC); s_JamIndex->HdrOffset = jamgetulong(buf,JAMINDEX_HDROFFSET); return 1; } int fwritejamindex(FILE *fp,s_JamIndex *s_JamIndex) { uchar buf[SIZE_JAMINDEX]; jamputulong(buf,JAMINDEX_USERCRC, s_JamIndex->UserCRC); jamputulong(buf,JAMINDEX_HDROFFSET, s_JamIndex->HdrOffset); if(fwrite(buf,SIZE_JAMINDEX,1,fp) != 1) return 0; return 1; } int freadjamlastread(FILE *fp,s_JamLastRead *s_JamLastRead) { uchar buf[SIZE_JAMLASTREAD]; if(fread(buf,SIZE_JAMLASTREAD,1,fp) != 1) return 0; s_JamLastRead->UserCRC = jamgetulong(buf,JAMLASTREAD_USERCRC); s_JamLastRead->UserID = jamgetulong(buf,JAMLASTREAD_USERID); s_JamLastRead->LastReadMsg = jamgetulong(buf,JAMLASTREAD_LASTREADMSG); s_JamLastRead->HighReadMsg = jamgetulong(buf,JAMLASTREAD_HIGHREADMSG); return 1; } int fwritejamlastread(FILE *fp,s_JamLastRead *s_JamLastRead) { uchar buf[SIZE_JAMLASTREAD]; jamputulong(buf,JAMLASTREAD_USERCRC,s_JamLastRead->UserCRC); jamputulong(buf,JAMLASTREAD_USERID,s_JamLastRead->UserID); jamputulong(buf,JAMLASTREAD_LASTREADMSG,s_JamLastRead->LastReadMsg); jamputulong(buf,JAMLASTREAD_HIGHREADMSG,s_JamLastRead->HighReadMsg); if(fwrite(buf,SIZE_JAMLASTREAD,1,fp) != 1) return 0; return 1; } int fwritejamsavesubfield(FILE *fp,s_JamSaveSubfield *s_JamSaveSubfield) { uchar buf[SIZE_JAMLASTREAD]; jamputuword(buf,JAMSAVESUBFIELD_LOID, s_JamSaveSubfield->LoID); jamputuword(buf,JAMSAVESUBFIELD_HIID, s_JamSaveSubfield->HiID); jamputulong(buf,JAMSAVESUBFIELD_DATLEN, s_JamSaveSubfield->DatLen); if(fwrite(buf,SIZE_JAMSAVESUBFIELD,1,fp) != 1) return 0; return 1; } void getjamsubfield(uchar *buf,s_JamSubfield *Subfield_S) { Subfield_S->LoID = jamgetuword(buf,JAMSAVESUBFIELD_LOID); Subfield_S->HiID = jamgetuword(buf,JAMSAVESUBFIELD_HIID); Subfield_S->DatLen = jamgetulong(buf,JAMSAVESUBFIELD_DATLEN); Subfield_S->Buffer = (uchar *) buf + SIZE_JAMSAVESUBFIELD; } jamnntpd-1.2/src/jamlib/structrw.h000066400000000000000000000057031141642135500172710ustar00rootroot00000000000000/* structrw - Platform-independent reading and writing of JAM structs Copyright (C) 1999 Johan Billing This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #define JAMBASEHEADER_SIGNATURE 0 #define JAMBASEHEADER_DATECREATED 4 #define JAMBASEHEADER_MODCOUNTER 8 #define JAMBASEHEADER_ACTIVEMSGS 12 #define JAMBASEHEADER_PASSWORDCRC 16 #define JAMBASEHEADER_BASEMSGNUM 20 #define JAMBASEHEADER_RSRVD 24 #define SIZE_JAMBASEHEADER 1024 #define JAMMSGHEADER_SIGNATURE 0 #define JAMMSGHEADER_REVISION 4 #define JAMMSGHEADER_RESERVEDWORD 6 #define JAMMSGHEADER_SUBFIELDLEN 8 #define JAMMSGHEADER_TIMESREAD 12 #define JAMMSGHEADER_MSGIDCRC 16 #define JAMMSGHEADER_REPLYCRC 20 #define JAMMSGHEADER_REPLYTO 24 #define JAMMSGHEADER_REPLY1ST 28 #define JAMMSGHEADER_REPLYNEXT 32 #define JAMMSGHEADER_DATEWRITTEN 36 #define JAMMSGHEADER_DATERECEIVED 40 #define JAMMSGHEADER_DATEPROCESSED 44 #define JAMMSGHEADER_MSGNUM 48 #define JAMMSGHEADER_ATTRIBUTE 52 #define JAMMSGHEADER_ATTRIBUTE2 56 #define JAMMSGHEADER_TXTOFFSET 60 #define JAMMSGHEADER_TXTLEN 64 #define JAMMSGHEADER_PASSWORDCRC 68 #define JAMMSGHEADER_COST 72 #define SIZE_JAMMSGHEADER 76 #define JAMINDEX_USERCRC 0 #define JAMINDEX_HDROFFSET 4 #define SIZE_JAMINDEX 8 #define JAMLASTREAD_USERCRC 0 #define JAMLASTREAD_USERID 4 #define JAMLASTREAD_LASTREADMSG 8 #define JAMLASTREAD_HIGHREADMSG 12 #define SIZE_JAMLASTREAD 16 #define JAMSAVESUBFIELD_LOID 0 #define JAMSAVESUBFIELD_HIID 2 #define JAMSAVESUBFIELD_DATLEN 4 #define SIZE_JAMSAVESUBFIELD 8 int freadjambaseheader(FILE *fp,s_JamBaseHeader *s_JamBaseHeader); int fwritejambaseheader(FILE *fp,s_JamBaseHeader *s_JamBaseHeader); int freadjammsgheader(FILE *fp,s_JamMsgHeader *s_JamMsgHeader); int fwritejammsgheader(FILE *fp,s_JamMsgHeader *s_JamMsgHeader); int freadjamindex(FILE *fp,s_JamIndex *s_JamIndex); int fwritejamindex(FILE *fp,s_JamIndex *s_JamIndex); int freadjamlastread(FILE *fp,s_JamLastRead *s_JamLastRead); int fwritejamlastread(FILE *fp,s_JamLastRead *s_JamLastRead); int fwritejamsavesubfield(FILE *fp,s_JamSaveSubfield *s_JamSaveSubfield); void getjamsubfield(uchar *buf,s_JamSubfield *Subfield_S); jamnntpd-1.2/src/jamlib/subpack.c000066400000000000000000000130571141642135500170200ustar00rootroot00000000000000/* JAMLIB - A JAM subroutine library Copyright (C) 1999 Björn Stenberg This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Changes made by Johan Billing 2000-04-16: - Fixed broken JAM_GetSubfield() - #includes stdlib.h instead of malloc.h and memory.h Changes made by Johan Billing 2000-09-17: - Added JAM_GetSubfield_R() Backported changes from JAMLIB 1.4.7 made by Johan Billing 2003-10-22 - JAM_NewSubPacket() and JAM_PutSubField() would give memory leaks under low memory conditions. Fixed. Other changes made by Johan Billing 2003-10-22 - Fixed comparison between signed and unsigned variable in JAM_DelSubPacket() and JAM_GetSubField() */ /*********************************************************************** ** ** SUBPACKET.C -- Subfield packet handling ** ** Author: Bj”rn Stenberg (bjorn.stenberg@sth.frontec.se) ** ***********************************************************************/ #include #include #include #include #include "jam.h" /*********************************************************************** ** ** JAM_NewSubPacket - Create a new subfield packet ** ***********************************************************************/ s_JamSubPacket* JAM_NewSubPacket( void ) { s_JamSubPacket* Sub_PS; /* allocate packet struct */ Sub_PS = (s_JamSubPacket*) malloc( sizeof( s_JamSubPacket ) ); if ( !Sub_PS ) return NULL; Sub_PS->NumAlloc = 20; Sub_PS->NumFields = 0; /* allocate pointer array */ Sub_PS->Fields = (s_JamSubfield**) calloc( Sub_PS->NumAlloc, sizeof( s_JamSubfield* ) ); if ( !Sub_PS->Fields ) { free (Sub_PS); return NULL; } return Sub_PS; } /*********************************************************************** ** ** JAM_DelSubPacket - Free the data associated with a subfield packet ** ***********************************************************************/ int JAM_DelSubPacket( s_JamSubPacket* SubPack_PS ) { ulong i; if (!SubPack_PS) return JAM_BAD_PARAM; for ( i=0; i < SubPack_PS->NumFields; i++ ) { s_JamSubfield* Field_PS = SubPack_PS->Fields[i]; if ( Field_PS->Buffer ) free( Field_PS->Buffer ); free( Field_PS ); } free( SubPack_PS->Fields ); free( SubPack_PS ); return 0; } /*********************************************************************** ** ** JAM_GetSubfield -- Get first/next subfield from a subfield packet ** (not reentrant) ** ***********************************************************************/ s_JamSubfield* JAM_GetSubfield( s_JamSubPacket* SubPack_PS ) { static s_JamSubPacket* LastPack_PS = NULL; static ulong NextIndex_I = 0; if ( SubPack_PS ) { LastPack_PS = SubPack_PS; NextIndex_I = 0; } if ( NextIndex_I < LastPack_PS->NumFields ) return LastPack_PS->Fields[ NextIndex_I++ ]; return NULL; } /*********************************************************************** ** ** JAM_GetSubfield_R -- Get first/next subfield from a subfield packet ** (reentrant) ** ***********************************************************************/ s_JamSubfield* JAM_GetSubfield_R( s_JamSubPacket* SubPack_PS , ulong* Count_PI) { if ( *Count_PI < SubPack_PS->NumFields ) return SubPack_PS->Fields[ (*Count_PI)++ ]; return NULL; } /*********************************************************************** ** ** JAM_PutSubfield -- Add a subfield to a subfield packet ** ***********************************************************************/ int JAM_PutSubfield( s_JamSubPacket* SubPack_PS, s_JamSubfield* Field_PS ) { s_JamSubfield* NewField_PS; uchar* NewBuf_PC; /* do we have to expand the array? */ if ( SubPack_PS->NumFields == SubPack_PS->NumAlloc ) { s_JamSubfield** Fields_PPS; SubPack_PS->NumAlloc *= 2; Fields_PPS = (s_JamSubfield**) realloc( SubPack_PS->Fields, SubPack_PS->NumAlloc * sizeof( s_JamSubfield* ) ); if ( !Fields_PPS ) return JAM_NO_MEMORY; SubPack_PS->Fields=Fields_PPS; } /* ** Copy the passed subfield */ /* allocate a new subfield */ NewField_PS = (s_JamSubfield*) malloc( sizeof( s_JamSubfield ) ); if ( !NewField_PS ) return JAM_NO_MEMORY; /* allocate a new buffer */ if ( Field_PS->DatLen ) { NewBuf_PC = (uchar*) malloc( Field_PS->DatLen ); if ( !NewBuf_PC ) { free (NewField_PS); return JAM_NO_MEMORY; } memcpy( NewBuf_PC, Field_PS->Buffer, Field_PS->DatLen ); } else NewBuf_PC = NULL; /* copy field struct */ NewField_PS->LoID = Field_PS->LoID; NewField_PS->HiID = Field_PS->HiID; NewField_PS->DatLen = Field_PS->DatLen; NewField_PS->Buffer = NewBuf_PC; /* ** Update subfield packet */ SubPack_PS->Fields[ SubPack_PS->NumFields ] = NewField_PS; SubPack_PS->NumFields++; return 0; } jamnntpd-1.2/src/login.c000066400000000000000000000032251141642135500152360ustar00rootroot00000000000000#include "nntpserv.h" bool login(struct var *var,uchar *user,uchar *pass) { FILE *fp; uchar s[1000],cfguser[100],cfgpass[100],cfgreadgroups[50],cfgpostgroups[50],realnames[100]; int res1,res2,res3,res4,res5; ulong pos,line; if(!(fp=fopen(cfg_usersfile,"r"))) { os_logwrite("(%s) Can't read users file %s",var->clientid,cfg_usersfile); return(FALSE); } while(fgets(s,999,fp)) { strip(s); pos=0; if(s[0]!=0 && s[0]!='#') { res1=getcfgword(s,&pos,cfguser,100); res2=getcfgword(s,&pos,cfgpass,100); res3=getcfgword(s,&pos,cfgreadgroups,50); res4=getcfgword(s,&pos,cfgpostgroups,50); res5=getcfgword(s,&pos,realnames,100); if(res1 && res2 && res3 && res4) { if(stricmp(cfguser,user) == 0) { if(strcmp(cfgpass,pass)!=0) { os_logwrite("(%s) Wrong password for %s",var->clientid,user); fclose(fp); return(FALSE); } os_logwrite("(%s) Logged in as %s",var->clientid,user); strcpy(var->readgroups,cfgreadgroups); strcpy(var->postgroups,cfgpostgroups); if(res5) strcpy(var->realnames,realnames); var->login=TRUE; fclose(fp); return(TRUE); } } else { os_logwrite("(%s) Syntax error on line %lu in %s, skipping line",var->clientid,line,cfg_usersfile); } } } os_logwrite("(%s) Unknown user %s",var->clientid,user); fclose(fp); return(FALSE); } jamnntpd-1.2/src/login.h000066400000000000000000000000651141642135500152420ustar00rootroot00000000000000bool login(struct var *var,uchar *user,uchar *pass); jamnntpd-1.2/src/main.c000066400000000000000000000342271141642135500150600ustar00rootroot00000000000000#include "nntpserv.h" #define MAXFILEARGS 100 char *fileargv[MAXFILEARGS]; int fileargc; bool readargs(uchar *file); void createconfig(uchar *file); bool parseargs(int argc, char **argv,uchar *filename,ulong line) { uchar *arg,src[100],tmp[200]; int c; src[0]=0; if(filename) sprintf(src," (%.95s line %ld)",filename,line); for(c=0;c\n"); if(cfg_guestsuffix) fprintf(fp,"guestsuffix \"%s\"\n",cfg_guestsuffix); else fprintf(fp,"#guestsuffix \n"); if(cfg_echomailjam) fprintf(fp,"echomailjam \"%s\"\n",cfg_echomailjam); else fprintf(fp,"#echomailjam \n"); fclose(fp); } void freeargs(void) { int c; for(c=0;c]\n" "\n" " General options:\n" "\n" " -p[ort] Port number for JamNNTPd (default: 5000)\n" " -m[ax] Maximum number of simultaneous connections (default: 5)\n" " -g[roups] Read this file instead of " CFG_GROUPSFILE "\n" " -a[llow] Read this file instead of " CFG_ALLOWFILE "\n" " -u[sers] Read this file instead of " CFG_USERSFILE "\n" " -x[lat] Read this file instead of " CFG_XLATFILE "\n" " -l[ogfile] Log to this file instead of " CFG_LOGFILE "\n" " -noecholog Do not write log messages to console\n" " -debug Write all network communication to console\n" "\n" " Options for displaying messages:\n" "\n" " -readorigin Get addresses from the origin line instead of JAM header\n" " -noencode Do not MIME encode headers with 8-bit characters\n" " -strictnetmail Use strict article counters in netmail areas\n" " -def_flowed on/off Default setting for format=flowed (RFC 2646)\n" " -def_showto on/off Default setting for the display of recipient on from line\n" "\n" " Options for posting messages:\n" "\n" " -nostripre Do not remove \"Re:\" from subject line\n" " -notearline Do not put X-Newsreader/User-Agent string on tearline\n" " -noreplyaddr Do not create REPLYADDR kludges\n" " -notzutc Do not create TZUTC kludges\n" " -nocancel Do not allow cancelling of messages\n" " -smartquote Reformat quoted text to fidonet style\n" " -origin Origin to use instead of contents of Organization line\n" " -guestsuffix Suffix added to from name of unauthenticated users\n" " -echomailjam Create echomail.jam file for CrashMail and other tossers\n" "\n" " Options for configuration files:\n" "\n" " -config Read options from this file\n" " -create Create a configuration file with the default options\n" "\n" "If no options are specified on the commandline, JamNNTPd will attempt to read\n" "options from " CONFIGFILE " (if it exists).\n" "\n"); return(FALSE); } if(argc == 1) { if((fp=fopen(CONFIGFILE,"r"))) { fclose(fp); if(!readargs(CONFIGFILE)) { freeargs(); exit(0); } } } else { if(!parseargs(argc-1,&argv[1],NULL,0)) { freeargs(); exit(0); } } if(!os_init()) { freeargs(); exit(10); } sock = socket(PF_INET,SOCK_STREAM,IPPROTO_TCP); if(sock == INVALID_SOCKET) { uchar err[200]; os_showerror("Failed to create socket: %s",os_strerr(os_errno(),err,200)); os_free(); freeargs(); exit(10); } memset(&local, 0, sizeof(local) ); local.sin_family = AF_INET; local.sin_addr.s_addr = INADDR_ANY; local.sin_port = htons(cfg_port); error = bind(sock,(struct sockaddr *)&local,sizeof(local)); if(error == SOCKET_ERROR) { uchar err[200]; os_showerror("Could not bind to port (server already running?): %s",os_strerr(os_errno(),err,200)); close(sock); os_free(); freeargs(); exit(10); } error = listen(sock,5); if(error == SOCKET_ERROR) { uchar err[200]; os_showerror("Could not listen to socket: %s",os_strerr(os_errno(),err,200)); close(sock); os_free(); freeargs(); exit(10); } os_logwrite(SERVER_NAME " " SERVER_VERSION " is running on port %d",cfg_port); if(cfg_debug) os_logwrite("Compiled " __DATE__ " " __TIME__); while(!get_server_quit()) { FD_ZERO(&fds); FD_SET(sock,&fds); tv.tv_sec=1; tv.tv_usec=0; res=select(sock+1,&fds,NULL,NULL,&tv); if(res != 0 && res != -1) { SOCKET active_sock; struct sockaddr_in from; int fromlen = sizeof(from); active_sock = accept(sock,(struct sockaddr *)&from,&fromlen); if(active_sock == SOCKET_ERROR) { uchar err[200]; os_showerror("Failed to accept incoming connection: %s",os_strerr(os_errno(),err,200)); break; } os_startserver(server,active_sock); } } if(get_server_openconnections()) { os_logwrite("Exiting. %ld connection(s) are active, waiting for them to quit", get_server_openconnections()); while(get_server_openconnections()) os_sleep(1); } close(sock); os_logwrite(SERVER_NAME " exited"); os_free(); freeargs(); exit(0); } jamnntpd-1.2/src/makechs.c000066400000000000000000000627551141642135500155560ustar00rootroot00000000000000#include #include #include #include typedef int bool; typedef unsigned char uchar; #ifndef linux typedef unsigned short ushort; typedef unsigned long ulong; #endif #define TRUE 1 #define FALSE 0 #ifdef PLATFORM_LINUX #define stricmp strcasecmp #define strnicmp strncasecmp #endif struct fallback { ushort u; uchar *str; }; /* The table below is Markus Kuhn's transliteration table transtab with some minor changes (see comments below) */ /* The original table can be found at http://www.cl.cam.ac.uk/~mgk25/download/transtab.tar.gz */ struct fallback transtab[] = { /* { 0x0027, "’" }, */ /* removed, is already ascii */ /* { 0x0060, "‛', '‘" }, */ /* removed, is already ascii */ { 0x00A0, " " }, { 0x00A1, "!" }, { 0x00A2, "c" }, { 0x00A3, "GBP" }, { 0x00A5, "Y" }, { 0x00A6, "|" }, { 0x00A7, "S" }, { 0x00A8, "\"" }, { 0x00A9, "(c)" }, { 0x00AA, "a" }, { 0x00AB, "<<" }, { 0x00AC, "-" }, { 0x00AD, "-" }, { 0x00AE, "(R)" }, { 0x00AF, "-" }, { 0x00B0, " " }, { 0x00B1, "+/-" }, { 0x00B2, "^2" }, { 0x00B3, "^3" }, { 0x00B4, "'" }, { 0x00B5, "u" }, { 0x00B6, "P" }, { 0x00B7, "." }, { 0x00B8, "," }, { 0x00B9, "1" }, { 0x00BA, "o" }, { 0x00BB, ">>" }, { 0x00BC, " 1/4" }, { 0x00BD, " 1/2" }, { 0x00BE, " 3/4" }, { 0x00BF, "?" }, { 0x00C0, "A" }, { 0x00C1, "A" }, { 0x00C2, "A" }, { 0x00C3, "A" }, { 0x00C4, "Ae" }, { 0x00C5, "Aa" }, { 0x00C6, "AE" }, { 0x00C7, "C" }, { 0x00C8, "E" }, { 0x00C9, "E" }, { 0x00CA, "E" }, { 0x00CB, "E" }, { 0x00CC, "I" }, { 0x00CD, "I" }, { 0x00CE, "I" }, { 0x00CF, "I" }, { 0x00D0, "D" }, { 0x00D1, "N" }, { 0x00D2, "O" }, { 0x00D3, "O" }, { 0x00D4, "O" }, { 0x00D5, "O" }, { 0x00D6, "Oe" }, { 0x00D7, "x" }, { 0x00D8, "O" }, { 0x00D9, "U" }, { 0x00DA, "U" }, { 0x00DB, "U" }, { 0x00DC, "Ue" }, { 0x00DD, "Y" }, { 0x00DE, "Th" }, { 0x00DF, "ss" }, { 0x00E0, "a" }, { 0x00E1, "a" }, { 0x00E2, "a" }, { 0x00E3, "a" }, { 0x00E4, "ae" }, { 0x00E5, "aa" }, { 0x00E6, "ae" }, { 0x00E7, "c" }, { 0x00E8, "e" }, { 0x00E9, "e" }, { 0x00EA, "e" }, { 0x00EB, "e" }, { 0x00EC, "i" }, { 0x00ED, "i" }, { 0x00EE, "i" }, { 0x00EF, "i" }, { 0x00F0, "d" }, { 0x00F1, "n" }, { 0x00F2, "o" }, { 0x00F3, "o" }, { 0x00F4, "o" }, { 0x00F5, "o" }, { 0x00F6, "oe" }, { 0x00F7, ":" }, { 0x00F8, "o" }, { 0x00F9, "u" }, { 0x00FA, "u" }, { 0x00FB, "u" }, { 0x00FC, "ue" }, { 0x00FD, "y" }, { 0x00FE, "th" }, { 0x00FF, "y" }, { 0x0100, "A" }, { 0x0101, "a" }, { 0x0102, "A" }, { 0x0103, "a" }, { 0x0104, "A" }, { 0x0105, "a" }, { 0x0106, "C" }, { 0x0107, "c" }, { 0x0108, "Ch" }, { 0x0109, "ch" }, { 0x010A, "C" }, { 0x010B, "c" }, { 0x010C, "C" }, { 0x010D, "c" }, { 0x010E, "D" }, { 0x010F, "d" }, { 0x0110, "D" }, { 0x0111, "d" }, { 0x0112, "E" }, { 0x0113, "e" }, { 0x0114, "E" }, { 0x0115, "e" }, { 0x0116, "E" }, { 0x0117, "e" }, { 0x0118, "E" }, { 0x0119, "e" }, { 0x011A, "E" }, { 0x011B, "e" }, { 0x011C, "Gh" }, { 0x011D, "gh" }, { 0x011E, "G" }, { 0x011F, "g" }, { 0x0120, "G" }, { 0x0121, "g" }, { 0x0122, "G" }, { 0x0123, "g" }, { 0x0124, "Hh" }, { 0x0125, "hh" }, { 0x0126, "H" }, { 0x0127, "h" }, { 0x0128, "I" }, { 0x0129, "i" }, { 0x012A, "I" }, { 0x012B, "i" }, { 0x012C, "I" }, { 0x012D, "i" }, { 0x012E, "I" }, { 0x012F, "i" }, { 0x0130, "I" }, { 0x0131, "i" }, { 0x0132, "IJ" }, { 0x0133, "ij" }, { 0x0134, "Jh" }, { 0x0135, "jh" }, { 0x0136, "K" }, { 0x0137, "k" }, { 0x0138, "k" }, { 0x0139, "L" }, { 0x013A, "l" }, { 0x013B, "L" }, { 0x013C, "l" }, { 0x013D, "L" }, { 0x013E, "l" }, { 0x013F, "L" }, { 0x0140, "l" }, { 0x0141, "L" }, { 0x0142, "l" }, { 0x0143, "N" }, { 0x0144, "n" }, { 0x0145, "N" }, { 0x0146, "n" }, { 0x0147, "N" }, { 0x0148, "n" }, { 0x0149, "'n" }, { 0x014A, "NG" }, { 0x014B, "ng" }, { 0x014C, "O" }, { 0x014D, "o" }, { 0x014E, "O" }, { 0x014F, "o" }, { 0x0150, "O" }, { 0x0151, "o" }, { 0x0152, "OE" }, { 0x0153, "oe" }, { 0x0154, "R" }, { 0x0155, "r" }, { 0x0156, "R" }, { 0x0157, "r" }, { 0x0158, "R" }, { 0x0159, "r" }, { 0x015A, "S" }, { 0x015B, "s" }, { 0x015C, "Sh" }, { 0x015D, "sh" }, { 0x015E, "S" }, { 0x015F, "s" }, { 0x0160, "S" }, { 0x0161, "s" }, { 0x0162, "T" }, { 0x0163, "t" }, { 0x0164, "T" }, { 0x0165, "t" }, { 0x0166, "T" }, { 0x0167, "t" }, { 0x0168, "U" }, { 0x0169, "u" }, { 0x016A, "U" }, { 0x016B, "u" }, { 0x016C, "U" }, { 0x016D, "u" }, { 0x016E, "U" }, { 0x016F, "u" }, { 0x0170, "U" }, { 0x0171, "u" }, { 0x0172, "U" }, { 0x0173, "u" }, { 0x0174, "W" }, { 0x0175, "w" }, { 0x0176, "Y" }, { 0x0177, "y" }, { 0x0178, "Y" }, { 0x0179, "Z" }, { 0x017A, "z" }, { 0x017B, "Z" }, { 0x017C, "z" }, { 0x017D, "Z" }, { 0x017E, "z" }, { 0x017F, "s" }, { 0x0192, "f" }, { 0x0218, "S" }, { 0x0219, "s" }, { 0x021A, "T" }, { 0x021B, "t" }, { 0x02B9, "'" }, { 0x02BB, "`" }, /* replaced, non-ascii */ { 0x02BC, "'" }, { 0x02BD, "`" }, /* replaced, non-ascii */ { 0x02C6, "^" }, { 0x02C8, "'" }, { 0x02C9, "-" }, /* replaced non-ascii */ { 0x02CC, "," }, { 0x02D0, ":" }, { 0x02DA, "deg" }, /* replaced, non-ascii */ { 0x02DC, "~" }, { 0x02DD, "\"" }, { 0x0374, "'" }, { 0x0375, "," }, { 0x0393, "Gamm" }, /* added */ { 0x0398, "Thet" }, /* added */ { 0x03a3, "Sigm" }, /* added */ { 0x03a6, "Phi" }, /* added */ { 0x03a9, "Omeg" }, /* added */ { 0x03b1, "alph" }, /* added */ { 0x03b4, "delt" }, /* added */ { 0x03c0, "pi" }, /* added */ { 0x03c3, "sigm" }, /* added */ { 0x03c4, "tau" }, /* added */ { 0x03b5, "eps" }, /* added */ { 0x03c6, "phi" }, /* added */ { 0x037E, ";" }, { 0x1E02, "B" }, { 0x1E03, "b" }, { 0x1E0A, "D" }, { 0x1E0B, "d" }, { 0x1E1E, "F" }, { 0x1E1F, "f" }, { 0x1E40, "M" }, { 0x1E41, "m" }, { 0x1E56, "P" }, { 0x1E57, "p" }, { 0x1E60, "S" }, { 0x1E61, "s" }, { 0x1E6A, "T" }, { 0x1E6B, "t" }, { 0x1E80, "W" }, { 0x1E81, "w" }, { 0x1E82, "W" }, { 0x1E83, "w" }, { 0x1E84, "W" }, { 0x1E85, "w" }, { 0x1EF2, "Y" }, { 0x1EF3, "y" }, { 0x2000, " " }, { 0x2001, " " }, { 0x2002, " " }, { 0x2003, " " }, { 0x2004, " " }, { 0x2005, " " }, { 0x2006, " " }, { 0x2007, " " }, { 0x2008, " " }, { 0x2009, " " }, { 0x200A, "" }, { 0x200B, "" }, { 0x200C, "" }, { 0x200D, "" }, { 0x200E, "" }, { 0x200F, "" }, { 0x2010, "-" }, { 0x2011, "-" }, { 0x2012, "-" }, { 0x2013, "-" }, { 0x2014, "--" }, { 0x2015, "--" }, { 0x2016, "||" }, { 0x2017, "_" }, { 0x2018, "'" }, { 0x2019, "'" }, { 0x201A, "'" }, { 0x201B, "'" }, { 0x201C, "\"" }, { 0x201D, "\"" }, { 0x201E, "\"" }, { 0x201F, "\"" }, { 0x2020, "+" }, { 0x2021, "++" }, { 0x2022, "o" }, { 0x2023, ">" }, { 0x2024, "." }, { 0x2025, ".." }, { 0x2026, "..." }, { 0x2027, "-" }, { 0x202A, "" }, { 0x202B, "" }, { 0x202C, "" }, { 0x202D, "" }, { 0x202E, "" }, { 0x202F, " " }, { 0x2030, "o/oo" }, /* replaced, too long */ { 0x2032, "'" }, { 0x2033, "\"" }, { 0x2034, "'''" }, { 0x2035, "`" }, { 0x2036, "``" }, { 0x2037, "```" }, { 0x2039, "<" }, { 0x203A, ">" }, { 0x203C, "!!" }, { 0x203E, "-" }, { 0x2043, "-" }, { 0x2044, "/" }, { 0x2048, "?!" }, { 0x2049, "!?" }, { 0x204A, "7" }, { 0x2070, "^0" }, { 0x2074, "^4" }, { 0x2075, "^5" }, { 0x2076, "^6" }, { 0x2077, "^7" }, { 0x2078, "^8" }, { 0x2079, "^9" }, { 0x207A, "^+" }, { 0x207C, "^=" }, { 0x207D, "^(" }, { 0x207E, "^)" }, { 0x207F, "^n" }, { 0x2080, "_0" }, { 0x2081, "_1" }, { 0x2082, "_2" }, { 0x2083, "_3" }, { 0x2084, "_4" }, { 0x2085, "_5" }, { 0x2086, "_6" }, { 0x2087, "_7" }, { 0x2088, "_8" }, { 0x2089, "_9" }, { 0x208A, "_+" }, { 0x208B, "_-" }, { 0x208C, "_=" }, { 0x208D, "_(" }, { 0x208E, "_)" }, { 0x20A7, "Pts" }, /* added */ { 0x20AC, "EUR" }, { 0x2100, "a/c" }, { 0x2101, "a/s" }, { 0x2103, "degC" }, /* replaced, non-ascii */ { 0x2105, "c/o" }, { 0x2106, "c/u" }, { 0x2109, "degF" }, /* replaced, non-ascii */ { 0x2113, "l" }, { 0x2116, "No" }, { 0x2117, "(P)" }, { 0x2120, "[SM]" }, { 0x2121, "TEL" }, { 0x2122, "[TM]" }, { 0x2126, "ohm" }, { 0x212A, "K" }, { 0x212B, "A" }, /* replaced, non-ascii */ { 0x212E, "e" }, { 0x2153, " 1/3" }, { 0x2154, " 2/3" }, { 0x2155, " 1/5" }, { 0x2156, " 2/5" }, { 0x2157, " 3/5" }, { 0x2158, " 4/5" }, { 0x2159, " 1/6" }, { 0x215A, " 5/6" }, { 0x215B, " 1/8" }, { 0x215C, " 3/8" }, { 0x215D, " 5/8" }, { 0x215E, " 7/8" }, { 0x215F, " 1/" }, { 0x2160, "I" }, { 0x2161, "II" }, { 0x2162, "III" }, { 0x2163, "IV" }, { 0x2164, "V" }, { 0x2165, "VI" }, { 0x2166, "VII" }, { 0x2167, "VIII" }, { 0x2168, "IX" }, { 0x2169, "X" }, { 0x216A, "XI" }, { 0x216B, "XII" }, { 0x216C, "L" }, { 0x216D, "C" }, { 0x216E, "D" }, { 0x216F, "M" }, { 0x2170, "i" }, { 0x2171, "ii" }, { 0x2172, "iii" }, { 0x2173, "iv" }, { 0x2174, "v" }, { 0x2175, "vi" }, { 0x2176, "vii" }, { 0x2177, "viii" }, { 0x2178, "ix" }, { 0x2179, "x" }, { 0x217A, "xi" }, { 0x217B, "xii" }, { 0x217C, "l" }, { 0x217D, "c" }, { 0x217E, "d" }, { 0x217F, "m" }, { 0x2190, "<-" }, { 0x2191, "^" }, { 0x2192, "->" }, { 0x2193, "v" }, { 0x2194, "<->" }, { 0x21D0, "<=" }, { 0x21D2, "=>" }, { 0x21D4, "<=>" }, { 0x2212, "-" }, { 0x2215, "/" }, { 0x2216, "\\" }, { 0x2217, "*" }, { 0x2218, "o" }, { 0x2219, "." }, /* replaced, non-ascii */ { 0x221a, "sqrt" }, /* added */ { 0x221E, "inf" }, { 0x2223, "|" }, { 0x2225, "||" }, { 0x2229, "n" }, /* added */ { 0x2236, ":" }, { 0x223C, "~" }, { 0x2248, "~~" }, /* added */ { 0x2260, "/=" }, { 0x2261, "=" }, { 0x2264, "<=" }, { 0x2265, ">=" }, { 0x226A, "<<" }, { 0x226B, ">>" }, { 0x2295, "(+)" }, { 0x2296, "(-)" }, { 0x2297, "(x)" }, { 0x2298, "(/)" }, { 0x22A2, "|-" }, { 0x22A3, "-|" }, { 0x22A6, "|-" }, { 0x22A7, "|=" }, { 0x22A8, "|=" }, { 0x22A9, "||-" }, { 0x22C5, "." }, /* replaced, non-ascii */ { 0x22C6, "*" }, { 0x22D5, "#" }, { 0x22D8, "<<<" }, { 0x22D9, ">>>" }, { 0x22EF, "..." }, { 0x2310, "NOT" }, /* added */ { 0x2320, "Inte" }, /* added */ { 0x2321, "gral" }, /* added */ { 0x2329, "<" }, { 0x232A, ">" }, { 0x2400, "NUL" }, { 0x2401, "SOH" }, { 0x2402, "STX" }, { 0x2403, "ETX" }, { 0x2404, "EOT" }, { 0x2405, "ENQ" }, { 0x2406, "ACK" }, { 0x2407, "BEL" }, { 0x2408, "BS" }, { 0x2409, "HT" }, { 0x240A, "LF" }, { 0x240B, "VT" }, { 0x240C, "FF" }, { 0x240D, "CR" }, { 0x240E, "SO" }, { 0x240F, "SI" }, { 0x2410, "DLE" }, { 0x2411, "DC1" }, { 0x2412, "DC2" }, { 0x2413, "DC3" }, { 0x2414, "DC4" }, { 0x2415, "NAK" }, { 0x2416, "SYN" }, { 0x2417, "ETB" }, { 0x2418, "CAN" }, { 0x2419, "EM" }, { 0x241A, "SUB" }, { 0x241B, "ESC" }, { 0x241C, "FS" }, { 0x241D, "GS" }, { 0x241E, "RS" }, { 0x241F, "US" }, { 0x2420, "SP" }, { 0x2421, "DEL" }, { 0x2423, "_" }, { 0x2424, "NL" }, { 0x2425, "///" }, { 0x2426, "?" }, { 0x2460, "(1)" }, { 0x2461, "(2)" }, { 0x2462, "(3)" }, { 0x2463, "(4)" }, { 0x2464, "(5)" }, { 0x2465, "(6)" }, { 0x2466, "(7)" }, { 0x2467, "(8)" }, { 0x2468, "(9)" }, { 0x2469, "(10)" }, { 0x246A, "(11)" }, { 0x246B, "(12)" }, { 0x246C, "(13)" }, { 0x246D, "(14)" }, { 0x246E, "(15)" }, { 0x246F, "(16)" }, { 0x2470, "(17)" }, { 0x2471, "(18)" }, { 0x2472, "(19)" }, { 0x2473, "(20)" }, { 0x2474, "(1)" }, { 0x2475, "(2)" }, { 0x2476, "(3)" }, { 0x2477, "(4)" }, { 0x2478, "(5)" }, { 0x2479, "(6)" }, { 0x247A, "(7)" }, { 0x247B, "(8)" }, { 0x247C, "(9)" }, { 0x247D, "(10)" }, { 0x247E, "(11)" }, { 0x247F, "(12)" }, { 0x2480, "(13)" }, { 0x2481, "(14)" }, { 0x2482, "(15)" }, { 0x2483, "(16)" }, { 0x2484, "(17)" }, { 0x2485, "(18)" }, { 0x2486, "(19)" }, { 0x2487, "(20)" }, { 0x2488, "1." }, { 0x2489, "2." }, { 0x248A, "3." }, { 0x248B, "4." }, { 0x248C, "5." }, { 0x248D, "6." }, { 0x248E, "7." }, { 0x248F, "8." }, { 0x2490, "9." }, { 0x2491, "10." }, { 0x2492, "11." }, { 0x2493, "12." }, { 0x2494, "13." }, { 0x2495, "14." }, { 0x2496, "15." }, { 0x2497, "16." }, { 0x2498, "17." }, { 0x2499, "18." }, { 0x249A, "19." }, { 0x249B, "20." }, { 0x249C, "(a)" }, { 0x249D, "(b)" }, { 0x249E, "(c)" }, { 0x249F, "(d)" }, { 0x24A0, "(e)" }, { 0x24A1, "(f)" }, { 0x24A2, "(g)" }, { 0x24A3, "(h)" }, { 0x24A4, "(i)" }, { 0x24A5, "(j)" }, { 0x24A6, "(k)" }, { 0x24A7, "(l)" }, { 0x24A8, "(m)" }, { 0x24A9, "(n)" }, { 0x24AA, "(o)" }, { 0x24AB, "(p)" }, { 0x24AC, "(q)" }, { 0x24AD, "(r)" }, { 0x24AE, "(s)" }, { 0x24AF, "(t)" }, { 0x24B0, "(u)" }, { 0x24B1, "(v)" }, { 0x24B2, "(w)" }, { 0x24B3, "(x)" }, { 0x24B4, "(y)" }, { 0x24B5, "(z)" }, { 0x24B6, "(A)" }, { 0x24B7, "(B)" }, { 0x24B8, "(C)" }, { 0x24B9, "(D)" }, { 0x24BA, "(E)" }, { 0x24BB, "(F)" }, { 0x24BC, "(G)" }, { 0x24BD, "(H)" }, { 0x24BE, "(I)" }, { 0x24BF, "(J)" }, { 0x24C0, "(K)" }, { 0x24C1, "(L)" }, { 0x24C2, "(M)" }, { 0x24C3, "(N)" }, { 0x24C4, "(O)" }, { 0x24C5, "(P)" }, { 0x24C6, "(Q)" }, { 0x24C7, "(R)" }, { 0x24C8, "(S)" }, { 0x24C9, "(T)" }, { 0x24CA, "(U)" }, { 0x24CB, "(V)" }, { 0x24CC, "(W)" }, { 0x24CD, "(X)" }, { 0x24CE, "(Y)" }, { 0x24CF, "(Z)" }, { 0x24D0, "(a)" }, { 0x24D1, "(b)" }, { 0x24D2, "(c)" }, { 0x24D3, "(d)" }, { 0x24D4, "(e)" }, { 0x24D5, "(f)" }, { 0x24D6, "(g)" }, { 0x24D7, "(h)" }, { 0x24D8, "(i)" }, { 0x24D9, "(j)" }, { 0x24DA, "(k)" }, { 0x24DB, "(l)" }, { 0x24DC, "(m)" }, { 0x24DD, "(n)" }, { 0x24DE, "(o)" }, { 0x24DF, "(p)" }, { 0x24E0, "(q)" }, { 0x24E1, "(r)" }, { 0x24E2, "(s)" }, { 0x24E3, "(t)" }, { 0x24E4, "(u)" }, { 0x24E5, "(v)" }, { 0x24E6, "(w)" }, { 0x24E7, "(x)" }, { 0x24E8, "(y)" }, { 0x24E9, "(z)" }, { 0x24EA, "(0)" }, { 0x2500, "-" }, { 0x2501, "=" }, { 0x2502, "|" }, { 0x2503, "|" }, { 0x2504, "-" }, { 0x2505, "=" }, { 0x2506, "|" }, { 0x2507, "|" }, { 0x2508, "-" }, { 0x2509, "=" }, { 0x250A, "|" }, { 0x250B, "|" }, { 0x250C, "+" }, { 0x250D, "+" }, { 0x250E, "+" }, { 0x250F, "+" }, { 0x2510, "+" }, { 0x2511, "+" }, { 0x2512, "+" }, { 0x2513, "+" }, { 0x2514, "+" }, { 0x2515, "+" }, { 0x2516, "+" }, { 0x2517, "+" }, { 0x2518, "+" }, { 0x2519, "+" }, { 0x251A, "+" }, { 0x251B, "+" }, { 0x251C, "+" }, { 0x251D, "+" }, { 0x251E, "+" }, { 0x251F, "+" }, { 0x2520, "+" }, { 0x2521, "+" }, { 0x2522, "+" }, { 0x2523, "+" }, { 0x2524, "+" }, { 0x2525, "+" }, { 0x2526, "+" }, { 0x2527, "+" }, { 0x2528, "+" }, { 0x2529, "+" }, { 0x252A, "+" }, { 0x252B, "+" }, { 0x252C, "+" }, { 0x252D, "+" }, { 0x252E, "+" }, { 0x252F, "+" }, { 0x2530, "+" }, { 0x2531, "+" }, { 0x2532, "+" }, { 0x2533, "+" }, { 0x2534, "+" }, { 0x2535, "+" }, { 0x2536, "+" }, { 0x2537, "+" }, { 0x2538, "+" }, { 0x2539, "+" }, { 0x253A, "+" }, { 0x253B, "+" }, { 0x253C, "+" }, { 0x253D, "+" }, { 0x253E, "+" }, { 0x253F, "+" }, { 0x2540, "+" }, { 0x2541, "+" }, { 0x2542, "+" }, { 0x2543, "+" }, { 0x2544, "+" }, { 0x2545, "+" }, { 0x2546, "+" }, { 0x2547, "+" }, { 0x2548, "+" }, { 0x2549, "+" }, { 0x254A, "+" }, { 0x254B, "+" }, { 0x254C, "-" }, { 0x254D, "=" }, { 0x254E, "|" }, { 0x254F, "|" }, { 0x2550, "=" }, { 0x2551, "|" }, { 0x2552, "+" }, { 0x2553, "+" }, { 0x2554, "+" }, { 0x2555, "+" }, { 0x2556, "+" }, { 0x2557, "+" }, { 0x2558, "+" }, { 0x2559, "+" }, { 0x255A, "+" }, { 0x255B, "+" }, { 0x255C, "+" }, { 0x255D, "+" }, { 0x255E, "+" }, { 0x255F, "+" }, { 0x2560, "+" }, { 0x2561, "+" }, { 0x2562, "+" }, { 0x2563, "+" }, { 0x2564, "+" }, { 0x2565, "+" }, { 0x2566, "+" }, { 0x2567, "+" }, { 0x2568, "+" }, { 0x2569, "+" }, { 0x256A, "+" }, { 0x256B, "+" }, { 0x256C, "+" }, { 0x256D, "+" }, { 0x256E, "+" }, { 0x256F, "+" }, { 0x2570, "+" }, { 0x2571, "/" }, { 0x2572, "\\" }, { 0x2573, "X" }, { 0x257C, "-" }, { 0x257D, "|" }, { 0x257E, "-" }, { 0x257F, "|" }, { 0x2580, "#" }, /* added for IBM block graphics */ { 0x2584, "#" }, /* added for IBM block graphics */ { 0x2588, "#" }, /* added for IBM block graphics */ { 0x258c, "#" }, /* added for IBM block graphics */ { 0x2590, "#" }, /* added for IBM block graphics */ { 0x2591, "#" }, /* added for IBM block graphics */ { 0x2592, "#" }, /* added for IBM block graphics */ { 0x2593, "#" }, /* added for IBM block graphics */ { 0x25A0, "#" }, /* added for IBM block graphics */ { 0x25CB, "o" }, { 0x25E6, "o" }, { 0x2605, "*" }, { 0x2606, "*" }, { 0x2612, "X" }, { 0x2613, "X" }, { 0x2639, ":-(" }, { 0x263A, ":-)" }, { 0x263B, "(-:" }, { 0x266D, "b" }, { 0x266F, "#" }, { 0x2701, "%<" }, { 0x2702, "%<" }, { 0x2703, "%<" }, { 0x2704, "%<" }, { 0x270C, "V" }, /* { 0x2713, "√" }, */ /* removed, non-ascii */ /* { 0x2714, "√" }, */ /* removed, non-ascii */ { 0x2715, "x" }, { 0x2716, "x" }, { 0x2717, "X" }, { 0x2718, "X" }, { 0x2719, "+" }, { 0x271A, "+" }, { 0x271B, "+" }, { 0x271C, "+" }, { 0x271D, "+" }, { 0x271E, "+" }, { 0x271F, "+" }, { 0x2720, "+" }, { 0x2721, "*" }, { 0x2722, "+" }, { 0x2723, "+" }, { 0x2724, "+" }, { 0x2725, "+" }, { 0x2726, "+" }, { 0x2727, "+" }, { 0x2729, "*" }, { 0x272A, "*" }, { 0x272B, "*" }, { 0x272C, "*" }, { 0x272D, "*" }, { 0x272E, "*" }, { 0x272F, "*" }, { 0x2730, "*" }, { 0x2731, "*" }, { 0x2732, "*" }, { 0x2733, "*" }, { 0x2734, "*" }, { 0x2735, "*" }, { 0x2736, "*" }, { 0x2737, "*" }, { 0x2738, "*" }, { 0x2739, "*" }, { 0x273A, "*" }, { 0x273B, "*" }, { 0x273C, "*" }, { 0x273D, "*" }, { 0x273E, "*" }, { 0x273F, "*" }, { 0x2740, "*" }, { 0x2741, "*" }, { 0x2742, "*" }, { 0x2743, "*" }, { 0x2744, "*" }, { 0x2745, "*" }, { 0x2746, "*" }, { 0x2747, "*" }, { 0x2748, "*" }, { 0x2749, "*" }, { 0x274A, "*" }, { 0x274B, "*" }, { 0xFB00, "ff" }, { 0xFB01, "fi" }, { 0xFB02, "fl" }, { 0xFB03, "ffi" }, { 0xFB04, "ffl" }, { 0xFB05, "st" }, { 0xFB06, "st" }, { 0xFEFF, "" }, { 0xFFFD, "?" }, { 0, "" } /* end of table */ }; void mystrncpy(uchar *dest,uchar *src,long len) { if(len == 0) return; strncpy(dest,src,(size_t)len-1); dest[len-1]=0; } bool mapgetword(uchar *line, ulong *pos, uchar *dest, ulong destlen) { ulong begin; while(isspace(line[*pos]) && line[*pos]!=0) (*pos)++; if(line[*pos] == 0) return(FALSE); begin=*pos; while(line[*pos]!=0 && !isspace(line[*pos])) (*pos)++; if(line[*pos] != 0) { line[*pos]=0; (*pos)++; } mystrncpy(dest,&line[begin],destlen); return(TRUE); } bool readmap(ushort *table,uchar *filename) { uchar line[200],buf1[20],buf2[20]; ulong pos,c,d,linenum; bool res1,res2; FILE *fp; if(!(fp=fopen(filename,"r"))) { fprintf(stderr,"Could not open %s\n",filename); return(FALSE); } /* Make default table */ for(c=0;c<256;c++) table[c]=c; /* Read table */ linenum=0; while(fgets(line,200,fp)) { linenum++; if(strchr(line,'#')) *strchr(line,'#')=0; /* Remove comments */ if(line[0] == '\x1a') line[0]=0; /* DOS EOF */ pos=0; res1=mapgetword(line,&pos,buf1,20); res2=mapgetword(line,&pos,buf2,20); if(res1) { if(strnicmp(buf1,"0x",2)!=0) { fprintf(stderr,"Syntax error on line %ld in %s",linenum,filename); return(FALSE); } sscanf(&buf1[2],"%lx",&c); if(res2) { if(strnicmp(buf2,"0x",2)!=0) { fprintf(stderr,"Syntax error on line %ld in %s",linenum,filename); return(FALSE); } sscanf(&buf2[2],"%lx",&d); } else { d=0; } if(c > 0xff || d > 0xffff) { fprintf(stderr,"Character out of range on line %ld in %s",linenum,filename); return(FALSE); } if(d == 0 && c != 0) table[c]='?'; else table[c]=d; } } fclose(fp); return(TRUE); } void printbyte(unsigned char b) { if(b == 0) { printf("\\0"); } else if(b > 127 || !isgraph(b) || b == '\\' || b ==';') { printf("\\x%02X",b); } else { printf("%c",b); } } int main(int argc, char **argv) { ushort fromtable[256],desttable[256]; int c,d,firstdiff; bool createutf; ushort uc; if(argc != 4 && argc!=5) { fprintf(stderr,"Usage: makechs []\n"); exit(0); } if(argc == 4) createutf=TRUE; else createutf=FALSE; if(!(readmap(fromtable,argv[3]))) exit(0); if(!createutf) { if(!(readmap(desttable,argv[4]))) exit(0); } if(createutf) { firstdiff=0; } else { for(c=0;c<256;c++) { if(fromtable[c] != desttable[c]) { firstdiff=c; break; } } } printf(";\n"); printf("; Generated by makechs 1.0 by Johan Billing. Some tweaking may be required.\n"); printf(";\n"); if(createutf || firstdiff < 128) printf("100000 ; ID number (when >65535, all 255 chars will be translated)\n"); else printf("0 ; ID number (when >65535, all 255 chars will be translated)\n"); printf("0 ; version number\n"); printf(";\n"); printf("2 ; level number\n"); printf(";\n"); printf("%s\n",argv[1]); printf("%s\n",argv[2]); printf(";\n"); for(c=0;c<256;c++) { if(createutf) { uc=fromtable[c]; if(uc < 0x80) { printbyte(0); printf("\t"); printbyte(uc); printf("\n"); } else if(uc < 0x800) { printbyte(0xC0 | (uc >> 6)); printf("\t"); printbyte(0x80 | (uc & 0x3F)); printf("\n"); } else { printbyte(0xE0 | (uc >> 12)); printf("\t"); printbyte(0x80 | ((uc >> 6) & 0x3F)); printf("\t"); printbyte(0x80 | (uc & 0x3F)); printf("\n"); } } else if(c>127 || firstdiff<128) { uc=fromtable[c]; if(uc < 128) { printbyte(0); printf("\t"); printbyte(uc); printf("\n"); } else { for(d=0;d<256;d++) if(desttable[d] == uc) break; if(d != 256) { /* found */ printbyte(0); printf("\t"); printbyte(d); printf("\n"); } else { /* use fallback */ for(d=0;transtab[d].u;d++) if(transtab[d].u == uc) break; if(transtab[d].u) { fprintf(stderr,"Warning: Unicode %04x not found in target charset, using fallback \"%s\"\n",uc,transtab[d].str); if(strlen(transtab[d].str) == 1) { printbyte(0); printf("\t"); printbyte(transtab[d].str[0]); printf("\n"); } else { if(strlen(transtab[d].str) > 0) { printbyte(transtab[d].str[0]); } if(strlen(transtab[d].str) > 1) { printf("\t"); printbyte(transtab[d].str[1]); } if(strlen(transtab[d].str) > 2) { printf("\t"); printbyte(transtab[d].str[2]); } if(strlen(transtab[d].str) > 3) { printf("\t"); printbyte(transtab[d].str[3]); } if(strlen(transtab[d].str) > 4) { fprintf(stderr,"Warning: fallback %s too long\n",transtab[d].str); } printf("\n"); } } else { fprintf(stderr,"Warning: Unicode %04x not found in target charset, no fallback found\n",uc); printbyte(0); printf("\t"); printbyte('?'); printf("\n"); } } } } } printf("END\n"); exit(0); } jamnntpd-1.2/src/mime.c000066400000000000000000000237271141642135500150660ustar00rootroot00000000000000#include "nntpserv.h" /******************************* MIME decoding *****************************/ void decodeb64(uchar *in,uchar *out) { uchar *found,*b64="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; int c,d,count; ulong num; c=0; d=0; num=0; count=0; while(in[c]) { if((found=strchr(b64,in[c]))) { num <<= 6; num += found-b64; count++; } if(count == 4 || in[c] == '=') { if(count == 3) num <<= 6; if(count == 2) num <<= 12; if(count >= 2) out[d++] = (num >> 16) & 0xff; if(count >= 3) out[d++] = (num >> 8) & 0xff; if(count == 4) out[d++] = num & 0xff; count=0; num=0; } c++; } out[d]=0; } void decodeqpbody(uchar *in,uchar *out) { int c,d; uchar *f1,*f2; uchar *hex="0123456789ABCDEF"; /* Strip trailing whitespace */ c=0; d=0; while(in[c]) { if(in[c] == 13) while(d > 0 && (out[d-1] == 32 || out[d-1] == 9)) d--; out[d++]=in[c++]; } /* Decode */ c=0; d=0; while(out[c]) { if(out[c] == '=' && out[c+1] == 13) { c+=2; if(out[c] == 10) c++; } else if(out[c] == '=' && out[c+1] && out[c+2]) { f1=strchr(hex,out[c+1]); f2=strchr(hex,out[c+2]); if(!f1 || !f2) out[d++] = '?'; else out[d++]=(f1-hex)*16+(f2-hex); c+=3; } else { out[d++] = out[c++]; } } out[d]=0; } void decodeqpheader(uchar *in,uchar *out) { int c,d; uchar *f1,*f2; uchar *hex="0123456789ABCDEF"; c=0; d=0; while(in[c]) { if(in[c] == '=' && in[c+1] && in[c+2]) { f1=strchr(hex,in[c+1]); f2=strchr(hex,in[c+2]); if(!f1 || !f2) out[d++] = '?'; else out[d++]=(f1-hex)*16+(f2-hex); c+=3; } else if(in[c] == '_') { out[d++] = ' '; c++; } else { out[d++] = in[c++]; } } out[d]=0; } void setcharset(uchar *newchrs,uchar *chrs,uchar *chrs2,ulong chrslen) { if(newchrs[0] != 0 && stricmp(chrs,newchrs) != 0) { /* We have a charset that doesn't match the previously found charset */ if(chrs[0] == 0) { /* There was no previously found charset */ mystrncpy(chrs,newchrs,chrslen); } else if(stricmp(chrs,"us-ascii") == 0) { /* Old charset was us-ascii. We assume that all other charsets are compatible with us-ascii. The charset found here will now be the charset for the message */ mystrncpy(chrs,newchrs,chrslen); } else if(stricmp(newchrs,"us-ascii") != 0) { /* If the new charset isn't us-ascii, we have more than one charset in the message */ mystrncpy(chrs2,newchrs,chrslen); } } } void unmime(uchar *text,uchar *chrs,uchar *chrs2,ulong chrslen) { int c,d,begin,end; uchar *encoding; c=0; d=0; while(text[c]) { if(text[c]=='=' && text[c+1]=='?') { /* Get charset */ begin=c+2; end=begin; while(text[end] != '?' && text[end] != 0) end++; if(text[end] == 0) { text[d]=0; return; /* Ended prematurely */ } text[end]=0; setcharset(&text[begin],chrs,chrs2,chrslen); /* Get encoding method */ begin=end+1; end=begin; while(text[end] != '?' && text[end] != 0) end++; if(text[end] == 0) { text[d]=0; return; /* Ended prematurely */ } text[end]=0; encoding=&text[begin]; /* Get encoded data */ begin=end+1; end=begin; while(text[end] != '?' && text[end] != 0) end++; if(text[end] == 0) { text[d]=0; return; /* Ended prematurely */ } text[end]=0; /* Decode */ if(stricmp(encoding,"q") == 0) { decodeqpheader(&text[begin],&text[d]); d=strlen(text); } else if(stricmp(encoding,"b") == 0) { decodeb64(&text[begin],&text[d]); d=strlen(text); } else { strcpy(&text[d],&text[begin]); d=strlen(text); } if(text[end+1] == '=') c=end+2; else c=end+1; /* Check if new encoded word follows directly */ end=c; while(text[end] != 0 && (text[end] == 32 || text[end] == 9)) end++; if(text[end] == '=' && text[end+1] == '?') c=end; } else { while(text[c] != 0 && text[c] != 32 && text[c] != 9) text[d++]=text[c++]; if(text[c] != 0) text[d++]=text[c++]; } } text[d]=0; } /********************************* MIME encoding *******************************/ /* Returns number of encoded characters */ int encodeqp(uchar *data,uchar *dest,uchar *specials,int maxdestlen) { int c,d; uchar buf[10]; c=0; d=0; while(data[c]) { if(data[c] > 127 || strchr(specials,data[c])) { if(d + 3 > maxdestlen) return(c); sprintf(buf,"%02X",data[c]); dest[d++]='='; dest[d++]=buf[0]; dest[d++]=buf[1]; dest[d]=0; } else { if(d + 1 > maxdestlen) return(c); if(data[c] == ' ') dest[d++]='_'; else dest[d++]=data[c]; dest[d]=0; } c++; } return(c); } /* Returns number of encoded characters */ int encodeb64(uchar *data,uchar *dest,uchar *specials,int maxdestlen) { int c,d; ulong num; uchar *b64="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; c=0; d=0; while(data[c]) { if(d + 4 > maxdestlen) return(c); if(data[c] && data[c+1] && data[c+2]) { num=(data[c] << 16) + (data[c+1] << 8) + data[c+2]; dest[d] = b64[(num >> 18) & 63]; dest[d+1] = b64[(num >> 12) & 63]; dest[d+2] = b64[(num >> 6) & 63]; dest[d+3] = b64[num & 63]; dest[d+4] = 0; c+=3; d+=4; } else if(data[c] && data[c+1]) { num=(data[c] << 16) + (data[c+1] << 8); dest[d] = b64[(num >> 18) & 63]; dest[d+1] = b64[(num >> 12) & 63]; dest[d+2] = b64[(num >> 6) & 63]; dest[d+3] = '='; dest[d+4] = 0; c+=2; d+=4; } else { num=(data[c] << 16); dest[d] = b64[(num >> 18) & 63]; dest[d+1] = b64[(num >> 12) & 63]; dest[d+2] = '='; dest[d+3] = '='; dest[d+4] = 0; c+=1; d+=4; } } return(c); } void mimemakeheaderline(uchar *dest,ulong destlen,uchar *keyword,uchar *data,uchar *chrs,uchar *fromaddr,bool noencode) { uchar *specials,*mimespecials="_=?\t",*fromspecials="_=?\t" "()<>@,;:\\\".[]"; bool mime; ulong c,d,num8bit; uchar prefix[50],line[350],quoted[200],method; dest[0]=0; num8bit=count8bit(data); if(num8bit) mime=TRUE; else mime=FALSE; if(num8bit > 5 && num8bit > strlen(data)/2) method='b'; else method='q'; if(!mime || noencode) { if(fromaddr) { for(c=0;data[c];c++) if(strchr(fromspecials,data[c])) break; if(data[c]) { /* Needs quoting */ d=0; quoted[d++]='"'; for(c=0;data[c];c++) { if(data[c] == '"' || data[c] == '\\' || data[c] == 13) quoted[d++]='\\'; quoted[d++]=data[c]; } quoted[d++]='"'; quoted[d]=0; } else { strcpy(quoted,data); } sprintf(line,"%s: %s <%s>" CRLF,keyword,quoted,fromaddr); } else { sprintf(line,"%s: %s" CRLF,keyword,data); } if(strlen(line) < destlen) strcpy(dest,line); return; } if(fromaddr) specials=fromspecials; else specials=mimespecials; sprintf(prefix,"=?%s?%c?",chrs,method); c=0; sprintf(line,"%s: %s",keyword,prefix); d=strlen(line); while(data[c]) { if(method == 'b') c+=encodeb64(&data[c],&line[d],specials,76-d-2); if(method == 'q') c+=encodeqp(&data[c],&line[d],specials,76-d-2); if(data[c]) { /* Start new line */ strcat(line,"?=" CRLF); if(strlen(dest) + strlen(line) < destlen) strcat(dest,line); else return; sprintf(line," %s",prefix); d=strlen(line); } } strcat(line,"?="); if(fromaddr) { if(strlen(line) + strlen(fromaddr) + 3 > 76) { strcat(line,CRLF); if(strlen(dest) + strlen(line) < destlen) strcat(dest,line); else return; strcpy(line," "); d=strlen(line); } else { strcat(line," "); } strcat(line,"<"); strcat(line,fromaddr); strcat(line,">"); } strcat(line,CRLF); if(strlen(dest) + strlen(line) < destlen) strcat(dest,line); } void mimesendheaderline(struct var *var,uchar *keyword,uchar *data,uchar *chrs,uchar *fromaddr,bool noencode) { uchar destbuf[1000]; ulong c,lastline; uchar bak; /* Make buffer */ mimemakeheaderline(destbuf,1000,keyword,data,chrs,fromaddr,noencode); /* Send buffer line by line */ c=0; lastline=0; while(destbuf[c]) { if(destbuf[c] == 13 && destbuf[c+1] == 10) { bak=destbuf[c+2]; destbuf[c+2]=0; socksendtext(var,&destbuf[lastline]); destbuf[c+2]=bak; lastline=c+2; c+=2; } else { c++; } } } jamnntpd-1.2/src/mime.h000066400000000000000000000007551141642135500150670ustar00rootroot00000000000000void unmime(uchar *text,uchar *chrs,uchar *chrs2,ulong chrslen); void setcharset(uchar *newchrs,uchar *chrs,uchar *chrs2,ulong chrslen); void decodeqpheader(uchar *in,uchar *out); void decodeqpbody(uchar *in,uchar *out); void decodeb64(uchar *in,uchar *out); void mimesendheaderline(struct var *var,uchar *keyword,uchar *data,uchar *chrs,uchar *fromaddr,bool noencode); void mimemakeheaderline(uchar *dest,ulong destlen,uchar *keyword,uchar *data,uchar *chrs,uchar *fromaddr,bool noencode); jamnntpd-1.2/src/misc.c000066400000000000000000000072161141642135500150650ustar00rootroot00000000000000#include "nntpserv.h" void mystrncpy(uchar *dest,uchar *src,long len) { if(len == 0) return; strncpy(dest,src,(size_t)len-1); dest[len-1]=0; } void strip(uchar *str) { int c; for(c=strlen(str)-1;str[c] < 33 && c>=0;c--) str[c]=0; } void makedate(time_t t,uchar *dest,uchar *tz) { time_t t1,t2; struct tm *tp; ulong jam_utcoffset; uchar rfctz[6]; uchar *monthnames[]={"Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"}; uchar *daynames[]={"Sun","Mon","Tue","Wed","Thu","Fri","Sat"}; /* Some timezone tricks */ t1=time(NULL); tp=gmtime(&t1); tp->tm_isdst=-1; t2=mktime(tp); jam_utcoffset=t2-t1; t1=t+jam_utcoffset; if(tz[0]) { if(tz[0] == '-') mystrncpy(rfctz,tz,6); else sprintf(rfctz,"+%.4s",tz); } else { strcpy(rfctz, "GMT"); t1=t1+jam_utcoffset; } tp=localtime(&t1); sprintf(dest,"%s, %d %s %d %02d:%02d:%02d %s", daynames[tp->tm_wday], tp->tm_mday, monthnames[tp->tm_mon], 1900+tp->tm_year, tp->tm_hour, tp->tm_min, tp->tm_sec, rfctz); } bool setboolonoff(uchar *opt,bool *var) { if(stricmp(opt,"on")==0) { *var=TRUE; return(TRUE); } if(stricmp(opt,"off")==0) { *var=FALSE; return(TRUE); } return(FALSE); } bool getcfgword(uchar *line, ulong *pos, uchar *dest, ulong destlen) { bool quote; ulong begin; quote=FALSE; while(isspace(line[*pos]) && line[*pos]!=0) (*pos)++; if(line[*pos] == 0) return(FALSE); if(line[*pos] == '"') { quote=TRUE; (*pos)++; } begin=*pos; while(line[*pos]!=0 && !(isspace(line[*pos]) && !quote) && !(line[*pos] == '"' && quote)) (*pos)++; if(line[*pos] != 0) { line[*pos]=0; (*pos)++; } mystrncpy(dest,&line[begin],destlen); return(TRUE); } bool getcomma(uchar *line, ulong *pos, uchar *dest, ulong destlen) { ulong c,d; c=*pos; d=0; for(;;) { if(line[c] == 0 || line[c] == ',') { if(line[c] != 0) c++; *pos=c; dest[d]=0; if(dest[0]) return(TRUE); else return(FALSE); } else { if(d < destlen-1) dest[d++]=line[c]; } c++; } } bool matchname(uchar *namelist,uchar *name) { uchar namepat[100]; ulong count; count=0; while(getcomma(namelist,&count,namepat,100)) if(matchpattern(namepat,name)) return(TRUE); return(FALSE); } bool matchgroup(uchar *groups,uchar group) { int c; if(strcmp(groups,"*") == 0) return(TRUE); if(strcmp(groups,"-") == 0) return(FALSE); for(c=0;groups[c];c++) if(tolower(groups[c]) == tolower(group)) return(TRUE); return(FALSE); } bool matchpattern(uchar *pat,uchar *str) { int c; for(c=0;pat[c];c++) { if(pat[c]=='*') return(TRUE); if(pat[c]!='?') { if(tolower(str[c]) != tolower(pat[c])) return(FALSE); } } if(str[c]) return(FALSE); return(TRUE); } bool ispattern(uchar *pat) { if(strchr(pat,'*')) return(TRUE); else return(FALSE); } void stripctrl(uchar *str) { int c,d; c=0; d=0; while(str[c]) { if(str[c] >= 32) str[d++]=str[c]; c++; } str[d]=0; } ulong count8bit(uchar *text) { ulong c,res; res=0; for(c=0;text[c];c++) if(text[c] & 0x80) res++; return(res); } void freelist(void *first) { void *ptr,*next; ptr=first; while(ptr) { next=*(void **)ptr; free(ptr); ptr=next; } } jamnntpd-1.2/src/misc.h000066400000000000000000000010401141642135500150570ustar00rootroot00000000000000void mystrncpy(uchar *dest,uchar *src,long len); void strip(uchar *str); void makedate(time_t t,uchar *dest,uchar *tz); bool setboolonoff(uchar *opt,bool *var); bool getcfgword(uchar *line, ulong *pos, uchar *dest, ulong destlen); bool matchgroup(uchar *groups,uchar group); bool matchpattern(uchar *pat,uchar *ip); void stripctrl(uchar *str); ulong count8bit(uchar *text); void freelist(void *first); bool ispattern(uchar *pat); bool getcomma(uchar *line, ulong *pos, uchar *dest, ulong destlen); bool matchname(uchar *namelist,uchar *name); jamnntpd-1.2/src/nntpserv.c000066400000000000000000002327471141642135500160220ustar00rootroot00000000000000#include "nntpserv.h" ulong cfg_port = CFG_PORT; ulong cfg_maxconn = CFG_MAXCONN; uchar *cfg_origin; uchar *cfg_guestsuffix; uchar *cfg_echomailjam; uchar *cfg_allowfile = CFG_ALLOWFILE; uchar *cfg_groupsfile = CFG_GROUPSFILE; uchar *cfg_logfile = CFG_LOGFILE; uchar *cfg_usersfile = CFG_USERSFILE; uchar *cfg_xlatfile = CFG_XLATFILE; bool cfg_def_flowed = CFG_DEF_FLOWED; bool cfg_def_showto = CFG_DEF_SHOWTO; bool cfg_debug; bool cfg_noecholog; bool cfg_nostripre; bool cfg_noreplyaddr; bool cfg_notearline; bool cfg_smartquote; bool cfg_noencode; bool cfg_notzutc; bool cfg_nocancel; bool cfg_strictnetmail; bool cfg_readorigin; int server_openconnections; int server_quit; ulong lastmsgidnum; int get_server_openconnections(void) { int res; os_getexclusive(); res=server_openconnections; os_stopexclusive(); return(res); } int get_server_quit(void) { int res; os_getexclusive(); res=server_quit; os_stopexclusive(); return(res); } ulong get_msgid_num(void) { ulong msgidnum; os_getexclusive(); msgidnum=(time(NULL)/10)*10; if(msgidnum <= lastmsgidnum) msgidnum = lastmsgidnum+1; lastmsgidnum=msgidnum; os_stopexclusive(); return(msgidnum); } uchar *parseinput(struct var *var) { long s; /* Skip whitespace */ while(var->input[var->inputpos]==' ') var->inputpos++; s=var->inputpos; if(var->input[var->inputpos] == 0) return(NULL); while(var->input[var->inputpos]!=' ' && var->input[var->inputpos]!=0) var->inputpos++; if(var->input[var->inputpos] == ' ') var->input[var->inputpos++]=0; return(&var->input[s]); } bool jamopenarea(struct var *var,struct group *group) { if(group == var->opengroup) return(TRUE); if(var->openmb) { JAM_CloseMB(var->openmb); free(var->openmb); var->openmb=NULL; var->opengroup=NULL; } if(JAM_OpenMB(group->jampath,&var->openmb)) { if(var->openmb) free(var->openmb); var->openmb=NULL; var->opengroup=NULL; os_logwrite("(%s) Failed to open JAM messagebase \"%s\"",var->clientid,group->jampath); return(FALSE); } var->opengroup=group; return(TRUE); } bool jamgetminmaxnum(struct var *var,struct group *group,ulong *min,ulong *max,ulong *num) { s_JamBaseHeader baseheader; if(!(jamopenarea(var,group))) return(FALSE); if(JAM_GetMBSize(var->openmb,num)) { os_logwrite("(%s) Failed to get size of JAM area \"%s\"",var->clientid,group->jampath); return(FALSE); } if(*num == 0) { *min=0; *max=0; return(TRUE); } if(JAM_ReadMBHeader(var->openmb,&baseheader)) { os_logwrite("(%s) Failed to read header of JAM area \"%s\"",var->clientid,group->jampath); return(FALSE); } *min=baseheader.BaseMsgNum; *max=baseheader.BaseMsgNum+*num-1; if(group->netmail && cfg_strictnetmail) { uchar fromname[100],toname[100],chrs[20],codepage[20],buf[100],*xlatres; struct xlat *xlat; ulong netmin,netmax,netnum,count,c; int res; s_JamSubPacket* subpack; s_JamMsgHeader header; s_JamSubfield* field; netmin=0; netmax=0; netnum=0; for(c=*min;c<=*max && !var->disconnect && !get_server_quit();c++) { res=JAM_ReadMsgHeader(var->openmb,c-baseheader.BaseMsgNum,&header,&subpack); if(res == 0) { if(!(header.Attribute & MSG_DELETED)) { count=0; fromname[0]=0; toname[0]=0; chrs[0]=0; codepage[0]=0; while((field=JAM_GetSubfield_R(subpack,&count))) { switch(field->LoID) { case JAMSFLD_SENDERNAME: mystrncpy(fromname,field->Buffer,min(field->DatLen+1,100)); break; case JAMSFLD_RECVRNAME: mystrncpy(toname,field->Buffer,min(field->DatLen+1,100)); break; case JAMSFLD_FTSKLUDGE: mystrncpy(buf,field->Buffer,min(field->DatLen+1,100)); if(strnicmp(buf,"CHRS: ",6)==0) { mystrncpy(chrs,&buf[6],20); if(strchr(chrs,' ')) *strchr(chrs,' ')=0; strip(chrs); } if(strnicmp(buf,"CHARSET: ",9)==0) mystrncpy(chrs,&buf[9],20); if(strnicmp(buf,"CODEPAGE: ",10)==0) mystrncpy(codepage,&buf[10],20); } } xlat=findreadxlat(var,group,chrs,codepage,NULL); if(xlat && xlat->xlattab) { if((xlatres=xlatstr(fromname,xlat->xlattab))) { mystrncpy(fromname,xlatres,100); free(xlatres); } if((xlatres=xlatstr(toname,xlat->xlattab))) { mystrncpy(toname,xlatres,100); free(xlatres); } } if(matchname(var->realnames,fromname) || matchname(var->realnames,toname)) { if(netmin == 0) netmin=c; netmax=c; netnum++; } } JAM_DelSubPacket(subpack); } } *min=netmin; *max=netmax; *num=netnum; } return(TRUE); } void readoriginaddr(s_JamBase *mb,ulong offset,ulong len,uchar *addr) { ulong d,textpos; uchar originbuf[100]; uchar *text; if(!(text=malloc(len+1))) return; if(JAM_ReadMsgText(mb,offset,len,text)) return; text[len]=0; textpos=0; originbuf[0]=0; /* Find origin line */ while(text[textpos]) { d=textpos; while(text[d] != 13 && text[d] != 0) d++; if(text[d] == 13) d++; if(d-textpos > 11 && strncmp(&text[textpos]," * Origin: ",11)==0) mystrncpy(originbuf,&text[textpos],min(d-textpos,100)); textpos=d; } if(originbuf[0]) { /* Find address part */ d=strlen(originbuf); while(d>0 && originbuf[d]!='(') d--; if(originbuf[d] == '(') { strcpy(addr,&originbuf[d+1]); if(strchr(addr,')')) *strchr(addr,')')=0; } } free(text); } void command_list(struct var *var) { struct group *g; ulong min,max,num; uchar *arg; bool listnewsgroups; listnewsgroups=FALSE; arg=parseinput(var); if(arg) { if(stricmp(arg,"overview.fmt") == 0) { socksendtext(var,"215 List of fields in XOVER result" CRLF); socksendtext(var,"Subject:" CRLF); socksendtext(var,"From:" CRLF); socksendtext(var,"Date:" CRLF); socksendtext(var,"Message-ID:" CRLF); socksendtext(var,"References:" CRLF); socksendtext(var,"Bytes:" CRLF), socksendtext(var,"Lines:" CRLF); socksendtext(var,"." CRLF); return; } else if(stricmp(arg,"newsgroups") == 0) { if(parseinput(var)) { socksendtext(var,"501 Patterns not supported for LIST NEWSGROUPS" CRLF); return; } listnewsgroups=TRUE; } else if(stricmp(arg,"active") != 0) { socksendtext(var,"501 Unknown argument for LIST command" CRLF); return; } } socksendtext(var,"215 List of newsgroups follows" CRLF); for(g=var->firstgroup;g && !var->disconnect && !get_server_quit();g=g->next) { if(matchgroup(var->readgroups,g->group)) { if(listnewsgroups) { sockprintf(var,"%s\t" CRLF,g->tagname); } else { if(!jamgetminmaxnum(var,g,&min,&max,&num)) { min=0; max=0; num=0; } if(matchgroup(var->postgroups,g->group)) sockprintf(var,"%s %lu %lu y" CRLF,g->tagname,min,max); else sockprintf(var,"%s %lu %lu n" CRLF,g->tagname,min,max); } } } socksendtext(var,"." CRLF); } void command_group(struct var *var) { uchar *groupname; struct group *g; ulong min,max,num; if(!(groupname=parseinput(var))) { socksendtext(var,"501 No group specified" CRLF); return; } for(g=var->firstgroup;g;g=g->next) if(matchgroup(var->readgroups,g->group) && stricmp(g->tagname,groupname)==0) break; if(!g) { socksendtext(var,"411 No such newsgroup" CRLF); return; } if(!jamgetminmaxnum(var,g,&min,&max,&num)) { socksendtext(var,"503 Local error: Could not get size of messagebase" CRLF); return; } var->currentgroup=g; var->currentarticle=min; sockprintf(var,"211 %lu %lu %lu %s Group selected" CRLF,num,min,max,g->tagname); } void command_next(struct var *var) { ulong min,max,num; if(!var->currentgroup) { socksendtext(var,"412 No newsgroup selected" CRLF); return; } if(!var->currentarticle) { socksendtext(var,"420 No current article has been selected" CRLF); return; } if(!jamgetminmaxnum(var,var->currentgroup,&min,&max,&num)) { socksendtext(var,"503 Local error: Could not get size of messagebase" CRLF); return; } if(var->currentarticle+1 > max) { socksendtext(var,"421 No next article in this group" CRLF); return; } var->currentarticle++; sockprintf(var,"223 %lu <%lu$%s@JamNNTPd> Article retrieved" CRLF, var->currentarticle,var->currentarticle,var->currentgroup->tagname); } void command_last(struct var *var) { ulong min,max,num; if(!var->currentgroup) { socksendtext(var,"412 No newsgroup selected" CRLF); return; } if(!var->currentarticle) { socksendtext(var,"420 No current article has been selected" CRLF); return; } if(!jamgetminmaxnum(var,var->currentgroup,&min,&max,&num)) { socksendtext(var,"503 Local error: Could not get size of messagebase" CRLF); return; } if(var->currentarticle-1 < min) { socksendtext(var,"422 No previous article in this group" CRLF); return; } var->currentarticle--; sockprintf(var,"223 %lu <%lu$%s@JamNNTPd> Article retrieved" CRLF, var->currentarticle,var->currentarticle,var->currentgroup->tagname); } struct attributename { ulong attr; uchar *name; }; struct attributename attributenames[] = { { MSG_LOCAL, "Local" }, { MSG_INTRANSIT, "InTransit" }, { MSG_PRIVATE, "Private" }, { MSG_READ, "Read" }, { MSG_SENT, "Sent" }, { MSG_KILLSENT, "KillSent" }, { MSG_ARCHIVESENT, "ArchiveSent" }, { MSG_HOLD, "Hold" }, { MSG_CRASH, "Crash" }, { MSG_IMMEDIATE, "Immediate" }, { MSG_DIRECT, "Direct" }, { MSG_GATE, "Gate" }, { MSG_FILEREQUEST, "FReq" }, { MSG_FILEATTACH, "FAttach" }, { MSG_TRUNCFILE, "TruncFile" }, { MSG_KILLFILE, "KillFile" }, { MSG_RECEIPTREQ, "ReceiptReq" }, { MSG_CONFIRMREQ, "ConfirmReq" }, { MSG_ORPHAN, "Orphan" }, { MSG_ENCRYPT, "Encrypted" }, { MSG_COMPRESS, "Compressed" }, { MSG_ESCAPED, "Escaped" }, { MSG_FPU, "ForcePickup" }, { MSG_TYPELOCAL, "TypeLocal" }, { MSG_TYPEECHO, "TypeEcho" }, { MSG_TYPENET, "TypeNet" }, { MSG_NODISP, "NoDisp" }, { MSG_LOCKED, "Locked" }, { MSG_DELETED, "Deleted" }, { 0, NULL } }; #define WRAP_WIDTH 72 #define LINE_WIDTH 79 #define MAX_WIDTH 997 void copyline(uchar *dest,uchar *src,long len) { int d,c; d=0; for(c=0;cdisconnect && !get_server_quit()) { lastspace=0; c=0; wrapped=FALSE; /* Find last space before WRAP_WIDTH */ while(c<=WRAP_WIDTH && text[textpos+c]!=0 && text[textpos+c]!=13) { if(text[textpos+c]==32) lastspace=c; c++; } /* It might not be necessary to wrap after all if we find EOL before LINE_WIDTH */ if(text[textpos+c]!=13 && text[textpos+c]!=0) { d=c+1; while(text[textpos+d]!=0 && text[textpos+d]!=13 && dopt_flowed && strcmp(buf,"-- ")!=0) { if(wrapped) strcat(buf," "); /* For format=flowed */ else strip(buf); if(buf[0] == ' ' || strncmp(buf,"From ",5)==0) { strcpy(buf2,buf); strcpy(buf," "); strcat(buf,buf2); } } /* End format=flowed */ if(stricmp(buf,".")==0) /* "." means end of message in NNTP */ strcpy(buf,".."); strcat(buf,CRLF); if(xlat && xlat->xlattab) { if((xlatres=xlatstr(buf,xlat->xlattab))) { socksendtext(var,xlatres); free(xlatres); } } else { socksendtext(var,buf); } } } void stripreplyaddr(uchar *str) { /* to take care of "full name" formar */ uchar *ch; if((ch=strchr(str,'<'))) { strcpy(str,ch+1); if((ch=strchr(str,'>'))) *ch=0; } } void command_abhs(struct var *var,uchar *cmd) { uchar *article; ulong articlenum; struct group *group; ulong min,max,num,c,d; uchar datebuf[50]; uchar jamfromaddr[100],jamtoaddr[100],replyaddr[100],fromaddr[100]; uchar fromname[100],toname[100],subject[100]; uchar chrs[20],codepage[20],encoding[20],format[20],timezone[20]; uchar buf[250]; uchar *at,*pc; uchar *text; struct xlat *xlat; uchar *xlatres; s_JamBaseHeader baseheader; s_JamSubPacket* subpack; s_JamMsgHeader header; s_JamSubfield* field; int res; ulong count; article=parseinput(var); if(!article) { if(!var->currentgroup) { socksendtext(var,"412 No newsgroup selected" CRLF); return; } if(!var->currentarticle) { socksendtext(var,"420 No current article has been selected" CRLF); return; } articlenum=var->currentarticle; group=var->currentgroup; } else if(article[0] == '<' && article[strlen(article)-1] == '>') { strcpy(article,&article[1]); article[strlen(article)-1]=0; at=strchr(article,'@'); pc=strchr(article,'$'); if(!at || !pc) { socksendtext(var,"430 No such article found" CRLF); return; } *at=0; *pc=0; at++; pc++; if(strcmp(at,"JamNNTPd") != 0) { socksendtext(var,"430 No such article found" CRLF); return; } for(group=var->firstgroup;group;group=group->next) if(matchgroup(var->readgroups,group->group) && stricmp(pc,group->tagname) == 0) break; if(!group) { socksendtext(var,"430 No such article found" CRLF); return; } articlenum=atol(article); jamgetminmaxnum(var,group,&min,&max,&num); if(articlenum < min || articlenum > max) { socksendtext(var,"430 No such article found" CRLF); return; } } else if(atol(article) > 0) { if(!var->currentgroup) { socksendtext(var,"412 No newsgroup selected" CRLF); return; } articlenum=atol(article); group=var->currentgroup; if(!jamgetminmaxnum(var,var->currentgroup,&min,&max,&num)) { socksendtext(var,"503 Local error: Could not get size of messagebase" CRLF); return; } jamgetminmaxnum(var,group,&min,&max,&num); if(articlenum < min || articlenum > max) { socksendtext(var,"423 No such article number in this group" CRLF); return; } var->currentarticle = articlenum; } else { socksendtext(var,"501 Invalid article number specified" CRLF); return; } if(stricmp(cmd,"STAT") == 0) { sockprintf(var,"223 %lu <%lu$%s@JamNNTPd> Article retrieved" CRLF, articlenum,articlenum,group->tagname); return; } if(!jamopenarea(var,group)) { socksendtext(var,"503 Local error: Could not open messagebase" CRLF); return; } if(JAM_ReadMBHeader(var->openmb,&baseheader)) { os_logwrite("(%s) Could not read messagebase header of \"%s\"",var->clientid,var->opengroup->jampath); socksendtext(var,"503 Local error: Could not read messagebase header" CRLF); return; } res=JAM_ReadMsgHeader(var->openmb,articlenum-baseheader.BaseMsgNum,&header,&subpack); if(res != 0 && res != JAM_NO_MESSAGE) { os_logwrite("(%s) Could not read message %lu in \"%s\"",var->clientid,articlenum,var->opengroup->jampath); socksendtext(var,"503 Local error: Could not read message header" CRLF); JAM_DelSubPacket(subpack); return; } if(res == JAM_NO_MESSAGE || (header.Attribute & MSG_DELETED)) { socksendtext(var,"503 Message has been deleted" CRLF); JAM_DelSubPacket(subpack); return; } if(!(text=malloc(header.TxtLen+1))) { socksendtext(var,"503 Local error: Out of memory" CRLF); JAM_DelSubPacket(subpack); return; } if(header.TxtLen) { res=JAM_ReadMsgText(var->openmb,header.TxtOffset,header.TxtLen,text); if(res) { socksendtext(var,"503 Local error: Could not read message text" CRLF); JAM_DelSubPacket(subpack); free(text); return; } } text[header.TxtLen]=0; fromname[0]=0; jamfromaddr[0]=0; toname[0]=0; jamtoaddr[0]=0; subject[0]=0; replyaddr[0]=0; timezone[0]=0; chrs[0]=0; codepage[0]=0; count=0; while((field=JAM_GetSubfield_R(subpack,&count))) { switch(field->LoID) { case JAMSFLD_SENDERNAME: mystrncpy(fromname,field->Buffer,min(field->DatLen+1,100)); break; case JAMSFLD_RECVRNAME: mystrncpy(toname,field->Buffer,min(field->DatLen+1,100)); break; case JAMSFLD_OADDRESS: mystrncpy(jamfromaddr,field->Buffer,min(field->DatLen+1,100)); break; case JAMSFLD_DADDRESS: mystrncpy(jamtoaddr,field->Buffer,min(field->DatLen+1,100)); break; case JAMSFLD_SUBJECT: mystrncpy(subject,field->Buffer,min(field->DatLen+1,100)); break; case JAMSFLD_TZUTCINFO: mystrncpy(timezone,field->Buffer,min(field->DatLen+1,20)); break; case JAMSFLD_FTSKLUDGE: mystrncpy(buf,field->Buffer,min(field->DatLen+1,100)); if(strnicmp(buf,"REPLYADDR ",10)==0) mystrncpy(replyaddr,&buf[10],100); if(strnicmp(buf,"REPLYADDR: ",11)==0) mystrncpy(replyaddr,&buf[11],100); if(strnicmp(buf,"TZUTC: ",7)==0) mystrncpy(timezone,&buf[7],20); if(strnicmp(buf,"TZUTCINFO: ",11)==0) mystrncpy(timezone,&buf[11],20); if(strnicmp(buf,"CHRS: ",6)==0) { mystrncpy(chrs,&buf[6],20); if(strchr(chrs,' ')) *strchr(chrs,' ')=0; strip(chrs); } if(strnicmp(buf,"CHARSET: ",9)==0) { mystrncpy(chrs,&buf[9],20); strip(chrs); } if(strnicmp(buf,"CODEPAGE: ",10)==0) { mystrncpy(codepage,&buf[10],20); strip(codepage); } break; } } if(cfg_readorigin && !group->netmail && !group->local) readoriginaddr(var->openmb,header.TxtOffset,header.TxtLen,jamfromaddr); stripreplyaddr(replyaddr); xlat=findreadxlat(var,group,chrs,codepage,NULL); if(xlat) strcpy(chrs,xlat->tochrs); else strcpy(chrs,"unknown-8bit"); if(xlat && xlat->xlattab) { if((xlatres=xlatstr(fromname,xlat->xlattab))) { mystrncpy(fromname,xlatres,100); free(xlatres); } if((xlatres=xlatstr(toname,xlat->xlattab))) { mystrncpy(toname,xlatres,100); free(xlatres); } if((xlatres=xlatstr(subject,xlat->xlattab))) { mystrncpy(subject,xlatres,100); free(xlatres); } } if(group->netmail) { if(!matchname(var->realnames,fromname) && !matchname(var->realnames,toname)) { socksendtext(var,"503 Access denied" CRLF); JAM_DelSubPacket(subpack); free(text); return; } } if(stricmp(cmd,"ARTICLE")==0) sockprintf(var,"220 %ld <%ld$%s@JamNNTPd> Article retrieved - Head and body follow" CRLF,articlenum,articlenum,group->tagname); if(stricmp(cmd,"HEAD")==0) sockprintf(var,"221 %ld <%ld$%s@JamNNTPd> Article retrieved - Head follows" CRLF,articlenum,articlenum,group->tagname); if(stricmp(cmd,"BODY")==0) sockprintf(var,"222 %ld <%ld$%s@JamNNTPd> Article retrieved - Body follows" CRLF,articlenum,articlenum,group->tagname); if(stricmp(cmd,"ARTICLE") == 0 || stricmp(cmd,"HEAD") == 0) { if(replyaddr[0]) strcpy(fromaddr,replyaddr); else strcpy(fromaddr,jamfromaddr); if(fromaddr[0] == 0) strcpy(fromaddr,"unknown"); if(fromname[0] == 0) strcpy(fromname,"unknown"); if(toname[0] == 0) strcpy(toname,"(none)"); makedate(header.DateWritten,datebuf,timezone); sockprintf(var,"Path: JamNNTPd!not-for-mail" CRLF); if(var->opt_showto) sprintf(buf,"%s -> %s",fromname,toname); else strcpy(buf,fromname); { unsigned zone,net,node,point; if(sscanf(fromaddr,"%u:%u/%u.%u", &zone, &net, &node, &point)==4) sprintf(fromaddr,"%u@%u.%u.%u", point, node, net, zone); else if(sscanf(fromaddr,"%u:%u/%u", &zone, &net, &node)==3) sprintf(fromaddr,"0@%u.%u.%u", node, net, zone); } mimesendheaderline(var,"From",buf,chrs,fromaddr,cfg_noencode); mimesendheaderline(var,"X-Comment-To",toname,chrs,NULL,cfg_noencode); sockprintf(var,"Newsgroups: %s" CRLF,group->tagname); mimesendheaderline(var,"Subject",subject,chrs,NULL,cfg_noencode); sockprintf(var,"Date: %s" CRLF,datebuf); sockprintf(var,"Message-ID: <%ld$%s@JamNNTPd>" CRLF,articlenum,group->tagname); if(header.ReplyTo) sockprintf(var,"References: <%ld$%s@JamNNTPd>" CRLF,header.ReplyTo,group->tagname); if(jamfromaddr[0]) sockprintf(var,"X-JAM-From: %s <%s>" CRLF,fromname,jamfromaddr); else sockprintf(var,"X-JAM-From: %s" CRLF,fromname); if(toname[0] || jamtoaddr[0]) { if(jamtoaddr[0]) sockprintf(var,"X-JAM-To: %s <%s>" CRLF,toname,jamtoaddr); else sockprintf(var,"X-JAM-To: %s" CRLF,toname); } count=0; while((field=JAM_GetSubfield_R(subpack,&count))) { switch(field->LoID) { case JAMSFLD_MSGID: mystrncpy(buf,field->Buffer,min(field->DatLen+1,200)); sockprintf(var,"X-JAM-MSGID: %s" CRLF,buf); break; case JAMSFLD_REPLYID: mystrncpy(buf,field->Buffer,min(field->DatLen+1,200)); sockprintf(var,"X-JAM-REPLYID: %s" CRLF,buf); break; case JAMSFLD_PID: mystrncpy(buf,field->Buffer,min(field->DatLen+1,200)); sockprintf(var,"X-JAM-PID: %s" CRLF,buf); break; case JAMSFLD_FLAGS: mystrncpy(buf,field->Buffer,min(field->DatLen+1,200)); sockprintf(var,"X-JAM-FLAGS: %s" CRLF,buf); break; case JAMSFLD_TRACE: mystrncpy(buf,field->Buffer,min(field->DatLen+1,200)); sockprintf(var,"X-JAM-TRACE: %s" CRLF,buf); break; case JAMSFLD_TZUTCINFO: mystrncpy(buf,field->Buffer,min(field->DatLen+1,200)); sockprintf(var,"X-JAM-TZUTCINFO: %s" CRLF,buf); break; case JAMSFLD_SEENBY2D: mystrncpy(buf,field->Buffer,min(field->DatLen+1,200)); sockprintf(var,"X-JAM-SEENBY2D: %s" CRLF,buf); break; case JAMSFLD_PATH2D: mystrncpy(buf,field->Buffer,min(field->DatLen+1,200)); sockprintf(var,"X-JAM-PATH2D: %s" CRLF,buf); break; case JAMSFLD_FTSKLUDGE: mystrncpy(buf,field->Buffer,min(field->DatLen+1,200)); sockprintf(var,"X-JAM-FTSKLUDGE: %s" CRLF,buf); break; } } if(header.Attribute) { int c; strcpy(buf,"X-JAM-Attributes:"); for(c=0;attributenames[c].name;c++) if(header.Attribute & attributenames[c].attr) { strcat(buf," "); strcat(buf,attributenames[c].name); } strcat(buf,CRLF); socksendtext(var,buf); } /* MIME headers */ socksendtext(var,"MIME-Version: 1.0" CRLF); if(count8bit(text)) { strcpy(encoding,"8bit"); } else { strcpy(encoding,"7bit"); strcpy(chrs,"us-ascii"); } if(var->opt_flowed) strcpy(format,"flowed"); else strcpy(format,"fixed"); sockprintf(var,"Content-Type: text/plain; charset=%s; format=%s" CRLF,chrs,format); sockprintf(var,"Content-Transfer-Encoding: %s" CRLF,encoding); } if(stricmp(cmd,"ARTICLE") == 0) socksendtext(var,CRLF); if(stricmp(cmd,"ARTICLE") == 0 || stricmp(cmd,"BODY") == 0) { if(header.TxtLen) { if(!(xlat && xlat->keepsoftcr)) { d=0; for(c=0;text[c];c++) if(text[c] != 0x8d) text[d++]=text[c]; text[d]=0; } sendtextblock(var,text,xlat); } } socksendtext(var,"." CRLF); JAM_DelSubPacket(subpack); free(text); } void command_xover(struct var *var) { uchar *article,*dash; ulong min,max,num; ulong first,last,c; uchar msgid[150],reply[150],buf[250],chrs[20],codepage[20],datebuf[50],timezone[20]; uchar fromname[100],toname[100],fromaddr[100],subject[100],replyaddr[100]; uchar mimefrom[1000],mimesubj[1000],xoverres[2500]; struct xlat *xlat; uchar *xlatres; s_JamBaseHeader baseheader; s_JamSubPacket* subpack; s_JamMsgHeader header; s_JamSubfield* field; int res; ulong count; bool access; if(!var->currentgroup) { socksendtext(var,"412 No newsgroup selected" CRLF); return; } jamgetminmaxnum(var,var->currentgroup,&min,&max,&num); article=parseinput(var); if(!article) { if(!var->currentarticle) { socksendtext(var,"420 No current article has been selected" CRLF); return; } first=var->currentarticle; last=var->currentarticle; } else { dash=strchr(article,'-'); if(dash) { *dash=0; dash++; first=atol(article); if(dash[0] == 0) last=max; else last=atol(dash); } else { first=atol(article); last=atol(article); } } if(first < min) first=min; if(last > max) last=max; if(first > last || num == 0) { socksendtext(var,"420 No articles found in this range" CRLF); return; } if(!jamopenarea(var,var->currentgroup)) { socksendtext(var,"503 Local error: Could not open messagebase" CRLF); return; } if(JAM_ReadMBHeader(var->openmb,&baseheader)) { os_logwrite("(%s) Could not read messagebase header of \"%s\"",var->clientid,var->opengroup->jampath); socksendtext(var,"503 Local error: Could not read messagebase header" CRLF); return; } socksendtext(var,"224 Overview information follows" CRLF); for(c=first;c<=last && !var->disconnect && !get_server_quit();c++) { res=JAM_ReadMsgHeader(var->openmb,c-baseheader.BaseMsgNum,&header,&subpack); if(res == 0) { if(!(header.Attribute & MSG_DELETED)) { count=0; fromname[0]=0; fromaddr[0]=0; subject[0]=0; toname[0]=0; chrs[0]=0; codepage[0]=0; replyaddr[0]=0; timezone[0]=0; while((field=JAM_GetSubfield_R(subpack,&count))) { switch(field->LoID) { case JAMSFLD_OADDRESS: mystrncpy(fromaddr,field->Buffer,min(field->DatLen+1,100)); break; case JAMSFLD_SENDERNAME: mystrncpy(fromname,field->Buffer,min(field->DatLen+1,100)); break; case JAMSFLD_RECVRNAME: mystrncpy(toname,field->Buffer,min(field->DatLen+1,100)); break; case JAMSFLD_SUBJECT: mystrncpy(subject,field->Buffer,min(field->DatLen+1,100)); break; case JAMSFLD_TZUTCINFO: mystrncpy(timezone,field->Buffer,min(field->DatLen+1,20)); break; case JAMSFLD_FTSKLUDGE: mystrncpy(buf,field->Buffer,min(field->DatLen+1,100)); if(strnicmp(buf,"CHRS: ",6)==0) { mystrncpy(chrs,&buf[6],20); if(strchr(chrs,' ')) *strchr(chrs,' ')=0; strip(chrs); } if(strnicmp(buf,"CHARSET: ",9)==0) mystrncpy(chrs,&buf[9],20); if(strnicmp(buf,"CODEPAGE: ",10)==0) mystrncpy(codepage,&buf[10],20); if(strnicmp(buf,"REPLYADDR ",10)==0) mystrncpy(replyaddr,&buf[10],100); if(strnicmp(buf,"REPLYADDR: ",11)==0) mystrncpy(replyaddr,&buf[11],100); if(strnicmp(buf,"TZUTC: ",7)==0) mystrncpy(timezone,&buf[7],20); if(strnicmp(buf,"TZUTCINFO: ",11)==0) mystrncpy(timezone,&buf[11],20); } } if(cfg_readorigin && !var->currentgroup->netmail && !var->currentgroup->local) readoriginaddr(var->openmb,header.TxtOffset,header.TxtLen,fromaddr); stripreplyaddr(replyaddr); xlat=findreadxlat(var,var->currentgroup,chrs,codepage,NULL); if(xlat) strcpy(chrs,xlat->tochrs); else strcpy(chrs,"unknown-8bit"); if(xlat && xlat->xlattab) { if((xlatres=xlatstr(fromname,xlat->xlattab))) { mystrncpy(fromname,xlatres,100); free(xlatres); } if((xlatres=xlatstr(toname,xlat->xlattab))) { mystrncpy(toname,xlatres,100); free(xlatres); } if((xlatres=xlatstr(subject,xlat->xlattab))) { mystrncpy(subject,xlatres,100); free(xlatres); } } access=TRUE; if(var->currentgroup->netmail) { if(!matchname(var->realnames,fromname) && !matchname(var->realnames,toname)) access=FALSE; } if(access) { if(fromaddr[0] == 0) strcpy(fromaddr,"unknown"); if(fromname[0] == 0) strcpy(fromname,"unknown"); if(toname[0] == 0) strcpy(toname,"(none)"); makedate(header.DateWritten,datebuf,timezone); sprintf(msgid,"<%ld$%s@JamNNTPd>",c,var->currentgroup->tagname); reply[0]=0; if(header.ReplyTo) sprintf(reply,"<%ld$%s@JamNNTPd>",header.ReplyTo,var->currentgroup->tagname); if(var->opt_showto) { sprintf(buf,"%s -> %s",fromname,toname); mystrncpy(fromname,buf,100); } { unsigned zone,net,node,point; if(sscanf(fromaddr,"%u:%u/%u.%u", &zone, &net, &node, &point)==4) sprintf(fromaddr,"%u@%u.%u.%u", point, node, net, zone); else if(sscanf(fromaddr,"%u:%u/%u", &zone, &net, &node)==3) sprintf(fromaddr,"0@%u.%u.%u", node, net, zone); } if(replyaddr[0]) mimemakeheaderline(mimefrom,1000,"From",fromname,chrs,replyaddr,cfg_noencode); else mimemakeheaderline(mimefrom,1000,"From",fromname,chrs,fromaddr,cfg_noencode); mimemakeheaderline(mimesubj,1000,"Subject",subject,chrs,NULL,cfg_noencode); strcpy(mimefrom,&mimefrom[6]); strcpy(mimesubj,&mimesubj[9]); stripctrl(mimesubj); stripctrl(mimefrom); sprintf(xoverres,"%ld\t%s\t%s\t%s\t%s\t%s\t\t" CRLF, c,mimesubj,mimefrom,datebuf,msgid,reply); socksendtext(var,xoverres); } } JAM_DelSubPacket(subpack); } } socksendtext(var,"." CRLF); } #define POST_MAXSIZE 20000 bool getcontenttypepart(uchar *line,ulong *pos,uchar *dest,ulong destlen) { bool quote; ulong c,d; quote=FALSE; c=*pos; d=0; /* Skip initial whitespace */ while(isspace(line[c])) c++; /* Check if there is anything to copy */ if(line[c] == 0) { *pos=c; return(FALSE); } /* Copy until ; or 0. Ignore unquoted whitespace */ for(;;) { if(line[c] == '"') { if(quote) quote=FALSE; else quote=TRUE; } else if(line[c] == 0 || (line[c] == ';' && !quote)) { if(line[c] != 0) c++; *pos=c; dest[d]=0; return(TRUE); } else if(quote || !isspace(line[c])) { if(d < destlen-1) dest[d++]=line[c]; } c++; } } void unmimecpy(uchar *dest,uchar *src,ulong destlen,uchar *chrs,uchar *chrs2,ulong chrslen) { unmime(src,chrs,chrs2,chrslen); mystrncpy(dest,src,destlen); } void unbackslashquote(uchar *text) { int c,d; d=0; for(c=0;text[c];c++) { if(text[c] == '\\' && text[c+1] != 0) c++; text[d++]=text[c]; } text[d]=0; } void addjamfield(s_JamSubPacket *SubPacket_PS,ulong fieldnum,uchar *fielddata) { s_JamSubfield Subfield_S; Subfield_S.LoID = fieldnum; Subfield_S.HiID = 0; Subfield_S.DatLen = strlen(fielddata); Subfield_S.Buffer = fielddata; JAM_PutSubfield( SubPacket_PS, &Subfield_S); } void getparentinfo(struct var *var,uchar *article,uchar *currentgroup,uchar *msgid,uchar *fromname,uchar *fromaddr,ulong *msgnum,struct xlat *postxlat,bool readorigin) { uchar *at,*pc; struct group *group; ulong articlenum; s_JamBaseHeader baseheader; s_JamSubPacket* subpack; s_JamMsgHeader header; s_JamSubfield* field; int res; ulong count; uchar buf[100],jam_fromname[100],jam_fromaddr[100],jam_toname[100],jam_msgid[100],jam_chrs[20],jam_codepage[20]; struct xlat *xlat; uchar *xlatres; msgid[0]=0; fromname[0]=0; fromaddr[0]=0; *msgnum=0; /* Parse messageid */ if(article[0] != '<' || article[strlen(article)-1] != '>') return; strcpy(article,&article[1]); article[strlen(article)-1]=0; at=strchr(article,'@'); pc=strchr(article,'$'); if(!at || !pc) return; *at=0; *pc=0; at++; pc++; if(strcmp(at,"JamNNTPd") != 0) return; /* Find group */ for(group=var->firstgroup;group;group=group->next) if(matchgroup(var->readgroups,group->group) && stricmp(pc,group->tagname) == 0) break; if(!group) return; articlenum=atol(article); /* Only set parent message number if in the same group */ if(stricmp(pc,currentgroup) == 0) *msgnum=articlenum; /* Read parent message */ if(!jamopenarea(var,group)) return; if(JAM_ReadMBHeader(var->openmb,&baseheader)) { os_logwrite("(%s) Could not read messagebase header of \"%s\"",var->clientid,var->opengroup->jampath); return; } res=JAM_ReadMsgHeader(var->openmb,articlenum-baseheader.BaseMsgNum,&header,&subpack); if(res != 0 && res != JAM_NO_MESSAGE) { os_logwrite("(%s) Could not read message %lu in \"%s\"",var->clientid,articlenum,var->opengroup->jampath); JAM_DelSubPacket(subpack); return; } if(res == JAM_NO_MESSAGE) { JAM_DelSubPacket(subpack); return; } count=0; jam_fromname[0]=0; jam_toname[0]=0; jam_msgid[0]=0; jam_chrs[0]=0; jam_codepage[0]=0; jam_fromaddr[0]=0; while((field=JAM_GetSubfield_R(subpack,&count))) { if(field->LoID == JAMSFLD_MSGID) mystrncpy(jam_msgid,field->Buffer,min(field->DatLen+1,100)); if(field->LoID == JAMSFLD_SENDERNAME) mystrncpy(jam_fromname,field->Buffer,min(field->DatLen+1,100)); if(field->LoID == JAMSFLD_OADDRESS) mystrncpy(jam_fromaddr,field->Buffer,min(field->DatLen+1,100)); if(field->LoID == JAMSFLD_RECVRNAME) mystrncpy(jam_toname,field->Buffer,min(field->DatLen+1,100)); if(field->LoID == JAMSFLD_FTSKLUDGE) { mystrncpy(buf,field->Buffer,min(field->DatLen+1,100)); if(strnicmp(buf,"CHRS: ",6)==0) { mystrncpy(jam_chrs,&buf[6],20); if(strchr(jam_chrs,' ')) *strchr(jam_chrs,' ')=0; strip(jam_chrs); } if(strnicmp(buf,"CHARSET: ",9)==0) mystrncpy(jam_chrs,&buf[9],20); if(strnicmp(buf,"CODEPAGE: ",10)==0) mystrncpy(jam_codepage,&buf[10],20); } } xlat=findreadxlat(var,group,jam_chrs,jam_codepage,postxlat->fromchrs); if(xlat && xlat->xlattab) { if((xlatres=xlatstr(jam_fromname,xlat->xlattab))) { mystrncpy(jam_fromname,xlatres,100); free(xlatres); } if((xlatres=xlatstr(jam_toname,xlat->xlattab))) { mystrncpy(jam_toname,xlatres,100); free(xlatres); } } if(group->netmail) { if(!matchname(var->realnames,jam_fromname) && !matchname(var->realnames,jam_toname)) { JAM_DelSubPacket(subpack); return; } } if(readorigin && !group->netmail && !group->local && header.TxtLen) readoriginaddr(var->openmb,header.TxtOffset,header.TxtLen,jam_fromaddr); if(xlat && postxlat->xlattab) { if((xlatres=xlatstr(jam_fromname,postxlat->xlattab))) { mystrncpy(jam_fromname,xlatres,100); free(xlatres); } } strcpy(fromname,jam_fromname); strcpy(fromaddr,jam_fromaddr); strcpy(msgid,jam_msgid); JAM_DelSubPacket(subpack); return; } void cancelmessage(struct var *var,uchar *article,struct xlat *postxlat) { uchar *at,*pc; struct group *group; ulong num,count; int res; s_JamBaseHeader baseheader; s_JamSubPacket* subpack; s_JamMsgHeader header; s_JamSubfield* field; struct xlat *xlat; uchar *xlatres; uchar buf[100],fromname[100],chrs[20],codepage[20]; if(article[0] != '<' || article[strlen(article)-1] != '>') { socksendtext(var,"441 POST failed (Article to cancel not found)" CRLF); return; } strcpy(article,&article[1]); article[strlen(article)-1]=0; at=strchr(article,'@'); pc=strchr(article,'$'); if(!at || !pc) { socksendtext(var,"441 POST failed (Article to cancel not found)" CRLF); return; } *at=0; *pc=0; at++; pc++; if(strcmp(at,"JamNNTPd") != 0) { socksendtext(var,"441 POST failed (Article to cancel not found)" CRLF); return; } for(group=var->firstgroup;group;group=group->next) if(matchgroup(var->readgroups,group->group) && stricmp(pc,group->tagname) == 0) break; if(strcmp(at,"JamNNTPd") != 0) { socksendtext(var,"441 POST failed (Article to cancel not found)" CRLF); return; } num=atol(article); if(!jamopenarea(var,group)) { socksendtext(var,"441 POST failed (Article to cancel not found)" CRLF); return; } if(JAM_ReadMBHeader(var->openmb,&baseheader)) { os_logwrite("(%s) Could not read messagebase header of \"%s\"",var->clientid,group->jampath); socksendtext(var,"441 POST failed (Could not read message to cancel)" CRLF); return; } res=JAM_ReadMsgHeader(var->openmb,num-baseheader.BaseMsgNum,&header,&subpack); if(res != 0 && res != JAM_NO_MESSAGE) { os_logwrite("(%s) Could not read message %lu in \"%s\"",var->clientid,num,var->opengroup->jampath); socksendtext(var,"441 POST failed (Could not read message to cancel)" CRLF); JAM_DelSubPacket(subpack); return; } if(res == JAM_NO_MESSAGE) { socksendtext(var,"441 POST failed (Article to cancel not found)" CRLF); JAM_DelSubPacket(subpack); return; } fromname[0]=0; chrs[0]=0; codepage[0]=0; count=0; while((field=JAM_GetSubfield_R(subpack,&count))) { if(field->LoID == JAMSFLD_SENDERNAME) mystrncpy(fromname,field->Buffer,min(field->DatLen+1,100)); if(field->LoID == JAMSFLD_FTSKLUDGE) { mystrncpy(buf,field->Buffer,min(field->DatLen+1,100)); if(strnicmp(buf,"CHRS: ",6)==0) { mystrncpy(chrs,&buf[6],20); if(strchr(chrs,' ')) *strchr(chrs,' ')=0; strip(chrs); } if(strnicmp(buf,"CHARSET: ",9)==0) mystrncpy(chrs,&buf[9],20); if(strnicmp(buf,"CODEPAGE: ",10)==0) mystrncpy(codepage,&buf[10],20); } } xlat=findreadxlat(var,group,chrs,codepage,postxlat->fromchrs); if(xlat && xlat->xlattab) { if((xlatres=xlatstr(fromname,xlat->xlattab))) { mystrncpy(fromname,xlatres,100); free(xlatres); } } if(!matchname(var->realnames,fromname)) { socksendtext(var,"441 POST failed (Cannot cancel, message not from you)" CRLF); JAM_DelSubPacket(subpack); return; } if(!(header.Attribute & MSG_LOCAL)) { socksendtext(var,"441 POST failed (Cannot cancel, message not local)" CRLF); JAM_DelSubPacket(subpack); return; } if(header.Attribute & MSG_SENT) { socksendtext(var,"441 POST failed (Cannot cancel, message already sent)" CRLF); JAM_DelSubPacket(subpack); return; } if(header.Attribute & MSG_LOCKED) { socksendtext(var,"441 POST failed (Cannot cancel, message is locked)" CRLF); JAM_DelSubPacket(subpack); return; } if(JAM_LockMB(var->openmb,10)) { os_logwrite("(%s) Failed to lock JAM messagebase \"%s\"",var->clientid,group->jampath); socksendtext(var,"441 Local error: Failed to lock messagebase" CRLF); JAM_DelSubPacket(subpack); return; } header.Attribute |= MSG_DELETED; res=JAM_ChangeMsgHeader(var->openmb,num-baseheader.BaseMsgNum,&header); JAM_UnlockMB(var->openmb); if(res != 0) { os_logwrite("(%s) Could not delete message %lu in \"%s\"",var->clientid,num,var->opengroup->jampath); socksendtext(var,"441 Local error: Failed to delete message" CRLF); JAM_DelSubPacket(subpack); return; } socksendtext(var,"240 Article cancelled" CRLF); JAM_DelSubPacket(subpack); return; } /* line should have some extra room. line may grow by one or two characters */ void tidyquote(char *line) { int lastquote,numquotes,c; char *input,*initials; if(!(input=strdup(line))) return; strip(input); numquotes=0; lastquote=0; for(c=0;input[c]!=0;c++) { if(input[c] == '>') { lastquote=c; numquotes++; } else if(input[c] == '<') { break; } else if(input[c] != ' ' && input[c+1] == ' ') { break; } } if(numquotes) { initials=""; /* Find end of initials */ c=lastquote; while(c > 0 && input[c] == '>') c--; if(input[c] != '>') { /* Initials found */ input[c+1]=0; while(c > 0 && input[c] != ' ' && input[c] != '>') c--; if(input[c] == ' ' || input[c] == '>') initials=&input[c+1]; else initials=&input[c]; } /* Recreate line */ if(input[lastquote+1] == 0) { strcpy(line,"\x0d"); } else { strcpy(line," "); strcat(line,initials); for(c=0;c"); strcat(line," "); if(input[lastquote+1] == ' ') strcat(line,&input[lastquote+2]); else strcat(line,&input[lastquote+1]); strcat(line,"\x0d"); } } free(input); } uchar *smartquote(uchar *oldtext,ulong maxlen,uchar *fromname) { uchar *newtext,line[300],mark[100]; int c,d,linebegins; if(!(newtext=malloc(maxlen))) return(NULL); d=0; for(c=0;fromname[c];c++) if(c==0 || (c!=0 && fromname[c-1]==32)) mark[d++]=fromname[c]; mark[d]=0; c=0; d=0; while(oldtext[c]) { linebegins=c; while(oldtext[c] != 13 && oldtext[c] != 0) c++; if(oldtext[c] == 13) c++; if(oldtext[linebegins] == '>' && c-linebegins < 200) { strcpy(line,mark); strcat(line,">"); if(oldtext[linebegins+1] == '>') strcat(line," "); strncat(line,&oldtext[linebegins+1],c-linebegins-1); tidyquote(line); if(strlen(line)+d+1 > maxlen) { /* We ran out of room */ free(newtext); return(NULL); } strcpy(&newtext[d],line); d+=strlen(line); } else { if(c-linebegins+d+1 > maxlen) { /* We ran out of room */ free(newtext); return(NULL); } strncpy(&newtext[d],&oldtext[linebegins],c-linebegins); d+=c-linebegins; } } newtext[d]=0; return(newtext); } void setreply(struct var *var,ulong parentmsg,ulong newmsg) { s_JamBaseHeader baseheader; s_JamMsgHeader header; int res; ulong nextreply,msg; if(JAM_ReadMBHeader(var->openmb,&baseheader)) { os_logwrite("(%s) Could not read messagebase header of \"%s\"",var->clientid,var->opengroup->jampath); return; } /* Get parent message */ res=JAM_ReadMsgHeader(var->openmb,parentmsg-baseheader.BaseMsgNum,&header,NULL); if(res != 0) return; if(header.Reply1st == 0) { /* This is the first reply. Set Reply1st and update header */ header.Reply1st=newmsg; JAM_ChangeMsgHeader(var->openmb,parentmsg-baseheader.BaseMsgNum,&header); return; } /* There were other replies. Find the last. */ nextreply=header.Reply1st; msg=0; while(nextreply) { res=JAM_ReadMsgHeader(var->openmb,nextreply-baseheader.BaseMsgNum,&header,NULL); if(res != 0) return; msg=nextreply; nextreply=header.ReplyNext; } /* Found last reply. Set ReplyNext and update header */ header.ReplyNext=newmsg; JAM_ChangeMsgHeader(var->openmb,msg-baseheader.BaseMsgNum,&header); } bool validateaddr(uchar *str) { unsigned int zone,net,node,point; char ch; /* Remove domain if present */ if(strchr(str,'@')) *strchr(str,'@')=0; if(sscanf(str,"%u:%u/%u.%u%c",&zone,&net,&node,&point,&ch) != 4) { point=0; if(sscanf(str,"%u:%u/%u%c",&zone,&net,&node,&ch) != 3) return(FALSE); } if(point) sprintf(str,"%u:%u/%u.%u",zone,net,node,point); else sprintf(str,"%u:%u/%u",zone,net,node); return(TRUE); } void command_post(struct var *var) { uchar *text,*newtext,*xlatres,line[1000],buf[100],*ch; ulong allocsize,textlen,textpos,getctpos,c,d,parentmsg,count; bool finished,toobig; uchar from[100],fromaddr[100],toname[100],subject[100],organization[100],newsgroup[100]; uchar contenttype[100],contenttransferencoding[100],reference[100],newsreader[100]; uchar msgid[100],replyid[100],replyto[100],chrs[20],chrs2[20],codepage[20],timezone[13]; uchar control[100],dispname[100],toaddr[100],quotename[100]; struct group *g; struct xlat *xlat; s_JamSubPacket* SubPacket_PS; s_JamMsgHeader Header_S; time_t t1,t2; struct tm *tp; int res,timeofs,timesign,tr; bool flowed; FILE *fp; allocsize=POST_MAXSIZE+500; /* Some extra room for tearline and origin */ if(!(text=malloc(allocsize))) { socksendtext(var,"503 Out of memory" CRLF); return; } socksendtext(var,"340 Send article to be posted. End with ." CRLF); finished=FALSE; toobig=FALSE; textpos=0; while(!finished && !var->disconnect && !get_server_quit() && sockreadline(var,line,1000)) { if(line[0] && cfg_debug) printf("(%s) < %s",var->clientid,line); if(stricmp(line,"." CRLF) == 0) { finished=TRUE; } else { if(textpos + strlen(line) > POST_MAXSIZE-1) { toobig=TRUE; } else { strcpy(&text[textpos],line); textpos+=strlen(line); } } } text[textpos]=0; if(get_server_quit()) { free(text); return; } if(toobig) { sockprintf(var,"441 Posting failed (message too long, maximum size %ld bytes" CRLF,POST_MAXSIZE); os_logwrite("(%s) POST failed (message too long, maximum size %ld bytes)",var->clientid,POST_MAXSIZE); free(text); return; } from[0]=0; fromaddr[0]=0; newsgroup[0]=0; subject[0]=0; replyto[0]=0; contenttype[0]=0; chrs[0]=0; chrs2[0]=0; contenttransferencoding[0]=0; reference[0]=0; organization[0]=0; newsreader[0]=0; control[0]=0; flowed=FALSE; textpos=0; textlen=strlen(text); finished=FALSE; while(text[textpos] != 0 && !finished) { c=0; for(;;) { if(text[textpos] == 0) { break; } else if(c>0 && text[textpos-1] == 13 && text[textpos] == 10) { if(c>1 && (text[textpos+1] == ' ' || text[textpos+1] == '\t')) { /* Multi-line header */ while(text[textpos+1] == ' ' || text[textpos+1] == '\t') textpos++; line[c-1]=' '; } else { line[c-1]=0; textpos++; break; } } else { if(c<999) line[c++]=text[textpos]; } textpos++; } line[c]=0; strip(line); if(strnicmp(line,"From: ",6)==0) { if(line[strlen(line)-1] == '>' && strchr(line,'<')) { /* From: Mark Horton */ line[strlen(line)-1]=0; unmimecpy(fromaddr,strrchr(line,'<')+1,100,chrs,chrs2,20); strip(fromaddr); *strchr(line,'<')=0; unmimecpy(from,&line[6],100,chrs,chrs2,20); strip(from); } else if(line[strlen(line)-1] == ')' && strchr(line,'(')) { /* From: mark@cbosgd.ATT.COM (Mark Horton) */ line[strlen(line)-1]=0; unbackslashquote(strrchr(line,'(')+1); /* Comments should be un-backslash-quoted */ unmimecpy(from,strrchr(line,'(')+1,100,chrs,chrs2,20); strip(from); *strrchr(line,'(')=0; unmimecpy(fromaddr,&line[6],100,chrs,chrs2,20); strip(fromaddr); } else { unmimecpy(from,&line[6],100,chrs,chrs2,20); unmimecpy(fromaddr,&line[6],100,chrs,chrs2,20); } if(strlen(from) > 0) { /* Remove quotes if any */ if(from[0] == '\"' && from[strlen(from)-1]=='\"') { from[strlen(from)-1]=0; strcpy(from,&from[1]); unbackslashquote(from); /* Text in "" should be un-backslash-quoted */ } } } else if(strnicmp(line,"Newsgroups: ",12)==0) { mystrncpy(newsgroup,&line[12],100); } else if(strnicmp(line,"Subject: ",9)==0) { unmimecpy(subject,&line[9],100,chrs,chrs2,20); } else if(strnicmp(line,"Reply-To: ",10)==0) { unmimecpy(replyto,&line[10],100,chrs,chrs2,20); } else if(strnicmp(line,"Content-Type: ",14)==0) { getctpos=14; if(!getcontenttypepart(line,&getctpos,contenttype,100)) contenttype[0]=0; while(getcontenttypepart(line,&getctpos,buf,100)) { if(strnicmp(buf,"charset=",8)==0) setcharset(&buf[8],chrs,chrs2,20); else if(stricmp(buf,"format=flowed")==0) flowed=TRUE; } } else if(strnicmp(line,"Content-Transfer-Encoding: ",27)==0) { getctpos=27; if(!getcontenttypepart(line,&getctpos,contenttransferencoding,100)) contenttransferencoding[0]=0; } else if(strnicmp(line,"References: ",12)==0) { if(strrchr(line,'<')) mystrncpy(reference,strrchr(line,'<'),100); } else if(strnicmp(line,"Organization: ",14)==0) { unmimecpy(organization,&line[14],100,chrs,chrs2,20); } else if(strnicmp(line,"X-Newsreader: ",14)==0) { unmimecpy(newsreader,&line[14],100,chrs,chrs2,20); } else if(strnicmp(line,"User-Agent: ",12)==0) { unmimecpy(newsreader,&line[12],100,chrs,chrs2,20); } else if(strnicmp(line,"Control: ",9)==0) { mystrncpy(control,&line[9],100); } else if(line[0] == 0) { finished=TRUE; /* End of headers */ } } /* Strip Re: */ if(!cfg_nostripre && (strncmp(subject,"Re: ",4)==0 || strcmp(subject,"Re:")==0)) strcpy(subject,&subject[4]); /* Truncate strings */ from[36]=0; subject[72]=0; organization[70]=0; newsreader[75]=0; /* Check syntax */ if(newsgroup[0] == 0) { sockprintf(var,"441 Posting failed (No valid Newsgroups line found)" CRLF); os_logwrite("(%s) POST failed (No valid Newsgroups line found)",var->clientid); free(text); return; } if(from[0] == 0 || fromaddr[0] == 0) { sockprintf(var,"441 Posting failed (No valid From line found)" CRLF); os_logwrite("(%s) POST failed (No valid From line found)",var->clientid); free(text); return; } if(strchr(newsgroup,',')) { sockprintf(var,"441 Posting failed (Crossposts are not allowed)" CRLF); os_logwrite("(%s) POST failed (Crossposts are not allowed)",var->clientid); free(text); return; } if(contenttype[0] && stricmp(contenttype,"text/plain")!=0) { sockprintf(var,"441 Posting failed (Content-Type \"%s\" not allowed, please use text/plain)" CRLF,contenttype); os_logwrite("(%s) POST failed (Content-Type \"%s\" not allowed)",var->clientid,contenttype); free(text); return; } /* Decode message */ if(stricmp(contenttransferencoding,"quoted-printable")==0) { decodeqpbody(&text[textpos],&text[textpos]); } else if(stricmp(contenttransferencoding,"base64")==0) { decodeb64(&text[textpos],&text[textpos]); } else if(contenttransferencoding[0] && stricmp(contenttransferencoding,"8bit")!=0 && stricmp(contenttransferencoding,"7bit")!=0) { sockprintf(var,"441 Posting failed (unknown Content-Transfer-Encoding \"%s\")" CRLF,contenttransferencoding); os_logwrite("(%s) POST failed (Content-Transfer-Encoding \"%s\" not allowed)",var->clientid,contenttransferencoding); free(text); return; } /* Reformat text */ d=0; while(text[textpos]) { c=0; for(;;) { if(text[textpos] == 0) { break; } else if(text[textpos] == 13 || c==999) { textpos++; break; } else { if(text[textpos]!=10) line[c++]=text[textpos]; textpos++; } } line[c]=0; if(flowed && line[0]!=0 && line[0]!='>' && strncmp(line,"-- ",3)!=0) { if(line[0] == ' ') strcpy(line,&line[1]); if(line[strlen(line)-1] == ' ') { strip(line); strcpy(&text[d],line); d+=strlen(line); text[d++]=' '; } else { strip(line); strcpy(&text[d],line); d+=strlen(line); text[d++]=13; } } else { if(strncmp(line,"-- ",3)!=0) strip(line); strcpy(&text[d],line); d+=strlen(line); text[d++]=13; } } /* Reformat CR:s at the end of the text */ while(d > 0 && text[d-1] == 13) d--; if(d > 0 && d <= POST_MAXSIZE-3) text[d++]=13; text[d]=0; /* Check access rights */ for(g=var->firstgroup;g;g=g->next) if(stricmp(newsgroup,g->tagname)==0) break; if(!g) { sockprintf(var,"441 Posting failed (Unknown newsgroup %s)" CRLF,newsgroup); os_logwrite("(%s) POST failed (Unknown newsgroup %s)",var->clientid,newsgroup); free(text); return; } if(!(matchgroup(var->postgroups,g->group))) { sockprintf(var,"441 Posting failed (Posting access denied to %s)" CRLF,newsgroup); os_logwrite("(%s) POST failed (Posting access denied to %s)",var->clientid,newsgroup); free(text); return; } /* Check charset */ if(chrs2[0]) { sockprintf(var,"441 Posting failed (Message contains multiple charsets, \"%s\" and \"%s\")" CRLF,chrs,chrs2); os_logwrite("(%s) POST failed (Message contains multiple charsets, \"%s\" and \"%s\")",var->clientid,chrs,chrs2); free(text); return; } if(g->defaultchrs[0] == '!' || var->defaultreadchrs[0] == '!') { if(g->defaultchrs[0] == '!') xlat=findpostxlat(var,chrs,&g->defaultchrs[1]); else xlat=findpostxlat(var,chrs,&var->defaultreadchrs[1]); if(!xlat) { sockprintf(var,"441 Posting failed (Unsupported charset \"%s\" for area %s)" CRLF,chrs,g->tagname); os_logwrite("(%s) POST failed (Unsupported charset \"%s\" for area %s)",var->clientid,chrs,g->tagname); free(text); return; } } else { xlat=findpostxlat(var,chrs,NULL); if(!xlat) { sockprintf(var,"441 Posting failed (Unsupported charset \"%s\")" CRLF,chrs); os_logwrite("(%s) POST failed (Unsupported charset \"%s\")",var->clientid,chrs); free(text); return; } } if(strnicmp(control,"cancel ",7)==0) { if(!cfg_nocancel) { cancelmessage(var,&control[7],xlat); free(text); return; } else { sockprintf(var,"441 Posting failed (Cancel messages are not permitted)" CRLF); free(text); return; } } replyid[0]=0; toname[0]=0; toaddr[0]=0; parentmsg=0; quotename[0]=0; sprintf(msgid,"%s %08lx",g->aka,get_msgid_num()); if(reference[0]) { if(g->netmail) getparentinfo(var,reference,g->tagname,replyid,toname,toaddr,&parentmsg,xlat,TRUE); else getparentinfo(var,reference,g->tagname,replyid,toname,toaddr,&parentmsg,xlat,FALSE); strcpy(quotename,toname); toname[36]=0; } else { strcpy(toname,"All"); } /* Parse To: */ if(strnicmp(text,"To:",3)==0) { if(text[3] == ' ') c=4; else c=3; d=0; while(text[c] != 13 && text[c] != 0) { if(d < 99) line[d++]=text[c++]; else c++; } line[d]=0; if(text[c] == 13) c++; if(text[c] == 13) c++; strcpy(text,&text[c]); if((ch=strchr(line,','))) { /* Format: To: name,address */ *ch=0; ch++; while(*ch == ' ') ch++; mystrncpy(toname,line,36); mystrncpy(toaddr,ch,100); strip(toname); strip(toaddr); } else { /* Format: To: name */ mystrncpy(toname,line,36); strip(toname); } if(xlat->xlattab) { if((xlatres=xlatstr(toname,xlat->xlattab))) { mystrncpy(toname,xlatres,36); free(xlatres); } } } else if(g->netmail && !reference[0]) { sockprintf(var,"441 Posting failed (No \"To:\" line found)" CRLF); free(text); return; } /* Validate address */ if(g->netmail) { if(!toaddr[0]) { sockprintf(var,"441 Posting failed (No destination address specified on \"To:\" line)" CRLF); free(text); return; } if(!validateaddr(toaddr)) { sockprintf(var,"441 Posting failed (Invalid address %s)" CRLF,toaddr); free(text); return; } } /* Reformat quotes */ if(reference[0] && cfg_smartquote) { if((newtext=smartquote(text,allocsize,quotename))) { free(text); text=newtext; } } /* Make JAM header */ JAM_ClearMsgHeader(&Header_S); if(!(SubPacket_PS = JAM_NewSubPacket())) { socksendtext(var,"503 Local error: JAM_NewSubPacket() failed" CRLF); free(text); return; } t1=time(NULL); tp=gmtime(&t1); tp->tm_isdst=-1; t2=mktime(tp); timeofs=(t1-t2)/60; timesign=timeofs < 0 ? -1 : 1; sprintf(timezone,"TZUTC: %s%02d%02d", (t1 < t2 ? "-" : ""), (timesign * timeofs) / 60, (timesign * timeofs) % 60); Header_S.DateWritten = time(NULL)-t2+t1; Header_S.DateReceived = time(NULL)-t2+t1; Header_S.DateProcessed = time(NULL)-t2+t1; /* Set MSGID and REPLY */ addjamfield(SubPacket_PS,JAMSFLD_MSGID,msgid); if(replyid[0]) addjamfield(SubPacket_PS,JAMSFLD_REPLYID,replyid); Header_S.MsgIdCRC = JAM_Crc32(msgid,strlen(msgid)); Header_S.ReplyCRC = JAM_Crc32(replyid,strlen(replyid)); Header_S.ReplyTo = parentmsg; /* Add tearline and origin */ if(!g->netmail && !g->local) { if(newsreader[0]==0 || cfg_notearline) strcpy(line,CR "---" CR); else sprintf(line,CR "--- %s" CR,newsreader); if(strlen(text) + strlen(line) < allocsize-1) strcat(text,line); if(cfg_origin) sprintf(line," * Origin: %s (%s)" CR,cfg_origin,g->aka); else sprintf(line," * Origin: %s (%s)" CR,organization,g->aka); if(strlen(text) + strlen(line) < allocsize-1) strcat(text,line); } count=0; if(getcomma(var->realnames,&count,dispname,100)) if(!ispattern(dispname)) mystrncpy(from,dispname,36); if(!var->login && cfg_guestsuffix) { tr=36-strlen(cfg_guestsuffix)-1; if(tr < 0) tr=0; from[tr]=0; strcat(from,cfg_guestsuffix); } /* Do xlat */ if(xlat->xlattab) { if((xlatres=xlatstr(from,xlat->xlattab))) { mystrncpy(from,xlatres,36); free(xlatres); } if((xlatres=xlatstr(subject,xlat->xlattab))) { mystrncpy(subject,xlatres,72); free(xlatres); } if((xlatres=xlatstr(text,xlat->xlattab))) { free(text); text=xlatres; } } addjamfield(SubPacket_PS,JAMSFLD_SENDERNAME,from); addjamfield(SubPacket_PS,JAMSFLD_RECVRNAME,toname); addjamfield(SubPacket_PS,JAMSFLD_SUBJECT,subject); if(!g->local) addjamfield(SubPacket_PS,JAMSFLD_OADDRESS,g->aka); if(g->netmail) addjamfield(SubPacket_PS,JAMSFLD_DADDRESS,toaddr); if(!cfg_noreplyaddr) { if(replyto[0]) sprintf(line,"REPLYADDR %s",replyto); else sprintf(line,"REPLYADDR %s",fromaddr); addjamfield(SubPacket_PS,JAMSFLD_FTSKLUDGE,line); } strcpy(line,SERVER_NAME " " SERVER_PIDVERSION); addjamfield(SubPacket_PS,JAMSFLD_PID,line); if(xlat->tochrs[0] && !g->nochrs) { setchrscodepage(chrs,codepage,xlat->tochrs); if(chrs[0]) { sprintf(line,"CHRS: %s 2",chrs); addjamfield(SubPacket_PS,JAMSFLD_FTSKLUDGE,line); } if(codepage[0]) { sprintf(line,"CODEPAGE: %s",codepage); addjamfield(SubPacket_PS,JAMSFLD_FTSKLUDGE,line); } } if(!cfg_notzutc) addjamfield(SubPacket_PS,JAMSFLD_FTSKLUDGE,timezone); if(g->netmail) Header_S.Attribute = MSG_LOCAL | MSG_PRIVATE | MSG_TYPENET; else if(g->local) Header_S.Attribute = MSG_LOCAL | MSG_TYPELOCAL; else Header_S.Attribute = MSG_LOCAL | MSG_TYPEECHO; /* Write message */ if(!jamopenarea(var,g)) { socksendtext(var,"503 Local error: Could not open messagebase" CRLF); free(text); JAM_DelSubPacket(SubPacket_PS); return; } if(JAM_LockMB(var->openmb,10)) { os_logwrite("(%s) Failed to lock JAM messagebase \"%s\"",var->clientid,g->jampath); socksendtext(var,"503 Local error: Failed to lock messagebase" CRLF); free(text); JAM_DelSubPacket(SubPacket_PS); return; } res=JAM_AddMessage(var->openmb,&Header_S,SubPacket_PS,text,strlen(text)); if(res) { socksendtext(var,"503 Local error: Failed to write to messagebase" CRLF); os_logwrite("(%s) Failed to write message to JAM messagebase \"%s\"",var->clientid,g->jampath); } else { socksendtext(var,"240 Article posted" CRLF); os_logwrite("(%s) Posted message to %s (#%lu)",var->clientid,newsgroup,Header_S.MsgNum); } JAM_DelSubPacket(SubPacket_PS); if(parentmsg) setreply(var,parentmsg,Header_S.MsgNum); JAM_UnlockMB(var->openmb); if(cfg_echomailjam) { if(!(fp=fopen(cfg_echomailjam,"a"))) { os_logwrite("(%s) Failed to open %s",var->clientid,cfg_echomailjam); } else { fprintf(fp,"%s %ld\n",g->jampath,Header_S.MsgNum); fclose(fp); } } free(text); } void command_authinfo(struct var *var) { uchar *tmp,*opt,*next,*equal; bool flowed,showto; if(!(tmp=parseinput(var))) { socksendtext(var,"501 Only AUTHINFO USER or AUTHINFO pass are understood" CRLF); return; } if(stricmp(tmp,"user")!=0 && stricmp(tmp,"pass")!=0) { socksendtext(var,"501 Only AUTHINFO USER or AUTHINFO pass are understood" CRLF); return; } if(stricmp(tmp,"user")==0) { if(!(tmp=parseinput(var))) { socksendtext(var,"482 No user specified for AUTHINFO USER" CRLF); return; } mystrncpy(var->loginname,tmp,100); socksendtext(var,"381 Received login name, now send password" CRLF); return; } /* AUTHINFO PASS */ if(var->loginname[0] == 0) { socksendtext(var,"482 Use AUTHINFO USER before AUTHINFO pass" CRLF); return; } if(!(tmp=parseinput(var))) { socksendtext(var,"482 No password specified for AUTHINFO PASS" CRLF); return; } mystrncpy(var->password,tmp,100); /* Parse loginname */ opt=NULL; flowed=var->opt_flowed; showto=var->opt_showto; if(strchr(var->loginname,'/')) { opt=strchr(var->loginname,'/'); *opt=0; opt++; } while(opt) { next=strchr(opt,','); if(next) { *next=0; next++; } equal=strchr(opt,'='); if(!equal) { sockprintf(var,"482 Invalid option format %s, use option=on/off" CRLF,opt); return; } *equal=0; equal++; if(stricmp(opt,"flowed")==0) { if(!(setboolonoff(equal,&flowed))) { sockprintf(var,"482 Unknown setting %s for option %s, use on or off" CRLF,equal,opt); return; } } else if(stricmp(opt,"showto")==0) { if(!(setboolonoff(equal,&showto))) { sockprintf(var,"482 Unknown setting %s for option %s, use on or off" CRLF,equal,opt); return; } } else { sockprintf(var,"482 Unknown option %s, known options: flowed, showto" CRLF,opt); return; } opt=next; } if(var->loginname[0]) { if(!(login(var,var->loginname,var->password))) { socksendtext(var,"481 Authentication rejected" CRLF); return; } socksendtext(var,"281 Authentication accepted" CRLF); } else { socksendtext(var,"281 Authentication accepted (options set, no login)" CRLF); } var->opt_flowed=flowed; var->opt_showto=showto; return; } void server(SOCKET s) { uchar line[1000],lookup[200],*cmd; struct var var; struct hostent *hostent; struct sockaddr_in fromsa; int fromsa_len = sizeof(struct sockaddr_in); os_getexclusive(); server_openconnections++; os_stopexclusive(); var.disconnect=0; var.currentgroup=NULL; var.currentarticle=0; var.openmb=NULL; var.opengroup=NULL; var.firstgroup=NULL; var.firstreadxlat=NULL; var.firstpostxlat=NULL; var.firstreadalias=NULL; var.firstpostalias=NULL; var.firstxlattab=NULL; var.readgroups[0]=0; var.postgroups[0]=0; var.loginname[0]=0; var.password[0]=0; var.realnames[0]=0; var.opt_flowed=cfg_def_flowed; var.opt_showto=cfg_def_showto; if(getpeername(s,(struct sockaddr *)&fromsa,&fromsa_len) == SOCKET_ERROR) { os_showerror("getpeername() failed"); shutdown(s,2); close(s); os_getexclusive(); server_openconnections--; os_stopexclusive(); return; } if(!(var.sio=allocsockio(s))) { os_showerror("allocsockio() failed"); shutdown(s,2); close(s); os_getexclusive(); server_openconnections--; os_stopexclusive(); return; } sprintf(var.clientid,"%s:%u",inet_ntoa(fromsa.sin_addr),ntohs(fromsa.sin_port)); mystrncpy(lookup,inet_ntoa(fromsa.sin_addr),200); if((hostent=gethostbyaddr((char *)&fromsa.sin_addr,sizeof(fromsa.sin_addr),AF_INET))) mystrncpy(lookup,hostent->h_name,200); os_logwrite("(%s) Connection established to %s",var.clientid,lookup); if(!checkallow(&var,inet_ntoa(fromsa.sin_addr))) { socksendtext(&var,"502 Access denied." CRLF); os_logwrite("(%s) Access denied (not in allow list)",var.clientid); shutdown(s,2); close(s); freesockio(var.sio); os_getexclusive(); server_openconnections--; os_stopexclusive(); return; } if((ulong)get_server_openconnections() > cfg_maxconn) { os_logwrite("(%s) Access denied (server full)",var.clientid); socksendtext(&var,"502 Maximum number of connections reached, please try again later" CRLF); shutdown(s,2); close(s); freesockio(var.sio); os_getexclusive(); server_openconnections--; os_stopexclusive(); return; } if(!(readgroups(&var))) { socksendtext(&var,"503 Failed to read group configuration file" CRLF); shutdown(s,2); close(s); freesockio(var.sio); os_getexclusive(); server_openconnections--; os_stopexclusive(); return; } if(!(readxlat(&var))) { socksendtext(&var,"503 Failed to read xlat configuration file" CRLF); shutdown(s,2); close(s); freesockio(var.sio); freegroups(&var); os_getexclusive(); server_openconnections--; os_stopexclusive(); return; } socksendtext(&var,"200 Welcome to " SERVER_NAME " " SERVER_VERSION " (posting may or may not be allowed, try your luck)" CRLF); while(!var.disconnect && !get_server_quit() && sockreadline(&var,line,1000)) { strip(line); var.input=line; var.inputpos=0; if(line[0] && cfg_debug) printf("(%s) < %s\n",var.clientid,line); if((cmd=parseinput(&var))) { if(stricmp(cmd,"ARTICLE")==0) { command_abhs(&var,cmd); } else if(stricmp(cmd,"AUTHINFO")==0) { command_authinfo(&var); } else if(stricmp(cmd,"BODY")==0) { command_abhs(&var,cmd); } else if(stricmp(cmd,"HEAD")==0) { command_abhs(&var,cmd); } else if(stricmp(cmd,"STAT")==0) { command_abhs(&var,cmd); } else if(stricmp(cmd,"GROUP")==0) { command_group(&var); } else if(stricmp(cmd,"HELP")==0) { socksendtext(&var,"100 Help text follows" CRLF); socksendtext(&var,"Recognized commands:" CRLF); socksendtext(&var,CRLF); socksendtext(&var,"ARTICLE" CRLF); socksendtext(&var,"AUTHINFO" CRLF); socksendtext(&var,"BODY" CRLF); socksendtext(&var,"GROUP" CRLF); socksendtext(&var,"HEAD" CRLF); socksendtext(&var,"HELP" CRLF); socksendtext(&var,"IHAVE (not implemented, messages are always rejected)" CRLF); socksendtext(&var,"LAST" CRLF); socksendtext(&var,"LIST" CRLF); socksendtext(&var,"NEWGROUPS (not implemented, always returns an empty list)" CRLF); socksendtext(&var,"NEWNEWS (not implemented, always returns an empty list)" CRLF); socksendtext(&var,"NEXT" CRLF); socksendtext(&var,"QUIT" CRLF); socksendtext(&var,"SLAVE (has no effect)" CRLF); socksendtext(&var,"STAT" CRLF); socksendtext(&var,"XOVER (partially implemented, byte count and line count are always empty)" CRLF); socksendtext(&var,CRLF); socksendtext(&var,"JamNNTPd supports most of RFC-977 and also has support for AUTHINFO and" CRLF); socksendtext(&var,"limited XOVER support (RFC-2980)" CRLF); socksendtext(&var,"." CRLF); } else if(stricmp(cmd,"IHAVE")==0) { socksendtext(&var,"435 Article not wanted - do not send it" CRLF); } else if(stricmp(cmd,"LAST")==0) { command_last(&var); } else if(stricmp(cmd,"LIST")==0) { command_list(&var); } else if(stricmp(cmd,"NEWGROUPS")==0) { socksendtext(&var,"231 Warning: NEWGROUPS not implemented, returning empty list" CRLF); socksendtext(&var,"." CRLF); } else if(stricmp(cmd,"NEWNEWS")==0) { socksendtext(&var,"230 Warning: NEWNEWS not implemented, returning empty list" CRLF); socksendtext(&var,"." CRLF); } else if(stricmp(cmd,"NEXT")==0) { command_next(&var); } else if(stricmp(cmd,"POST")==0) { command_post(&var); } else if(stricmp(cmd,"SLAVE")==0) { socksendtext(&var,"202 Slave status noted (but ignored)" CRLF); } else if(stricmp(cmd,"QUIT")==0) { socksendtext(&var,"205 Goodbye" CRLF); var.disconnect=1; } else if(stricmp(cmd,"XOVER")==0) { command_xover(&var); } else { socksendtext(&var,"500 Unknown command" CRLF); } } } os_logwrite("(%s) Connection closed",var.clientid); if(var.openmb) { JAM_CloseMB(var.openmb); free(var.openmb); } freegroups(&var); freexlat(&var); freesockio(var.sio); os_getexclusive(); server_openconnections--; os_stopexclusive(); shutdown(s,2); close(s); } jamnntpd-1.2/src/nntpserv.h000066400000000000000000000050151141642135500160110ustar00rootroot00000000000000#include #include #include #include #include #include #ifndef PLATFORM_WIN32 #define INVALID_SOCKET -1 #define SOCKET_ERROR -1 typedef int SOCKET; #endif typedef int bool; #include "jamlib/jam.h" struct var { struct sockio *sio; bool disconnect; struct group *currentgroup; ulong currentarticle; struct group *opengroup; s_JamBase *openmb; ulong inputpos; uchar *input; uchar clientid[100]; struct group *firstgroup; struct xlat *firstreadxlat; struct xlat *firstpostxlat; struct xlatalias *firstreadalias; struct xlatalias *firstpostalias; struct xlattab *firstxlattab; uchar defaultreadchrs[20]; uchar defaultpostchrs[20]; uchar readgroups[50]; uchar postgroups[50]; uchar loginname[100]; uchar password[100]; uchar realnames[36]; bool opt_flowed; bool opt_showto; bool login; }; #include "os.h" #include "groups.h" #include "misc.h" #include "xlat.h" #include "allow.h" #include "sockio.h" #include "login.h" #include "mime.h" #define CR "\x0d" #define LF "\x0a" #define CRLF CR LF #define SERVER_NAME "JamNNTPd/" PLATFORM_NAME #define SERVER_VERSION "1.2" #define SERVER_PIDVERSION "1" #define SOCKIO_TIMEOUT 5*60 extern int server_openconnections; extern int server_quit; int get_server_openconnections(void); int get_server_quit(void); void server(SOCKET s); #define CONFIGFILE CFG_BASEPATH "jamnntpd.config" #define CFG_PORT 5000 #define CFG_MAXCONN 5 #define CFG_ALLOWFILE CFG_BASEPATH "jamnntpd.allow" #define CFG_GROUPSFILE CFG_BASEPATH "jamnntpd.groups" #define CFG_USERSFILE CFG_BASEPATH "jamnntpd.users" #define CFG_XLATFILE CFG_BASEPATH "jamnntpd.xlat" #define CFG_LOGFILE LOG_BASEPATH "jamnntpd.log" #define CFG_DEF_FLOWED TRUE #define CFG_DEF_SHOWTO TRUE extern ulong cfg_port; extern ulong cfg_maxconn; extern uchar *cfg_allowfile; extern uchar *cfg_groupsfile; extern uchar *cfg_logfile; extern uchar *cfg_usersfile; extern uchar *cfg_xlatfile; extern uchar *cfg_origin; extern uchar *cfg_guestsuffix; extern uchar *cfg_echomailjam; extern bool cfg_debug; extern bool cfg_noxlat; extern bool cfg_noecholog; extern bool cfg_nostripre; extern bool cfg_notearline; extern bool cfg_noreplyaddr; extern bool cfg_smartquote; extern bool cfg_noencode; extern bool cfg_notzutc; extern bool cfg_nocancel; extern bool cfg_strictnetmail; extern bool cfg_readorigin; extern bool cfg_def_flowed; extern bool cfg_def_showto; jamnntpd-1.2/src/os.h000066400000000000000000000007271141642135500145600ustar00rootroot00000000000000#ifdef PLATFORM_WIN32 #include "os_win32.h" #endif #ifdef PLATFORM_LINUX #include "os_linux.h" #endif #ifdef PLATFORM_OS2 #include "os_os2.h" #endif bool os_init(void); void os_free(void); void os_startserver(void (*srv)(SOCKET sock),SOCKET sock); void os_sleep(int x); void os_getexclusive(void); void os_stopexclusive(void); void os_logwrite(uchar *fmt,...); void os_showerror(uchar *fmt,...); int os_errno(void); uchar *os_strerr(int err,uchar *str,ulong len); jamnntpd-1.2/src/os_linux.c000066400000000000000000000037171141642135500157740ustar00rootroot00000000000000#include "nntpserv.h" #include pthread_mutex_t linux_mutex = PTHREAD_MUTEX_INITIALIZER; void sighandler(int sig) { os_getexclusive(); server_quit=TRUE; os_stopexclusive(); } bool os_init(void) { signal(SIGINT,sighandler); signal(SIGPIPE,SIG_IGN); return(TRUE); } void os_free(void) { pthread_mutex_destroy(&linux_mutex); } void (*linux_srv)(SOCKET sock); void *linux_serverstub(void *arglist) { SOCKET s = (int) arglist; (*linux_srv)(s); return NULL; } void os_startserver(void (*srv)(SOCKET sock),SOCKET sock) { pthread_t thr; pthread_attr_t attr; linux_srv=srv; pthread_attr_init(&attr); pthread_attr_setdetachstate(&attr,PTHREAD_CREATE_DETACHED); pthread_create(&thr,&attr,linux_serverstub,(void *)sock); } void os_sleep(int x) { sleep(x); } void os_getexclusive(void) { pthread_mutex_lock(&linux_mutex); } void os_stopexclusive(void) { pthread_mutex_unlock(&linux_mutex); } void os_logwrite(uchar *fmt,...) { FILE *logfp; time_t t; struct tm *tp; uchar *monthnames[]={"Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec","???"}; uchar logline[500]; va_list args; time(&t); tp=localtime(&t); sprintf(logline,"%02d-%s-%02d %02d:%02d:%02d ", tp->tm_mday, monthnames[tp->tm_mon], tp->tm_year%100, tp->tm_hour, tp->tm_min, tp->tm_sec); va_start(args, fmt); vsprintf(&logline[strlen(logline)],fmt,args); va_end(args); if(!cfg_noecholog) puts(logline); strcat(logline,"\n"); if(!(logfp=fopen(cfg_logfile,"a"))) { os_showerror("Failed to open logfile %s",cfg_logfile); return; } fputs(logline,logfp); fclose(logfp); } void os_showerror(uchar *fmt,...) { va_list args; va_start(args, fmt); vprintf(fmt,args); printf("\n"); va_end(args); } int os_errno(void) { return errno; } uchar *os_strerr(int err,uchar *str,ulong len) { mystrncpy(str,strerror(err),len); return(str); } jamnntpd-1.2/src/os_linux.h000066400000000000000000000006341141642135500157740ustar00rootroot00000000000000#include #include #include #include #include #include #include #include #include #define stricmp strcasecmp #define strnicmp strncasecmp #define PLATFORM_NAME "Linux" #define CFG_BASEPATH "/etc/" #define LOG_BASEPATH "/var/spool/log/" #define TRUE 1 #define FALSE 0 #define min(x,y) (x #define THREAD_STACK_SIZE 65536 #include HMTX os2_mutex; HMODULE so32dll; int (*so32dll_select)(int *fds,int numread,int numwrite,int numexcept,long timeout); void sighandler(int sig) { os_getexclusive(); server_quit=TRUE; os_stopexclusive(); } bool os_init(void) { uchar objectname[40]; if(DosLoadModule(objectname,sizeof(objectname),"SO32DLL",&so32dll) != 0) { printf("Failed to load SO32DLL.DLL (Networking not installed?)\n"); return(FALSE); } if(DosQueryProcAddr(so32dll,0,"SELECT",&so32dll_select) != 0) { printf("SELECT function not found in SO32DLL.DLL (Wrong version of SO32DLL.DLL?)\n"); return(FALSE); } if(DosCreateMutexSem(NULL,&os2_mutex,0,FALSE) != 0) { printf("Failed to create mutex semaphore\n"); return(FALSE); } signal(SIGINT,sighandler); signal(SIGPIPE,sighandler); return(TRUE); } void os_free(void) { DosCloseMutexSem(os2_mutex); DosFreeModule(so32dll); } void (*os2_srv)(SOCKET sock); void os2_serverstub(void *arglist) { SOCKET s = (SOCKET) arglist; (*os2_srv)(s); } void os_startserver(void (*srv)(SOCKET sock),SOCKET sock) { int error; os2_srv=srv; error=_beginthread(os2_serverstub,NULL,THREAD_STACK_SIZE,(void *)sock); if(error == -1) os_logwrite("Failed to accept incoming connection (_beginthread failed)"); } void os_sleep(int x) { DosSleep(x*1000); } void os_getexclusive(void) { DosRequestMutexSem(os2_mutex,SEM_INDEFINITE_WAIT); } void os_stopexclusive(void) { DosReleaseMutexSem(os2_mutex); } void os_logwrite(uchar *fmt,...) { FILE *logfp; time_t t; struct tm *tp; uchar *monthnames[]={"Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec","???"}; uchar logline[500]; va_list args; time(&t); tp=localtime(&t); sprintf(logline,"%02d-%s-%02d %02d:%02d:%02d ", tp->tm_mday, monthnames[tp->tm_mon], tp->tm_year%100, tp->tm_hour, tp->tm_min, tp->tm_sec); va_start(args, fmt); vsprintf(&logline[strlen(logline)],fmt,args); va_end(args); if(!cfg_noecholog) puts(logline); strcat(logline,"\n"); if(!(logfp=fopen(cfg_logfile,"a"))) { os_showerror("Failed to open logfile %s",cfg_logfile); return; } fputs(logline,logfp); fclose(logfp); } void os_showerror(uchar *fmt,...) { va_list args; va_start(args, fmt); vprintf(fmt,args); printf("\n"); va_end(args); } int os_errno(void) { return errno; } uchar *os_strerr(int err,uchar *str,ulong len) { mystrncpy(str,strerror(err),len); return(str); } /* The EMX implementation of select() cannot be called from multiple threads simultaneously. Thanks to Darren Abbott for pointing out this workaround in the emx mailing list. */ int os2_select(int n,fd_set *readfds,fd_set *writefds,fd_set *exceptfds,struct timeval *timeout) { int os2_fds,ret; if(!FD_ISSET(n-1,readfds) || writefds || exceptfds) return(-1); /* This is not a full implementation nor does it aim to be */ os2_fds=_getsockhandle(n-1); ret=so32dll_select(&os2_fds,1,0,0,timeout->tv_sec*1000); if(ret>0 && os2_fds<0) FD_CLR(n-1,readfds); return(ret); } jamnntpd-1.2/src/os_os2.h000066400000000000000000000006451141642135500153420ustar00rootroot00000000000000#include #include #include #include #include #include #include #define PLATFORM_NAME "2" #define CFG_BASEPATH "" #define LOG_BASEPATH "" #define TRUE 1 #define FALSE 0 #define min(x,y) (x CRITICAL_SECTION win32_critsec; void sighandler(int sig) { os_getexclusive(); server_quit=TRUE; os_stopexclusive(); } bool os_init(void) { WSADATA wsaData; int error; signal(SIGINT,sighandler); error = WSAStartup(MAKEWORD(1,1),&wsaData); if(error) { os_showerror("Failed to initialize Winsock (error: %d)",error); return(FALSE); } InitializeCriticalSection(&win32_critsec); return(TRUE); } void os_free(void) { DeleteCriticalSection(&win32_critsec); WSACleanup(); } void (*win32_srv)(SOCKET sock); void _cdecl win32_serverstub(void *arglist) { SOCKET s = (SOCKET) arglist; (*win32_srv)(s); } void os_startserver(void (*srv)(SOCKET sock),SOCKET sock) { int error; win32_srv=srv; error=_beginthread(win32_serverstub,0,(void *)sock); if(error == -1) os_logwrite("Failed to accept incoming connection (_beginthread failed)"); } void os_getexclusive(void) { EnterCriticalSection(&win32_critsec); } void os_stopexclusive(void) { LeaveCriticalSection(&win32_critsec); } void os_sleep(int x) { Sleep(x*1000); } void os_logwrite(uchar *fmt,...) { FILE *logfp; time_t t; struct tm *tp; uchar *monthnames[]={"Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec","???"}; uchar logline[500]; va_list args; time(&t); tp=localtime(&t); sprintf(logline,"%02d-%s-%02d %02d:%02d:%02d ", tp->tm_mday, monthnames[tp->tm_mon], tp->tm_year%100, tp->tm_hour, tp->tm_min, tp->tm_sec); va_start(args, fmt); vsprintf(&logline[strlen(logline)],fmt,args); va_end(args); if(!cfg_noecholog) puts(logline); strcat(logline,"\n"); if(!(logfp=fopen(cfg_logfile,"a"))) { os_showerror("Failed to open logfile %s",cfg_logfile); return; } fputs(logline,logfp); fclose(logfp); } void os_showerror(uchar *fmt,...) { va_list args; va_start(args, fmt); vprintf(fmt,args); printf("\n"); va_end(args); } int os_errno(void) { return WSAGetLastError(); } uchar *os_strerr(int err,uchar *str,ulong len) { int res; res=FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_MAX_WIDTH_MASK,NULL,(DWORD)err,0,str,len,NULL); if(res) { CharToOem(str,str); } else { /* Fallback, FormatMessage() only works with winsock error codes on newer versions of Windows */ uchar buf[100]; sprintf(buf,"Winsock error %d",err); mystrncpy(str,buf,len); } return(str); } jamnntpd-1.2/src/os_win32.h000066400000000000000000000002341141642135500155730ustar00rootroot00000000000000#include #include #define close closesocket #define PLATFORM_NAME "Win32" #define CFG_BASEPATH "" #define LOG_BASEPATH "" jamnntpd-1.2/src/sockio.c000066400000000000000000000035561141642135500154240ustar00rootroot00000000000000#include "nntpserv.h" struct sockio *allocsockio(SOCKET socket) { struct sockio *sio; if(!(sio=(struct sockio *)malloc(sizeof(struct sockio)))) return(NULL); sio->bufpos=0; sio->buflen=0; sio->socket=socket; return(sio); } void freesockio(struct sockio *sio) { free(sio); } int sockreadchar(struct sockio *sio) { fd_set fds; struct timeval tv; int res,num; if(get_server_quit()) return(-1); if(sio->bufpos < sio->buflen) return(sio->buf[sio->bufpos++]); num=0; for(;;) { FD_ZERO(&fds); FD_SET(sio->socket,&fds); tv.tv_sec=1; tv.tv_usec=0; num++; res=select(sio->socket+1,&fds,NULL,NULL,&tv); if(res == -1) { return(-1); } else if(res) { res=recv(sio->socket,sio->buf,SOCKIO_BUFLEN,0); if(res <= 0) { return(-1); } sio->buflen=res; sio->bufpos=0; return(sio->buf[sio->bufpos++]); } if(num == SOCKIO_TIMEOUT || get_server_quit()) return(-1); } } bool sockreadline(struct var *var,uchar *buf,int len) { int ch,d; d=0; for(;;) { ch=sockreadchar(var->sio); if(ch == -1) { var->disconnect=TRUE; return(FALSE); } buf[d++]=ch; if(ch == 10 || d == len-1) { buf[d]=0; return(TRUE); } } } void socksendtext(struct var *var,uchar *buf) { if(var->disconnect) return; if(cfg_debug) printf("(%s) > %s",var->clientid,buf); if(send(var->sio->socket,buf,strlen(buf),0) == -1) { uchar err[200]; os_strerr(os_errno(),err,200); os_logwrite("(%s) Socket error \"%s\" (%lu), disconnecting",var->clientid,err,os_errno()); var->disconnect=TRUE; } } void sockprintf(struct var *var,uchar *fmt,...) { va_list args; uchar buf[1000]; va_start(args, fmt); vsprintf(buf,fmt,args); va_end(args); socksendtext(var,buf); } jamnntpd-1.2/src/sockio.h000066400000000000000000000005771141642135500154310ustar00rootroot00000000000000#define SOCKIO_BUFLEN 1024 struct sockio { SOCKET socket; uchar buf[SOCKIO_BUFLEN]; int buflen,bufpos; }; struct sockio *allocsockio(SOCKET socket); void freesockio(struct sockio *sio); int sockreadchar(struct sockio *sio); bool sockreadline(struct var *var,uchar *buf,int len); void socksendtext(struct var *var,uchar *buf); void sockprintf(struct var *var,uchar *fmt,...); jamnntpd-1.2/src/xlat.c000066400000000000000000000342301141642135500150760ustar00rootroot00000000000000#include "nntpserv.h" uchar *xlatstr(uchar *text,struct xlattab *xlattab) { uchar *newtext; long c,d,newlen; newlen=0; for(c=0;text[c];c++) { if(xlattab->table[text[c]*4]) newlen++; if(xlattab->table[text[c]*4+1]) newlen++; if(xlattab->table[text[c]*4+2]) newlen++; if(xlattab->table[text[c]*4+3]) newlen++; } newlen++; /* null-terminated */ if(!(newtext=malloc(newlen))) return(NULL); d=0; for(c=0;text[c];c++) { if(xlattab->table[text[c]*4]) newtext[d++]=xlattab->table[text[c]*4]; if(xlattab->table[text[c]*4+1]) newtext[d++]=xlattab->table[text[c]*4+1]; if(xlattab->table[text[c]*4+2]) newtext[d++]=xlattab->table[text[c]*4+2]; if(xlattab->table[text[c]*4+3]) newtext[d++]=xlattab->table[text[c]*4+3]; } newtext[d]=0; return(newtext); } bool chsgetline(FILE *fp,uchar *str,ulong len) { for(;;) { if(!fgets(str,len,fp)) return(FALSE); /* EOF */ if(str[0] != ';') return(TRUE); /* Not a comment */ } } uchar chsgetbyte(struct var *var,uchar *filename,uchar *buf) { ulong res; if(!buf) return(0); if(buf[0] == '\\') { if(buf[1] == '\\') { return('\\'); } else if(buf[1] == '0') { return(0); } else if(buf[1] == 'd') { return (uchar)atoi(&buf[2]); } else if(buf[1] == 'x') { sscanf(&buf[2],"%lx",&res); return (uchar)res; } else { os_logwrite("(%s) Warning: Unknown byte string %s in %s",var->clientid,buf,filename); return(0); } } if(strlen(buf) > 1) os_logwrite("(%s) Warning: Too long byte string %s in %s",var->clientid,buf,filename); return(buf[0]); } bool chsgetword(uchar *line, ulong *pos, uchar *dest, ulong destlen) { ulong begin; while(isspace(line[*pos]) && line[*pos]!=0) (*pos)++; if(line[*pos] == 0) return(FALSE); begin=*pos; while(line[*pos]!=0 && !isspace(line[*pos])) (*pos)++; if(line[*pos] != 0) { line[*pos]=0; (*pos)++; } mystrncpy(dest,&line[begin],destlen); return(TRUE); } struct xlattab *readchs(struct var *var,uchar *filename) { FILE *fp; uchar buf[100]; int level,c,basenum,readnum; ulong pos; struct xlattab *newxlattab,*lastxlattab; bool extended; uchar buf1[20],buf2[20],buf3[20],buf4[20],buf5[20]; uchar ch1,ch2,ch3,ch4; bool res1,res2,res3,res4,res5; uchar table[1024]; if(!(fp=fopen(filename,"r"))) { os_logwrite("(%s) Warning: Could not open charset file %s, translation disabled",var->clientid,filename); return(NULL); } if(!chsgetline(fp,buf,100)) /* ID number */ { os_logwrite("(%s) Warning: Unexpected EOF in %s when reading ID number, translation disabled",var->clientid,filename); fclose(fp); return(NULL); } if(atoi(buf) > 65535) extended=TRUE; else extended=FALSE; if(!chsgetline(fp,buf,100)) /* version number */ { os_logwrite("(%s) Warning: Unexpected EOF in %s when reading version number, translation disabled",var->clientid,filename); fclose(fp); return(NULL); } if(!chsgetline(fp,buf,100)) /* level number */ { os_logwrite("(%s) Warning: Unexpected EOF in %s when reading level number, translation disabled",var->clientid,filename); fclose(fp); return(NULL); } level=atoi(buf); if(!chsgetline(fp,buf,100)) { os_logwrite("(%s) Warning: Unexpected EOF in %s when reading source charset, translation disabled",var->clientid,filename); fclose(fp); return(NULL); } if(!chsgetline(fp,buf,100)) { os_logwrite("(%s) Warning: Unexpected EOF in %s when reading destination charset, translation disabled",var->clientid,filename); fclose(fp); return(NULL); } if(level !=1 && level != 2) { os_logwrite("(%s) Warning: %s is for level %d, translation disabled (only 1 and 2 are supported)",var->clientid,filename); fclose(fp); return(NULL); } /* init table */ for(c=0;c<256;c++) { table[c*4]=c; table[c*4+1]=0; table[c*4+2]=0; table[c*4+3]=0; } /* read table */ if(extended) { basenum=0; readnum=256; } else { readnum=128; if(level == 1) basenum=0; if(level == 2) basenum=128; } for(c=0;cclientid,filename,basenum+c); fclose(fp); return(NULL); } if(strchr(buf,';')) *strchr(buf,';')=0; strip(buf); pos=0; res1=chsgetword(buf,&pos,buf1,20); res2=chsgetword(buf,&pos,buf2,20); res3=chsgetword(buf,&pos,buf3,20); res4=chsgetword(buf,&pos,buf4,20); res5=chsgetword(buf,&pos,buf5,20); ch1=0; ch2=0; ch3=0; ch4=0; if(res1) ch1=chsgetbyte(var,filename,buf1); if(res2) ch2=chsgetbyte(var,filename,buf2); if(res3) ch3=chsgetbyte(var,filename,buf3); if(res4) ch4=chsgetbyte(var,filename,buf4); if(res5) os_logwrite("(%s) Warning: %s has translations longer than four chars (char %d)",var->clientid,filename,c); table[(basenum+c)*4]=ch1; table[(basenum+c)*4+1]=ch2; table[(basenum+c)*4+2]=ch3; table[(basenum+c)*4+3]=ch4; } fclose(fp); if(!(newxlattab=malloc(sizeof(struct xlattab)))) { return(FALSE); } lastxlattab=var->firstxlattab; if(lastxlattab) { while(lastxlattab->next) lastxlattab=lastxlattab->next; } newxlattab->next=NULL; if(!var->firstxlattab) var->firstxlattab=newxlattab; if(lastxlattab) lastxlattab->next=newxlattab; mystrncpy(newxlattab->filename,filename,100); memcpy(newxlattab->table,table,sizeof(table)); return(newxlattab); } bool matchcharset(uchar *pat,uchar *chrs,uchar *codepage) { uchar buf[20],buf2[20]; if(strchr(pat,',')) { /* Match chrs and codepage */ mystrncpy(buf,pat,20); if(strchr(buf,',')) *strchr(buf,',')=0; mystrncpy(buf2,strchr(pat,',')+1,20); if(matchpattern(buf,chrs) && matchpattern(buf2,codepage)) return(TRUE); return(FALSE); } else { /* Match chrs only */ return matchpattern(pat,chrs); } } void setchrscodepage(uchar *chrs,uchar *codepage,uchar *str) { if(strchr(str,',')) { mystrncpy(chrs,str,20); if(strchr(chrs,',')) *strchr(chrs,',')=0; mystrncpy(codepage,strchr(str,',')+1,20); } else { mystrncpy(chrs,str,20); codepage[0]=0; } } struct xlat *findreadxlat(struct var *var,struct group *group,uchar *ichrs,uchar *icodepage,uchar *destpat) { uchar chrs[20],codepage[20]; struct xlat *xlat; struct xlatalias *xlatalias; mystrncpy(chrs,ichrs,20); mystrncpy(codepage,icodepage,20); /* Do override */ if(group->defaultchrs[0] == '!') setchrscodepage(chrs,codepage,&group->defaultchrs[1]); else if(var->defaultreadchrs[0] == '!') setchrscodepage(chrs,codepage,&var->defaultreadchrs[1]); /* Set charset if missing */ if(chrs[0] == 0 && group->defaultchrs[0] != 0 && group->defaultchrs[0] != '!') setchrscodepage(chrs,codepage,group->defaultchrs); if(chrs[0] == 0 && var->defaultreadchrs[0] != 0 && var->defaultreadchrs[0] != '!') setchrscodepage(chrs,codepage,var->defaultreadchrs); /* Replace if an alias */ for(xlatalias=var->firstreadalias;xlatalias;xlatalias=xlatalias->next) if(matchcharset(xlatalias->pattern,chrs,codepage)) break; if(xlatalias) setchrscodepage(chrs,codepage,xlatalias->replace); /* Find in list */ if(destpat) { for(xlat=var->firstreadxlat;xlat;xlat=xlat->next) if(matchcharset(xlat->fromchrs,chrs,codepage) && matchpattern(destpat,xlat->tochrs)) break; } else { for(xlat=var->firstreadxlat;xlat;xlat=xlat->next) if(matchcharset(xlat->fromchrs,chrs,codepage)) break; } return(xlat); } struct xlat *findpostxlat(struct var *var,uchar *ichrs,uchar *destpat) { uchar chrs[20]; struct xlat *xlat; struct xlatalias *xlatalias; mystrncpy(chrs,ichrs,20); /* Set charset if missing */ if(chrs[0] == 0 && var->defaultpostchrs[0] != 0) mystrncpy(chrs,var->defaultpostchrs,20); /* Replace if an alias */ for(xlatalias=var->firstpostalias;xlatalias;xlatalias=xlatalias->next) if(matchpattern(xlatalias->pattern,chrs)) break; if(xlatalias) mystrncpy(chrs,xlatalias->replace,20); /* Find in list */ if(destpat) { for(xlat=var->firstpostxlat;xlat;xlat=xlat->next) if(matchpattern(xlat->fromchrs,chrs) && matchpattern(destpat,xlat->tochrs)) break; } else { for(xlat=var->firstpostxlat;xlat;xlat=xlat->next) if(matchpattern(xlat->fromchrs,chrs)) break; } return(xlat); } bool readxlat(struct var *var) { FILE *fp; uchar s[1000],type[20],fromchrs[100],tochrs[100],option[100]; uchar basename[100],fullfilename[250]; bool res1,res2,res3; ulong pos,line; struct xlat *newxlat,*lastreadxlat,*lastpostxlat; struct xlatalias *newxlatalias, *lastreadalias,*lastpostalias; struct xlattab *xlattab; if(!(fp=fopen(cfg_xlatfile,"r"))) { os_logwrite("(%s) Can't read xlat configuration file %s",var->clientid,cfg_xlatfile); return(FALSE); } lastreadxlat=NULL; lastpostxlat=NULL; lastreadalias=NULL; lastpostalias=NULL; var->firstreadxlat=NULL; var->firstpostxlat=NULL; var->firstreadalias=NULL; var->firstpostalias=NULL; var->firstxlattab=NULL; basename[0]=0; line=0; while(fgets(s,999,fp)) { line++; strip(s); pos=0; if(s[0]!=0 && s[0]!='#') { res1=getcfgword(s,&pos,type,20); res2=getcfgword(s,&pos,fromchrs,100); res3=getcfgword(s,&pos,tochrs,100); if(stricmp(type,"chsdir")==0 && res2) { mystrncpy(basename,fromchrs,100); } else if(stricmp(type,"defaultpost")==0 && res2) { mystrncpy(var->defaultpostchrs,fromchrs,20); } else if(stricmp(type,"defaultread")==0 && res2) { mystrncpy(var->defaultreadchrs,fromchrs,20); } else if(stricmp(type,"readalias")==0 && res2 && res3) { if(!(newxlatalias=(struct xlatalias *)malloc(sizeof(struct xlatalias)))) { fclose(fp); return(FALSE); } newxlatalias->next=NULL; if(!var->firstreadalias) var->firstreadalias=newxlatalias; if(lastreadalias) lastreadalias->next=newxlatalias; lastreadalias=newxlatalias; mystrncpy(newxlatalias->pattern,fromchrs,20); mystrncpy(newxlatalias->replace,tochrs,20); } else if(stricmp(type,"postalias")==0 && res2 && res3) { if(!(newxlatalias=(struct xlatalias *)malloc(sizeof(struct xlatalias)))) { fclose(fp); return(FALSE); } newxlatalias->next=NULL; if(!var->firstpostalias) var->firstpostalias=newxlatalias; if(lastpostalias) lastpostalias->next=newxlatalias; lastpostalias=newxlatalias; mystrncpy(newxlatalias->pattern,fromchrs,20); mystrncpy(newxlatalias->replace,tochrs,20); } else if(stricmp(type,"post") == 0 || stricmp(type,"read") == 0) { if(!(newxlat=(struct xlat *)malloc(sizeof(struct xlat)))) { fclose(fp); return(FALSE); } newxlat->next=NULL; if(stricmp(type,"post")==0) { if(!var->firstpostxlat) var->firstpostxlat=newxlat; if(lastpostxlat) lastpostxlat->next=newxlat; lastpostxlat=newxlat; } else { if(!var->firstreadxlat) var->firstreadxlat=newxlat; if(lastreadxlat) lastreadxlat->next=newxlat; lastreadxlat=newxlat; } mystrncpy(newxlat->fromchrs,fromchrs,20); mystrncpy(newxlat->tochrs,tochrs,20); newxlat->xlattab=NULL; newxlat->keepsoftcr=FALSE; while(getcfgword(s,&pos,option,100)) { if(stricmp(option,"-keepsoftcr")==0) { newxlat->keepsoftcr=TRUE; } else if(option[0] != '-' && !newxlat->xlattab) { strcpy(fullfilename,basename); if(strlen(fullfilename) != 0) { if(fullfilename[strlen(fullfilename)-1] != '/' && fullfilename[strlen(fullfilename)-1] != '\\') strcat(fullfilename,"/"); } strcat(fullfilename,option); for(xlattab=var->firstxlattab;xlattab;xlattab=xlattab->next) if(strcmp(xlattab->filename,fullfilename)==0) break; if(xlattab) newxlat->xlattab=xlattab; else newxlat->xlattab=readchs(var,fullfilename); } else { os_logwrite("(%s) Warning: Unknown option %s on line %lu in %s",var->clientid,option,line,cfg_xlatfile); } } } else { os_logwrite("(%s) Syntax error on line %lu in %s, skipping line",var->clientid,line,cfg_xlatfile); } } } fclose(fp); if(!var->firstpostxlat) { os_logwrite("(%s) No charsets for posting configured",var->clientid); return(FALSE); } return(TRUE); } void freexlat(struct var *var) { freelist(var->firstreadxlat); freelist(var->firstpostxlat); freelist(var->firstreadalias); freelist(var->firstpostalias); freelist(var->firstxlattab); var->firstreadxlat=NULL; var->firstpostxlat=NULL; var->firstreadalias=NULL; var->firstpostalias=NULL; var->firstxlattab=NULL; } jamnntpd-1.2/src/xlat.h000066400000000000000000000013421141642135500151010ustar00rootroot00000000000000struct xlattab { struct xlattab *next; uchar filename[100]; uchar table[1024]; }; struct xlat { struct xlat *next; uchar fromchrs[20]; uchar tochrs[20]; struct xlattab *xlattab; bool keepsoftcr; }; struct xlatalias { struct xlatalias *next; uchar pattern[20]; uchar replace[20]; }; uchar *xlatstr(uchar *text,struct xlattab *xlattab); bool readxlat(struct var *var); void freexlat(struct var *var); bool matchcharset(uchar *pat,uchar *chrs,uchar *codepage); void setchrscodepage(uchar *chrs,uchar *codepage,uchar *str); struct xlat *findreadxlat(struct var *var,struct group *group,uchar *ichrs,uchar *icodepage,uchar *destpat); struct xlat *findpostxlat(struct var *var,uchar *ichrs,uchar *destpat); jamnntpd-1.2/unicode/000077500000000000000000000000001141642135500146175ustar00rootroot00000000000000jamnntpd-1.2/unicode/ReadMe.txt000066400000000000000000000014511141642135500165160ustar00rootroot00000000000000How to get JamNNTPd to display texts in Unicode =============================================== With the help of the unicode/jamnntpd.xlat file and the *.chs files in unicode/xlat, it is possible to get JamNNTPd to display posts in Unicode. Posting in Unicode is unfortunately not possible. You should keep the "read" translations for iso-8859-1 in jamnntpd.xlat or JamNNTPd will not be able to properly translate the receiver name of messages that you post. It is also necessary to run JamNNTPd with the -noencode switch since the MIME encoder in JamNNTPd is not Unicode-aware and may otherwise choose to split an utf-8 character into several MIME segments. This means that you have to configure your newsreader to use utf-8 as the default charset. Sorry about that, this is a bit of a hack. :-) jamnntpd-1.2/unicode/jamnntpd.xlat000066400000000000000000000020271141642135500173250ustar00rootroot00000000000000# Charset configuration for JamNNTPd using Unicode # # It is necessary to still have the "read" translations for the charsets you # will be posting in or JamNNTPd will not be able to translate the receiver # name properly. Unfortunately posting in utf-8 is not possible at this time. chsdir /home/fido/jamnntpd/xlat defaultread IBMPC read CP437 utf-8 437_utf.chs read CP850 utf-8 850_utf.chs read CP865 utf-8 865_utf.chs read CP866 utf-8 866_utf.chs read LATIN-1 utf-8 iso_utf.chs read CP437 iso-8859-1 437_iso.chs read CP850 iso-8859-1 850_iso.chs read CP865 iso-8859-1 865_iso.chs read CP866 koi8-r 866_koi.chs read LATIN-1 iso-8859-1 readalias IBMPC,850 CP850 readalias IBMPC,865 CP865 readalias IBMPC,866 CP866 readalias IBMPC CP437 defaultpost iso-8859-1 post iso-8859-1 LATIN-1 post koi8-r CP866 koi_866.chs postalias windows-1252 iso-8859-1 postalias iso-8859-15 iso-8859-1 postalias us-ascii iso-8859-1 jamnntpd-1.2/unicode/xlat/000077500000000000000000000000001141642135500155675ustar00rootroot00000000000000jamnntpd-1.2/unicode/xlat/437_utf.chs000066400000000000000000000275561141642135500175000ustar00rootroot00000000000000; ; This file is a charset conversion module in text form. ; ; Source file: ; http://www.unicode.org/Public/MAPPINGS/VENDORS/MICSFT/PC/CP437.TXT ; 100000 ; ID number (when >65535, all 255 chars will be translated) 0 ; version number ; 2 ; level number ; CP437 UTF-8 ; \0 \0 ; NULL \0 \d1 ; START OF HEADING \0 \d2 ; START OF TEXT \0 \d3 ; END OF TEXT \0 \d4 ; END OF TRANSMISSION \0 \d5 ; ENQUIRY \0 \d6 ; ACKNOWLEDGE \0 \d7 ; BELL \0 \d8 ; BACKSPACE \0 \d9 ; HORIZONTAL TABULATION \0 \d10 ; LINE FEED \0 \d11 ; VERTICAL TABULATION \0 \d12 ; FORM FEED \0 \d13 ; CARRIAGE RETURN \0 \d14 ; SHIFT OUT \0 \d15 ; SHIFT IN \0 \d16 ; DATA LINK ESCAPE \0 \d17 ; DEVICE CONTROL ONE \0 \d18 ; DEVICE CONTROL TWO \0 \d19 ; DEVICE CONTROL THREE \0 \d20 ; DEVICE CONTROL FOUR \0 \d21 ; NEGATIVE ACKNOWLEDGE \0 \d22 ; SYNCHRONOUS IDLE \0 \d23 ; END OF TRANSMISSION BLOCK \0 \d24 ; CANCEL \0 \d25 ; END OF MEDIUM \0 \d26 ; SUBSTITUTE \0 \d27 ; ESCAPE \0 \d28 ; FILE SEPARATOR \0 \d29 ; GROUP SEPARATOR \0 \d30 ; RECORD SEPARATOR \0 \d31 ; UNIT SEPARATOR \0 \d32 ; SPACE \0 \d33 ; EXCLAMATION MARK \0 \d34 ; QUOTATION MARK \0 \d35 ; NUMBER SIGN \0 \d36 ; DOLLAR SIGN \0 \d37 ; PERCENT SIGN \0 \d38 ; AMPERSAND \0 \d39 ; APOSTROPHE \0 \d40 ; LEFT PARENTHESIS \0 \d41 ; RIGHT PARENTHESIS \0 \d42 ; ASTERISK \0 \d43 ; PLUS SIGN \0 \d44 ; COMMA \0 \d45 ; HYPHEN-MINUS \0 \d46 ; FULL STOP \0 \d47 ; SOLIDUS \0 \d48 ; DIGIT ZERO \0 \d49 ; DIGIT ONE \0 \d50 ; DIGIT TWO \0 \d51 ; DIGIT THREE \0 \d52 ; DIGIT FOUR \0 \d53 ; DIGIT FIVE \0 \d54 ; DIGIT SIX \0 \d55 ; DIGIT SEVEN \0 \d56 ; DIGIT EIGHT \0 \d57 ; DIGIT NINE \0 \d58 ; COLON \0 \d59 ; SEMICOLON \0 \d60 ; LESS-THAN SIGN \0 \d61 ; EQUALS SIGN \0 \d62 ; GREATER-THAN SIGN \0 \d63 ; QUESTION MARK \0 \d64 ; COMMERCIAL AT \0 \d65 ; LATIN CAPITAL LETTER A \0 \d66 ; LATIN CAPITAL LETTER B \0 \d67 ; LATIN CAPITAL LETTER C \0 \d68 ; LATIN CAPITAL LETTER D \0 \d69 ; LATIN CAPITAL LETTER E \0 \d70 ; LATIN CAPITAL LETTER F \0 \d71 ; LATIN CAPITAL LETTER G \0 \d72 ; LATIN CAPITAL LETTER H \0 \d73 ; LATIN CAPITAL LETTER I \0 \d74 ; LATIN CAPITAL LETTER J \0 \d75 ; LATIN CAPITAL LETTER K \0 \d76 ; LATIN CAPITAL LETTER L \0 \d77 ; LATIN CAPITAL LETTER M \0 \d78 ; LATIN CAPITAL LETTER N \0 \d79 ; LATIN CAPITAL LETTER O \0 \d80 ; LATIN CAPITAL LETTER P \0 \d81 ; LATIN CAPITAL LETTER Q \0 \d82 ; LATIN CAPITAL LETTER R \0 \d83 ; LATIN CAPITAL LETTER S \0 \d84 ; LATIN CAPITAL LETTER T \0 \d85 ; LATIN CAPITAL LETTER U \0 \d86 ; LATIN CAPITAL LETTER V \0 \d87 ; LATIN CAPITAL LETTER W \0 \d88 ; LATIN CAPITAL LETTER X \0 \d89 ; LATIN CAPITAL LETTER Y \0 \d90 ; LATIN CAPITAL LETTER Z \0 \d91 ; LEFT SQUARE BRACKET \0 \d92 ; REVERSE SOLIDUS \0 \d93 ; RIGHT SQUARE BRACKET \0 \d94 ; CIRCUMFLEX ACCENT \0 \d95 ; LOW LINE \0 \d96 ; GRAVE ACCENT \0 \d97 ; LATIN SMALL LETTER A \0 \d98 ; LATIN SMALL LETTER B \0 \d99 ; LATIN SMALL LETTER C \0 \d100 ; LATIN SMALL LETTER D \0 \d101 ; LATIN SMALL LETTER E \0 \d102 ; LATIN SMALL LETTER F \0 \d103 ; LATIN SMALL LETTER G \0 \d104 ; LATIN SMALL LETTER H \0 \d105 ; LATIN SMALL LETTER I \0 \d106 ; LATIN SMALL LETTER J \0 \d107 ; LATIN SMALL LETTER K \0 \d108 ; LATIN SMALL LETTER L \0 \d109 ; LATIN SMALL LETTER M \0 \d110 ; LATIN SMALL LETTER N \0 \d111 ; LATIN SMALL LETTER O \0 \d112 ; LATIN SMALL LETTER P \0 \d113 ; LATIN SMALL LETTER Q \0 \d114 ; LATIN SMALL LETTER R \0 \d115 ; LATIN SMALL LETTER S \0 \d116 ; LATIN SMALL LETTER T \0 \d117 ; LATIN SMALL LETTER U \0 \d118 ; LATIN SMALL LETTER V \0 \d119 ; LATIN SMALL LETTER W \0 \d120 ; LATIN SMALL LETTER X \0 \d121 ; LATIN SMALL LETTER Y \0 \d122 ; LATIN SMALL LETTER Z \0 \d123 ; LEFT CURLY BRACKET \0 \d124 ; VERTICAL LINE \0 \d125 ; RIGHT CURLY BRACKET \0 \d126 ; TILDE \0 \d127 ; DELETE \d195 \d135 ; LATIN CAPITAL LETTER C WITH CEDILLA \d195 \d188 ; LATIN SMALL LETTER U WITH DIAERESIS \d195 \d169 ; LATIN SMALL LETTER E WITH ACUTE \d195 \d162 ; LATIN SMALL LETTER A WITH CIRCUMFLEX \d195 \d164 ; LATIN SMALL LETTER A WITH DIAERESIS \d195 \d160 ; LATIN SMALL LETTER A WITH GRAVE \d195 \d165 ; LATIN SMALL LETTER A WITH RING ABOVE \d195 \d167 ; LATIN SMALL LETTER C WITH CEDILLA \d195 \d170 ; LATIN SMALL LETTER E WITH CIRCUMFLEX \d195 \d171 ; LATIN SMALL LETTER E WITH DIAERESIS \d195 \d168 ; LATIN SMALL LETTER E WITH GRAVE \d195 \d175 ; LATIN SMALL LETTER I WITH DIAERESIS \d195 \d174 ; LATIN SMALL LETTER I WITH CIRCUMFLEX \d195 \d172 ; LATIN SMALL LETTER I WITH GRAVE \d195 \d132 ; LATIN CAPITAL LETTER A WITH DIAERESIS \d195 \d133 ; LATIN CAPITAL LETTER A WITH RING ABOVE \d195 \d137 ; LATIN CAPITAL LETTER E WITH ACUTE \d195 \d166 ; LATIN SMALL LIGATURE AE \d195 \d134 ; LATIN CAPITAL LIGATURE AE \d195 \d180 ; LATIN SMALL LETTER O WITH CIRCUMFLEX \d195 \d182 ; LATIN SMALL LETTER O WITH DIAERESIS \d195 \d178 ; LATIN SMALL LETTER O WITH GRAVE \d195 \d187 ; LATIN SMALL LETTER U WITH CIRCUMFLEX \d195 \d185 ; LATIN SMALL LETTER U WITH GRAVE \d195 \d191 ; LATIN SMALL LETTER Y WITH DIAERESIS \d195 \d150 ; LATIN CAPITAL LETTER O WITH DIAERESIS \d195 \d156 ; LATIN CAPITAL LETTER U WITH DIAERESIS \d194 \d162 ; CENT SIGN \d194 \d163 ; POUND SIGN \d194 \d165 ; YEN SIGN \d226 \d130 \d167 ; PESETA SIGN \d198 \d146 ; LATIN SMALL LETTER F WITH HOOK \d195 \d161 ; LATIN SMALL LETTER A WITH ACUTE \d195 \d173 ; LATIN SMALL LETTER I WITH ACUTE \d195 \d179 ; LATIN SMALL LETTER O WITH ACUTE \d195 \d186 ; LATIN SMALL LETTER U WITH ACUTE \d195 \d177 ; LATIN SMALL LETTER N WITH TILDE \d195 \d145 ; LATIN CAPITAL LETTER N WITH TILDE \d194 \d170 ; FEMININE ORDINAL INDICATOR \d194 \d186 ; MASCULINE ORDINAL INDICATOR \d194 \d191 ; INVERTED QUESTION MARK \d226 \d140 \d144 ; REVERSED NOT SIGN \d194 \d172 ; NOT SIGN \d194 \d189 ; VULGAR FRACTION ONE HALF \d194 \d188 ; VULGAR FRACTION ONE QUARTER \d194 \d161 ; INVERTED EXCLAMATION MARK \d194 \d171 ; LEFT-POINTING DOUBLE ANGLE QUOTATION MARK \d194 \d187 ; RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK \d226 \d150 \d145 ; LIGHT SHADE \d226 \d150 \d146 ; MEDIUM SHADE \d226 \d150 \d147 ; DARK SHADE \d226 \d148 \d130 ; BOX DRAWINGS LIGHT VERTICAL \d226 \d148 \d164 ; BOX DRAWINGS LIGHT VERTICAL AND LEFT \d226 \d149 \d161 ; BOX DRAWINGS VERTICAL SINGLE AND LEFT DOUBLE \d226 \d149 \d162 ; BOX DRAWINGS VERTICAL DOUBLE AND LEFT SINGLE \d226 \d149 \d150 ; BOX DRAWINGS DOWN DOUBLE AND LEFT SINGLE \d226 \d149 \d149 ; BOX DRAWINGS DOWN SINGLE AND LEFT DOUBLE \d226 \d149 \d163 ; BOX DRAWINGS DOUBLE VERTICAL AND LEFT \d226 \d149 \d145 ; BOX DRAWINGS DOUBLE VERTICAL \d226 \d149 \d151 ; BOX DRAWINGS DOUBLE DOWN AND LEFT \d226 \d149 \d157 ; BOX DRAWINGS DOUBLE UP AND LEFT \d226 \d149 \d156 ; BOX DRAWINGS UP DOUBLE AND LEFT SINGLE \d226 \d149 \d155 ; BOX DRAWINGS UP SINGLE AND LEFT DOUBLE \d226 \d148 \d144 ; BOX DRAWINGS LIGHT DOWN AND LEFT \d226 \d148 \d148 ; BOX DRAWINGS LIGHT UP AND RIGHT \d226 \d148 \d180 ; BOX DRAWINGS LIGHT UP AND HORIZONTAL \d226 \d148 \d172 ; BOX DRAWINGS LIGHT DOWN AND HORIZONTAL \d226 \d148 \d156 ; BOX DRAWINGS LIGHT VERTICAL AND RIGHT \d226 \d148 \d128 ; BOX DRAWINGS LIGHT HORIZONTAL \d226 \d148 \d188 ; BOX DRAWINGS LIGHT VERTICAL AND HORIZONTAL \d226 \d149 \d158 ; BOX DRAWINGS VERTICAL SINGLE AND RIGHT DOUBLE \d226 \d149 \d159 ; BOX DRAWINGS VERTICAL DOUBLE AND RIGHT SINGLE \d226 \d149 \d154 ; BOX DRAWINGS DOUBLE UP AND RIGHT \d226 \d149 \d148 ; BOX DRAWINGS DOUBLE DOWN AND RIGHT \d226 \d149 \d169 ; BOX DRAWINGS DOUBLE UP AND HORIZONTAL \d226 \d149 \d166 ; BOX DRAWINGS DOUBLE DOWN AND HORIZONTAL \d226 \d149 \d160 ; BOX DRAWINGS DOUBLE VERTICAL AND RIGHT \d226 \d149 \d144 ; BOX DRAWINGS DOUBLE HORIZONTAL \d226 \d149 \d172 ; BOX DRAWINGS DOUBLE VERTICAL AND HORIZONTAL \d226 \d149 \d167 ; BOX DRAWINGS UP SINGLE AND HORIZONTAL DOUBLE \d226 \d149 \d168 ; BOX DRAWINGS UP DOUBLE AND HORIZONTAL SINGLE \d226 \d149 \d164 ; BOX DRAWINGS DOWN SINGLE AND HORIZONTAL DOUBLE \d226 \d149 \d165 ; BOX DRAWINGS DOWN DOUBLE AND HORIZONTAL SINGLE \d226 \d149 \d153 ; BOX DRAWINGS UP DOUBLE AND RIGHT SINGLE \d226 \d149 \d152 ; BOX DRAWINGS UP SINGLE AND RIGHT DOUBLE \d226 \d149 \d146 ; BOX DRAWINGS DOWN SINGLE AND RIGHT DOUBLE \d226 \d149 \d147 ; BOX DRAWINGS DOWN DOUBLE AND RIGHT SINGLE \d226 \d149 \d171 ; BOX DRAWINGS VERTICAL DOUBLE AND HORIZONTAL SINGLE \d226 \d149 \d170 ; BOX DRAWINGS VERTICAL SINGLE AND HORIZONTAL DOUBLE \d226 \d148 \d152 ; BOX DRAWINGS LIGHT UP AND LEFT \d226 \d148 \d140 ; BOX DRAWINGS LIGHT DOWN AND RIGHT \d226 \d150 \d136 ; FULL BLOCK \d226 \d150 \d132 ; LOWER HALF BLOCK \d226 \d150 \d140 ; LEFT HALF BLOCK \d226 \d150 \d144 ; RIGHT HALF BLOCK \d226 \d150 \d128 ; UPPER HALF BLOCK \d206 \d177 ; GREEK SMALL LETTER ALPHA \d195 \d159 ; LATIN SMALL LETTER SHARP S \d206 \d147 ; GREEK CAPITAL LETTER GAMMA \d207 \d128 ; GREEK SMALL LETTER PI \d206 \d163 ; GREEK CAPITAL LETTER SIGMA \d207 \d131 ; GREEK SMALL LETTER SIGMA \d194 \d181 ; MICRO SIGN \d207 \d132 ; GREEK SMALL LETTER TAU \d206 \d166 ; GREEK CAPITAL LETTER PHI \d206 \d152 ; GREEK CAPITAL LETTER THETA \d206 \d169 ; GREEK CAPITAL LETTER OMEGA \d206 \d180 ; GREEK SMALL LETTER DELTA \d226 \d136 \d158 ; INFINITY \d207 \d134 ; GREEK SMALL LETTER PHI \d206 \d181 ; GREEK SMALL LETTER EPSILON \d226 \d136 \d169 ; INTERSECTION \d226 \d137 \d161 ; IDENTICAL TO \d194 \d177 ; PLUS-MINUS SIGN \d226 \d137 \d165 ; GREATER-THAN OR EQUAL TO \d226 \d137 \d164 ; LESS-THAN OR EQUAL TO \d226 \d140 \d160 ; TOP HALF INTEGRAL \d226 \d140 \d161 ; BOTTOM HALF INTEGRAL \d195 \d183 ; DIVISION SIGN \d226 \d137 \d136 ; ALMOST EQUAL TO \d194 \d176 ; DEGREE SIGN \d226 \d136 \d153 ; BULLET OPERATOR \d194 \d183 ; MIDDLE DOT \d226 \d136 \d154 ; SQUARE ROOT \d226 \d129 \d191 ; SUPERSCRIPT LATIN SMALL LETTER N \d194 \d178 ; SUPERSCRIPT TWO \d226 \d150 \d160 ; BLACK SQUARE \d194 \d160 ; NO-BREAK SPACE END jamnntpd-1.2/unicode/xlat/850_utf.chs000066400000000000000000000273271141642135500174730ustar00rootroot00000000000000; ; This file is a charset conversion module in text form. ; ; Source file: ; http://www.unicode.org/Public/MAPPINGS/VENDORS/MICSFT/PC/CP850.TXT ; 100000 ; ID number (when >65535, all 255 chars will be translated) 0 ; version number ; 2 ; level number ; CP850 UTF-8 ; \0 \0 ; NULL \0 \d1 ; START OF HEADING \0 \d2 ; START OF TEXT \0 \d3 ; END OF TEXT \0 \d4 ; END OF TRANSMISSION \0 \d5 ; ENQUIRY \0 \d6 ; ACKNOWLEDGE \0 \d7 ; BELL \0 \d8 ; BACKSPACE \0 \d9 ; HORIZONTAL TABULATION \0 \d10 ; LINE FEED \0 \d11 ; VERTICAL TABULATION \0 \d12 ; FORM FEED \0 \d13 ; CARRIAGE RETURN \0 \d14 ; SHIFT OUT \0 \d15 ; SHIFT IN \0 \d16 ; DATA LINK ESCAPE \0 \d17 ; DEVICE CONTROL ONE \0 \d18 ; DEVICE CONTROL TWO \0 \d19 ; DEVICE CONTROL THREE \0 \d20 ; DEVICE CONTROL FOUR \0 \d21 ; NEGATIVE ACKNOWLEDGE \0 \d22 ; SYNCHRONOUS IDLE \0 \d23 ; END OF TRANSMISSION BLOCK \0 \d24 ; CANCEL \0 \d25 ; END OF MEDIUM \0 \d26 ; SUBSTITUTE \0 \d27 ; ESCAPE \0 \d28 ; FILE SEPARATOR \0 \d29 ; GROUP SEPARATOR \0 \d30 ; RECORD SEPARATOR \0 \d31 ; UNIT SEPARATOR \0 \d32 ; SPACE \0 \d33 ; EXCLAMATION MARK \0 \d34 ; QUOTATION MARK \0 \d35 ; NUMBER SIGN \0 \d36 ; DOLLAR SIGN \0 \d37 ; PERCENT SIGN \0 \d38 ; AMPERSAND \0 \d39 ; APOSTROPHE \0 \d40 ; LEFT PARENTHESIS \0 \d41 ; RIGHT PARENTHESIS \0 \d42 ; ASTERISK \0 \d43 ; PLUS SIGN \0 \d44 ; COMMA \0 \d45 ; HYPHEN-MINUS \0 \d46 ; FULL STOP \0 \d47 ; SOLIDUS \0 \d48 ; DIGIT ZERO \0 \d49 ; DIGIT ONE \0 \d50 ; DIGIT TWO \0 \d51 ; DIGIT THREE \0 \d52 ; DIGIT FOUR \0 \d53 ; DIGIT FIVE \0 \d54 ; DIGIT SIX \0 \d55 ; DIGIT SEVEN \0 \d56 ; DIGIT EIGHT \0 \d57 ; DIGIT NINE \0 \d58 ; COLON \0 \d59 ; SEMICOLON \0 \d60 ; LESS-THAN SIGN \0 \d61 ; EQUALS SIGN \0 \d62 ; GREATER-THAN SIGN \0 \d63 ; QUESTION MARK \0 \d64 ; COMMERCIAL AT \0 \d65 ; LATIN CAPITAL LETTER A \0 \d66 ; LATIN CAPITAL LETTER B \0 \d67 ; LATIN CAPITAL LETTER C \0 \d68 ; LATIN CAPITAL LETTER D \0 \d69 ; LATIN CAPITAL LETTER E \0 \d70 ; LATIN CAPITAL LETTER F \0 \d71 ; LATIN CAPITAL LETTER G \0 \d72 ; LATIN CAPITAL LETTER H \0 \d73 ; LATIN CAPITAL LETTER I \0 \d74 ; LATIN CAPITAL LETTER J \0 \d75 ; LATIN CAPITAL LETTER K \0 \d76 ; LATIN CAPITAL LETTER L \0 \d77 ; LATIN CAPITAL LETTER M \0 \d78 ; LATIN CAPITAL LETTER N \0 \d79 ; LATIN CAPITAL LETTER O \0 \d80 ; LATIN CAPITAL LETTER P \0 \d81 ; LATIN CAPITAL LETTER Q \0 \d82 ; LATIN CAPITAL LETTER R \0 \d83 ; LATIN CAPITAL LETTER S \0 \d84 ; LATIN CAPITAL LETTER T \0 \d85 ; LATIN CAPITAL LETTER U \0 \d86 ; LATIN CAPITAL LETTER V \0 \d87 ; LATIN CAPITAL LETTER W \0 \d88 ; LATIN CAPITAL LETTER X \0 \d89 ; LATIN CAPITAL LETTER Y \0 \d90 ; LATIN CAPITAL LETTER Z \0 \d91 ; LEFT SQUARE BRACKET \0 \d92 ; REVERSE SOLIDUS \0 \d93 ; RIGHT SQUARE BRACKET \0 \d94 ; CIRCUMFLEX ACCENT \0 \d95 ; LOW LINE \0 \d96 ; GRAVE ACCENT \0 \d97 ; LATIN SMALL LETTER A \0 \d98 ; LATIN SMALL LETTER B \0 \d99 ; LATIN SMALL LETTER C \0 \d100 ; LATIN SMALL LETTER D \0 \d101 ; LATIN SMALL LETTER E \0 \d102 ; LATIN SMALL LETTER F \0 \d103 ; LATIN SMALL LETTER G \0 \d104 ; LATIN SMALL LETTER H \0 \d105 ; LATIN SMALL LETTER I \0 \d106 ; LATIN SMALL LETTER J \0 \d107 ; LATIN SMALL LETTER K \0 \d108 ; LATIN SMALL LETTER L \0 \d109 ; LATIN SMALL LETTER M \0 \d110 ; LATIN SMALL LETTER N \0 \d111 ; LATIN SMALL LETTER O \0 \d112 ; LATIN SMALL LETTER P \0 \d113 ; LATIN SMALL LETTER Q \0 \d114 ; LATIN SMALL LETTER R \0 \d115 ; LATIN SMALL LETTER S \0 \d116 ; LATIN SMALL LETTER T \0 \d117 ; LATIN SMALL LETTER U \0 \d118 ; LATIN SMALL LETTER V \0 \d119 ; LATIN SMALL LETTER W \0 \d120 ; LATIN SMALL LETTER X \0 \d121 ; LATIN SMALL LETTER Y \0 \d122 ; LATIN SMALL LETTER Z \0 \d123 ; LEFT CURLY BRACKET \0 \d124 ; VERTICAL LINE \0 \d125 ; RIGHT CURLY BRACKET \0 \d126 ; TILDE \0 \d127 ; DELETE \d195 \d135 ; LATIN CAPITAL LETTER C WITH CEDILLA \d195 \d188 ; LATIN SMALL LETTER U WITH DIAERESIS \d195 \d169 ; LATIN SMALL LETTER E WITH ACUTE \d195 \d162 ; LATIN SMALL LETTER A WITH CIRCUMFLEX \d195 \d164 ; LATIN SMALL LETTER A WITH DIAERESIS \d195 \d160 ; LATIN SMALL LETTER A WITH GRAVE \d195 \d165 ; LATIN SMALL LETTER A WITH RING ABOVE \d195 \d167 ; LATIN SMALL LETTER C WITH CEDILLA \d195 \d170 ; LATIN SMALL LETTER E WITH CIRCUMFLEX \d195 \d171 ; LATIN SMALL LETTER E WITH DIAERESIS \d195 \d168 ; LATIN SMALL LETTER E WITH GRAVE \d195 \d175 ; LATIN SMALL LETTER I WITH DIAERESIS \d195 \d174 ; LATIN SMALL LETTER I WITH CIRCUMFLEX \d195 \d172 ; LATIN SMALL LETTER I WITH GRAVE \d195 \d132 ; LATIN CAPITAL LETTER A WITH DIAERESIS \d195 \d133 ; LATIN CAPITAL LETTER A WITH RING ABOVE \d195 \d137 ; LATIN CAPITAL LETTER E WITH ACUTE \d195 \d166 ; LATIN SMALL LIGATURE AE \d195 \d134 ; LATIN CAPITAL LIGATURE AE \d195 \d180 ; LATIN SMALL LETTER O WITH CIRCUMFLEX \d195 \d182 ; LATIN SMALL LETTER O WITH DIAERESIS \d195 \d178 ; LATIN SMALL LETTER O WITH GRAVE \d195 \d187 ; LATIN SMALL LETTER U WITH CIRCUMFLEX \d195 \d185 ; LATIN SMALL LETTER U WITH GRAVE \d195 \d191 ; LATIN SMALL LETTER Y WITH DIAERESIS \d195 \d150 ; LATIN CAPITAL LETTER O WITH DIAERESIS \d195 \d156 ; LATIN CAPITAL LETTER U WITH DIAERESIS \d195 \d184 ; LATIN SMALL LETTER O WITH STROKE \d194 \d163 ; POUND SIGN \d195 \d152 ; LATIN CAPITAL LETTER O WITH STROKE \d195 \d151 ; MULTIPLICATION SIGN \d198 \d146 ; LATIN SMALL LETTER F WITH HOOK \d195 \d161 ; LATIN SMALL LETTER A WITH ACUTE \d195 \d173 ; LATIN SMALL LETTER I WITH ACUTE \d195 \d179 ; LATIN SMALL LETTER O WITH ACUTE \d195 \d186 ; LATIN SMALL LETTER U WITH ACUTE \d195 \d177 ; LATIN SMALL LETTER N WITH TILDE \d195 \d145 ; LATIN CAPITAL LETTER N WITH TILDE \d194 \d170 ; FEMININE ORDINAL INDICATOR \d194 \d186 ; MASCULINE ORDINAL INDICATOR \d194 \d191 ; INVERTED QUESTION MARK \d194 \d174 ; REGISTERED SIGN \d194 \d172 ; NOT SIGN \d194 \d189 ; VULGAR FRACTION ONE HALF \d194 \d188 ; VULGAR FRACTION ONE QUARTER \d194 \d161 ; INVERTED EXCLAMATION MARK \d194 \d171 ; LEFT-POINTING DOUBLE ANGLE QUOTATION MARK \d194 \d187 ; RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK \d226 \d150 \d145 ; LIGHT SHADE \d226 \d150 \d146 ; MEDIUM SHADE \d226 \d150 \d147 ; DARK SHADE \d226 \d148 \d130 ; BOX DRAWINGS LIGHT VERTICAL \d226 \d148 \d164 ; BOX DRAWINGS LIGHT VERTICAL AND LEFT \d195 \d129 ; LATIN CAPITAL LETTER A WITH ACUTE \d195 \d130 ; LATIN CAPITAL LETTER A WITH CIRCUMFLEX \d195 \d128 ; LATIN CAPITAL LETTER A WITH GRAVE \d194 \d169 ; COPYRIGHT SIGN \d226 \d149 \d163 ; BOX DRAWINGS DOUBLE VERTICAL AND LEFT \d226 \d149 \d145 ; BOX DRAWINGS DOUBLE VERTICAL \d226 \d149 \d151 ; BOX DRAWINGS DOUBLE DOWN AND LEFT \d226 \d149 \d157 ; BOX DRAWINGS DOUBLE UP AND LEFT \d194 \d162 ; CENT SIGN \d194 \d165 ; YEN SIGN \d226 \d148 \d144 ; BOX DRAWINGS LIGHT DOWN AND LEFT \d226 \d148 \d148 ; BOX DRAWINGS LIGHT UP AND RIGHT \d226 \d148 \d180 ; BOX DRAWINGS LIGHT UP AND HORIZONTAL \d226 \d148 \d172 ; BOX DRAWINGS LIGHT DOWN AND HORIZONTAL \d226 \d148 \d156 ; BOX DRAWINGS LIGHT VERTICAL AND RIGHT \d226 \d148 \d128 ; BOX DRAWINGS LIGHT HORIZONTAL \d226 \d148 \d188 ; BOX DRAWINGS LIGHT VERTICAL AND HORIZONTAL \d195 \d163 ; LATIN SMALL LETTER A WITH TILDE \d195 \d131 ; LATIN CAPITAL LETTER A WITH TILDE \d226 \d149 \d154 ; BOX DRAWINGS DOUBLE UP AND RIGHT \d226 \d149 \d148 ; BOX DRAWINGS DOUBLE DOWN AND RIGHT \d226 \d149 \d169 ; BOX DRAWINGS DOUBLE UP AND HORIZONTAL \d226 \d149 \d166 ; BOX DRAWINGS DOUBLE DOWN AND HORIZONTAL \d226 \d149 \d160 ; BOX DRAWINGS DOUBLE VERTICAL AND RIGHT \d226 \d149 \d144 ; BOX DRAWINGS DOUBLE HORIZONTAL \d226 \d149 \d172 ; BOX DRAWINGS DOUBLE VERTICAL AND HORIZONTAL \d194 \d164 ; CURRENCY SIGN \d195 \d176 ; LATIN SMALL LETTER ETH \d195 \d144 ; LATIN CAPITAL LETTER ETH \d195 \d138 ; LATIN CAPITAL LETTER E WITH CIRCUMFLEX \d195 \d139 ; LATIN CAPITAL LETTER E WITH DIAERESIS \d195 \d136 ; LATIN CAPITAL LETTER E WITH GRAVE \d196 \d177 ; LATIN SMALL LETTER DOTLESS I \d195 \d141 ; LATIN CAPITAL LETTER I WITH ACUTE \d195 \d142 ; LATIN CAPITAL LETTER I WITH CIRCUMFLEX \d195 \d143 ; LATIN CAPITAL LETTER I WITH DIAERESIS \d226 \d148 \d152 ; BOX DRAWINGS LIGHT UP AND LEFT \d226 \d148 \d140 ; BOX DRAWINGS LIGHT DOWN AND RIGHT \d226 \d150 \d136 ; FULL BLOCK \d226 \d150 \d132 ; LOWER HALF BLOCK \d194 \d166 ; BROKEN BAR \d195 \d140 ; LATIN CAPITAL LETTER I WITH GRAVE \d226 \d150 \d128 ; UPPER HALF BLOCK \d195 \d147 ; LATIN CAPITAL LETTER O WITH ACUTE \d195 \d159 ; LATIN SMALL LETTER SHARP S \d195 \d148 ; LATIN CAPITAL LETTER O WITH CIRCUMFLEX \d195 \d146 ; LATIN CAPITAL LETTER O WITH GRAVE \d195 \d181 ; LATIN SMALL LETTER O WITH TILDE \d195 \d149 ; LATIN CAPITAL LETTER O WITH TILDE \d194 \d181 ; MICRO SIGN \d195 \d190 ; LATIN SMALL LETTER THORN \d195 \d158 ; LATIN CAPITAL LETTER THORN \d195 \d154 ; LATIN CAPITAL LETTER U WITH ACUTE \d195 \d155 ; LATIN CAPITAL LETTER U WITH CIRCUMFLEX \d195 \d153 ; LATIN CAPITAL LETTER U WITH GRAVE \d195 \d189 ; LATIN SMALL LETTER Y WITH ACUTE \d195 \d157 ; LATIN CAPITAL LETTER Y WITH ACUTE \d194 \d175 ; MACRON \d194 \d180 ; ACUTE ACCENT \d194 \d173 ; SOFT HYPHEN \d194 \d177 ; PLUS-MINUS SIGN \d226 \d128 \d151 ; DOUBLE LOW LINE \d194 \d190 ; VULGAR FRACTION THREE QUARTERS \d194 \d182 ; PILCROW SIGN \d194 \d167 ; SECTION SIGN \d195 \d183 ; DIVISION SIGN \d194 \d184 ; CEDILLA \d194 \d176 ; DEGREE SIGN \d194 \d168 ; DIAERESIS \d194 \d183 ; MIDDLE DOT \d194 \d185 ; SUPERSCRIPT ONE \d194 \d179 ; SUPERSCRIPT THREE \d194 \d178 ; SUPERSCRIPT TWO \d226 \d150 \d160 ; BLACK SQUARE \d194 \d160 ; NO-BREAK SPACE END jamnntpd-1.2/unicode/xlat/865_utf.chs000066400000000000000000000276021141642135500174750ustar00rootroot00000000000000; ; This file is a charset conversion module in text form. ; ; Source file: ; http://www.unicode.org/Public/MAPPINGS/VENDORS/MICSFT/PC/CP865.TXT ; 100000 ; ID number (when >65535, all 255 chars will be translated) 0 ; version number ; 2 ; level number ; CP865 UTF-8 ; \0 \0 ; NULL \0 \d1 ; START OF HEADING \0 \d2 ; START OF TEXT \0 \d3 ; END OF TEXT \0 \d4 ; END OF TRANSMISSION \0 \d5 ; ENQUIRY \0 \d6 ; ACKNOWLEDGE \0 \d7 ; BELL \0 \d8 ; BACKSPACE \0 \d9 ; HORIZONTAL TABULATION \0 \d10 ; LINE FEED \0 \d11 ; VERTICAL TABULATION \0 \d12 ; FORM FEED \0 \d13 ; CARRIAGE RETURN \0 \d14 ; SHIFT OUT \0 \d15 ; SHIFT IN \0 \d16 ; DATA LINK ESCAPE \0 \d17 ; DEVICE CONTROL ONE \0 \d18 ; DEVICE CONTROL TWO \0 \d19 ; DEVICE CONTROL THREE \0 \d20 ; DEVICE CONTROL FOUR \0 \d21 ; NEGATIVE ACKNOWLEDGE \0 \d22 ; SYNCHRONOUS IDLE \0 \d23 ; END OF TRANSMISSION BLOCK \0 \d24 ; CANCEL \0 \d25 ; END OF MEDIUM \0 \d26 ; SUBSTITUTE \0 \d27 ; ESCAPE \0 \d28 ; FILE SEPARATOR \0 \d29 ; GROUP SEPARATOR \0 \d30 ; RECORD SEPARATOR \0 \d31 ; UNIT SEPARATOR \0 \d32 ; SPACE \0 \d33 ; EXCLAMATION MARK \0 \d34 ; QUOTATION MARK \0 \d35 ; NUMBER SIGN \0 \d36 ; DOLLAR SIGN \0 \d37 ; PERCENT SIGN \0 \d38 ; AMPERSAND \0 \d39 ; APOSTROPHE \0 \d40 ; LEFT PARENTHESIS \0 \d41 ; RIGHT PARENTHESIS \0 \d42 ; ASTERISK \0 \d43 ; PLUS SIGN \0 \d44 ; COMMA \0 \d45 ; HYPHEN-MINUS \0 \d46 ; FULL STOP \0 \d47 ; SOLIDUS \0 \d48 ; DIGIT ZERO \0 \d49 ; DIGIT ONE \0 \d50 ; DIGIT TWO \0 \d51 ; DIGIT THREE \0 \d52 ; DIGIT FOUR \0 \d53 ; DIGIT FIVE \0 \d54 ; DIGIT SIX \0 \d55 ; DIGIT SEVEN \0 \d56 ; DIGIT EIGHT \0 \d57 ; DIGIT NINE \0 \d58 ; COLON \0 \d59 ; SEMICOLON \0 \d60 ; LESS-THAN SIGN \0 \d61 ; EQUALS SIGN \0 \d62 ; GREATER-THAN SIGN \0 \d63 ; QUESTION MARK \0 \d64 ; COMMERCIAL AT \0 \d65 ; LATIN CAPITAL LETTER A \0 \d66 ; LATIN CAPITAL LETTER B \0 \d67 ; LATIN CAPITAL LETTER C \0 \d68 ; LATIN CAPITAL LETTER D \0 \d69 ; LATIN CAPITAL LETTER E \0 \d70 ; LATIN CAPITAL LETTER F \0 \d71 ; LATIN CAPITAL LETTER G \0 \d72 ; LATIN CAPITAL LETTER H \0 \d73 ; LATIN CAPITAL LETTER I \0 \d74 ; LATIN CAPITAL LETTER J \0 \d75 ; LATIN CAPITAL LETTER K \0 \d76 ; LATIN CAPITAL LETTER L \0 \d77 ; LATIN CAPITAL LETTER M \0 \d78 ; LATIN CAPITAL LETTER N \0 \d79 ; LATIN CAPITAL LETTER O \0 \d80 ; LATIN CAPITAL LETTER P \0 \d81 ; LATIN CAPITAL LETTER Q \0 \d82 ; LATIN CAPITAL LETTER R \0 \d83 ; LATIN CAPITAL LETTER S \0 \d84 ; LATIN CAPITAL LETTER T \0 \d85 ; LATIN CAPITAL LETTER U \0 \d86 ; LATIN CAPITAL LETTER V \0 \d87 ; LATIN CAPITAL LETTER W \0 \d88 ; LATIN CAPITAL LETTER X \0 \d89 ; LATIN CAPITAL LETTER Y \0 \d90 ; LATIN CAPITAL LETTER Z \0 \d91 ; LEFT SQUARE BRACKET \0 \d92 ; REVERSE SOLIDUS \0 \d93 ; RIGHT SQUARE BRACKET \0 \d94 ; CIRCUMFLEX ACCENT \0 \d95 ; LOW LINE \0 \d96 ; GRAVE ACCENT \0 \d97 ; LATIN SMALL LETTER A \0 \d98 ; LATIN SMALL LETTER B \0 \d99 ; LATIN SMALL LETTER C \0 \d100 ; LATIN SMALL LETTER D \0 \d101 ; LATIN SMALL LETTER E \0 \d102 ; LATIN SMALL LETTER F \0 \d103 ; LATIN SMALL LETTER G \0 \d104 ; LATIN SMALL LETTER H \0 \d105 ; LATIN SMALL LETTER I \0 \d106 ; LATIN SMALL LETTER J \0 \d107 ; LATIN SMALL LETTER K \0 \d108 ; LATIN SMALL LETTER L \0 \d109 ; LATIN SMALL LETTER M \0 \d110 ; LATIN SMALL LETTER N \0 \d111 ; LATIN SMALL LETTER O \0 \d112 ; LATIN SMALL LETTER P \0 \d113 ; LATIN SMALL LETTER Q \0 \d114 ; LATIN SMALL LETTER R \0 \d115 ; LATIN SMALL LETTER S \0 \d116 ; LATIN SMALL LETTER T \0 \d117 ; LATIN SMALL LETTER U \0 \d118 ; LATIN SMALL LETTER V \0 \d119 ; LATIN SMALL LETTER W \0 \d120 ; LATIN SMALL LETTER X \0 \d121 ; LATIN SMALL LETTER Y \0 \d122 ; LATIN SMALL LETTER Z \0 \d123 ; LEFT CURLY BRACKET \0 \d124 ; VERTICAL LINE \0 \d125 ; RIGHT CURLY BRACKET \0 \d126 ; TILDE \0 \d127 ; DELETE \d195 \d135 ; LATIN CAPITAL LETTER C WITH CEDILLA \d195 \d188 ; LATIN SMALL LETTER U WITH DIAERESIS \d195 \d169 ; LATIN SMALL LETTER E WITH ACUTE \d195 \d162 ; LATIN SMALL LETTER A WITH CIRCUMFLEX \d195 \d164 ; LATIN SMALL LETTER A WITH DIAERESIS \d195 \d160 ; LATIN SMALL LETTER A WITH GRAVE \d195 \d165 ; LATIN SMALL LETTER A WITH RING ABOVE \d195 \d167 ; LATIN SMALL LETTER C WITH CEDILLA \d195 \d170 ; LATIN SMALL LETTER E WITH CIRCUMFLEX \d195 \d171 ; LATIN SMALL LETTER E WITH DIAERESIS \d195 \d168 ; LATIN SMALL LETTER E WITH GRAVE \d195 \d175 ; LATIN SMALL LETTER I WITH DIAERESIS \d195 \d174 ; LATIN SMALL LETTER I WITH CIRCUMFLEX \d195 \d172 ; LATIN SMALL LETTER I WITH GRAVE \d195 \d132 ; LATIN CAPITAL LETTER A WITH DIAERESIS \d195 \d133 ; LATIN CAPITAL LETTER A WITH RING ABOVE \d195 \d137 ; LATIN CAPITAL LETTER E WITH ACUTE \d195 \d166 ; LATIN SMALL LIGATURE AE \d195 \d134 ; LATIN CAPITAL LIGATURE AE \d195 \d180 ; LATIN SMALL LETTER O WITH CIRCUMFLEX \d195 \d182 ; LATIN SMALL LETTER O WITH DIAERESIS \d195 \d178 ; LATIN SMALL LETTER O WITH GRAVE \d195 \d187 ; LATIN SMALL LETTER U WITH CIRCUMFLEX \d195 \d185 ; LATIN SMALL LETTER U WITH GRAVE \d195 \d191 ; LATIN SMALL LETTER Y WITH DIAERESIS \d195 \d150 ; LATIN CAPITAL LETTER O WITH DIAERESIS \d195 \d156 ; LATIN CAPITAL LETTER U WITH DIAERESIS \d195 \d184 ; LATIN SMALL LETTER O WITH STROKE \d194 \d163 ; POUND SIGN \d195 \d152 ; LATIN CAPITAL LETTER O WITH STROKE \d226 \d130 \d167 ; PESETA SIGN \d198 \d146 ; LATIN SMALL LETTER F WITH HOOK \d195 \d161 ; LATIN SMALL LETTER A WITH ACUTE \d195 \d173 ; LATIN SMALL LETTER I WITH ACUTE \d195 \d179 ; LATIN SMALL LETTER O WITH ACUTE \d195 \d186 ; LATIN SMALL LETTER U WITH ACUTE \d195 \d177 ; LATIN SMALL LETTER N WITH TILDE \d195 \d145 ; LATIN CAPITAL LETTER N WITH TILDE \d194 \d170 ; FEMININE ORDINAL INDICATOR \d194 \d186 ; MASCULINE ORDINAL INDICATOR \d194 \d191 ; INVERTED QUESTION MARK \d226 \d140 \d144 ; REVERSED NOT SIGN \d194 \d172 ; NOT SIGN \d194 \d189 ; VULGAR FRACTION ONE HALF \d194 \d188 ; VULGAR FRACTION ONE QUARTER \d194 \d161 ; INVERTED EXCLAMATION MARK \d194 \d171 ; LEFT-POINTING DOUBLE ANGLE QUOTATION MARK \d194 \d164 ; CURRENCY SIGN \d226 \d150 \d145 ; LIGHT SHADE \d226 \d150 \d146 ; MEDIUM SHADE \d226 \d150 \d147 ; DARK SHADE \d226 \d148 \d130 ; BOX DRAWINGS LIGHT VERTICAL \d226 \d148 \d164 ; BOX DRAWINGS LIGHT VERTICAL AND LEFT \d226 \d149 \d161 ; BOX DRAWINGS VERTICAL SINGLE AND LEFT DOUBLE \d226 \d149 \d162 ; BOX DRAWINGS VERTICAL DOUBLE AND LEFT SINGLE \d226 \d149 \d150 ; BOX DRAWINGS DOWN DOUBLE AND LEFT SINGLE \d226 \d149 \d149 ; BOX DRAWINGS DOWN SINGLE AND LEFT DOUBLE \d226 \d149 \d163 ; BOX DRAWINGS DOUBLE VERTICAL AND LEFT \d226 \d149 \d145 ; BOX DRAWINGS DOUBLE VERTICAL \d226 \d149 \d151 ; BOX DRAWINGS DOUBLE DOWN AND LEFT \d226 \d149 \d157 ; BOX DRAWINGS DOUBLE UP AND LEFT \d226 \d149 \d156 ; BOX DRAWINGS UP DOUBLE AND LEFT SINGLE \d226 \d149 \d155 ; BOX DRAWINGS UP SINGLE AND LEFT DOUBLE \d226 \d148 \d144 ; BOX DRAWINGS LIGHT DOWN AND LEFT \d226 \d148 \d148 ; BOX DRAWINGS LIGHT UP AND RIGHT \d226 \d148 \d180 ; BOX DRAWINGS LIGHT UP AND HORIZONTAL \d226 \d148 \d172 ; BOX DRAWINGS LIGHT DOWN AND HORIZONTAL \d226 \d148 \d156 ; BOX DRAWINGS LIGHT VERTICAL AND RIGHT \d226 \d148 \d128 ; BOX DRAWINGS LIGHT HORIZONTAL \d226 \d148 \d188 ; BOX DRAWINGS LIGHT VERTICAL AND HORIZONTAL \d226 \d149 \d158 ; BOX DRAWINGS VERTICAL SINGLE AND RIGHT DOUBLE \d226 \d149 \d159 ; BOX DRAWINGS VERTICAL DOUBLE AND RIGHT SINGLE \d226 \d149 \d154 ; BOX DRAWINGS DOUBLE UP AND RIGHT \d226 \d149 \d148 ; BOX DRAWINGS DOUBLE DOWN AND RIGHT \d226 \d149 \d169 ; BOX DRAWINGS DOUBLE UP AND HORIZONTAL \d226 \d149 \d166 ; BOX DRAWINGS DOUBLE DOWN AND HORIZONTAL \d226 \d149 \d160 ; BOX DRAWINGS DOUBLE VERTICAL AND RIGHT \d226 \d149 \d144 ; BOX DRAWINGS DOUBLE HORIZONTAL \d226 \d149 \d172 ; BOX DRAWINGS DOUBLE VERTICAL AND HORIZONTAL \d226 \d149 \d167 ; BOX DRAWINGS UP SINGLE AND HORIZONTAL DOUBLE \d226 \d149 \d168 ; BOX DRAWINGS UP DOUBLE AND HORIZONTAL SINGLE \d226 \d149 \d164 ; BOX DRAWINGS DOWN SINGLE AND HORIZONTAL DOUBLE \d226 \d149 \d165 ; BOX DRAWINGS DOWN DOUBLE AND HORIZONTAL SINGLE \d226 \d149 \d153 ; BOX DRAWINGS UP DOUBLE AND RIGHT SINGLE \d226 \d149 \d152 ; BOX DRAWINGS UP SINGLE AND RIGHT DOUBLE \d226 \d149 \d146 ; BOX DRAWINGS DOWN SINGLE AND RIGHT DOUBLE \d226 \d149 \d147 ; BOX DRAWINGS DOWN DOUBLE AND RIGHT SINGLE \d226 \d149 \d171 ; BOX DRAWINGS VERTICAL DOUBLE AND HORIZONTAL SINGLE \d226 \d149 \d170 ; BOX DRAWINGS VERTICAL SINGLE AND HORIZONTAL DOUBLE \d226 \d148 \d152 ; BOX DRAWINGS LIGHT UP AND LEFT \d226 \d148 \d140 ; BOX DRAWINGS LIGHT DOWN AND RIGHT \d226 \d150 \d136 ; FULL BLOCK \d226 \d150 \d132 ; LOWER HALF BLOCK \d226 \d150 \d140 ; LEFT HALF BLOCK \d226 \d150 \d144 ; RIGHT HALF BLOCK \d226 \d150 \d128 ; UPPER HALF BLOCK \d206 \d177 ; GREEK SMALL LETTER ALPHA \d195 \d159 ; LATIN SMALL LETTER SHARP S \d206 \d147 ; GREEK CAPITAL LETTER GAMMA \d207 \d128 ; GREEK SMALL LETTER PI \d206 \d163 ; GREEK CAPITAL LETTER SIGMA \d207 \d131 ; GREEK SMALL LETTER SIGMA \d194 \d181 ; MICRO SIGN \d207 \d132 ; GREEK SMALL LETTER TAU \d206 \d166 ; GREEK CAPITAL LETTER PHI \d206 \d152 ; GREEK CAPITAL LETTER THETA \d206 \d169 ; GREEK CAPITAL LETTER OMEGA \d206 \d180 ; GREEK SMALL LETTER DELTA \d226 \d136 \d158 ; INFINITY \d207 \d134 ; GREEK SMALL LETTER PHI \d206 \d181 ; GREEK SMALL LETTER EPSILON \d226 \d136 \d169 ; INTERSECTION \d226 \d137 \d161 ; IDENTICAL TO \d194 \d177 ; PLUS-MINUS SIGN \d226 \d137 \d165 ; GREATER-THAN OR EQUAL TO \d226 \d137 \d164 ; LESS-THAN OR EQUAL TO \d226 \d140 \d160 ; TOP HALF INTEGRAL \d226 \d140 \d161 ; BOTTOM HALF INTEGRAL \d195 \d183 ; DIVISION SIGN \d226 \d137 \d136 ; ALMOST EQUAL TO \d194 \d176 ; DEGREE SIGN \d226 \d136 \d153 ; BULLET OPERATOR \d194 \d183 ; MIDDLE DOT \d226 \d136 \d154 ; SQUARE ROOT \d226 \d129 \d191 ; SUPERSCRIPT LATIN SMALL LETTER N \d194 \d178 ; SUPERSCRIPT TWO \d226 \d150 \d160 ; BLACK SQUARE \d194 \d160 ; NO-BREAK SPACE END jamnntpd-1.2/unicode/xlat/866_utf.chs000066400000000000000000000274701141642135500175010ustar00rootroot00000000000000; ; This file is a charset conversion module in text form. ; ; Source file: ; http://www.unicode.org/Public/MAPPINGS/VENDORS/MICSFT/PC/CP866.TXT ; 100000 ; ID number (when >65535, all 255 chars will be translated) 0 ; version number ; 2 ; level number ; CP866 UTF-8 ; \0 \0 ; NULL \0 \d1 ; START OF HEADING \0 \d2 ; START OF TEXT \0 \d3 ; END OF TEXT \0 \d4 ; END OF TRANSMISSION \0 \d5 ; ENQUIRY \0 \d6 ; ACKNOWLEDGE \0 \d7 ; BELL \0 \d8 ; BACKSPACE \0 \d9 ; HORIZONTAL TABULATION \0 \d10 ; LINE FEED \0 \d11 ; VERTICAL TABULATION \0 \d12 ; FORM FEED \0 \d13 ; CARRIAGE RETURN \0 \d14 ; SHIFT OUT \0 \d15 ; SHIFT IN \0 \d16 ; DATA LINK ESCAPE \0 \d17 ; DEVICE CONTROL ONE \0 \d18 ; DEVICE CONTROL TWO \0 \d19 ; DEVICE CONTROL THREE \0 \d20 ; DEVICE CONTROL FOUR \0 \d21 ; NEGATIVE ACKNOWLEDGE \0 \d22 ; SYNCHRONOUS IDLE \0 \d23 ; END OF TRANSMISSION BLOCK \0 \d24 ; CANCEL \0 \d25 ; END OF MEDIUM \0 \d26 ; SUBSTITUTE \0 \d27 ; ESCAPE \0 \d28 ; FILE SEPARATOR \0 \d29 ; GROUP SEPARATOR \0 \d30 ; RECORD SEPARATOR \0 \d31 ; UNIT SEPARATOR \0 \d32 ; SPACE \0 \d33 ; EXCLAMATION MARK \0 \d34 ; QUOTATION MARK \0 \d35 ; NUMBER SIGN \0 \d36 ; DOLLAR SIGN \0 \d37 ; PERCENT SIGN \0 \d38 ; AMPERSAND \0 \d39 ; APOSTROPHE \0 \d40 ; LEFT PARENTHESIS \0 \d41 ; RIGHT PARENTHESIS \0 \d42 ; ASTERISK \0 \d43 ; PLUS SIGN \0 \d44 ; COMMA \0 \d45 ; HYPHEN-MINUS \0 \d46 ; FULL STOP \0 \d47 ; SOLIDUS \0 \d48 ; DIGIT ZERO \0 \d49 ; DIGIT ONE \0 \d50 ; DIGIT TWO \0 \d51 ; DIGIT THREE \0 \d52 ; DIGIT FOUR \0 \d53 ; DIGIT FIVE \0 \d54 ; DIGIT SIX \0 \d55 ; DIGIT SEVEN \0 \d56 ; DIGIT EIGHT \0 \d57 ; DIGIT NINE \0 \d58 ; COLON \0 \d59 ; SEMICOLON \0 \d60 ; LESS-THAN SIGN \0 \d61 ; EQUALS SIGN \0 \d62 ; GREATER-THAN SIGN \0 \d63 ; QUESTION MARK \0 \d64 ; COMMERCIAL AT \0 \d65 ; LATIN CAPITAL LETTER A \0 \d66 ; LATIN CAPITAL LETTER B \0 \d67 ; LATIN CAPITAL LETTER C \0 \d68 ; LATIN CAPITAL LETTER D \0 \d69 ; LATIN CAPITAL LETTER E \0 \d70 ; LATIN CAPITAL LETTER F \0 \d71 ; LATIN CAPITAL LETTER G \0 \d72 ; LATIN CAPITAL LETTER H \0 \d73 ; LATIN CAPITAL LETTER I \0 \d74 ; LATIN CAPITAL LETTER J \0 \d75 ; LATIN CAPITAL LETTER K \0 \d76 ; LATIN CAPITAL LETTER L \0 \d77 ; LATIN CAPITAL LETTER M \0 \d78 ; LATIN CAPITAL LETTER N \0 \d79 ; LATIN CAPITAL LETTER O \0 \d80 ; LATIN CAPITAL LETTER P \0 \d81 ; LATIN CAPITAL LETTER Q \0 \d82 ; LATIN CAPITAL LETTER R \0 \d83 ; LATIN CAPITAL LETTER S \0 \d84 ; LATIN CAPITAL LETTER T \0 \d85 ; LATIN CAPITAL LETTER U \0 \d86 ; LATIN CAPITAL LETTER V \0 \d87 ; LATIN CAPITAL LETTER W \0 \d88 ; LATIN CAPITAL LETTER X \0 \d89 ; LATIN CAPITAL LETTER Y \0 \d90 ; LATIN CAPITAL LETTER Z \0 \d91 ; LEFT SQUARE BRACKET \0 \d92 ; REVERSE SOLIDUS \0 \d93 ; RIGHT SQUARE BRACKET \0 \d94 ; CIRCUMFLEX ACCENT \0 \d95 ; LOW LINE \0 \d96 ; GRAVE ACCENT \0 \d97 ; LATIN SMALL LETTER A \0 \d98 ; LATIN SMALL LETTER B \0 \d99 ; LATIN SMALL LETTER C \0 \d100 ; LATIN SMALL LETTER D \0 \d101 ; LATIN SMALL LETTER E \0 \d102 ; LATIN SMALL LETTER F \0 \d103 ; LATIN SMALL LETTER G \0 \d104 ; LATIN SMALL LETTER H \0 \d105 ; LATIN SMALL LETTER I \0 \d106 ; LATIN SMALL LETTER J \0 \d107 ; LATIN SMALL LETTER K \0 \d108 ; LATIN SMALL LETTER L \0 \d109 ; LATIN SMALL LETTER M \0 \d110 ; LATIN SMALL LETTER N \0 \d111 ; LATIN SMALL LETTER O \0 \d112 ; LATIN SMALL LETTER P \0 \d113 ; LATIN SMALL LETTER Q \0 \d114 ; LATIN SMALL LETTER R \0 \d115 ; LATIN SMALL LETTER S \0 \d116 ; LATIN SMALL LETTER T \0 \d117 ; LATIN SMALL LETTER U \0 \d118 ; LATIN SMALL LETTER V \0 \d119 ; LATIN SMALL LETTER W \0 \d120 ; LATIN SMALL LETTER X \0 \d121 ; LATIN SMALL LETTER Y \0 \d122 ; LATIN SMALL LETTER Z \0 \d123 ; LEFT CURLY BRACKET \0 \d124 ; VERTICAL LINE \0 \d125 ; RIGHT CURLY BRACKET \0 \d126 ; TILDE \0 \d127 ; DELETE \d208 \d144 ; CYRILLIC CAPITAL LETTER A \d208 \d145 ; CYRILLIC CAPITAL LETTER BE \d208 \d146 ; CYRILLIC CAPITAL LETTER VE \d208 \d147 ; CYRILLIC CAPITAL LETTER GHE \d208 \d148 ; CYRILLIC CAPITAL LETTER DE \d208 \d149 ; CYRILLIC CAPITAL LETTER IE \d208 \d150 ; CYRILLIC CAPITAL LETTER ZHE \d208 \d151 ; CYRILLIC CAPITAL LETTER ZE \d208 \d152 ; CYRILLIC CAPITAL LETTER I \d208 \d153 ; CYRILLIC CAPITAL LETTER SHORT I \d208 \d154 ; CYRILLIC CAPITAL LETTER KA \d208 \d155 ; CYRILLIC CAPITAL LETTER EL \d208 \d156 ; CYRILLIC CAPITAL LETTER EM \d208 \d157 ; CYRILLIC CAPITAL LETTER EN \d208 \d158 ; CYRILLIC CAPITAL LETTER O \d208 \d159 ; CYRILLIC CAPITAL LETTER PE \d208 \d160 ; CYRILLIC CAPITAL LETTER ER \d208 \d161 ; CYRILLIC CAPITAL LETTER ES \d208 \d162 ; CYRILLIC CAPITAL LETTER TE \d208 \d163 ; CYRILLIC CAPITAL LETTER U \d208 \d164 ; CYRILLIC CAPITAL LETTER EF \d208 \d165 ; CYRILLIC CAPITAL LETTER HA \d208 \d166 ; CYRILLIC CAPITAL LETTER TSE \d208 \d167 ; CYRILLIC CAPITAL LETTER CHE \d208 \d168 ; CYRILLIC CAPITAL LETTER SHA \d208 \d169 ; CYRILLIC CAPITAL LETTER SHCHA \d208 \d170 ; CYRILLIC CAPITAL LETTER HARD SIGN \d208 \d171 ; CYRILLIC CAPITAL LETTER YERU \d208 \d172 ; CYRILLIC CAPITAL LETTER SOFT SIGN \d208 \d173 ; CYRILLIC CAPITAL LETTER E \d208 \d174 ; CYRILLIC CAPITAL LETTER YU \d208 \d175 ; CYRILLIC CAPITAL LETTER YA \d208 \d176 ; CYRILLIC SMALL LETTER A \d208 \d177 ; CYRILLIC SMALL LETTER BE \d208 \d178 ; CYRILLIC SMALL LETTER VE \d208 \d179 ; CYRILLIC SMALL LETTER GHE \d208 \d180 ; CYRILLIC SMALL LETTER DE \d208 \d181 ; CYRILLIC SMALL LETTER IE \d208 \d182 ; CYRILLIC SMALL LETTER ZHE \d208 \d183 ; CYRILLIC SMALL LETTER ZE \d208 \d184 ; CYRILLIC SMALL LETTER I \d208 \d185 ; CYRILLIC SMALL LETTER SHORT I \d208 \d186 ; CYRILLIC SMALL LETTER KA \d208 \d187 ; CYRILLIC SMALL LETTER EL \d208 \d188 ; CYRILLIC SMALL LETTER EM \d208 \d189 ; CYRILLIC SMALL LETTER EN \d208 \d190 ; CYRILLIC SMALL LETTER O \d208 \d191 ; CYRILLIC SMALL LETTER PE \d226 \d150 \d145 ; LIGHT SHADE \d226 \d150 \d146 ; MEDIUM SHADE \d226 \d150 \d147 ; DARK SHADE \d226 \d148 \d130 ; BOX DRAWINGS LIGHT VERTICAL \d226 \d148 \d164 ; BOX DRAWINGS LIGHT VERTICAL AND LEFT \d226 \d149 \d161 ; BOX DRAWINGS VERTICAL SINGLE AND LEFT DOUBLE \d226 \d149 \d162 ; BOX DRAWINGS VERTICAL DOUBLE AND LEFT SINGLE \d226 \d149 \d150 ; BOX DRAWINGS DOWN DOUBLE AND LEFT SINGLE \d226 \d149 \d149 ; BOX DRAWINGS DOWN SINGLE AND LEFT DOUBLE \d226 \d149 \d163 ; BOX DRAWINGS DOUBLE VERTICAL AND LEFT \d226 \d149 \d145 ; BOX DRAWINGS DOUBLE VERTICAL \d226 \d149 \d151 ; BOX DRAWINGS DOUBLE DOWN AND LEFT \d226 \d149 \d157 ; BOX DRAWINGS DOUBLE UP AND LEFT \d226 \d149 \d156 ; BOX DRAWINGS UP DOUBLE AND LEFT SINGLE \d226 \d149 \d155 ; BOX DRAWINGS UP SINGLE AND LEFT DOUBLE \d226 \d148 \d144 ; BOX DRAWINGS LIGHT DOWN AND LEFT \d226 \d148 \d148 ; BOX DRAWINGS LIGHT UP AND RIGHT \d226 \d148 \d180 ; BOX DRAWINGS LIGHT UP AND HORIZONTAL \d226 \d148 \d172 ; BOX DRAWINGS LIGHT DOWN AND HORIZONTAL \d226 \d148 \d156 ; BOX DRAWINGS LIGHT VERTICAL AND RIGHT \d226 \d148 \d128 ; BOX DRAWINGS LIGHT HORIZONTAL \d226 \d148 \d188 ; BOX DRAWINGS LIGHT VERTICAL AND HORIZONTAL \d226 \d149 \d158 ; BOX DRAWINGS VERTICAL SINGLE AND RIGHT DOUBLE \d226 \d149 \d159 ; BOX DRAWINGS VERTICAL DOUBLE AND RIGHT SINGLE \d226 \d149 \d154 ; BOX DRAWINGS DOUBLE UP AND RIGHT \d226 \d149 \d148 ; BOX DRAWINGS DOUBLE DOWN AND RIGHT \d226 \d149 \d169 ; BOX DRAWINGS DOUBLE UP AND HORIZONTAL \d226 \d149 \d166 ; BOX DRAWINGS DOUBLE DOWN AND HORIZONTAL \d226 \d149 \d160 ; BOX DRAWINGS DOUBLE VERTICAL AND RIGHT \d226 \d149 \d144 ; BOX DRAWINGS DOUBLE HORIZONTAL \d226 \d149 \d172 ; BOX DRAWINGS DOUBLE VERTICAL AND HORIZONTAL \d226 \d149 \d167 ; BOX DRAWINGS UP SINGLE AND HORIZONTAL DOUBLE \d226 \d149 \d168 ; BOX DRAWINGS UP DOUBLE AND HORIZONTAL SINGLE \d226 \d149 \d164 ; BOX DRAWINGS DOWN SINGLE AND HORIZONTAL DOUBLE \d226 \d149 \d165 ; BOX DRAWINGS DOWN DOUBLE AND HORIZONTAL SINGLE \d226 \d149 \d153 ; BOX DRAWINGS UP DOUBLE AND RIGHT SINGLE \d226 \d149 \d152 ; BOX DRAWINGS UP SINGLE AND RIGHT DOUBLE \d226 \d149 \d146 ; BOX DRAWINGS DOWN SINGLE AND RIGHT DOUBLE \d226 \d149 \d147 ; BOX DRAWINGS DOWN DOUBLE AND RIGHT SINGLE \d226 \d149 \d171 ; BOX DRAWINGS VERTICAL DOUBLE AND HORIZONTAL SINGLE \d226 \d149 \d170 ; BOX DRAWINGS VERTICAL SINGLE AND HORIZONTAL DOUBLE \d226 \d148 \d152 ; BOX DRAWINGS LIGHT UP AND LEFT \d226 \d148 \d140 ; BOX DRAWINGS LIGHT DOWN AND RIGHT \d226 \d150 \d136 ; FULL BLOCK \d226 \d150 \d132 ; LOWER HALF BLOCK \d226 \d150 \d140 ; LEFT HALF BLOCK \d226 \d150 \d144 ; RIGHT HALF BLOCK \d226 \d150 \d128 ; UPPER HALF BLOCK \d209 \d128 ; CYRILLIC SMALL LETTER ER \d209 \d129 ; CYRILLIC SMALL LETTER ES \d209 \d130 ; CYRILLIC SMALL LETTER TE \d209 \d131 ; CYRILLIC SMALL LETTER U \d209 \d132 ; CYRILLIC SMALL LETTER EF \d209 \d133 ; CYRILLIC SMALL LETTER HA \d209 \d134 ; CYRILLIC SMALL LETTER TSE \d209 \d135 ; CYRILLIC SMALL LETTER CHE \d209 \d136 ; CYRILLIC SMALL LETTER SHA \d209 \d137 ; CYRILLIC SMALL LETTER SHCHA \d209 \d138 ; CYRILLIC SMALL LETTER HARD SIGN \d209 \d139 ; CYRILLIC SMALL LETTER YERU \d209 \d140 ; CYRILLIC SMALL LETTER SOFT SIGN \d209 \d141 ; CYRILLIC SMALL LETTER E \d209 \d142 ; CYRILLIC SMALL LETTER YU \d209 \d143 ; CYRILLIC SMALL LETTER YA \d208 \d129 ; CYRILLIC CAPITAL LETTER IO \d209 \d145 ; CYRILLIC SMALL LETTER IO \d208 \d132 ; CYRILLIC CAPITAL LETTER UKRAINIAN IE \d209 \d148 ; CYRILLIC SMALL LETTER UKRAINIAN IE \d208 \d135 ; CYRILLIC CAPITAL LETTER YI \d209 \d151 ; CYRILLIC SMALL LETTER YI \d208 \d142 ; CYRILLIC CAPITAL LETTER SHORT U \d209 \d158 ; CYRILLIC SMALL LETTER SHORT U \d194 \d176 ; DEGREE SIGN \d226 \d136 \d153 ; BULLET OPERATOR \d194 \d183 ; MIDDLE DOT \d226 \d136 \d154 ; SQUARE ROOT \d226 \d132 \d150 ; NUMERO SIGN \d194 \d164 ; CURRENCY SIGN \d226 \d150 \d160 ; BLACK SQUARE \d194 \d160 ; NO-BREAK SPACE END jamnntpd-1.2/unicode/xlat/iso_utf.chs000066400000000000000000000266241141642135500177500ustar00rootroot00000000000000; ; This file is a charset conversion module in text form. ; ; Source file: ; http://www.unicode.org/Public/MAPPINGS/ISO8859/8859-1.TXT ; 100000 ; ID number (when >65535, all 255 chars will be translated) 0 ; version number ; 2 ; level number ; LATIN-1 UTF-8 ; \0 \0 ; NULL \0 \d1 ; START OF HEADING \0 \d2 ; START OF TEXT \0 \d3 ; END OF TEXT \0 \d4 ; END OF TRANSMISSION \0 \d5 ; ENQUIRY \0 \d6 ; ACKNOWLEDGE \0 \d7 ; BELL \0 \d8 ; BACKSPACE \0 \d9 ; HORIZONTAL TABULATION \0 \d10 ; LINE FEED \0 \d11 ; VERTICAL TABULATION \0 \d12 ; FORM FEED \0 \d13 ; CARRIAGE RETURN \0 \d14 ; SHIFT OUT \0 \d15 ; SHIFT IN \0 \d16 ; DATA LINK ESCAPE \0 \d17 ; DEVICE CONTROL ONE \0 \d18 ; DEVICE CONTROL TWO \0 \d19 ; DEVICE CONTROL THREE \0 \d20 ; DEVICE CONTROL FOUR \0 \d21 ; NEGATIVE ACKNOWLEDGE \0 \d22 ; SYNCHRONOUS IDLE \0 \d23 ; END OF TRANSMISSION BLOCK \0 \d24 ; CANCEL \0 \d25 ; END OF MEDIUM \0 \d26 ; SUBSTITUTE \0 \d27 ; ESCAPE \0 \d28 ; FILE SEPARATOR \0 \d29 ; GROUP SEPARATOR \0 \d30 ; RECORD SEPARATOR \0 \d31 ; UNIT SEPARATOR \0 \d32 ; SPACE \0 \d33 ; EXCLAMATION MARK \0 \d34 ; QUOTATION MARK \0 \d35 ; NUMBER SIGN \0 \d36 ; DOLLAR SIGN \0 \d37 ; PERCENT SIGN \0 \d38 ; AMPERSAND \0 \d39 ; APOSTROPHE \0 \d40 ; LEFT PARENTHESIS \0 \d41 ; RIGHT PARENTHESIS \0 \d42 ; ASTERISK \0 \d43 ; PLUS SIGN \0 \d44 ; COMMA \0 \d45 ; HYPHEN-MINUS \0 \d46 ; FULL STOP \0 \d47 ; SOLIDUS \0 \d48 ; DIGIT ZERO \0 \d49 ; DIGIT ONE \0 \d50 ; DIGIT TWO \0 \d51 ; DIGIT THREE \0 \d52 ; DIGIT FOUR \0 \d53 ; DIGIT FIVE \0 \d54 ; DIGIT SIX \0 \d55 ; DIGIT SEVEN \0 \d56 ; DIGIT EIGHT \0 \d57 ; DIGIT NINE \0 \d58 ; COLON \0 \d59 ; SEMICOLON \0 \d60 ; LESS-THAN SIGN \0 \d61 ; EQUALS SIGN \0 \d62 ; GREATER-THAN SIGN \0 \d63 ; QUESTION MARK \0 \d64 ; COMMERCIAL AT \0 \d65 ; LATIN CAPITAL LETTER A \0 \d66 ; LATIN CAPITAL LETTER B \0 \d67 ; LATIN CAPITAL LETTER C \0 \d68 ; LATIN CAPITAL LETTER D \0 \d69 ; LATIN CAPITAL LETTER E \0 \d70 ; LATIN CAPITAL LETTER F \0 \d71 ; LATIN CAPITAL LETTER G \0 \d72 ; LATIN CAPITAL LETTER H \0 \d73 ; LATIN CAPITAL LETTER I \0 \d74 ; LATIN CAPITAL LETTER J \0 \d75 ; LATIN CAPITAL LETTER K \0 \d76 ; LATIN CAPITAL LETTER L \0 \d77 ; LATIN CAPITAL LETTER M \0 \d78 ; LATIN CAPITAL LETTER N \0 \d79 ; LATIN CAPITAL LETTER O \0 \d80 ; LATIN CAPITAL LETTER P \0 \d81 ; LATIN CAPITAL LETTER Q \0 \d82 ; LATIN CAPITAL LETTER R \0 \d83 ; LATIN CAPITAL LETTER S \0 \d84 ; LATIN CAPITAL LETTER T \0 \d85 ; LATIN CAPITAL LETTER U \0 \d86 ; LATIN CAPITAL LETTER V \0 \d87 ; LATIN CAPITAL LETTER W \0 \d88 ; LATIN CAPITAL LETTER X \0 \d89 ; LATIN CAPITAL LETTER Y \0 \d90 ; LATIN CAPITAL LETTER Z \0 \d91 ; LEFT SQUARE BRACKET \0 \d92 ; REVERSE SOLIDUS \0 \d93 ; RIGHT SQUARE BRACKET \0 \d94 ; CIRCUMFLEX ACCENT \0 \d95 ; LOW LINE \0 \d96 ; GRAVE ACCENT \0 \d97 ; LATIN SMALL LETTER A \0 \d98 ; LATIN SMALL LETTER B \0 \d99 ; LATIN SMALL LETTER C \0 \d100 ; LATIN SMALL LETTER D \0 \d101 ; LATIN SMALL LETTER E \0 \d102 ; LATIN SMALL LETTER F \0 \d103 ; LATIN SMALL LETTER G \0 \d104 ; LATIN SMALL LETTER H \0 \d105 ; LATIN SMALL LETTER I \0 \d106 ; LATIN SMALL LETTER J \0 \d107 ; LATIN SMALL LETTER K \0 \d108 ; LATIN SMALL LETTER L \0 \d109 ; LATIN SMALL LETTER M \0 \d110 ; LATIN SMALL LETTER N \0 \d111 ; LATIN SMALL LETTER O \0 \d112 ; LATIN SMALL LETTER P \0 \d113 ; LATIN SMALL LETTER Q \0 \d114 ; LATIN SMALL LETTER R \0 \d115 ; LATIN SMALL LETTER S \0 \d116 ; LATIN SMALL LETTER T \0 \d117 ; LATIN SMALL LETTER U \0 \d118 ; LATIN SMALL LETTER V \0 \d119 ; LATIN SMALL LETTER W \0 \d120 ; LATIN SMALL LETTER X \0 \d121 ; LATIN SMALL LETTER Y \0 \d122 ; LATIN SMALL LETTER Z \0 \d123 ; LEFT CURLY BRACKET \0 \d124 ; VERTICAL LINE \0 \d125 ; RIGHT CURLY BRACKET \0 \d126 ; TILDE \0 \d127 ; DELETE \d194 \d128 ; \d194 \d129 ; \d194 \d130 ; \d194 \d131 ; \d194 \d132 ; \d194 \d133 ; \d194 \d134 ; \d194 \d135 ; \d194 \d136 ; \d194 \d137 ; \d194 \d138 ; \d194 \d139 ; \d194 \d140 ; \d194 \d141 ; \d194 \d142 ; \d194 \d143 ; \d194 \d144 ; \d194 \d145 ; \d194 \d146 ; \d194 \d147 ; \d194 \d148 ; \d194 \d149 ; \d194 \d150 ; \d194 \d151 ; \d194 \d152 ; \d194 \d153 ; \d194 \d154 ; \d194 \d155 ; \d194 \d156 ; \d194 \d157 ; \d194 \d158 ; \d194 \d159 ; \d194 \d160 ; NO-BREAK SPACE \d194 \d161 ; INVERTED EXCLAMATION MARK \d194 \d162 ; CENT SIGN \d194 \d163 ; POUND SIGN \d194 \d164 ; CURRENCY SIGN \d194 \d165 ; YEN SIGN \d194 \d166 ; BROKEN BAR \d194 \d167 ; SECTION SIGN \d194 \d168 ; DIAERESIS \d194 \d169 ; COPYRIGHT SIGN \d194 \d170 ; FEMININE ORDINAL INDICATOR \d194 \d171 ; LEFT-POINTING DOUBLE ANGLE QUOTATION MARK \d194 \d172 ; NOT SIGN \d194 \d173 ; SOFT HYPHEN \d194 \d174 ; REGISTERED SIGN \d194 \d175 ; MACRON \d194 \d176 ; DEGREE SIGN \d194 \d177 ; PLUS-MINUS SIGN \d194 \d178 ; SUPERSCRIPT TWO \d194 \d179 ; SUPERSCRIPT THREE \d194 \d180 ; ACUTE ACCENT \d194 \d181 ; MICRO SIGN \d194 \d182 ; PILCROW SIGN \d194 \d183 ; MIDDLE DOT \d194 \d184 ; CEDILLA \d194 \d185 ; SUPERSCRIPT ONE \d194 \d186 ; MASCULINE ORDINAL INDICATOR \d194 \d187 ; RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK \d194 \d188 ; VULGAR FRACTION ONE QUARTER \d194 \d189 ; VULGAR FRACTION ONE HALF \d194 \d190 ; VULGAR FRACTION THREE QUARTERS \d194 \d191 ; INVERTED QUESTION MARK \d195 \d128 ; LATIN CAPITAL LETTER A WITH GRAVE \d195 \d129 ; LATIN CAPITAL LETTER A WITH ACUTE \d195 \d130 ; LATIN CAPITAL LETTER A WITH CIRCUMFLEX \d195 \d131 ; LATIN CAPITAL LETTER A WITH TILDE \d195 \d132 ; LATIN CAPITAL LETTER A WITH DIAERESIS \d195 \d133 ; LATIN CAPITAL LETTER A WITH RING ABOVE \d195 \d134 ; LATIN CAPITAL LETTER AE \d195 \d135 ; LATIN CAPITAL LETTER C WITH CEDILLA \d195 \d136 ; LATIN CAPITAL LETTER E WITH GRAVE \d195 \d137 ; LATIN CAPITAL LETTER E WITH ACUTE \d195 \d138 ; LATIN CAPITAL LETTER E WITH CIRCUMFLEX \d195 \d139 ; LATIN CAPITAL LETTER E WITH DIAERESIS \d195 \d140 ; LATIN CAPITAL LETTER I WITH GRAVE \d195 \d141 ; LATIN CAPITAL LETTER I WITH ACUTE \d195 \d142 ; LATIN CAPITAL LETTER I WITH CIRCUMFLEX \d195 \d143 ; LATIN CAPITAL LETTER I WITH DIAERESIS \d195 \d144 ; LATIN CAPITAL LETTER ETH (Icelandic) \d195 \d145 ; LATIN CAPITAL LETTER N WITH TILDE \d195 \d146 ; LATIN CAPITAL LETTER O WITH GRAVE \d195 \d147 ; LATIN CAPITAL LETTER O WITH ACUTE \d195 \d148 ; LATIN CAPITAL LETTER O WITH CIRCUMFLEX \d195 \d149 ; LATIN CAPITAL LETTER O WITH TILDE \d195 \d150 ; LATIN CAPITAL LETTER O WITH DIAERESIS \d195 \d151 ; MULTIPLICATION SIGN \d195 \d152 ; LATIN CAPITAL LETTER O WITH STROKE \d195 \d153 ; LATIN CAPITAL LETTER U WITH GRAVE \d195 \d154 ; LATIN CAPITAL LETTER U WITH ACUTE \d195 \d155 ; LATIN CAPITAL LETTER U WITH CIRCUMFLEX \d195 \d156 ; LATIN CAPITAL LETTER U WITH DIAERESIS \d195 \d157 ; LATIN CAPITAL LETTER Y WITH ACUTE \d195 \d158 ; LATIN CAPITAL LETTER THORN (Icelandic) \d195 \d159 ; LATIN SMALL LETTER SHARP S (German) \d195 \d160 ; LATIN SMALL LETTER A WITH GRAVE \d195 \d161 ; LATIN SMALL LETTER A WITH ACUTE \d195 \d162 ; LATIN SMALL LETTER A WITH CIRCUMFLEX \d195 \d163 ; LATIN SMALL LETTER A WITH TILDE \d195 \d164 ; LATIN SMALL LETTER A WITH DIAERESIS \d195 \d165 ; LATIN SMALL LETTER A WITH RING ABOVE \d195 \d166 ; LATIN SMALL LETTER AE \d195 \d167 ; LATIN SMALL LETTER C WITH CEDILLA \d195 \d168 ; LATIN SMALL LETTER E WITH GRAVE \d195 \d169 ; LATIN SMALL LETTER E WITH ACUTE \d195 \d170 ; LATIN SMALL LETTER E WITH CIRCUMFLEX \d195 \d171 ; LATIN SMALL LETTER E WITH DIAERESIS \d195 \d172 ; LATIN SMALL LETTER I WITH GRAVE \d195 \d173 ; LATIN SMALL LETTER I WITH ACUTE \d195 \d174 ; LATIN SMALL LETTER I WITH CIRCUMFLEX \d195 \d175 ; LATIN SMALL LETTER I WITH DIAERESIS \d195 \d176 ; LATIN SMALL LETTER ETH (Icelandic) \d195 \d177 ; LATIN SMALL LETTER N WITH TILDE \d195 \d178 ; LATIN SMALL LETTER O WITH GRAVE \d195 \d179 ; LATIN SMALL LETTER O WITH ACUTE \d195 \d180 ; LATIN SMALL LETTER O WITH CIRCUMFLEX \d195 \d181 ; LATIN SMALL LETTER O WITH TILDE \d195 \d182 ; LATIN SMALL LETTER O WITH DIAERESIS \d195 \d183 ; DIVISION SIGN \d195 \d184 ; LATIN SMALL LETTER O WITH STROKE \d195 \d185 ; LATIN SMALL LETTER U WITH GRAVE \d195 \d186 ; LATIN SMALL LETTER U WITH ACUTE \d195 \d187 ; LATIN SMALL LETTER U WITH CIRCUMFLEX \d195 \d188 ; LATIN SMALL LETTER U WITH DIAERESIS \d195 \d189 ; LATIN SMALL LETTER Y WITH ACUTE \d195 \d190 ; LATIN SMALL LETTER THORN (Icelandic) \d195 \d191 ; LATIN SMALL LETTER Y WITH DIAERESIS END jamnntpd-1.2/xlat/000077500000000000000000000000001141642135500141415ustar00rootroot00000000000000jamnntpd-1.2/xlat/437_iso.chs000066400000000000000000000020631141642135500160300ustar00rootroot00000000000000; ; Generated by makechs 1.0 by Johan Billing. Some tweaking may be required. ; 0 ; ID number (when >65535, all 255 chars will be translated) 0 ; version number ; 2 ; level number ; CP437 LATIN-1 ; \0 \xC7 \0 \xFC \0 \xE9 \0 \xE2 \0 \xE4 \0 \xE0 \0 \xE5 \0 \xE7 \0 \xEA \0 \xEB \0 \xE8 \0 \xEF \0 \xEE \0 \xEC \0 \xC4 \0 \xC5 \0 \xC9 \0 \xE6 \0 \xC6 \0 \xF4 \0 \xF6 \0 \xF2 \0 \xFB \0 \xF9 \0 \xFF \0 \xD6 \0 \xDC \0 \xA2 \0 \xA3 \0 \xA5 P t s \0 f \0 \xE1 \0 \xED \0 \xF3 \0 \xFA \0 \xF1 \0 \xD1 \0 \xAA \0 \xBA \0 \xBF N O T \0 \xAC \0 \xBD \0 \xBC \0 \xA1 \0 \xAB \0 \xBB \0 # \0 # \0 # \0 | \0 + \0 + \0 + \0 + \0 + \0 + \0 | \0 + \0 + \0 + \0 + \0 + \0 + \0 + \0 + \0 + \0 - \0 + \0 + \0 + \0 + \0 + \0 + \0 + \0 + \0 = \0 + \0 + \0 + \0 + \0 + \0 + \0 + \0 + \0 + \0 + \0 + \0 + \0 + \0 # \0 # \0 # \0 # \0 # a l p h \0 \xDF G a m m p i S i g m s i g m \0 \xB5 t a u P h i T h e t O m e g d e l t i n f p h i e p s \0 n \0 = \0 \xB1 > = < = I n t e g r a l \0 \xF7 ~ ~ \0 \xB0 \0 . \0 \xB7 s q r t ^ n \0 \xB2 \0 # \0 \xA0 END jamnntpd-1.2/xlat/850_iso.chs000066400000000000000000000022241141642135500160260ustar00rootroot00000000000000; ; Generated by makechs 1.0 by Johan Billing. Some tweaking may be required. ; 0 ; ID number (when >65535, all 255 chars will be translated) 0 ; version number ; 2 ; level number ; CP850 LATIN-1 ; \0 \xC7 \0 \xFC \0 \xE9 \0 \xE2 \0 \xE4 \0 \xE0 \0 \xE5 \0 \xE7 \0 \xEA \0 \xEB \0 \xE8 \0 \xEF \0 \xEE \0 \xEC \0 \xC4 \0 \xC5 \0 \xC9 \0 \xE6 \0 \xC6 \0 \xF4 \0 \xF6 \0 \xF2 \0 \xFB \0 \xF9 \0 \xFF \0 \xD6 \0 \xDC \0 \xF8 \0 \xA3 \0 \xD8 \0 \xD7 \0 f \0 \xE1 \0 \xED \0 \xF3 \0 \xFA \0 \xF1 \0 \xD1 \0 \xAA \0 \xBA \0 \xBF \0 \xAE \0 \xAC \0 \xBD \0 \xBC \0 \xA1 \0 \xAB \0 \xBB \0 # \0 # \0 # \0 | \0 + \0 \xC1 \0 \xC2 \0 \xC0 \0 \xA9 \0 + \0 | \0 + \0 + \0 \xA2 \0 \xA5 \0 + \0 + \0 + \0 + \0 + \0 - \0 + \0 \xE3 \0 \xC3 \0 + \0 + \0 + \0 + \0 + \0 = \0 + \0 \xA4 \0 \xF0 \0 \xD0 \0 \xCA \0 \xCB \0 \xC8 \0 i \0 \xCD \0 \xCE \0 \xCF \0 + \0 + \0 # \0 # \0 \xA6 \0 \xCC \0 # \0 \xD3 \0 \xDF \0 \xD4 \0 \xD2 \0 \xF5 \0 \xD5 \0 \xB5 \0 \xFE \0 \xDE \0 \xDA \0 \xDB \0 \xD9 \0 \xFD \0 \xDD \0 \xAF \0 \xB4 \0 \xAD \0 \xB1 \0 _ \0 \xBE \0 \xB6 \0 \xA7 \0 \xF7 \0 \xB8 \0 \xB0 \0 \xA8 \0 \xB7 \0 \xB9 \0 \xB3 \0 \xB2 \0 # \0 \xA0 END jamnntpd-1.2/xlat/865_iso.chs000066400000000000000000000020631141642135500160350ustar00rootroot00000000000000; ; Generated by makechs 1.0 by Johan Billing. Some tweaking may be required. ; 0 ; ID number (when >65535, all 255 chars will be translated) 0 ; version number ; 2 ; level number ; CP865 LATIN-1 ; \0 \xC7 \0 \xFC \0 \xE9 \0 \xE2 \0 \xE4 \0 \xE0 \0 \xE5 \0 \xE7 \0 \xEA \0 \xEB \0 \xE8 \0 \xEF \0 \xEE \0 \xEC \0 \xC4 \0 \xC5 \0 \xC9 \0 \xE6 \0 \xC6 \0 \xF4 \0 \xF6 \0 \xF2 \0 \xFB \0 \xF9 \0 \xFF \0 \xD6 \0 \xDC \0 \xF8 \0 \xA3 \0 \xD8 P t s \0 f \0 \xE1 \0 \xED \0 \xF3 \0 \xFA \0 \xF1 \0 \xD1 \0 \xAA \0 \xBA \0 \xBF N O T \0 \xAC \0 \xBD \0 \xBC \0 \xA1 \0 \xAB \0 \xA4 \0 # \0 # \0 # \0 | \0 + \0 + \0 + \0 + \0 + \0 + \0 | \0 + \0 + \0 + \0 + \0 + \0 + \0 + \0 + \0 + \0 - \0 + \0 + \0 + \0 + \0 + \0 + \0 + \0 + \0 = \0 + \0 + \0 + \0 + \0 + \0 + \0 + \0 + \0 + \0 + \0 + \0 + \0 + \0 # \0 # \0 # \0 # \0 # a l p h \0 \xDF G a m m p i S i g m s i g m \0 \xB5 t a u P h i T h e t O m e g d e l t i n f p h i e p s \0 n \0 = \0 \xB1 > = < = I n t e g r a l \0 \xF7 ~ ~ \0 \xB0 \0 . \0 \xB7 s q r t ^ n \0 \xB2 \0 # \0 \xA0 END jamnntpd-1.2/xlat/866_koi.chs000066400000000000000000000023331141642135500160260ustar00rootroot00000000000000; ; Generated by makechs 1.0 by Johan Billing. Some tweaking may be required. ; 0 ; ID number (when >65535, all 255 chars will be translated) 0 ; version number ; 2 ; level number ; CP866 LATIN-1 ; \0 \xE1 \0 \xE2 \0 \xF7 \0 \xE7 \0 \xE4 \0 \xE5 \0 \xF6 \0 \xFA \0 \xE9 \0 \xEA \0 \xEB \0 \xEC \0 \xED \0 \xEE \0 \xEF \0 \xF0 \0 \xF2 \0 \xF3 \0 \xF4 \0 \xF5 \0 \xE6 \0 \xE8 \0 \xE3 \0 \xFE \0 \xFB \0 \xFD \0 \xFF \0 \xF9 \0 \xF8 \0 \xFC \0 \xE0 \0 \xF1 \0 \xC1 \0 \xC2 \0 \xD7 \0 \xC7 \0 \xC4 \0 \xC5 \0 \xD6 \0 \xDA \0 \xC9 \0 \xCA \0 \xCB \0 \xCC \0 \xCD \0 \xCE \0 \xCF \0 \xD0 \0 \x90 \0 \x91 \0 \x92 \0 \x81 \0 \x87 \0 \xB2 \0 \xB4 \0 \xA7 \0 \xA6 \0 \xB5 \0 \xA1 \0 \xA8 \0 \xAE \0 \xAD \0 \xAC \0 \x83 \0 \x84 \0 \x89 \0 \x88 \0 \x86 \0 \x80 \0 \x8A \0 \xAF \0 \xB0 \0 \xAB \0 \xA5 \0 \xBB \0 \xB8 \0 \xB1 \0 \xA0 \0 \xBE \0 \xB9 \0 \xBA \0 \xB6 \0 \xB7 \0 \xAA \0 \xA9 \0 \xA2 \0 \xA4 \0 \xBD \0 \xBC \0 \x85 \0 \x82 \0 \x8D \0 \x8C \0 \x8E \0 \x8F \0 \x8B \0 \xD2 \0 \xD3 \0 \xD4 \0 \xD5 \0 \xC6 \0 \xC8 \0 \xC3 \0 \xDE \0 \xDB \0 \xDD \0 \xDF \0 \xD9 \0 \xD8 \0 \xDC \0 \xC0 \0 \xD1 \0 \xB3 \0 \xA3 \0 ? \0 ? \0 ? \0 ? \0 ? \0 ? \0 \x9C \0 \x95 \0 \x9E \0 \x96 N o \0 ? \0 \x94 \0 \x9A END jamnntpd-1.2/xlat/iso_437.chs000066400000000000000000000046471141642135500160420ustar00rootroot00000000000000; ; Generated by makechs 1.0 by Johan Billing. Some tweaking may be required. ; 0 ; ID number (when >65535, all 255 chars will be translated) 0 ; version number ; 2 ; level number ; LATIN-1 CP437 ; E U R ; windows-1252 extension \0 ? ; windows-1252 extension \0 ' ; windows-1252 extension \0 \x9F ; windows-1252 extension \0 " ; windows-1252 extension . . . ; windows-1252 extension \0 + ; windows-1252 extension + + ; windows-1252 extension \0 ^ ; windows-1252 extension o / o o ; windows-1252 extension \0 S ; windows-1252 extension \0 < ; windows-1252 extension O E ; windows-1252 extension \0 ? ; windows-1252 extension \0 Z ; windows-1252 extension \0 ? ; windows-1252 extension \0 ? ; windows-1252 extension \0 ' ; windows-1252 extension \0 ' ; windows-1252 extension \0 " ; windows-1252 extension \0 " ; windows-1252 extension \0 o ; windows-1252 extension \0 - ; windows-1252 extension - - ; windows-1252 extension \0 ~ ; windows-1252 extension [ T M ] ; windows-1252 extension \0 s ; windows-1252 extension \0 > ; windows-1252 extension o e ; windows-1252 extension \0 ? ; windows-1252 extension \0 z ; windows-1252 extension \0 Y ; windows-1252 extension \0 \xFF \0 \xAD \0 \x9B \0 \x9C \0 ? \0 \x9D \0 | \0 S \0 " ( c ) \0 \xA6 \0 \xAE \0 \xAA \0 - ( R ) \0 - \0 \xF8 \0 \xF1 \0 \xFD ^ 3 \0 ' \0 \xE6 \0 P \0 \xFA \0 , \0 1 \0 \xA7 \0 \xAF \0 \xAC \0 \xAB \x20 3 / 4 \0 \xA8 \0 A \0 A \0 A \0 A \0 \x8E \0 \x8F \0 \x92 \0 \x80 \0 E \0 \x90 \0 E \0 E \0 I \0 I \0 I \0 I \0 D \0 \xA5 \0 O \0 O \0 O \0 O \0 \x99 \0 x \0 O \0 U \0 U \0 U \0 \x9A \0 Y T h \0 \xE1 \0 \x85 \0 \xA0 \0 \x83 \0 a \0 \x84 \0 \x86 \0 \x91 \0 \x87 \0 \x8A \0 \x82 \0 \x88 \0 \x89 \0 \x8D \0 \xA1 \0 \x8C \0 \x8B \0 d \0 \xA4 \0 \x95 \0 \xA2 \0 \x93 \0 o \0 \x94 \0 \xF6 \0 o \0 \x97 \0 \xA3 \0 \x96 \0 \x81 \0 y t h \0 \x98 END jamnntpd-1.2/xlat/iso_850.chs000066400000000000000000000050431141642135500160300ustar00rootroot00000000000000; ; Generated by makechs 1.0 by Johan Billing. Some tweaking may be required. ; 0 ; ID number (when >65535, all 255 chars will be translated) 0 ; version number ; 2 ; level number ; LATIN-1 CP850 ; E U R ; windows-1252 extension \0 ? ; windows-1252 extension \0 ' ; windows-1252 extension \0 \x9F ; windows-1252 extension \0 " ; windows-1252 extension . . . ; windows-1252 extension \0 + ; windows-1252 extension + + ; windows-1252 extension \0 ^ ; windows-1252 extension o / o o ; windows-1252 extension \0 S ; windows-1252 extension \0 < ; windows-1252 extension O E ; windows-1252 extension \0 ? ; windows-1252 extension \0 Z ; windows-1252 extension \0 ? ; windows-1252 extension \0 ? ; windows-1252 extension \0 ' ; windows-1252 extension \0 ' ; windows-1252 extension \0 " ; windows-1252 extension \0 " ; windows-1252 extension \0 o ; windows-1252 extension \0 - ; windows-1252 extension - - ; windows-1252 extension \0 ~ ; windows-1252 extension [ T M ] ; windows-1252 extension \0 s ; windows-1252 extension \0 > ; windows-1252 extension o e ; windows-1252 extension \0 ? ; windows-1252 extension \0 z ; windows-1252 extension \0 Y ; windows-1252 extension \0 \xFF \0 \xAD \0 \xBD \0 \x9C \0 \xCF \0 \xBE \0 \xDD \0 \xF5 \0 \xF9 \0 \xB8 \0 \xA6 \0 \xAE \0 \xAA \0 \xF0 \0 \xA9 \0 \xEE \0 \xF8 \0 \xF1 \0 \xFD \0 \xFC \0 \xEF \0 \xE6 \0 \xF4 \0 \xFA \0 \xF7 \0 \xFB \0 \xA7 \0 \xAF \0 \xAC \0 \xAB \0 \xF3 \0 \xA8 \0 \xB7 \0 \xB5 \0 \xB6 \0 \xC7 \0 \x8E \0 \x8F \0 \x92 \0 \x80 \0 \xD4 \0 \x90 \0 \xD2 \0 \xD3 \0 \xDE \0 \xD6 \0 \xD7 \0 \xD8 \0 \xD1 \0 \xA5 \0 \xE3 \0 \xE0 \0 \xE2 \0 \xE5 \0 \x99 \0 \x9E \0 \x9D \0 \xEB \0 \xE9 \0 \xEA \0 \x9A \0 \xED \0 \xE8 \0 \xE1 \0 \x85 \0 \xA0 \0 \x83 \0 \xC6 \0 \x84 \0 \x86 \0 \x91 \0 \x87 \0 \x8A \0 \x82 \0 \x88 \0 \x89 \0 \x8D \0 \xA1 \0 \x8C \0 \x8B \0 \xD0 \0 \xA4 \0 \x95 \0 \xA2 \0 \x93 \0 \xE4 \0 \x94 \0 \xF6 \0 \x9B \0 \x97 \0 \xA3 \0 \x96 \0 \x81 \0 \xEC \0 \xE7 \0 \x98 END jamnntpd-1.2/xlat/iso_865.chs000066400000000000000000000046461141642135500160460ustar00rootroot00000000000000; ; Generated by makechs 1.0 by Johan Billing. Some tweaking may be required. ; 0 ; ID number (when >65535, all 255 chars will be translated) 0 ; version number ; 2 ; level number ; LATIN-1 CP865 ; E U R ; windows-1252 extension \0 ? ; windows-1252 extension \0 ' ; windows-1252 extension \0 \x9F ; windows-1252 extension \0 " ; windows-1252 extension . . . ; windows-1252 extension \0 + ; windows-1252 extension + + ; windows-1252 extension \0 ^ ; windows-1252 extension o / o o ; windows-1252 extension \0 S ; windows-1252 extension \0 < ; windows-1252 extension O E ; windows-1252 extension \0 ? ; windows-1252 extension \0 Z ; windows-1252 extension \0 ? ; windows-1252 extension \0 ? ; windows-1252 extension \0 ' ; windows-1252 extension \0 ' ; windows-1252 extension \0 " ; windows-1252 extension \0 " ; windows-1252 extension \0 o ; windows-1252 extension \0 - ; windows-1252 extension - - ; windows-1252 extension \0 ~ ; windows-1252 extension [ T M ] ; windows-1252 extension \0 s ; windows-1252 extension \0 > ; windows-1252 extension o e ; windows-1252 extension \0 ? ; windows-1252 extension \0 z ; windows-1252 extension \0 Y ; windows-1252 extension \0 \xFF \0 \xAD \0 c \0 \x9C \0 \xAF \0 Y \0 | \0 S \0 " ( c ) \0 \xA6 \0 \xAE \0 \xAA \0 - ( R ) \0 - \0 \xF8 \0 \xF1 \0 \xFD ^ 3 \0 ' \0 \xE6 \0 P \0 \xFA \0 , \0 1 \0 \xA7 > > \0 \xAC \0 \xAB \x20 3 / 4 \0 \xA8 \0 A \0 A \0 A \0 A \0 \x8E \0 \x8F \0 \x92 \0 \x80 \0 E \0 \x90 \0 E \0 E \0 I \0 I \0 I \0 I \0 D \0 \xA5 \0 O \0 O \0 O \0 O \0 \x99 \0 x \0 \x9D \0 U \0 U \0 U \0 \x9A \0 Y T h \0 \xE1 \0 \x85 \0 \xA0 \0 \x83 \0 a \0 \x84 \0 \x86 \0 \x91 \0 \x87 \0 \x8A \0 \x82 \0 \x88 \0 \x89 \0 \x8D \0 \xA1 \0 \x8C \0 \x8B \0 d \0 \xA4 \0 \x95 \0 \xA2 \0 \x93 \0 o \0 \x94 \0 \xF6 \0 \x9B \0 \x97 \0 \xA3 \0 \x96 \0 \x81 \0 y t h \0 \x98 END jamnntpd-1.2/xlat/koi_866.chs000066400000000000000000000023311141642135500160240ustar00rootroot00000000000000; ; Generated by makechs 1.0 by Johan Billing. Some tweaking may be required. ; 0 ; ID number (when >65535, all 255 chars will be translated) 0 ; version number ; 2 ; level number ; KOI8-R CP866 ; \0 \xC4 \0 \xB3 \0 \xDA \0 \xBF \0 \xC0 \0 \xD9 \0 \xC3 \0 \xB4 \0 \xC2 \0 \xC1 \0 \xC5 \0 \xDF \0 \xDC \0 \xDB \0 \xDD \0 \xDE \0 \xB0 \0 \xB1 \0 \xB2 \0 ? \0 \xFE \0 \xF9 \0 \xFB \0 ? < = > = \0 \xFF \0 ? \0 \xF8 ^ 2 \0 \xFA \0 : \0 \xCD \0 \xBA \0 \xD5 \0 \xF1 \0 \xD6 \0 \xC9 \0 \xB8 \0 \xB7 \0 \xBB \0 \xD4 \0 \xD3 \0 \xC8 \0 \xBE \0 \xBD \0 \xBC \0 \xC6 \0 \xC7 \0 \xCC \0 \xB5 \0 \xF0 \0 \xB6 \0 \xB9 \0 \xD1 \0 \xD2 \0 \xCB \0 \xCF \0 \xD0 \0 \xCA \0 \xD8 \0 \xD7 \0 \xCE ( c ) \0 \xEE \0 \xA0 \0 \xA1 \0 \xE6 \0 \xA4 \0 \xA5 \0 \xE4 \0 \xA3 \0 \xE5 \0 \xA8 \0 \xA9 \0 \xAA \0 \xAB \0 \xAC \0 \xAD \0 \xAE \0 \xAF \0 \xEF \0 \xE0 \0 \xE1 \0 \xE2 \0 \xE3 \0 \xA6 \0 \xA2 \0 \xEC \0 \xEB \0 \xA7 \0 \xE8 \0 \xED \0 \xE9 \0 \xE7 \0 \xEA \0 \x9E \0 \x80 \0 \x81 \0 \x96 \0 \x84 \0 \x85 \0 \x94 \0 \x83 \0 \x95 \0 \x88 \0 \x89 \0 \x8A \0 \x8B \0 \x8C \0 \x8D \0 \x8E \0 \x8F \0 \x9F \0 \x90 \0 \x91 \0 \x92 \0 \x93 \0 \x86 \0 \x82 \0 \x9C \0 \x9B \0 \x87 \0 \x98 \0 \x9D \0 \x99 \0 \x97 \0 \x9A END