author | chris <chris@marvin> |
Fri Jun 26 16:48:50 2009 +0200 (2009-06-26) | |
changeset 1 | 6fceb66e1ad7 |
parent 0 | f907866f0e4b |
child 2 | 1090e2141798 |
1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/.hgtags Fri Jun 26 16:48:50 2009 +0200 1.3 @@ -0,0 +1,2 @@ 1.4 +42b394eda04ba06126b04e66606ff9ce769652fc oneThreadPerSocket 1.5 +19130f88c6b80cbcda5626c0a49fb35b28a8e3cb sonews-0.5.0
2.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 2.2 +++ b/AUTHORS Fri Jun 26 16:48:50 2009 +0200 2.3 @@ -0,0 +1,26 @@ 2.4 +AUTHORS & CREDITS 2.5 +================= 2.6 + 2.7 +As most software applications "sonews" is based on the work 2.8 +of individuals or projects. These fine people contributing to 2.9 +the Free Software community are mentioned here: 2.10 + 2.11 +sonews News Server 2.12 +------------------- 2.13 +Copyright (c) 2009 by Christian Lins <christian.lins@fh-osnabrueck.de> 2.14 + 2.15 +based partly upon 2.16 + 2.17 +Neat NNTP Daemon (n3tpd) 2.18 +------------------------ 2.19 +Copyright (c) 2007, 2008 by Christian Lins <christian.lins@web.de> 2.20 + 2.21 +based partly upon 2.22 + 2.23 +tnntpd 2.24 +------ 2.25 +Copyright (c) 2003 by Dennis Schwerdel 2.26 + 2.27 +If you find someone missing here, please contact the project leader! 2.28 + 2.29 +Thanks to Sun Microsystems for supporting this project!!
3.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 3.2 +++ b/COPYING Fri Jun 26 16:48:50 2009 +0200 3.3 @@ -0,0 +1,674 @@ 3.4 + GNU GENERAL PUBLIC LICENSE 3.5 + Version 3, 29 June 2007 3.6 + 3.7 + Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/> 3.8 + Everyone is permitted to copy and distribute verbatim copies 3.9 + of this license document, but changing it is not allowed. 3.10 + 3.11 + Preamble 3.12 + 3.13 + The GNU General Public License is a free, copyleft license for 3.14 +software and other kinds of works. 3.15 + 3.16 + The licenses for most software and other practical works are designed 3.17 +to take away your freedom to share and change the works. By contrast, 3.18 +the GNU General Public License is intended to guarantee your freedom to 3.19 +share and change all versions of a program--to make sure it remains free 3.20 +software for all its users. We, the Free Software Foundation, use the 3.21 +GNU General Public License for most of our software; it applies also to 3.22 +any other work released this way by its authors. You can apply it to 3.23 +your programs, too. 3.24 + 3.25 + When we speak of free software, we are referring to freedom, not 3.26 +price. Our General Public Licenses are designed to make sure that you 3.27 +have the freedom to distribute copies of free software (and charge for 3.28 +them if you wish), that you receive source code or can get it if you 3.29 +want it, that you can change the software or use pieces of it in new 3.30 +free programs, and that you know you can do these things. 3.31 + 3.32 + To protect your rights, we need to prevent others from denying you 3.33 +these rights or asking you to surrender the rights. Therefore, you have 3.34 +certain responsibilities if you distribute copies of the software, or if 3.35 +you modify it: responsibilities to respect the freedom of others. 3.36 + 3.37 + For example, if you distribute copies of such a program, whether 3.38 +gratis or for a fee, you must pass on to the recipients the same 3.39 +freedoms that you received. You must make sure that they, too, receive 3.40 +or can get the source code. And you must show them these terms so they 3.41 +know their rights. 3.42 + 3.43 + Developers that use the GNU GPL protect your rights with two steps: 3.44 +(1) assert copyright on the software, and (2) offer you this License 3.45 +giving you legal permission to copy, distribute and/or modify it. 3.46 + 3.47 + For the developers' and authors' protection, the GPL clearly explains 3.48 +that there is no warranty for this free software. For both users' and 3.49 +authors' sake, the GPL requires that modified versions be marked as 3.50 +changed, so that their problems will not be attributed erroneously to 3.51 +authors of previous versions. 3.52 + 3.53 + Some devices are designed to deny users access to install or run 3.54 +modified versions of the software inside them, although the manufacturer 3.55 +can do so. This is fundamentally incompatible with the aim of 3.56 +protecting users' freedom to change the software. The systematic 3.57 +pattern of such abuse occurs in the area of products for individuals to 3.58 +use, which is precisely where it is most unacceptable. Therefore, we 3.59 +have designed this version of the GPL to prohibit the practice for those 3.60 +products. If such problems arise substantially in other domains, we 3.61 +stand ready to extend this provision to those domains in future versions 3.62 +of the GPL, as needed to protect the freedom of users. 3.63 + 3.64 + Finally, every program is threatened constantly by software patents. 3.65 +States should not allow patents to restrict development and use of 3.66 +software on general-purpose computers, but in those that do, we wish to 3.67 +avoid the special danger that patents applied to a free program could 3.68 +make it effectively proprietary. To prevent this, the GPL assures that 3.69 +patents cannot be used to render the program non-free. 3.70 + 3.71 + The precise terms and conditions for copying, distribution and 3.72 +modification follow. 3.73 + 3.74 + TERMS AND CONDITIONS 3.75 + 3.76 + 0. Definitions. 3.77 + 3.78 + "This License" refers to version 3 of the GNU General Public License. 3.79 + 3.80 + "Copyright" also means copyright-like laws that apply to other kinds of 3.81 +works, such as semiconductor masks. 3.82 + 3.83 + "The Program" refers to any copyrightable work licensed under this 3.84 +License. Each licensee is addressed as "you". "Licensees" and 3.85 +"recipients" may be individuals or organizations. 3.86 + 3.87 + To "modify" a work means to copy from or adapt all or part of the work 3.88 +in a fashion requiring copyright permission, other than the making of an 3.89 +exact copy. The resulting work is called a "modified version" of the 3.90 +earlier work or a work "based on" the earlier work. 3.91 + 3.92 + A "covered work" means either the unmodified Program or a work based 3.93 +on the Program. 3.94 + 3.95 + To "propagate" a work means to do anything with it that, without 3.96 +permission, would make you directly or secondarily liable for 3.97 +infringement under applicable copyright law, except executing it on a 3.98 +computer or modifying a private copy. Propagation includes copying, 3.99 +distribution (with or without modification), making available to the 3.100 +public, and in some countries other activities as well. 3.101 + 3.102 + To "convey" a work means any kind of propagation that enables other 3.103 +parties to make or receive copies. Mere interaction with a user through 3.104 +a computer network, with no transfer of a copy, is not conveying. 3.105 + 3.106 + An interactive user interface displays "Appropriate Legal Notices" 3.107 +to the extent that it includes a convenient and prominently visible 3.108 +feature that (1) displays an appropriate copyright notice, and (2) 3.109 +tells the user that there is no warranty for the work (except to the 3.110 +extent that warranties are provided), that licensees may convey the 3.111 +work under this License, and how to view a copy of this License. If 3.112 +the interface presents a list of user commands or options, such as a 3.113 +menu, a prominent item in the list meets this criterion. 3.114 + 3.115 + 1. Source Code. 3.116 + 3.117 + The "source code" for a work means the preferred form of the work 3.118 +for making modifications to it. "Object code" means any non-source 3.119 +form of a work. 3.120 + 3.121 + A "Standard Interface" means an interface that either is an official 3.122 +standard defined by a recognized standards body, or, in the case of 3.123 +interfaces specified for a particular programming language, one that 3.124 +is widely used among developers working in that language. 3.125 + 3.126 + The "System Libraries" of an executable work include anything, other 3.127 +than the work as a whole, that (a) is included in the normal form of 3.128 +packaging a Major Component, but which is not part of that Major 3.129 +Component, and (b) serves only to enable use of the work with that 3.130 +Major Component, or to implement a Standard Interface for which an 3.131 +implementation is available to the public in source code form. A 3.132 +"Major Component", in this context, means a major essential component 3.133 +(kernel, window system, and so on) of the specific operating system 3.134 +(if any) on which the executable work runs, or a compiler used to 3.135 +produce the work, or an object code interpreter used to run it. 3.136 + 3.137 + The "Corresponding Source" for a work in object code form means all 3.138 +the source code needed to generate, install, and (for an executable 3.139 +work) run the object code and to modify the work, including scripts to 3.140 +control those activities. However, it does not include the work's 3.141 +System Libraries, or general-purpose tools or generally available free 3.142 +programs which are used unmodified in performing those activities but 3.143 +which are not part of the work. For example, Corresponding Source 3.144 +includes interface definition files associated with source files for 3.145 +the work, and the source code for shared libraries and dynamically 3.146 +linked subprograms that the work is specifically designed to require, 3.147 +such as by intimate data communication or control flow between those 3.148 +subprograms and other parts of the work. 3.149 + 3.150 + The Corresponding Source need not include anything that users 3.151 +can regenerate automatically from other parts of the Corresponding 3.152 +Source. 3.153 + 3.154 + The Corresponding Source for a work in source code form is that 3.155 +same work. 3.156 + 3.157 + 2. Basic Permissions. 3.158 + 3.159 + All rights granted under this License are granted for the term of 3.160 +copyright on the Program, and are irrevocable provided the stated 3.161 +conditions are met. This License explicitly affirms your unlimited 3.162 +permission to run the unmodified Program. The output from running a 3.163 +covered work is covered by this License only if the output, given its 3.164 +content, constitutes a covered work. This License acknowledges your 3.165 +rights of fair use or other equivalent, as provided by copyright law. 3.166 + 3.167 + You may make, run and propagate covered works that you do not 3.168 +convey, without conditions so long as your license otherwise remains 3.169 +in force. You may convey covered works to others for the sole purpose 3.170 +of having them make modifications exclusively for you, or provide you 3.171 +with facilities for running those works, provided that you comply with 3.172 +the terms of this License in conveying all material for which you do 3.173 +not control copyright. Those thus making or running the covered works 3.174 +for you must do so exclusively on your behalf, under your direction 3.175 +and control, on terms that prohibit them from making any copies of 3.176 +your copyrighted material outside their relationship with you. 3.177 + 3.178 + Conveying under any other circumstances is permitted solely under 3.179 +the conditions stated below. Sublicensing is not allowed; section 10 3.180 +makes it unnecessary. 3.181 + 3.182 + 3. Protecting Users' Legal Rights From Anti-Circumvention Law. 3.183 + 3.184 + No covered work shall be deemed part of an effective technological 3.185 +measure under any applicable law fulfilling obligations under article 3.186 +11 of the WIPO copyright treaty adopted on 20 December 1996, or 3.187 +similar laws prohibiting or restricting circumvention of such 3.188 +measures. 3.189 + 3.190 + When you convey a covered work, you waive any legal power to forbid 3.191 +circumvention of technological measures to the extent such circumvention 3.192 +is effected by exercising rights under this License with respect to 3.193 +the covered work, and you disclaim any intention to limit operation or 3.194 +modification of the work as a means of enforcing, against the work's 3.195 +users, your or third parties' legal rights to forbid circumvention of 3.196 +technological measures. 3.197 + 3.198 + 4. Conveying Verbatim Copies. 3.199 + 3.200 + You may convey verbatim copies of the Program's source code as you 3.201 +receive it, in any medium, provided that you conspicuously and 3.202 +appropriately publish on each copy an appropriate copyright notice; 3.203 +keep intact all notices stating that this License and any 3.204 +non-permissive terms added in accord with section 7 apply to the code; 3.205 +keep intact all notices of the absence of any warranty; and give all 3.206 +recipients a copy of this License along with the Program. 3.207 + 3.208 + You may charge any price or no price for each copy that you convey, 3.209 +and you may offer support or warranty protection for a fee. 3.210 + 3.211 + 5. Conveying Modified Source Versions. 3.212 + 3.213 + You may convey a work based on the Program, or the modifications to 3.214 +produce it from the Program, in the form of source code under the 3.215 +terms of section 4, provided that you also meet all of these conditions: 3.216 + 3.217 + a) The work must carry prominent notices stating that you modified 3.218 + it, and giving a relevant date. 3.219 + 3.220 + b) The work must carry prominent notices stating that it is 3.221 + released under this License and any conditions added under section 3.222 + 7. This requirement modifies the requirement in section 4 to 3.223 + "keep intact all notices". 3.224 + 3.225 + c) You must license the entire work, as a whole, under this 3.226 + License to anyone who comes into possession of a copy. This 3.227 + License will therefore apply, along with any applicable section 7 3.228 + additional terms, to the whole of the work, and all its parts, 3.229 + regardless of how they are packaged. This License gives no 3.230 + permission to license the work in any other way, but it does not 3.231 + invalidate such permission if you have separately received it. 3.232 + 3.233 + d) If the work has interactive user interfaces, each must display 3.234 + Appropriate Legal Notices; however, if the Program has interactive 3.235 + interfaces that do not display Appropriate Legal Notices, your 3.236 + work need not make them do so. 3.237 + 3.238 + A compilation of a covered work with other separate and independent 3.239 +works, which are not by their nature extensions of the covered work, 3.240 +and which are not combined with it such as to form a larger program, 3.241 +in or on a volume of a storage or distribution medium, is called an 3.242 +"aggregate" if the compilation and its resulting copyright are not 3.243 +used to limit the access or legal rights of the compilation's users 3.244 +beyond what the individual works permit. Inclusion of a covered work 3.245 +in an aggregate does not cause this License to apply to the other 3.246 +parts of the aggregate. 3.247 + 3.248 + 6. Conveying Non-Source Forms. 3.249 + 3.250 + You may convey a covered work in object code form under the terms 3.251 +of sections 4 and 5, provided that you also convey the 3.252 +machine-readable Corresponding Source under the terms of this License, 3.253 +in one of these ways: 3.254 + 3.255 + a) Convey the object code in, or embodied in, a physical product 3.256 + (including a physical distribution medium), accompanied by the 3.257 + Corresponding Source fixed on a durable physical medium 3.258 + customarily used for software interchange. 3.259 + 3.260 + b) Convey the object code in, or embodied in, a physical product 3.261 + (including a physical distribution medium), accompanied by a 3.262 + written offer, valid for at least three years and valid for as 3.263 + long as you offer spare parts or customer support for that product 3.264 + model, to give anyone who possesses the object code either (1) a 3.265 + copy of the Corresponding Source for all the software in the 3.266 + product that is covered by this License, on a durable physical 3.267 + medium customarily used for software interchange, for a price no 3.268 + more than your reasonable cost of physically performing this 3.269 + conveying of source, or (2) access to copy the 3.270 + Corresponding Source from a network server at no charge. 3.271 + 3.272 + c) Convey individual copies of the object code with a copy of the 3.273 + written offer to provide the Corresponding Source. This 3.274 + alternative is allowed only occasionally and noncommercially, and 3.275 + only if you received the object code with such an offer, in accord 3.276 + with subsection 6b. 3.277 + 3.278 + d) Convey the object code by offering access from a designated 3.279 + place (gratis or for a charge), and offer equivalent access to the 3.280 + Corresponding Source in the same way through the same place at no 3.281 + further charge. You need not require recipients to copy the 3.282 + Corresponding Source along with the object code. If the place to 3.283 + copy the object code is a network server, the Corresponding Source 3.284 + may be on a different server (operated by you or a third party) 3.285 + that supports equivalent copying facilities, provided you maintain 3.286 + clear directions next to the object code saying where to find the 3.287 + Corresponding Source. Regardless of what server hosts the 3.288 + Corresponding Source, you remain obligated to ensure that it is 3.289 + available for as long as needed to satisfy these requirements. 3.290 + 3.291 + e) Convey the object code using peer-to-peer transmission, provided 3.292 + you inform other peers where the object code and Corresponding 3.293 + Source of the work are being offered to the general public at no 3.294 + charge under subsection 6d. 3.295 + 3.296 + A separable portion of the object code, whose source code is excluded 3.297 +from the Corresponding Source as a System Library, need not be 3.298 +included in conveying the object code work. 3.299 + 3.300 + A "User Product" is either (1) a "consumer product", which means any 3.301 +tangible personal property which is normally used for personal, family, 3.302 +or household purposes, or (2) anything designed or sold for incorporation 3.303 +into a dwelling. In determining whether a product is a consumer product, 3.304 +doubtful cases shall be resolved in favor of coverage. For a particular 3.305 +product received by a particular user, "normally used" refers to a 3.306 +typical or common use of that class of product, regardless of the status 3.307 +of the particular user or of the way in which the particular user 3.308 +actually uses, or expects or is expected to use, the product. A product 3.309 +is a consumer product regardless of whether the product has substantial 3.310 +commercial, industrial or non-consumer uses, unless such uses represent 3.311 +the only significant mode of use of the product. 3.312 + 3.313 + "Installation Information" for a User Product means any methods, 3.314 +procedures, authorization keys, or other information required to install 3.315 +and execute modified versions of a covered work in that User Product from 3.316 +a modified version of its Corresponding Source. The information must 3.317 +suffice to ensure that the continued functioning of the modified object 3.318 +code is in no case prevented or interfered with solely because 3.319 +modification has been made. 3.320 + 3.321 + If you convey an object code work under this section in, or with, or 3.322 +specifically for use in, a User Product, and the conveying occurs as 3.323 +part of a transaction in which the right of possession and use of the 3.324 +User Product is transferred to the recipient in perpetuity or for a 3.325 +fixed term (regardless of how the transaction is characterized), the 3.326 +Corresponding Source conveyed under this section must be accompanied 3.327 +by the Installation Information. But this requirement does not apply 3.328 +if neither you nor any third party retains the ability to install 3.329 +modified object code on the User Product (for example, the work has 3.330 +been installed in ROM). 3.331 + 3.332 + The requirement to provide Installation Information does not include a 3.333 +requirement to continue to provide support service, warranty, or updates 3.334 +for a work that has been modified or installed by the recipient, or for 3.335 +the User Product in which it has been modified or installed. Access to a 3.336 +network may be denied when the modification itself materially and 3.337 +adversely affects the operation of the network or violates the rules and 3.338 +protocols for communication across the network. 3.339 + 3.340 + Corresponding Source conveyed, and Installation Information provided, 3.341 +in accord with this section must be in a format that is publicly 3.342 +documented (and with an implementation available to the public in 3.343 +source code form), and must require no special password or key for 3.344 +unpacking, reading or copying. 3.345 + 3.346 + 7. Additional Terms. 3.347 + 3.348 + "Additional permissions" are terms that supplement the terms of this 3.349 +License by making exceptions from one or more of its conditions. 3.350 +Additional permissions that are applicable to the entire Program shall 3.351 +be treated as though they were included in this License, to the extent 3.352 +that they are valid under applicable law. If additional permissions 3.353 +apply only to part of the Program, that part may be used separately 3.354 +under those permissions, but the entire Program remains governed by 3.355 +this License without regard to the additional permissions. 3.356 + 3.357 + When you convey a copy of a covered work, you may at your option 3.358 +remove any additional permissions from that copy, or from any part of 3.359 +it. (Additional permissions may be written to require their own 3.360 +removal in certain cases when you modify the work.) You may place 3.361 +additional permissions on material, added by you to a covered work, 3.362 +for which you have or can give appropriate copyright permission. 3.363 + 3.364 + Notwithstanding any other provision of this License, for material you 3.365 +add to a covered work, you may (if authorized by the copyright holders of 3.366 +that material) supplement the terms of this License with terms: 3.367 + 3.368 + a) Disclaiming warranty or limiting liability differently from the 3.369 + terms of sections 15 and 16 of this License; or 3.370 + 3.371 + b) Requiring preservation of specified reasonable legal notices or 3.372 + author attributions in that material or in the Appropriate Legal 3.373 + Notices displayed by works containing it; or 3.374 + 3.375 + c) Prohibiting misrepresentation of the origin of that material, or 3.376 + requiring that modified versions of such material be marked in 3.377 + reasonable ways as different from the original version; or 3.378 + 3.379 + d) Limiting the use for publicity purposes of names of licensors or 3.380 + authors of the material; or 3.381 + 3.382 + e) Declining to grant rights under trademark law for use of some 3.383 + trade names, trademarks, or service marks; or 3.384 + 3.385 + f) Requiring indemnification of licensors and authors of that 3.386 + material by anyone who conveys the material (or modified versions of 3.387 + it) with contractual assumptions of liability to the recipient, for 3.388 + any liability that these contractual assumptions directly impose on 3.389 + those licensors and authors. 3.390 + 3.391 + All other non-permissive additional terms are considered "further 3.392 +restrictions" within the meaning of section 10. If the Program as you 3.393 +received it, or any part of it, contains a notice stating that it is 3.394 +governed by this License along with a term that is a further 3.395 +restriction, you may remove that term. If a license document contains 3.396 +a further restriction but permits relicensing or conveying under this 3.397 +License, you may add to a covered work material governed by the terms 3.398 +of that license document, provided that the further restriction does 3.399 +not survive such relicensing or conveying. 3.400 + 3.401 + If you add terms to a covered work in accord with this section, you 3.402 +must place, in the relevant source files, a statement of the 3.403 +additional terms that apply to those files, or a notice indicating 3.404 +where to find the applicable terms. 3.405 + 3.406 + Additional terms, permissive or non-permissive, may be stated in the 3.407 +form of a separately written license, or stated as exceptions; 3.408 +the above requirements apply either way. 3.409 + 3.410 + 8. Termination. 3.411 + 3.412 + You may not propagate or modify a covered work except as expressly 3.413 +provided under this License. Any attempt otherwise to propagate or 3.414 +modify it is void, and will automatically terminate your rights under 3.415 +this License (including any patent licenses granted under the third 3.416 +paragraph of section 11). 3.417 + 3.418 + However, if you cease all violation of this License, then your 3.419 +license from a particular copyright holder is reinstated (a) 3.420 +provisionally, unless and until the copyright holder explicitly and 3.421 +finally terminates your license, and (b) permanently, if the copyright 3.422 +holder fails to notify you of the violation by some reasonable means 3.423 +prior to 60 days after the cessation. 3.424 + 3.425 + Moreover, your license from a particular copyright holder is 3.426 +reinstated permanently if the copyright holder notifies you of the 3.427 +violation by some reasonable means, this is the first time you have 3.428 +received notice of violation of this License (for any work) from that 3.429 +copyright holder, and you cure the violation prior to 30 days after 3.430 +your receipt of the notice. 3.431 + 3.432 + Termination of your rights under this section does not terminate the 3.433 +licenses of parties who have received copies or rights from you under 3.434 +this License. If your rights have been terminated and not permanently 3.435 +reinstated, you do not qualify to receive new licenses for the same 3.436 +material under section 10. 3.437 + 3.438 + 9. Acceptance Not Required for Having Copies. 3.439 + 3.440 + You are not required to accept this License in order to receive or 3.441 +run a copy of the Program. Ancillary propagation of a covered work 3.442 +occurring solely as a consequence of using peer-to-peer transmission 3.443 +to receive a copy likewise does not require acceptance. However, 3.444 +nothing other than this License grants you permission to propagate or 3.445 +modify any covered work. These actions infringe copyright if you do 3.446 +not accept this License. Therefore, by modifying or propagating a 3.447 +covered work, you indicate your acceptance of this License to do so. 3.448 + 3.449 + 10. Automatic Licensing of Downstream Recipients. 3.450 + 3.451 + Each time you convey a covered work, the recipient automatically 3.452 +receives a license from the original licensors, to run, modify and 3.453 +propagate that work, subject to this License. You are not responsible 3.454 +for enforcing compliance by third parties with this License. 3.455 + 3.456 + An "entity transaction" is a transaction transferring control of an 3.457 +organization, or substantially all assets of one, or subdividing an 3.458 +organization, or merging organizations. If propagation of a covered 3.459 +work results from an entity transaction, each party to that 3.460 +transaction who receives a copy of the work also receives whatever 3.461 +licenses to the work the party's predecessor in interest had or could 3.462 +give under the previous paragraph, plus a right to possession of the 3.463 +Corresponding Source of the work from the predecessor in interest, if 3.464 +the predecessor has it or can get it with reasonable efforts. 3.465 + 3.466 + You may not impose any further restrictions on the exercise of the 3.467 +rights granted or affirmed under this License. For example, you may 3.468 +not impose a license fee, royalty, or other charge for exercise of 3.469 +rights granted under this License, and you may not initiate litigation 3.470 +(including a cross-claim or counterclaim in a lawsuit) alleging that 3.471 +any patent claim is infringed by making, using, selling, offering for 3.472 +sale, or importing the Program or any portion of it. 3.473 + 3.474 + 11. Patents. 3.475 + 3.476 + A "contributor" is a copyright holder who authorizes use under this 3.477 +License of the Program or a work on which the Program is based. The 3.478 +work thus licensed is called the contributor's "contributor version". 3.479 + 3.480 + A contributor's "essential patent claims" are all patent claims 3.481 +owned or controlled by the contributor, whether already acquired or 3.482 +hereafter acquired, that would be infringed by some manner, permitted 3.483 +by this License, of making, using, or selling its contributor version, 3.484 +but do not include claims that would be infringed only as a 3.485 +consequence of further modification of the contributor version. For 3.486 +purposes of this definition, "control" includes the right to grant 3.487 +patent sublicenses in a manner consistent with the requirements of 3.488 +this License. 3.489 + 3.490 + Each contributor grants you a non-exclusive, worldwide, royalty-free 3.491 +patent license under the contributor's essential patent claims, to 3.492 +make, use, sell, offer for sale, import and otherwise run, modify and 3.493 +propagate the contents of its contributor version. 3.494 + 3.495 + In the following three paragraphs, a "patent license" is any express 3.496 +agreement or commitment, however denominated, not to enforce a patent 3.497 +(such as an express permission to practice a patent or covenant not to 3.498 +sue for patent infringement). To "grant" such a patent license to a 3.499 +party means to make such an agreement or commitment not to enforce a 3.500 +patent against the party. 3.501 + 3.502 + If you convey a covered work, knowingly relying on a patent license, 3.503 +and the Corresponding Source of the work is not available for anyone 3.504 +to copy, free of charge and under the terms of this License, through a 3.505 +publicly available network server or other readily accessible means, 3.506 +then you must either (1) cause the Corresponding Source to be so 3.507 +available, or (2) arrange to deprive yourself of the benefit of the 3.508 +patent license for this particular work, or (3) arrange, in a manner 3.509 +consistent with the requirements of this License, to extend the patent 3.510 +license to downstream recipients. "Knowingly relying" means you have 3.511 +actual knowledge that, but for the patent license, your conveying the 3.512 +covered work in a country, or your recipient's use of the covered work 3.513 +in a country, would infringe one or more identifiable patents in that 3.514 +country that you have reason to believe are valid. 3.515 + 3.516 + If, pursuant to or in connection with a single transaction or 3.517 +arrangement, you convey, or propagate by procuring conveyance of, a 3.518 +covered work, and grant a patent license to some of the parties 3.519 +receiving the covered work authorizing them to use, propagate, modify 3.520 +or convey a specific copy of the covered work, then the patent license 3.521 +you grant is automatically extended to all recipients of the covered 3.522 +work and works based on it. 3.523 + 3.524 + A patent license is "discriminatory" if it does not include within 3.525 +the scope of its coverage, prohibits the exercise of, or is 3.526 +conditioned on the non-exercise of one or more of the rights that are 3.527 +specifically granted under this License. You may not convey a covered 3.528 +work if you are a party to an arrangement with a third party that is 3.529 +in the business of distributing software, under which you make payment 3.530 +to the third party based on the extent of your activity of conveying 3.531 +the work, and under which the third party grants, to any of the 3.532 +parties who would receive the covered work from you, a discriminatory 3.533 +patent license (a) in connection with copies of the covered work 3.534 +conveyed by you (or copies made from those copies), or (b) primarily 3.535 +for and in connection with specific products or compilations that 3.536 +contain the covered work, unless you entered into that arrangement, 3.537 +or that patent license was granted, prior to 28 March 2007. 3.538 + 3.539 + Nothing in this License shall be construed as excluding or limiting 3.540 +any implied license or other defenses to infringement that may 3.541 +otherwise be available to you under applicable patent law. 3.542 + 3.543 + 12. No Surrender of Others' Freedom. 3.544 + 3.545 + If conditions are imposed on you (whether by court order, agreement or 3.546 +otherwise) that contradict the conditions of this License, they do not 3.547 +excuse you from the conditions of this License. If you cannot convey a 3.548 +covered work so as to satisfy simultaneously your obligations under this 3.549 +License and any other pertinent obligations, then as a consequence you may 3.550 +not convey it at all. For example, if you agree to terms that obligate you 3.551 +to collect a royalty for further conveying from those to whom you convey 3.552 +the Program, the only way you could satisfy both those terms and this 3.553 +License would be to refrain entirely from conveying the Program. 3.554 + 3.555 + 13. Use with the GNU Affero General Public License. 3.556 + 3.557 + Notwithstanding any other provision of this License, you have 3.558 +permission to link or combine any covered work with a work licensed 3.559 +under version 3 of the GNU Affero General Public License into a single 3.560 +combined work, and to convey the resulting work. The terms of this 3.561 +License will continue to apply to the part which is the covered work, 3.562 +but the special requirements of the GNU Affero General Public License, 3.563 +section 13, concerning interaction through a network will apply to the 3.564 +combination as such. 3.565 + 3.566 + 14. Revised Versions of this License. 3.567 + 3.568 + The Free Software Foundation may publish revised and/or new versions of 3.569 +the GNU General Public License from time to time. Such new versions will 3.570 +be similar in spirit to the present version, but may differ in detail to 3.571 +address new problems or concerns. 3.572 + 3.573 + Each version is given a distinguishing version number. If the 3.574 +Program specifies that a certain numbered version of the GNU General 3.575 +Public License "or any later version" applies to it, you have the 3.576 +option of following the terms and conditions either of that numbered 3.577 +version or of any later version published by the Free Software 3.578 +Foundation. If the Program does not specify a version number of the 3.579 +GNU General Public License, you may choose any version ever published 3.580 +by the Free Software Foundation. 3.581 + 3.582 + If the Program specifies that a proxy can decide which future 3.583 +versions of the GNU General Public License can be used, that proxy's 3.584 +public statement of acceptance of a version permanently authorizes you 3.585 +to choose that version for the Program. 3.586 + 3.587 + Later license versions may give you additional or different 3.588 +permissions. However, no additional obligations are imposed on any 3.589 +author or copyright holder as a result of your choosing to follow a 3.590 +later version. 3.591 + 3.592 + 15. Disclaimer of Warranty. 3.593 + 3.594 + THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY 3.595 +APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT 3.596 +HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY 3.597 +OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, 3.598 +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 3.599 +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM 3.600 +IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF 3.601 +ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 3.602 + 3.603 + 16. Limitation of Liability. 3.604 + 3.605 + IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING 3.606 +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS 3.607 +THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY 3.608 +GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE 3.609 +USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF 3.610 +DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD 3.611 +PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), 3.612 +EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF 3.613 +SUCH DAMAGES. 3.614 + 3.615 + 17. Interpretation of Sections 15 and 16. 3.616 + 3.617 + If the disclaimer of warranty and limitation of liability provided 3.618 +above cannot be given local legal effect according to their terms, 3.619 +reviewing courts shall apply local law that most closely approximates 3.620 +an absolute waiver of all civil liability in connection with the 3.621 +Program, unless a warranty or assumption of liability accompanies a 3.622 +copy of the Program in return for a fee. 3.623 + 3.624 + END OF TERMS AND CONDITIONS 3.625 + 3.626 + How to Apply These Terms to Your New Programs 3.627 + 3.628 + If you develop a new program, and you want it to be of the greatest 3.629 +possible use to the public, the best way to achieve this is to make it 3.630 +free software which everyone can redistribute and change under these terms. 3.631 + 3.632 + To do so, attach the following notices to the program. It is safest 3.633 +to attach them to the start of each source file to most effectively 3.634 +state the exclusion of warranty; and each file should have at least 3.635 +the "copyright" line and a pointer to where the full notice is found. 3.636 + 3.637 + <one line to give the program's name and a brief idea of what it does.> 3.638 + Copyright (C) <year> <name of author> 3.639 + 3.640 + This program is free software: you can redistribute it and/or modify 3.641 + it under the terms of the GNU General Public License as published by 3.642 + the Free Software Foundation, either version 3 of the License, or 3.643 + (at your option) any later version. 3.644 + 3.645 + This program is distributed in the hope that it will be useful, 3.646 + but WITHOUT ANY WARRANTY; without even the implied warranty of 3.647 + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 3.648 + GNU General Public License for more details. 3.649 + 3.650 + You should have received a copy of the GNU General Public License 3.651 + along with this program. If not, see <http://www.gnu.org/licenses/>. 3.652 + 3.653 +Also add information on how to contact you by electronic and paper mail. 3.654 + 3.655 + If the program does terminal interaction, make it output a short 3.656 +notice like this when it starts in an interactive mode: 3.657 + 3.658 + <program> Copyright (C) <year> <name of author> 3.659 + This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. 3.660 + This is free software, and you are welcome to redistribute it 3.661 + under certain conditions; type `show c' for details. 3.662 + 3.663 +The hypothetical commands `show w' and `show c' should show the appropriate 3.664 +parts of the General Public License. Of course, your program's commands 3.665 +might be different; for a GUI interface, you would use an "about box". 3.666 + 3.667 + You should also get your employer (if you work as a programmer) or school, 3.668 +if any, to sign a "copyright disclaimer" for the program, if necessary. 3.669 +For more information on this, and how to apply and follow the GNU GPL, see 3.670 +<http://www.gnu.org/licenses/>. 3.671 + 3.672 + The GNU General Public License does not permit incorporating your program 3.673 +into proprietary programs. If your program is a subroutine library, you 3.674 +may consider it more useful to permit linking proprietary applications with 3.675 +the library. If this is what you want to do, use the GNU Lesser General 3.676 +Public License instead of this License. But first, please read 3.677 +<http://www.gnu.org/philosophy/why-not-lgpl.html>. 3.678 \ No newline at end of file
4.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 4.2 +++ b/DEBIAN-web/README.Debian Fri Jun 26 16:48:50 2009 +0200 4.3 @@ -0,0 +1,6 @@ 4.4 +cync for Debian 4.5 +--------------- 4.6 + 4.7 +cync is still a very early alpha version, so be careful using it. You have been warned! 4.8 + 4.9 + -- Jens Mühlenhoff <jens@xerxys.org> Mon, 11 Aug 2008 17:05:23 +0200
5.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 5.2 +++ b/DEBIAN-web/compat Fri Jun 26 16:48:50 2009 +0200 5.3 @@ -0,0 +1,1 @@ 5.4 +6
6.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 6.2 +++ b/DEBIAN-web/control Fri Jun 26 16:48:50 2009 +0200 6.3 @@ -0,0 +1,15 @@ 6.4 +Source: sonews 6.5 +Section: web 6.6 +Priority: optional 6.7 +Maintainer: Christian Lins <cli@openoffice.org> 6.8 +Homepage: http://www.sonews.org/ 6.9 +Package: sonews-web 6.10 +Version: 0.5.0-beta1 6.11 +Architecture: all 6.12 +Depends: kitten, libjchart2d-java, sonews 6.13 +Description: Webinterface for sonews 6.14 + sonews is a modern Usenet server providing newsgroups via NNTP. 6.15 + The lightweight servlet server kitten is used to provide an optional 6.16 + configuration web interface. 6.17 + This metapackage depends on all required prerequisites to run the 6.18 + servlet based webinterface of sonews.
7.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 7.2 +++ b/DEBIAN/README.Debian Fri Jun 26 16:48:50 2009 +0200 7.3 @@ -0,0 +1,6 @@ 7.4 +cync for Debian 7.5 +--------------- 7.6 + 7.7 +cync is still a very early alpha version, so be careful using it. You have been warned! 7.8 + 7.9 + -- Jens Mühlenhoff <jens@xerxys.org> Mon, 11 Aug 2008 17:05:23 +0200
8.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 8.2 +++ b/DEBIAN/compat Fri Jun 26 16:48:50 2009 +0200 8.3 @@ -0,0 +1,1 @@ 8.4 +6
9.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 9.2 +++ b/DEBIAN/conffiles Fri Jun 26 16:48:50 2009 +0200 9.3 @@ -0,0 +1,1 @@ 9.4 +/etc/sonews/sonews.conf
10.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 10.2 +++ b/DEBIAN/control Fri Jun 26 16:48:50 2009 +0200 10.3 @@ -0,0 +1,15 @@ 10.4 +Source: sonews 10.5 +Section: news 10.6 +Priority: optional 10.7 +Maintainer: Christian Lins <cli@openoffice.org> 10.8 +Homepage: http://www.sonews.org/ 10.9 +Package: sonews 10.10 +Version: 0.5.0 10.11 +Architecture: all 10.12 +Depends: openjdk-6-jre-headless | openjdk-6-jre | sun-java6-jre | cacao | jamvm, glassfish-mail, libmysql-java 10.13 +Suggests: kitten, libpg-java, mysql-server, libjchart2d-java 10.14 +Description: Usenet news server 10.15 + sonews is a modern Usenet server providing newsgroups via NNTP. 10.16 + A relational database backend is used to store the news data. 10.17 + The lightweight servlet server kitten is used to provide an optional 10.18 + configuration web interface.
11.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 11.2 +++ b/README Fri Jun 26 16:48:50 2009 +0200 11.3 @@ -0,0 +1,27 @@ 11.4 +sonews README 11.5 +============= 11.6 + 11.7 +Prerequisites: 11.8 +-------------- 11.9 + 11.10 +* Java 6 Runtime or higher 11.11 +* MySQL v5 or PostgreSQL v8 or higher 11.12 +* JDBC driver for your database system 11.13 + 11.14 + 11.15 +Installation: 11.16 +------------- 11.17 + 11.18 +* Create a database in your DBMS, e.g. named like 'sonews' 11.19 +* Create the necessary table structure using the helpers/*.sql file 11.20 + (you may use the experimental helper application: 11.21 + java -cp sonews.jar:<jdbcdriver.jar> DatabaseSetup ) 11.22 +* Customize the settings within the sonews.conf file or add config values to 11.23 + the 'config' table. 11.24 +* Invoke 'bin/sonews.sh start' to start the daemon 11.25 + 11.26 +Bugs and other Issues: 11.27 +---------------------- 11.28 + 11.29 +Please mail them to christian.lins@fh-osnabrueck.de or better issue them 11.30 +into the bugtracker at http://bugs.xerxys.info/ . 11.31 \ No newline at end of file
12.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 12.2 +++ b/RFC3977 Fri Jun 26 16:48:50 2009 +0200 12.3 @@ -0,0 +1,6998 @@ 12.4 + 12.5 +Network Working Group C. Feather 12.6 +Request for Comments: 3977 THUS plc 12.7 +Obsoletes: 977 October 2006 12.8 +Updates: 2980 12.9 +Category: Standards Track 12.10 + 12.11 + 12.12 + Network News Transfer Protocol (NNTP) 12.13 + 12.14 +Status of This Memo 12.15 + 12.16 + This document specifies an Internet standards track protocol for the 12.17 + Internet community, and requests discussion and suggestions for 12.18 + improvements. Please refer to the current edition of the "Internet 12.19 + Official Protocol Standards" (STD 1) for the standardization state 12.20 + and status of this protocol. Distribution of this memo is unlimited. 12.21 + 12.22 +Copyright Notice 12.23 + 12.24 + Copyright (C) The Internet Society (2006). 12.25 + 12.26 +Abstract 12.27 + 12.28 + The Network News Transfer Protocol (NNTP) has been in use in the 12.29 + Internet for a decade, and remains one of the most popular protocols 12.30 + (by volume) in use today. This document is a replacement for 12.31 + RFC 977, and officially updates the protocol specification. It 12.32 + clarifies some vagueness in RFC 977, includes some new base 12.33 + functionality, and provides a specific mechanism to add standardized 12.34 + extensions to NNTP. 12.35 + 12.36 +Table of Contents 12.37 + 12.38 + 1. Introduction . . . . . . . . . . . . . . . . . . . . . . . . 3 12.39 + 1.1. Author's Note . . . . . . . . . . . . . . . . . . . . . . 4 12.40 + 2. Notation . . . . . . . . . . . . . . . . . . . . . . . . . . 5 12.41 + 3. Basic Concepts . . . . . . . . . . . . . . . . . . . . . . . 6 12.42 + 3.1. Commands and Responses . . . . . . . . . . . . . . . . . 6 12.43 + 3.1.1. Multi-line Data Blocks . . . . . . . . . . . . . . . . 8 12.44 + 3.2. Response Codes . . . . . . . . . . . . . . . . . . . . . 9 12.45 + 3.2.1. Generic Response Codes . . . . . . . . . . . . . . . 10 12.46 + 3.2.1.1. Examples . . . . . . . . . . . . . . . . . . . . 12 12.47 + 3.3. Capabilities and Extensions . . . . . . . . . . . . . . . 14 12.48 + 3.3.1. Capability Descriptions . . . . . . . . . . . . . . . 14 12.49 + 3.3.2. Standard Capabilities . . . . . . . . . . . . . . . . 15 12.50 + 3.3.3. Extensions . . . . . . . . . . . . . . . . . . . . . 16 12.51 + 3.3.4. Initial IANA Register . . . . . . . . . . . . . . . . 18 12.52 + 3.4. Mandatory and Optional Commands . . . . . . . . . . . . . 20 12.53 + 12.54 + 12.55 + 12.56 +Feather Standards Track [Page 1] 12.57 + 12.58 +RFC 3977 Network News Transfer Protocol (NNTP) October 2006 12.59 + 12.60 + 12.61 + 3.4.1. Reading and Transit Servers . . . . . . . . . . . . . 21 12.62 + 3.4.2. Mode Switching . . . . . . . . . . . . . . . . . . . 21 12.63 + 3.5. Pipelining . . . . . . . . . . . . . . . . . . . . . . . 22 12.64 + 3.5.1. Examples . . . . . . . . . . . . . . . . . . . . . . 23 12.65 + 3.6. Articles . . . . . . . . . . . . . . . . . . . . . . . . 24 12.66 + 4. The WILDMAT Format . . . . . . . . . . . . . . . . . . . . . 25 12.67 + 4.1. Wildmat Syntax . . . . . . . . . . . . . . . . . . . . . 26 12.68 + 4.2. Wildmat Semantics . . . . . . . . . . . . . . . . . . . . 26 12.69 + 4.3. Extensions . . . . . . . . . . . . . . . . . . . . . . . 27 12.70 + 4.4. Examples . . . . . . . . . . . . . . . . . . . . . . . . 27 12.71 + 5. Session Administration Commands . . . . . . . . . . . . . . . 28 12.72 + 5.1. Initial Connection . . . . . . . . . . . . . . . . . . . 28 12.73 + 5.2. CAPABILITIES . . . . . . . . . . . . . . . . . . . . . . 29 12.74 + 5.3. MODE READER . . . . . . . . . . . . . . . . . . . . . . . 32 12.75 + 5.4. QUIT . . . . . . . . . . . . . . . . . . . . . . . . . . 34 12.76 + 6. Article Posting and Retrieval . . . . . . . . . . . . . . . . 35 12.77 + 6.1. Group and Article Selection . . . . . . . . . . . . . . . 36 12.78 + 6.1.1. GROUP . . . . . . . . . . . . . . . . . . . . . . . . 36 12.79 + 6.1.2. LISTGROUP . . . . . . . . . . . . . . . . . . . . . . 39 12.80 + 6.1.3. LAST . . . . . . . . . . . . . . . . . . . . . . . . 42 12.81 + 6.1.4. NEXT . . . . . . . . . . . . . . . . . . . . . . . . 44 12.82 + 6.2. Retrieval of Articles and Article Sections . . . . . . . 45 12.83 + 6.2.1. ARTICLE . . . . . . . . . . . . . . . . . . . . . . . 46 12.84 + 6.2.2. HEAD . . . . . . . . . . . . . . . . . . . . . . . . 49 12.85 + 6.2.3. BODY . . . . . . . . . . . . . . . . . . . . . . . . 51 12.86 + 6.2.4. STAT . . . . . . . . . . . . . . . . . . . . . . . . 53 12.87 + 6.3. Article Posting . . . . . . . . . . . . . . . . . . . . . 56 12.88 + 6.3.1. POST . . . . . . . . . . . . . . . . . . . . . . . . 56 12.89 + 6.3.2. IHAVE . . . . . . . . . . . . . . . . . . . . . . . . 58 12.90 + 7. Information Commands . . . . . . . . . . . . . . . . . . . . 61 12.91 + 7.1. DATE . . . . . . . . . . . . . . . . . . . . . . . . . . 61 12.92 + 7.2. HELP . . . . . . . . . . . . . . . . . . . . . . . . . . 62 12.93 + 7.3. NEWGROUPS . . . . . . . . . . . . . . . . . . . . . . . . 63 12.94 + 7.4. NEWNEWS . . . . . . . . . . . . . . . . . . . . . . . . . 64 12.95 + 7.5. Time . . . . . . . . . . . . . . . . . . . . . . . . . . 65 12.96 + 7.5.1. Examples . . . . . . . . . . . . . . . . . . . . . . 66 12.97 + 7.6. The LIST Commands . . . . . . . . . . . . . . . . . . . . 66 12.98 + 7.6.1. LIST . . . . . . . . . . . . . . . . . . . . . . . . 67 12.99 + 7.6.2. Standard LIST Keywords . . . . . . . . . . . . . . . 69 12.100 + 7.6.3. LIST ACTIVE . . . . . . . . . . . . . . . . . . . . . 70 12.101 + 7.6.4. LIST ACTIVE.TIMES . . . . . . . . . . . . . . . . . . 71 12.102 + 7.6.5. LIST DISTRIB.PATS . . . . . . . . . . . . . . . . . . 72 12.103 + 7.6.6. LIST NEWSGROUPS . . . . . . . . . . . . . . . . . . . 73 12.104 + 8. Article Field Access Commands . . . . . . . . . . . . . . . . 73 12.105 + 8.1. Article Metadata . . . . . . . . . . . . . . . . . . . . 74 12.106 + 8.1.1. The :bytes Metadata Item . . . . . . . . . . . . . . 74 12.107 + 8.1.2. The :lines Metadata Item . . . . . . . . . . . . . . 75 12.108 + 8.2. Database Consistency . . . . . . . . . . . . . . . . . . 75 12.109 + 12.110 + 12.111 + 12.112 +Feather Standards Track [Page 2] 12.113 + 12.114 +RFC 3977 Network News Transfer Protocol (NNTP) October 2006 12.115 + 12.116 + 12.117 + 8.3. OVER . . . . . . . . . . . . . . . . . . . . . . . . . . 76 12.118 + 8.4. LIST OVERVIEW.FMT . . . . . . . . . . . . . . . . . . . . 81 12.119 + 8.5. HDR . . . . . . . . . . . . . . . . . . . . . . . . . . . 83 12.120 + 8.6. LIST HEADERS . . . . . . . . . . . . . . . . . . . . . . 87 12.121 + 9. Augmented BNF Syntax for NNTP . . . . . . . . . . . . . . . . 90 12.122 + 9.1. Introduction . . . . . . . . . . . . . . . . . . . . . . 90 12.123 + 9.2. Commands . . . . . . . . . . . . . . . . . . . . . . . . 92 12.124 + 9.3. Command Continuation . . . . . . . . . . . . . . . . . . 93 12.125 + 9.4. Responses . . . . . . . . . . . . . . . . . . . . . . . . 93 12.126 + 9.4.1. Generic Responses . . . . . . . . . . . . . . . . . . 93 12.127 + 9.4.2. Initial Response Line Contents . . . . . . . . . . . 94 12.128 + 9.4.3. Multi-line Response Contents . . . . . . . . . . . . 94 12.129 + 9.5. Capability Lines . . . . . . . . . . . . . . . . . . . . 95 12.130 + 9.6. LIST Variants . . . . . . . . . . . . . . . . . . . . . . 96 12.131 + 9.7. Articles . . . . . . . . . . . . . . . . . . . . . . . . 97 12.132 + 9.8. General Non-terminals . . . . . . . . . . . . . . . . . . 97 12.133 + 9.9. Extensions and Validation . . . . . . . . . . . . . . . . 99 12.134 + 10. Internationalisation Considerations . . . . . . . . . . . . .100 12.135 + 10.1. Introduction and Historical Situation . . . . . . . . . .100 12.136 + 10.2. This Specification . . . . . . . . . . . . . . . . . . .101 12.137 + 10.3. Outstanding Issues . . . . . . . . . . . . . . . . . . .102 12.138 + 11. IANA Considerations . . . . . . . . . . . . . . . . . . . . .103 12.139 + 12. Security Considerations . . . . . . . . . . . . . . . . . . .103 12.140 + 12.1. Personal and Proprietary Information . . . . . . . . . .104 12.141 + 12.2. Abuse of Server Log Information . . . . . . . . . . . . .104 12.142 + 12.3. Weak Authentication and Access Control . . . . . . . . .104 12.143 + 12.4. DNS Spoofing . . . . . . . . . . . . . . . . . . . . . .104 12.144 + 12.5. UTF-8 Issues . . . . . . . . . . . . . . . . . . . . . .105 12.145 + 12.6. Caching of Capability Lists . . . . . . . . . . . . . . .106 12.146 + 13. Acknowledgements . . . . . . . . . . . . . . . . . . . . . .107 12.147 + 14. References . . . . . . . . . . . . . . . . . . . . . . . . .110 12.148 + 14.1. Normative References . . . . . . . . . . . . . . . . . .110 12.149 + 14.2. Informative References . . . . . . . . . . . . . . . . .110 12.150 + A. Interaction with Other Specifications . . . . . . . . . . . .112 12.151 + A.1. Header Folding . . . . . . . . . . . . . . . . . . . . .112 12.152 + A.2. Message-IDs . . . . . . . . . . . . . . . . . . . . . . .112 12.153 + A.3. Article Posting . . . . . . . . . . . . . . . . . . . . .114 12.154 + B. Summary of Commands . . . . . . . . . . . . . . . . . . . . .115 12.155 + C. Summary of Response Codes . . . . . . . . . . . . . . . . . .117 12.156 + D. Changes from RFC 977 . . . . . . . . . . . . . . . . . . . .121 12.157 + 12.158 +1. Introduction 12.159 + 12.160 + This document specifies the Network News Transfer Protocol (NNTP), 12.161 + which is used for the distribution, inquiry, retrieval, and posting 12.162 + of Netnews articles using a reliable stream-based mechanism. For 12.163 + news-reading clients, NNTP enables retrieval of news articles that 12.164 + 12.165 + 12.166 + 12.167 + 12.168 +Feather Standards Track [Page 3] 12.169 + 12.170 +RFC 3977 Network News Transfer Protocol (NNTP) October 2006 12.171 + 12.172 + 12.173 + are stored in a central database, giving subscribers the ability to 12.174 + select only those articles they wish to read. 12.175 + 12.176 + The Netnews model provides for indexing, cross-referencing, and 12.177 + expiration of aged messages. NNTP is designed for efficient 12.178 + transmission of Netnews articles over a reliable full duplex 12.179 + communication channel. 12.180 + 12.181 + Although the protocol specification in this document is largely 12.182 + compatible with the version specified in RFC 977 [RFC977], a number 12.183 + of changes are summarised in Appendix D. In particular: 12.184 + 12.185 + o the default character set is changed from US-ASCII [ANSI1986] to 12.186 + UTF-8 [RFC3629] (note that US-ASCII is a subset of UTF-8); 12.187 + 12.188 + o a number of commands that were optional in RFC 977 or that have 12.189 + been taken from RFC 2980 [RFC2980] are now mandatory; and 12.190 + 12.191 + o a CAPABILITIES command has been added to allow clients to 12.192 + determine what functionality is available from a server. 12.193 + 12.194 + The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", 12.195 + "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this 12.196 + document are to be interpreted as described in RFC 2119 [RFC2119]. 12.197 + 12.198 + An implementation is not compliant if it fails to satisfy one or more 12.199 + of the MUST requirements for this protocol. An implementation that 12.200 + satisfies all the MUST and all the SHOULD requirements for its 12.201 + protocols is said to be "unconditionally compliant"; one that 12.202 + satisfies all the MUST requirements but not all the SHOULD 12.203 + requirements for NNTP is said to be "conditionally compliant". 12.204 + 12.205 + For the remainder of this document, the terms "client" and "client 12.206 + host" refer to a host making use of the NNTP service, while the terms 12.207 + "server" and "server host" refer to a host that offers the NNTP 12.208 + service. 12.209 + 12.210 +1.1. Author's Note 12.211 + 12.212 + This document is written in XML using an NNTP-specific DTD. Custom 12.213 + software is used to convert this to RFC 2629 [RFC2629] format, and 12.214 + then the public "xml2rfc" package to further reduce this to text, 12.215 + nroff source, and HTML. 12.216 + 12.217 + No perl was used in producing this document. 12.218 + 12.219 + 12.220 + 12.221 + 12.222 + 12.223 + 12.224 +Feather Standards Track [Page 4] 12.225 + 12.226 +RFC 3977 Network News Transfer Protocol (NNTP) October 2006 12.227 + 12.228 + 12.229 +2. Notation 12.230 + 12.231 + The following notational conventions are used in this document. 12.232 + 12.233 + UPPERCASE indicates literal text to be included in the 12.234 + command. 12.235 + 12.236 + lowercase indicates a token described elsewhere. 12.237 + 12.238 + [brackets] indicate that the enclosed material is optional. 12.239 + 12.240 + elliptical indicates that the argument may be repeated any 12.241 + ... marks number of times (it must occur at least once). 12.242 + 12.243 + vertical|bar indicates a choice of two mutually exclusive 12.244 + arguments (exactly one must be provided). 12.245 + 12.246 + The name "message-id" for a command or response argument indicates 12.247 + that it is the message-id of an article as described in Section 3.6, 12.248 + including the angle brackets. 12.249 + 12.250 + The name "wildmat" for an argument indicates that it is a wildmat as 12.251 + defined in Section 4. If the argument does not meet the requirements 12.252 + of that section (for example, if it does not fit the grammar of 12.253 + Section 4.1), the NNTP server MAY place some interpretation on it 12.254 + (not specified by this document) or otherwise MUST treat it as a 12.255 + syntax error. 12.256 + 12.257 + Responses for each command will be described in tables listing the 12.258 + required format of a response followed by the meaning that should be 12.259 + ascribed to that response. 12.260 + 12.261 + The terms "NUL", "TAB", "LF", "CR, and "space" refer to the octets 12.262 + %x00, %x09, %x0A, %x0D, and %x20, respectively (that is, the octets 12.263 + with those codes in US-ASCII [ANSI1986] and thus in UTF-8 [RFC3629]). 12.264 + The term "CRLF" or "CRLF pair" means the sequence CR immediately 12.265 + followed by LF (that is, %x0D.0A). A "printable US-ASCII character" 12.266 + is an octet in the range %x21-7E. Quoted characters refer to the 12.267 + octets with those codes in US-ASCII (so "." and "<" refer to %x2E and 12.268 + %x3C) and will always be printable US-ASCII characters; similarly, 12.269 + "digit" refers to the octets %x30-39. 12.270 + 12.271 + A "keyword" MUST consist only of US-ASCII letters, digits, and the 12.272 + characters dot (".") and dash ("-") and MUST begin with a letter. 12.273 + Keywords MUST be at least three characters in length. 12.274 + 12.275 + 12.276 + 12.277 + 12.278 + 12.279 + 12.280 +Feather Standards Track [Page 5] 12.281 + 12.282 +RFC 3977 Network News Transfer Protocol (NNTP) October 2006 12.283 + 12.284 + 12.285 + Examples in this document are not normative but serve to illustrate 12.286 + usages, arguments, and responses. In the examples, a "[C]" will be 12.287 + used to represent the client host and an "[S]" will be used to 12.288 + represent the server host. Most of the examples do not rely on a 12.289 + particular server state. In some cases, however, they do assume that 12.290 + the currently selected newsgroup (see the GROUP command, 12.291 + Section 6.1.1) is invalid; when so, this is indicated at the start of 12.292 + the example. Examples may use commands or other keywords not defined 12.293 + in this specification (such as an XENCRYPT command). These will be 12.294 + used to illustrate some point and do not imply that any such command 12.295 + is defined elsewhere or needs to exist in any particular 12.296 + implementation. 12.297 + 12.298 + Terms that might be read as specifying details of a client or server 12.299 + implementation, such as "database", are used simply to ease 12.300 + description. Provided that implementations conform to the protocol 12.301 + and format specifications in this document, no specific technique is 12.302 + mandated. 12.303 + 12.304 +3. Basic Concepts 12.305 + 12.306 +3.1. Commands and Responses 12.307 + 12.308 + NNTP operates over any reliable bi-directional 8-bit-wide data stream 12.309 + channel. When the connection is established, the NNTP server host 12.310 + MUST send a greeting. The client host and server host then exchange 12.311 + commands and responses (respectively) until the connection is closed 12.312 + or aborted. If the connection used is TCP, then the server host 12.313 + starts the NNTP service by listening on a TCP port. When a client 12.314 + host wishes to make use of the service, it MUST establish a TCP 12.315 + connection with the server host by connecting to that host on the 12.316 + same port on which the server is listening. 12.317 + 12.318 + The character set for all NNTP commands is UTF-8 [RFC3629]. Commands 12.319 + in NNTP MUST consist of a keyword, which MAY be followed by one or 12.320 + more arguments. A CRLF pair MUST terminate all commands. Multiple 12.321 + commands MUST NOT be on the same line. Unless otherwise noted 12.322 + elsewhere in this document, arguments SHOULD consist of printable US- 12.323 + ASCII characters. Keywords and arguments MUST each be separated by 12.324 + one or more space or TAB characters. Command lines MUST NOT exceed 12.325 + 512 octets, which includes the terminating CRLF pair. The arguments 12.326 + MUST NOT exceed 497 octets. A server MAY relax these limits for 12.327 + commands defined in an extension. 12.328 + 12.329 + Where this specification permits UTF-8 characters outside the range 12.330 + of U+0000 to U+007F, implementations MUST NOT use the Byte Order Mark 12.331 + (U+FEFF, encoding %xEF.BB.BF) and MUST use the Word Joiner (U+2060, 12.332 + encoding %xE2.91.A0) for the meaning Zero Width No-Break Space in 12.333 + 12.334 + 12.335 + 12.336 +Feather Standards Track [Page 6] 12.337 + 12.338 +RFC 3977 Network News Transfer Protocol (NNTP) October 2006 12.339 + 12.340 + 12.341 + command lines and the initial lines of responses. Implementations 12.342 + SHOULD apply these same principles throughout. 12.343 + 12.344 + The term "character" means a single Unicode code point. 12.345 + Implementations are not required to carry out Unicode normalisation. 12.346 + Thus, U+0084 (A-dieresis) is one character, while U+0041 U+0308 (A 12.347 + composed with dieresis) is two; the two need not be treated as 12.348 + equivalent. 12.349 + 12.350 + Commands may have variants; if so, they use a second keyword 12.351 + immediately after the first to indicate which variant is required. 12.352 + The only such commands in this specification are LIST and MODE. Note 12.353 + that such variants are sometimes referred to as if they were commands 12.354 + in their own right: "the LIST ACTIVE" command should be read as 12.355 + shorthand for "the ACTIVE variant of the LIST command". 12.356 + 12.357 + Keywords are case insensitive; the case of keywords for commands MUST 12.358 + be ignored by the server. Command and response arguments are case or 12.359 + language specific only when stated, either in this document or in 12.360 + other relevant specifications. 12.361 + 12.362 + In some cases, a command involves more data than just a single line. 12.363 + The further data may be sent either immediately after the command 12.364 + line (there are no instances of this in this specification, but there 12.365 + are in extensions such as [NNTP-STREAM]) or following a request from 12.366 + the server (indicated by a 3xx response). 12.367 + 12.368 + Each response MUST start with a three-digit response code that is 12.369 + sufficient to distinguish all responses. Certain valid responses are 12.370 + defined to be multi-line; for all others, the response is contained 12.371 + in a single line. The initial line of the response MUST NOT exceed 12.372 + 512 octets, which includes the response code and the terminating CRLF 12.373 + pair; an extension MAY specify a greater maximum for commands that it 12.374 + defines, but not for any other command. Single-line responses 12.375 + consist of an initial line only. Multi-line responses consist of an 12.376 + initial line followed by a multi-line data block. 12.377 + 12.378 + An NNTP server MAY have an inactivity autologout timer. Such a timer 12.379 + SHOULD be of at least three minutes' duration, with the exception 12.380 + that there MAY be a shorter limit on how long the server is willing 12.381 + to wait for the first command from the client. The receipt of any 12.382 + command from the client during the timer interval SHOULD suffice to 12.383 + reset the autologout timer. Similarly, the receipt of any 12.384 + significant amount of data from a client that is sending a multi-line 12.385 + data block (such as during a POST or IHAVE command) SHOULD suffice to 12.386 + reset the autologout timer. When the timer expires, the server 12.387 + SHOULD close the connection without sending any response to the 12.388 + client. 12.389 + 12.390 + 12.391 + 12.392 +Feather Standards Track [Page 7] 12.393 + 12.394 +RFC 3977 Network News Transfer Protocol (NNTP) October 2006 12.395 + 12.396 + 12.397 +3.1.1. Multi-line Data Blocks 12.398 + 12.399 + A multi-line data block is used in certain commands and responses. 12.400 + It MUST adhere to the following rules: 12.401 + 12.402 + 1. The block consists of a sequence of zero or more "lines", each 12.403 + being a stream of octets ending with a CRLF pair. Apart from 12.404 + those line endings, the stream MUST NOT include the octets NUL, 12.405 + LF, or CR. 12.406 + 12.407 + 2. In a multi-line response, the block immediately follows the CRLF 12.408 + at the end of the initial line of the response. When used in any 12.409 + other context, the specific command will define when the block is 12.410 + sent. 12.411 + 12.412 + 3. If any line of the data block begins with the "termination octet" 12.413 + ("." or %x2E), that line MUST be "dot-stuffed" by prepending an 12.414 + additional termination octet to that line of the block. 12.415 + 12.416 + 4. The lines of the block MUST be followed by a terminating line 12.417 + consisting of a single termination octet followed by a CRLF pair 12.418 + in the normal way. Thus, unless it is empty, a multi-line block 12.419 + is always terminated with the five octets CRLF "." CRLF 12.420 + (%x0D.0A.2E.0D.0A). 12.421 + 12.422 + 5. When a multi-line block is interpreted, the "dot-stuffing" MUST 12.423 + be undone; i.e., the recipient MUST ensure that, in any line 12.424 + beginning with the termination octet followed by octets other 12.425 + than a CRLF pair, that initial termination octet is disregarded. 12.426 + 12.427 + 6. Likewise, the terminating line ("." CRLF or %x2E.0D.0A) MUST NOT 12.428 + be considered part of the multi-line block; i.e., the recipient 12.429 + MUST ensure that any line beginning with the termination octet 12.430 + followed immediately by a CRLF pair is disregarded. (The first 12.431 + CRLF pair of the terminating CRLF "." CRLF of a non-empty block 12.432 + is, of course, part of the last line of the block.) 12.433 + 12.434 + Note that texts using an encoding (such as UTF-16 or UTF-32) that may 12.435 + contain the octets NUL, LF, or CR other than a CRLF pair cannot be 12.436 + reliably conveyed in the above format (that is, they violate the MUST 12.437 + requirement above). However, except when stated otherwise, this 12.438 + specification does not require the content to be UTF-8, and therefore 12.439 + (subject to that same requirement) it MAY include octets above and 12.440 + below 128 mixed arbitrarily. 12.441 + 12.442 + This document does not place any limit on the length of a line in a 12.443 + multi-line block. However, the standards that define the format of 12.444 + articles may do so. 12.445 + 12.446 + 12.447 + 12.448 +Feather Standards Track [Page 8] 12.449 + 12.450 +RFC 3977 Network News Transfer Protocol (NNTP) October 2006 12.451 + 12.452 + 12.453 +3.2. Response Codes 12.454 + 12.455 + Each response MUST begin with a three-digit status indicator. These 12.456 + are status reports from the server and indicate the response to the 12.457 + last command received from the client. 12.458 + 12.459 + The first digit of the response broadly indicates the success, 12.460 + failure, or progress of the previous command: 12.461 + 12.462 + 1xx - Informative message 12.463 + 2xx - Command completed OK 12.464 + 3xx - Command OK so far; send the rest of it 12.465 + 4xx - Command was syntactically correct but failed for some reason 12.466 + 5xx - Command unknown, unsupported, unavailable, or syntax error 12.467 + 12.468 + The next digit in the code indicates the function response category: 12.469 + 12.470 + x0x - Connection, setup, and miscellaneous messages 12.471 + x1x - Newsgroup selection 12.472 + x2x - Article selection 12.473 + x3x - Distribution functions 12.474 + x4x - Posting 12.475 + x8x - Reserved for authentication and privacy extensions 12.476 + x9x - Reserved for private use (non-standard extensions) 12.477 + 12.478 + Certain responses contain arguments such as numbers and names in 12.479 + addition to the status indicator. In those cases, to simplify 12.480 + interpretation by the client, the number and type of such arguments 12.481 + is fixed for each response code, as is whether the code is 12.482 + single-line or multi-line. Any extension MUST follow this principle 12.483 + as well. Note that, for historical reasons, the 211 response code is 12.484 + an exception to this in that the response may be single-line or 12.485 + multi-line depending on the command (GROUP or LISTGROUP) that 12.486 + generated it. In all other cases, the client MUST only use the 12.487 + status indicator itself to determine the nature of the response. The 12.488 + exact response codes that can be returned by any given command are 12.489 + detailed in the description of that command. 12.490 + 12.491 + Arguments MUST be separated from the numeric status indicator and 12.492 + from each other by a single space. All numeric arguments MUST be in 12.493 + base 10 (decimal) format and MAY have leading zeros. String 12.494 + arguments MUST contain at least one character and MUST NOT contain 12.495 + TAB, LF, CR, or space. The server MAY add any text after the 12.496 + response code or last argument, as appropriate, and the client MUST 12.497 + NOT make decisions based on this text. Such text MUST be separated 12.498 + from the numeric status indicator or the last argument by at least 12.499 + one space. 12.500 + 12.501 + 12.502 + 12.503 + 12.504 +Feather Standards Track [Page 9] 12.505 + 12.506 +RFC 3977 Network News Transfer Protocol (NNTP) October 2006 12.507 + 12.508 + 12.509 + The server MUST respond to any command with the appropriate generic 12.510 + response (given in Section 3.2.1) if it represents the situation. 12.511 + Otherwise, each recognized command MUST return one of the response 12.512 + codes specifically listed in its description or in an extension. A 12.513 + server MAY provide extensions to this specification, including new 12.514 + commands, new variants or features of existing commands, and other 12.515 + ways of changing the internal state of the server. However, the 12.516 + server MUST NOT produce any other responses to a client that does not 12.517 + invoke any of the additional features. (Therefore, a client that 12.518 + restricts itself to this specification will only receive the 12.519 + responses that are listed.) 12.520 + 12.521 + If a client receives an unexpected response, it SHOULD use the first 12.522 + digit of the response to determine the result. For example, an 12.523 + unexpected 2xx should be taken as success, and an unexpected 4xx or 12.524 + 5xx as failure. 12.525 + 12.526 + Response codes not specified in this document MAY be used for any 12.527 + installation-specific additional commands also not specified. These 12.528 + SHOULD be chosen to fit the pattern of x9x specified above. 12.529 + 12.530 + Neither this document nor any registered extension (see 12.531 + Section 3.3.3) will specify any response codes of the x9x pattern. 12.532 + (Implementers of extensions are accordingly cautioned not to use such 12.533 + responses for extensions that may subsequently be submitted for 12.534 + registration.) 12.535 + 12.536 +3.2.1. Generic Response Codes 12.537 + 12.538 + The server MUST respond to any command with the appropriate one of 12.539 + the following generic responses if it represents the situation. 12.540 + 12.541 + If the command is not recognized, or if it is an optional command 12.542 + that is not implemented by the server, the response code 500 MUST be 12.543 + returned. 12.544 + 12.545 + If there is a syntax error in the arguments of a recognized command, 12.546 + including the case where more arguments are provided than the command 12.547 + specifies or the command line is longer than the server accepts, the 12.548 + response code 501 MUST be returned. The line MUST NOT be truncated 12.549 + or split and then interpreted. Note that where a command has 12.550 + variants depending on a second keyword (e.g., LIST ACTIVE and LIST 12.551 + NEWSGROUPS), 501 MUST be used when the base command is implemented 12.552 + but the requested variant is not, and 500 MUST be used only when the 12.553 + base command itself is not implemented. 12.554 + 12.555 + If an argument is required to be a base64-encoded string [RFC4648] 12.556 + (there are no such arguments in this specification, but there may be 12.557 + 12.558 + 12.559 + 12.560 +Feather Standards Track [Page 10] 12.561 + 12.562 +RFC 3977 Network News Transfer Protocol (NNTP) October 2006 12.563 + 12.564 + 12.565 + in extensions) and is not validly encoded, the response code 504 MUST 12.566 + be returned. 12.567 + 12.568 + If the server experiences an internal fault or problem that means it 12.569 + is unable to carry out the command (for example, a necessary file is 12.570 + missing or a necessary service could not be contacted), the response 12.571 + code 403 MUST be returned. If the server recognizes the command but 12.572 + does not provide an optional feature (for example, because it does 12.573 + not store the required information), or if it only handles a subset 12.574 + of legitimate cases (see the HDR command, Section 8.5, for an 12.575 + example), the response code 503 MUST be returned. 12.576 + 12.577 + If the client is not authorized to use the specified facility when 12.578 + the server is in its current state, then the appropriate one of the 12.579 + following response codes MUST be used. 12.580 + 12.581 + 502: It is necessary to terminate the connection and to start a new 12.582 + one with the appropriate authority before the command can be used. 12.583 + Historically, some mode-switching servers (see Section 3.4.1) used 12.584 + this response to indicate that this command will become available 12.585 + after the MODE READER command (Section 5.3) is used, but this 12.586 + usage does not conform to this specification and MUST NOT be used. 12.587 + Note that the server MUST NOT close the connection immediately 12.588 + after a 502 response except at the initial connection 12.589 + (Section 5.1) and with the MODE READER command. 12.590 + 12.591 + 480: The client must authenticate itself to the server (that is, it 12.592 + must provide information as to the identity of the client) before 12.593 + the facility can be used on this connection. This will involve 12.594 + the use of an authentication extension such as [NNTP-AUTH]. 12.595 + 12.596 + 483: The client must negotiate appropriate privacy protection on the 12.597 + connection. This will involve the use of a privacy extension such 12.598 + as [NNTP-TLS]. 12.599 + 12.600 + 401: The client must change the state of the connection in some other 12.601 + manner. The first argument of the response MUST be the capability 12.602 + label (see Section 5.2) of the facility that provides the 12.603 + necessary mechanism (usually an extension, which may be a private 12.604 + extension). The server MUST NOT use this response code except as 12.605 + specified by the definition of the capability in question. 12.606 + 12.607 + If the server has to terminate the connection for some reason, it 12.608 + MUST give a 400 response code to the next command and then 12.609 + immediately close the connection. Following a 400 response, clients 12.610 + SHOULD NOT simply reconnect immediately and retry the same actions. 12.611 + Rather, a client SHOULD either use an exponentially increasing delay 12.612 + between retries (e.g., double the waiting time after each 400 12.613 + 12.614 + 12.615 + 12.616 +Feather Standards Track [Page 11] 12.617 + 12.618 +RFC 3977 Network News Transfer Protocol (NNTP) October 2006 12.619 + 12.620 + 12.621 + response) or present any associated text to the user for them to 12.622 + decide whether and when to retry. 12.623 + 12.624 + The client MUST be prepared to receive any of these responses for any 12.625 + command (except, of course, that the server MUST NOT generate a 500 12.626 + response code for mandatory commands). 12.627 + 12.628 +3.2.1.1. Examples 12.629 + 12.630 + Example of an unknown command: 12.631 + 12.632 + [C] MAIL 12.633 + [S] 500 Unknown command 12.634 + 12.635 + Example of an unsupported command: 12.636 + 12.637 + [C] CAPABILITIES 12.638 + [S] 101 Capability list: 12.639 + [S] VERSION 2 12.640 + [S] READER 12.641 + [S] NEWNEWS 12.642 + [S] LIST ACTIVE NEWSGROUPS 12.643 + [S] . 12.644 + [C] OVER 12.645 + [S] 500 Unknown command 12.646 + 12.647 + Example of an unsupported variant: 12.648 + 12.649 + [C] MODE POSTER 12.650 + [S] 501 Unknown MODE option 12.651 + 12.652 + Example of a syntax error: 12.653 + 12.654 + [C] ARTICLE a.message.id@no.angle.brackets 12.655 + [S] 501 Syntax error 12.656 + 12.657 + Example of an overlong command line: 12.658 + 12.659 + [C] HEAD 53 54 55 12.660 + [S] 501 Too many arguments 12.661 + 12.662 + Example of a bad wildmat: 12.663 + 12.664 + [C] LIST ACTIVE u[ks].* 12.665 + [S] 501 Syntax error 12.666 + 12.667 + 12.668 + 12.669 + 12.670 + 12.671 + 12.672 +Feather Standards Track [Page 12] 12.673 + 12.674 +RFC 3977 Network News Transfer Protocol (NNTP) October 2006 12.675 + 12.676 + 12.677 + Example of a base64-encoding error (the second argument is meant to 12.678 + be base64 encoded): 12.679 + 12.680 + [C] XENCRYPT RSA abcd=efg 12.681 + [S] 504 Base64 encoding error 12.682 + 12.683 + Example of an attempt to access a facility not available to this 12.684 + connection: 12.685 + 12.686 + [C] MODE READER 12.687 + [S] 200 Reader mode, posting permitted 12.688 + [C] IHAVE <i.am.an.article.you.will.want@example.com> 12.689 + [S] 500 Permission denied 12.690 + 12.691 + Example of an attempt to access a facility requiring authentication: 12.692 + 12.693 + [C] GROUP secret.group 12.694 + [S] 480 Permission denied 12.695 + 12.696 + Example of a successful attempt following such authentication: 12.697 + 12.698 + [C] XSECRET fred flintstone 12.699 + [S] 290 Password for fred accepted 12.700 + [C] GROUP secret.group 12.701 + [S] 211 5 1 20 secret.group selected 12.702 + 12.703 + Example of an attempt to access a facility requiring privacy: 12.704 + 12.705 + [C] GROUP secret.group 12.706 + [S] 483 Secure connection required 12.707 + [C] XENCRYPT 12.708 + [Client and server negotiate encryption on the link] 12.709 + [S] 283 Encrypted link established 12.710 + [C] GROUP secret.group 12.711 + [S] 211 5 1 20 secret.group selected 12.712 + 12.713 + Example of a need to change mode before a facility is used: 12.714 + 12.715 + [C] GROUP binary.group 12.716 + [S] 401 XHOST Not on this virtual host 12.717 + [C] XHOST binary.news.example.org 12.718 + [S] 290 binary.news.example.org virtual host selected 12.719 + [C] GROUP binary.group 12.720 + [S] 211 5 1 77 binary.group selected 12.721 + 12.722 + 12.723 + 12.724 + 12.725 + 12.726 + 12.727 + 12.728 +Feather Standards Track [Page 13] 12.729 + 12.730 +RFC 3977 Network News Transfer Protocol (NNTP) October 2006 12.731 + 12.732 + 12.733 + Example of a temporary failure: 12.734 + 12.735 + [C] GROUP archive.local 12.736 + [S] 403 Archive server temporarily offline 12.737 + 12.738 + Example of the server needing to close down immediately: 12.739 + 12.740 + [C] ARTICLE 123 12.741 + [S] 400 Power supply failed, running on UPS 12.742 + [Server closes connection.] 12.743 + 12.744 +3.3. Capabilities and Extensions 12.745 + 12.746 + Not all NNTP servers provide exactly the same facilities, both 12.747 + because this specification allows variation and because servers may 12.748 + provide extensions. A set of facilities that are related are called 12.749 + a "capability". This specification provides a way to determine what 12.750 + capabilities are available, includes a list of standard capabilities, 12.751 + and includes a mechanism (the extension mechanism) for defining new 12.752 + capabilities. 12.753 + 12.754 +3.3.1. Capability Descriptions 12.755 + 12.756 + A client can determine the available capabilities of the server by 12.757 + using the CAPABILITIES command (Section 5.2). This returns a 12.758 + capability list, which is a list of capability lines. Each line 12.759 + describes one available capability. 12.760 + 12.761 + Each capability line consists of one or more tokens, which MUST be 12.762 + separated by one or more space or TAB characters. A token is a 12.763 + string of 1 or more printable UTF-8 characters (that is, either 12.764 + printable US-ASCII characters or any UTF-8 sequence outside the US- 12.765 + ASCII range, but not space or TAB). Unless stated otherwise, tokens 12.766 + are case insensitive. Each capability line consists of the 12.767 + following: 12.768 + 12.769 + o The capability label, which is a keyword indicating the 12.770 + capability. A capability label may be defined by this 12.771 + specification or a successor, or by an extension. 12.772 + 12.773 + o The label is then followed by zero or more tokens, which are 12.774 + arguments of the capability. The form and meaning of these tokens 12.775 + is specific to each capability. 12.776 + 12.777 + The server MUST ensure that the capability list accurately reflects 12.778 + the capabilities (including extensions) currently available. If a 12.779 + capability is only available with the server in a certain state (for 12.780 + example, only after authentication), the list MUST only include the 12.781 + 12.782 + 12.783 + 12.784 +Feather Standards Track [Page 14] 12.785 + 12.786 +RFC 3977 Network News Transfer Protocol (NNTP) October 2006 12.787 + 12.788 + 12.789 + capability label when the server is in that state. Similarly, if 12.790 + only some of the commands in an extension will be available, or if 12.791 + the behaviour of the extension will change in some other manner, 12.792 + according to the state of the server, this MUST be indicated by 12.793 + different arguments in the capability line. 12.794 + 12.795 + Note that a capability line can only begin with a letter. Lines 12.796 + beginning with other characters are reserved for future versions of 12.797 + this specification. In order to interoperate with such versions, 12.798 + clients MUST be prepared to receive lines beginning with other 12.799 + characters and MUST ignore any they do not understand. 12.800 + 12.801 +3.3.2. Standard Capabilities 12.802 + 12.803 + The following capabilities are defined by this specification. 12.804 + 12.805 + VERSION 12.806 + This capability MUST be advertised by all servers and MUST be the 12.807 + first capability in the capability list; it indicates the 12.808 + version(s) of NNTP that the server supports. There must be at 12.809 + least one argument; each argument is a decimal number and MUST NOT 12.810 + have a leading zero. Version numbers are assigned only in RFCs 12.811 + that update or replace this specification; servers MUST NOT create 12.812 + their own version numbers. 12.813 + 12.814 + The version number of this specification is 2. 12.815 + 12.816 + READER 12.817 + This capability indicates that the server implements the various 12.818 + commands useful for reading clients. 12.819 + 12.820 + IHAVE 12.821 + This capability indicates that the server implements the IHAVE 12.822 + command. 12.823 + 12.824 + POST 12.825 + This capability indicates that the server implements the POST 12.826 + command. 12.827 + 12.828 + NEWNEWS 12.829 + This capability indicates that the server implements the NEWNEWS 12.830 + command. 12.831 + 12.832 + HDR 12.833 + This capability indicates that the server implements the header 12.834 + access commands (HDR and LIST HEADERS). 12.835 + 12.836 + 12.837 + 12.838 + 12.839 + 12.840 +Feather Standards Track [Page 15] 12.841 + 12.842 +RFC 3977 Network News Transfer Protocol (NNTP) October 2006 12.843 + 12.844 + 12.845 + OVER 12.846 + This capability indicates that the server implements the overview 12.847 + access commands (OVER and LIST OVERVIEW.FMT). If and only if the 12.848 + server supports the message-id form of the OVER command, there 12.849 + must be a single argument MSGID. 12.850 + 12.851 + LIST 12.852 + This capability indicates that the server implements at least one 12.853 + variant of the LIST command. There MUST be one argument for each 12.854 + variant of the LIST command supported by the server, giving the 12.855 + keyword for that variant. 12.856 + 12.857 + IMPLEMENTATION 12.858 + This capability MAY be provided by a server. If so, the arguments 12.859 + SHOULD be used to provide information such as the server software 12.860 + name and version number. The client MUST NOT use this line to 12.861 + determine capabilities of the server. (While servers often 12.862 + provide this information in the initial greeting, clients need to 12.863 + guess whether this is the case; this capability makes it clear 12.864 + what the information is.) 12.865 + 12.866 + MODE-READER 12.867 + This capability indicates that the server is mode-switching 12.868 + (Section 3.4.2) and that the MODE READER command needs to be used 12.869 + to enable the READER capability. 12.870 + 12.871 +3.3.3. Extensions 12.872 + 12.873 + Although NNTP is widely and robustly deployed, some parts of the 12.874 + Internet community might wish to extend the NNTP service. It must be 12.875 + emphasized that any extension to NNTP should not be considered 12.876 + lightly. NNTP's strength comes primarily from its simplicity. 12.877 + Experience with many protocols has shown that: 12.878 + 12.879 + Protocols with few options tend towards ubiquity, whilst protocols 12.880 + with many options tend towards obscurity. 12.881 + 12.882 + This means that each and every extension, regardless of its benefits, 12.883 + must be carefully scrutinized with respect to its implementation, 12.884 + deployment, and interoperability costs. In many cases, the cost of 12.885 + extending the NNTP service will likely outweigh the benefit. 12.886 + 12.887 + An extension is a package of associated facilities, often but not 12.888 + always including one or more new commands. Each extension MUST 12.889 + define at least one new capability label (this will often, but need 12.890 + not, be the name of one of these new commands). While any additional 12.891 + capability information can normally be specified using arguments to 12.892 + 12.893 + 12.894 + 12.895 + 12.896 +Feather Standards Track [Page 16] 12.897 + 12.898 +RFC 3977 Network News Transfer Protocol (NNTP) October 2006 12.899 + 12.900 + 12.901 + that label, an extension MAY define more than one capability label. 12.902 + However, this SHOULD be limited to exceptional circumstances. 12.903 + 12.904 + An extension is either a private extension, or its capabilities are 12.905 + included in the IANA registry of capabilities (see Section 3.3.4) and 12.906 + it is defined in an RFC (in which case it is a "registered 12.907 + extension"). Such RFCs either must be on the standards track or must 12.908 + define an IESG-approved experimental protocol. 12.909 + 12.910 + The definition of an extension must include the following: 12.911 + 12.912 + o a descriptive name for the extension. 12.913 + 12.914 + o the capability label or labels defined by the extension (the 12.915 + capability label of a registered extension MUST NOT begin with 12.916 + "X"). 12.917 + 12.918 + o The syntax, values, and meanings of any arguments for each 12.919 + capability label defined by the extension. 12.920 + 12.921 + o Any new NNTP commands associated with the extension (the names of 12.922 + commands associated with registered extensions MUST NOT begin with 12.923 + "X"). 12.924 + 12.925 + o The syntax and possible values of arguments associated with the 12.926 + new NNTP commands. 12.927 + 12.928 + o The response codes and possible values of arguments for the 12.929 + responses of the new NNTP commands. 12.930 + 12.931 + o Any new arguments the extension associates with any other 12.932 + pre-existing NNTP commands. 12.933 + 12.934 + o Any increase in the maximum length of commands and initial 12.935 + response lines over the value specified in this document. 12.936 + 12.937 + o A specific statement about the effect on pipelining that this 12.938 + extension may have (if any). 12.939 + 12.940 + o A specific statement about the circumstances when use of this 12.941 + extension can alter the contents of the capabilities list (other 12.942 + than the new capability labels it defines). 12.943 + 12.944 + o A specific statement about the circumstances under which the 12.945 + extension can cause any pre-existing command to produce a 401, 12.946 + 480, or 483 response. 12.947 + 12.948 + 12.949 + 12.950 + 12.951 + 12.952 +Feather Standards Track [Page 17] 12.953 + 12.954 +RFC 3977 Network News Transfer Protocol (NNTP) October 2006 12.955 + 12.956 + 12.957 + o A description of how the use of MODE READER on a mode-switching 12.958 + server interacts with the extension. 12.959 + 12.960 + o A description of how support for the extension affects the 12.961 + behaviour of a server and NNTP client in any other manner not 12.962 + outlined above. 12.963 + 12.964 + o Formal syntax as described in Section 9.9. 12.965 + 12.966 + A private extension MAY or MAY NOT be included in the capabilities 12.967 + list. If it is, the capability label MUST begin with "X". A server 12.968 + MAY provide additional keywords (for new commands and also for new 12.969 + variants of existing commands) as part of a private extension. To 12.970 + avoid the risk of a clash with a future registered extension, these 12.971 + keywords SHOULD begin with "X". 12.972 + 12.973 + If the server advertises a capability defined by a registered 12.974 + extension, it MUST implement the extension so as to fully conform 12.975 + with the specification (for example, it MUST implement all the 12.976 + commands that the extension describes as mandatory). If it does not 12.977 + implement the extension as specified, it MUST NOT list the extension 12.978 + in the capabilities list under its registered name. In that case, it 12.979 + MAY, but SHOULD NOT, provide a private extension (not listed, or 12.980 + listed with a different name) that implements part of the extension 12.981 + or implements the commands of the extension with a different meaning. 12.982 + 12.983 + A server MUST NOT send different response codes to basic NNTP 12.984 + commands documented here or to commands documented in registered 12.985 + extensions in response to the availability or use of a private 12.986 + extension. 12.987 + 12.988 +3.3.4. Initial IANA Register 12.989 + 12.990 + IANA will maintain a registry of NNTP capability labels. All 12.991 + capability labels in the registry MUST be keywords and MUST NOT begin 12.992 + with X. 12.993 + 12.994 + 12.995 + 12.996 + 12.997 + 12.998 + 12.999 + 12.1000 + 12.1001 + 12.1002 + 12.1003 + 12.1004 + 12.1005 + 12.1006 + 12.1007 + 12.1008 +Feather Standards Track [Page 18] 12.1009 + 12.1010 +RFC 3977 Network News Transfer Protocol (NNTP) October 2006 12.1011 + 12.1012 + 12.1013 + The initial content of the registry consists of these entries: 12.1014 + 12.1015 + +-------------------+--------------------------+--------------------+ 12.1016 + | Label | Meaning | Definition | 12.1017 + +-------------------+--------------------------+--------------------+ 12.1018 + | AUTHINFO | Authentication | [NNTP-AUTH] | 12.1019 + | | | | 12.1020 + | HDR | Batched header retrieval | Section 3.3.2, | 12.1021 + | | | Section 8.5, and | 12.1022 + | | | Section 8.6 | 12.1023 + | | | | 12.1024 + | IHAVE | IHAVE command available | Section 3.3.2 and | 12.1025 + | | | Section 6.3.2 | 12.1026 + | | | | 12.1027 + | IMPLEMENTATION | Server | Section 3.3.2 | 12.1028 + | | implementation-specific | | 12.1029 + | | information | | 12.1030 + | | | | 12.1031 + | LIST | LIST command variants | Section 3.3.2 and | 12.1032 + | | | Section 7.6.1 | 12.1033 + | | | | 12.1034 + | MODE-READER | Mode-switching server | Section 3.4.2 | 12.1035 + | | and MODE READER command | | 12.1036 + | | available | | 12.1037 + | | | | 12.1038 + | NEWNEWS | NEWNEWS command | Section 3.3.2 and | 12.1039 + | | available | Section 7.4 | 12.1040 + | | | | 12.1041 + | OVER | Overview support | Section 3.3.2, | 12.1042 + | | | Section 8.3, and | 12.1043 + | | | Section 8.4 | 12.1044 + | | | | 12.1045 + | POST | POST command available | Section 3.3.2 and | 12.1046 + | | | Section 6.3.1 | 12.1047 + | | | | 12.1048 + | READER | Reader commands | Section 3.3.2 | 12.1049 + | | available | | 12.1050 + | | | | 12.1051 + | SASL | Supported SASL | [NNTP-AUTH] | 12.1052 + | | mechanisms | | 12.1053 + | | | | 12.1054 + | STARTTLS | Transport layer security | [NNTP-TLS] | 12.1055 + | | | | 12.1056 + | STREAMING | Streaming feeds | [NNTP-STREAM] | 12.1057 + | | | | 12.1058 + | VERSION | Supported NNTP versions | Section 3.3.2 | 12.1059 + +-------------------+--------------------------+--------------------+ 12.1060 + 12.1061 + 12.1062 + 12.1063 + 12.1064 +Feather Standards Track [Page 19] 12.1065 + 12.1066 +RFC 3977 Network News Transfer Protocol (NNTP) October 2006 12.1067 + 12.1068 + 12.1069 +3.4. Mandatory and Optional Commands 12.1070 + 12.1071 + For a number of reasons, not all the commands in this specification 12.1072 + are mandatory. However, it is equally undesirable for every command 12.1073 + to be optional, since this means that a client will have no idea what 12.1074 + facilities are available. Therefore, as a compromise, some of the 12.1075 + commands in this specification are mandatory (they must be supported 12.1076 + by all servers) while the remainder are not. The latter are then 12.1077 + subdivided into bundles, each indicated by a single capability label. 12.1078 + 12.1079 + o If the label is included in the capability list returned by the 12.1080 + server, the server MUST support all commands in that bundle. 12.1081 + 12.1082 + o If the label is not included, the server MAY support none or some 12.1083 + of the commands but SHOULD NOT support all of them. In general, 12.1084 + there will be no way for a client to determine which commands are 12.1085 + supported without trying them. 12.1086 + 12.1087 + The bundles have been chosen to provide useful functionality, and 12.1088 + therefore server authors are discouraged from implementing only part 12.1089 + of a bundle. 12.1090 + 12.1091 + The description of each command will either indicate that it is 12.1092 + mandatory, or will give, using the term "indicating capability", the 12.1093 + capability label indicating whether the bundle including this command 12.1094 + is available. 12.1095 + 12.1096 + Where a server does not implement a command, it MUST always generate 12.1097 + a 500 generic response code (or a 501 generic response code in the 12.1098 + case of a variant of a command depending on a second keyword where 12.1099 + the base command is recognised). Otherwise, the command MUST be 12.1100 + fully implemented as specified; a server MUST NOT only partially 12.1101 + implement any of the commands in this specification. (Client authors 12.1102 + should note that some servers not conforming to this specification 12.1103 + will return a 502 generic response code to some commands that are not 12.1104 + implemented.) 12.1105 + 12.1106 + Note: some commands have cases that require other commands to be used 12.1107 + first. If the former command is implemented but the latter is not, 12.1108 + the former MUST still generate the relevant specific response code. 12.1109 + For example, if ARTICLE (Section 6.2.1) is implemented but GROUP 12.1110 + (Section 6.1.1) is not, the correct response to "ARTICLE 1234" 12.1111 + remains 412. 12.1112 + 12.1113 + 12.1114 + 12.1115 + 12.1116 + 12.1117 + 12.1118 + 12.1119 + 12.1120 +Feather Standards Track [Page 20] 12.1121 + 12.1122 +RFC 3977 Network News Transfer Protocol (NNTP) October 2006 12.1123 + 12.1124 + 12.1125 +3.4.1. Reading and Transit Servers 12.1126 + 12.1127 + NNTP is traditionally used in two different ways. The first use is 12.1128 + "reading", where the client fetches articles from a large store 12.1129 + maintained by the server for immediate or later presentation to a 12.1130 + user and sends articles created by that user back to the server (an 12.1131 + action called "posting") to be stored and distributed to other stores 12.1132 + and users. The second use is for the bulk transfer of articles from 12.1133 + one store to another. Since the hosts making this transfer tend to 12.1134 + be peers in a network that transmit articles among one another, and 12.1135 + not end-user systems, this process is called "peering" or "transit". 12.1136 + (Even so, one host is still the client and the other is the server). 12.1137 + 12.1138 + In practice, these two uses are so different that some server 12.1139 + implementations are optimised for reading or for transit and, as a 12.1140 + result, do not offer the other facility or only offer limited 12.1141 + features. Other implementations are more general and offer both. 12.1142 + This specification allows for this by bundling the relevant commands 12.1143 + accordingly: the IHAVE command is designed for transit, while the 12.1144 + commands indicated by the READER capability are designed for reading 12.1145 + clients. 12.1146 + 12.1147 + Except as an effect of the MODE READER command (Section 5.3) on a 12.1148 + mode-switching server, once a server advertises either or both of the 12.1149 + IHAVE or READER capabilities, it MUST continue to advertise them for 12.1150 + the entire session. 12.1151 + 12.1152 + A server MAY provide different modes of behaviour (transit, reader, 12.1153 + or a combination) to different client connections and MAY use 12.1154 + external information, such as the IP address of the client, to 12.1155 + determine which mode to provide to any given connection. 12.1156 + 12.1157 + The official TCP port for the NNTP service is 119. However, if a 12.1158 + host wishes to offer separate servers for transit and reading 12.1159 + clients, port 433 SHOULD be used for the transit server and 119 for 12.1160 + the reading server. 12.1161 + 12.1162 +3.4.2. Mode Switching 12.1163 + 12.1164 + An implementation MAY, but SHOULD NOT, provide both transit and 12.1165 + reader facilities on the same server but require the client to select 12.1166 + which it wishes to use. Such an arrangement is called a 12.1167 + "mode-switching" server. 12.1168 + 12.1169 + 12.1170 + 12.1171 + 12.1172 + 12.1173 + 12.1174 + 12.1175 + 12.1176 +Feather Standards Track [Page 21] 12.1177 + 12.1178 +RFC 3977 Network News Transfer Protocol (NNTP) October 2006 12.1179 + 12.1180 + 12.1181 + A mode-switching server has two modes: 12.1182 + 12.1183 + o Transit mode, which applies after the initial connection. 12.1184 + 12.1185 + * It MUST advertise the MODE-READER capability. 12.1186 + 12.1187 + * It MUST NOT advertise the READER capability. 12.1188 + 12.1189 + However, the server MAY cease to advertise the MODE-READER 12.1190 + capability after the client uses any command except CAPABILITIES. 12.1191 + 12.1192 + o Reading mode, after a successful MODE READER command (see Section 12.1193 + 5.3). 12.1194 + 12.1195 + * It MUST NOT advertise the MODE-READER capability. 12.1196 + 12.1197 + * It MUST advertise the READER capability. 12.1198 + 12.1199 + * It MAY NOT advertise the IHAVE capability, even if it was 12.1200 + advertising it in transit mode. 12.1201 + 12.1202 + A client SHOULD only issue a MODE READER command to a server if it is 12.1203 + advertising the MODE-READER capability. If the server does not 12.1204 + support CAPABILITIES (and therefore does not conform to this 12.1205 + specification), the client MAY use the following heuristic: 12.1206 + 12.1207 + o If the client wishes to use any "reader" commands, it SHOULD use 12.1208 + the MODE READER command immediately after the initial connection. 12.1209 + 12.1210 + o Otherwise, it SHOULD NOT use the MODE READER command. 12.1211 + 12.1212 + In each case, it should be prepared for some commands to be 12.1213 + unavailable that would have been available if it had made the other 12.1214 + choice. 12.1215 + 12.1216 +3.5. Pipelining 12.1217 + 12.1218 + NNTP is designed to operate over a reliable bi-directional 12.1219 + connection, such as TCP. Therefore, if a command does not depend on 12.1220 + the response to the previous one, it should not matter if it is sent 12.1221 + before that response is received. Doing this is called "pipelining". 12.1222 + However, certain server implementations throw away all text received 12.1223 + from the client following certain commands before sending their 12.1224 + response. If this happens, pipelining will be affected because one 12.1225 + or more commands will have been ignored or misinterpreted, and the 12.1226 + client will be matching the wrong responses to each command. Since 12.1227 + there are significant benefits to pipelining, but also circumstances 12.1228 + where it is reasonable or common for servers to behave in the above 12.1229 + 12.1230 + 12.1231 + 12.1232 +Feather Standards Track [Page 22] 12.1233 + 12.1234 +RFC 3977 Network News Transfer Protocol (NNTP) October 2006 12.1235 + 12.1236 + 12.1237 + manner, this document puts certain requirements on both clients and 12.1238 + servers. 12.1239 + 12.1240 + Except where stated otherwise, a client MAY use pipelining. That is, 12.1241 + it may send a command before receiving the response for the previous 12.1242 + command. The server MUST allow pipelining and MUST NOT throw away 12.1243 + any text received after a command. Irrespective of whether 12.1244 + pipelining is used, the server MUST process commands in the order 12.1245 + they are sent. 12.1246 + 12.1247 + If the specific description of a command says it "MUST NOT be 12.1248 + pipelined", that command MUST end any pipeline of commands. That is, 12.1249 + the client MUST NOT send any following command until it receives the 12.1250 + CRLF at the end of the response from the command. The server MAY 12.1251 + ignore any data received after the command and before the CRLF at the 12.1252 + end of the response is sent to the client. 12.1253 + 12.1254 + The initial connection must not be part of a pipeline; that is, the 12.1255 + client MUST NOT send any command until it receives the CRLF at the 12.1256 + end of the greeting. 12.1257 + 12.1258 + If the client uses blocking system calls to send commands, it MUST 12.1259 + ensure that the amount of text sent in pipelining does not cause a 12.1260 + deadlock between transmission and reception. The amount of text 12.1261 + involved will depend on window sizes in the transmission layer; 12.1262 + typically, it is 4k octets for TCP. (Since the server only sends 12.1263 + data in response to commands from the client, the converse problem 12.1264 + does not occur.) 12.1265 + 12.1266 +3.5.1. Examples 12.1267 + 12.1268 + Example of correct use of pipelining: 12.1269 + 12.1270 + [C] GROUP misc.test 12.1271 + [C] STAT 12.1272 + [C] NEXT 12.1273 + [S] 211 1234 3000234 3002322 misc.test 12.1274 + [S] 223 3000234 <45223423@example.com> retrieved 12.1275 + [S] 223 3000237 <668929@example.org> retrieved 12.1276 + 12.1277 + Example of incorrect use of pipelining (the MODE READER command may 12.1278 + not be pipelined): 12.1279 + 12.1280 + [C] MODE READER 12.1281 + [C] DATE 12.1282 + [C] NEXT 12.1283 + [S] 200 Server ready, posting allowed 12.1284 + [S] 223 3000237 <668929@example.org> retrieved 12.1285 + 12.1286 + 12.1287 + 12.1288 +Feather Standards Track [Page 23] 12.1289 + 12.1290 +RFC 3977 Network News Transfer Protocol (NNTP) October 2006 12.1291 + 12.1292 + 12.1293 + The DATE command has been thrown away by the server, so there is no 12.1294 + 111 response to match it. 12.1295 + 12.1296 +3.6. Articles 12.1297 + 12.1298 + NNTP is intended to transfer articles between clients and servers. 12.1299 + For the purposes of this specification, articles are required to 12.1300 + conform to the rules in this section, and clients and servers MUST 12.1301 + correctly process any article received from the other that does so. 12.1302 + Note that this requirement applies only to the contents of 12.1303 + communications over NNTP; it does not prevent the client or server 12.1304 + from subsequently rejecting an article for reasons of local policy. 12.1305 + Also see Appendix A for further restrictions on the format of 12.1306 + articles in some uses of NNTP. 12.1307 + 12.1308 + An article consists of two parts: the headers and the body. They are 12.1309 + separated by a single empty line, or in other words by two 12.1310 + consecutive CRLF pairs (if there is more than one empty line, the 12.1311 + second and subsequent ones are part of the body). In order to meet 12.1312 + the general requirements of NNTP, an article MUST NOT include the 12.1313 + octet NUL, MUST NOT contain the octets LF and CR other than as part 12.1314 + of a CRLF pair, and MUST end with a CRLF pair. This specification 12.1315 + puts no further restrictions on the body; in particular, it MAY be 12.1316 + empty. 12.1317 + 12.1318 + The headers of an article consist of one or more header lines. Each 12.1319 + header line consists of a header name, a colon, a space, the header 12.1320 + content, and a CRLF, in that order. The name consists of one or more 12.1321 + printable US-ASCII characters other than colon and, for the purposes 12.1322 + of this specification, is not case sensitive. There MAY be more than 12.1323 + one header line with the same name. The content MUST NOT contain 12.1324 + CRLF; it MAY be empty. A header may be "folded"; that is, a CRLF 12.1325 + pair may be placed before any TAB or space in the line. There MUST 12.1326 + still be some other octet between any two CRLF pairs in a header 12.1327 + line. (Note that folding means that the header line occupies more 12.1328 + than one line when displayed or transmitted; nevertheless, it is 12.1329 + still referred to as "a" header line.) The presence or absence of 12.1330 + folding does not affect the meaning of the header line; that is, the 12.1331 + CRLF pairs introduced by folding are not considered part of the 12.1332 + header content. Header lines SHOULD NOT be folded before the space 12.1333 + after the colon that follows the header name and SHOULD include at 12.1334 + least one octet other than %x09 or %x20 between CRLF pairs. However, 12.1335 + if an article that fails to satisfy this requirement has been 12.1336 + received from elsewhere, clients and servers MAY transfer it to each 12.1337 + other without re-folding it. 12.1338 + 12.1339 + 12.1340 + 12.1341 + 12.1342 + 12.1343 + 12.1344 +Feather Standards Track [Page 24] 12.1345 + 12.1346 +RFC 3977 Network News Transfer Protocol (NNTP) October 2006 12.1347 + 12.1348 + 12.1349 + The content of a header SHOULD be in UTF-8. However, if an 12.1350 + implementation receives an article from elsewhere that uses octets in 12.1351 + the range 128 to 255 in some other manner, it MAY pass it to a client 12.1352 + or server without modification. Therefore, implementations MUST be 12.1353 + prepared to receive such headers, and data derived from them (e.g., 12.1354 + in the responses from the OVER command, Section 8.3), and MUST NOT 12.1355 + assume that they are always UTF-8. Any external processing of those 12.1356 + headers, including identifying the encoding used, is outside the 12.1357 + scope of this document. 12.1358 + 12.1359 + Each article MUST have a unique message-id; two articles offered by 12.1360 + an NNTP server MUST NOT have the same message-id. For the purposes 12.1361 + of this specification, message-ids are opaque strings that MUST meet 12.1362 + the following requirements: 12.1363 + 12.1364 + o A message-id MUST begin with "<", end with ">", and MUST NOT 12.1365 + contain the latter except at the end. 12.1366 + 12.1367 + o A message-id MUST be between 3 and 250 octets in length. 12.1368 + 12.1369 + o A message-id MUST NOT contain octets other than printable US-ASCII 12.1370 + characters. 12.1371 + 12.1372 + Two message-ids are the same if and only if they consist of the same 12.1373 + sequence of octets. 12.1374 + 12.1375 + This specification does not describe how the message-id of an article 12.1376 + is determined. If the server does not have any way to determine a 12.1377 + message-id from the article itself, it MUST synthesize one (this 12.1378 + specification does not require that the article be changed as a 12.1379 + result). See also Appendix A.2. 12.1380 + 12.1381 +4. The WILDMAT Format 12.1382 + 12.1383 + The WILDMAT format described here is based on the version first 12.1384 + developed by Rich Salz [SALZ1992], which was in turn derived from the 12.1385 + format used in the UNIX "find" command to articulate file names. It 12.1386 + was developed to provide a uniform mechanism for matching patterns in 12.1387 + the same manner that the UNIX shell matches filenames. 12.1388 + 12.1389 + 12.1390 + 12.1391 + 12.1392 + 12.1393 + 12.1394 + 12.1395 + 12.1396 + 12.1397 + 12.1398 + 12.1399 + 12.1400 +Feather Standards Track [Page 25] 12.1401 + 12.1402 +RFC 3977 Network News Transfer Protocol (NNTP) October 2006 12.1403 + 12.1404 + 12.1405 +4.1. Wildmat Syntax 12.1406 + 12.1407 + A wildmat is described by the following ABNF [RFC4234] syntax, which 12.1408 + is an extract of that in Section 9.8. 12.1409 + 12.1410 + wildmat = wildmat-pattern *("," ["!"] wildmat-pattern) 12.1411 + wildmat-pattern = 1*wildmat-item 12.1412 + wildmat-item = wildmat-exact / wildmat-wild 12.1413 + wildmat-exact = %x22-29 / %x2B / %x2D-3E / %x40-5A / %x5E-7E / 12.1414 + UTF8-non-ascii ; exclude ! * , ? [ \ ] 12.1415 + wildmat-wild = "*" / "?" 12.1416 + 12.1417 + Note: the characters ",", "\", "[", and "]" are not allowed in 12.1418 + wildmats, while * and ? are always wildcards. This should not be a 12.1419 + problem, since these characters cannot occur in newsgroup names, 12.1420 + which is the only current use of wildmats. Backslash is commonly 12.1421 + used to suppress the special meaning of characters, whereas brackets 12.1422 + are used to introduce sets. However, these usages are not universal, 12.1423 + and interpretation of these characters in the context of UTF-8 12.1424 + strings is potentially complex and differs from existing practice, so 12.1425 + they were omitted from this specification. A future extension to 12.1426 + this specification may provide semantics for these characters. 12.1427 + 12.1428 +4.2. Wildmat Semantics 12.1429 + 12.1430 + A wildmat is tested against a string and either matches or does not 12.1431 + match. To do this, each constituent <wildmat-pattern> is matched 12.1432 + against the string, and the rightmost pattern that matches is 12.1433 + identified. If that <wildmat-pattern> is not preceded with "!", the 12.1434 + whole wildmat matches. If it is preceded by "!", or if no <wildmat- 12.1435 + pattern> matches, the whole wildmat does not match. 12.1436 + 12.1437 + For example, consider the wildmat "a*,!*b,*c*": 12.1438 + 12.1439 + o The string "aaa" matches because the rightmost match is with "a*". 12.1440 + 12.1441 + o The string "abb" does not match because the rightmost match is 12.1442 + with "*b". 12.1443 + 12.1444 + o The string "ccb" matches because the rightmost match is with 12.1445 + "*c*". 12.1446 + 12.1447 + o The string "xxx" does not match because no <wildmat-pattern> 12.1448 + matches. 12.1449 + 12.1450 + A <wildmat-pattern> matches a string if the string can be broken into 12.1451 + components, each of which matches the corresponding <wildmat-item> in 12.1452 + the pattern. The matches must be in the same order, and the whole 12.1453 + 12.1454 + 12.1455 + 12.1456 +Feather Standards Track [Page 26] 12.1457 + 12.1458 +RFC 3977 Network News Transfer Protocol (NNTP) October 2006 12.1459 + 12.1460 + 12.1461 + string must be used in the match. The pattern is "anchored"; that 12.1462 + is, the first and last characters in the string must match the first 12.1463 + and last item, respectively (unless that item is an asterisk matching 12.1464 + zero characters). 12.1465 + 12.1466 + A <wildmat-exact> matches the same character (which may be more than 12.1467 + one octet in UTF-8). 12.1468 + 12.1469 + "?" matches exactly one character (which may be more than one octet). 12.1470 + 12.1471 + "*" matches zero or more characters. It can match an empty string, 12.1472 + but it cannot match a subsequence of a UTF-8 sequence that is not 12.1473 + aligned to the character boundaries. 12.1474 + 12.1475 +4.3. Extensions 12.1476 + 12.1477 + An NNTP server or extension MAY extend the syntax or semantics of 12.1478 + wildmats provided that all wildmats that meet the requirements of 12.1479 + Section 4.1 have the meaning ascribed to them by Section 4.2. Future 12.1480 + editions of this document may also extend wildmats. 12.1481 + 12.1482 +4.4. Examples 12.1483 + 12.1484 + In these examples, $ and @ are used to represent the two octets %xC2 12.1485 + and %xA3, respectively; $@ is thus the UTF-8 encoding for the pound 12.1486 + sterling symbol, shown as # in the descriptions. 12.1487 + 12.1488 + Wildmat Description of strings that match 12.1489 + abc The one string "abc" 12.1490 + abc,def The two strings "abc" and "def" 12.1491 + $@ The one character string "#" 12.1492 + a* Any string that begins with "a" 12.1493 + a*b Any string that begins with "a" and ends with "b" 12.1494 + a*,*b Any string that begins with "a" or ends with "b" 12.1495 + a*,!*b Any string that begins with "a" and does not end with 12.1496 + "b" 12.1497 + a*,!*b,c* Any string that begins with "a" and does not end with 12.1498 + "b", and any string that begins with "c" no matter 12.1499 + what it ends with 12.1500 + a*,c*,!*b Any string that begins with "a" or "c" and does not 12.1501 + end with "b" 12.1502 + ?a* Any string with "a" as its second character 12.1503 + ??a* Any string with "a" as its third character 12.1504 + *a? Any string with "a" as its penultimate character 12.1505 + *a?? Any string with "a" as its antepenultimate character 12.1506 + 12.1507 + 12.1508 + 12.1509 + 12.1510 + 12.1511 + 12.1512 +Feather Standards Track [Page 27] 12.1513 + 12.1514 +RFC 3977 Network News Transfer Protocol (NNTP) October 2006 12.1515 + 12.1516 + 12.1517 +5. Session Administration Commands 12.1518 + 12.1519 +5.1. Initial Connection 12.1520 + 12.1521 +5.1.1. Usage 12.1522 + 12.1523 + This command MUST NOT be pipelined. 12.1524 + 12.1525 + Responses [1] 12.1526 + 200 Service available, posting allowed 12.1527 + 201 Service available, posting prohibited 12.1528 + 400 Service temporarily unavailable [2] 12.1529 + 502 Service permanently unavailable [2] 12.1530 + 12.1531 + [1] These are the only valid response codes for the initial greeting; 12.1532 + the server MUST not return any other generic response code. 12.1533 + 12.1534 + [2] Following a 400 or 502 response, the server MUST immediately 12.1535 + close the connection. 12.1536 + 12.1537 +5.1.2. Description 12.1538 + 12.1539 + There is no command presented by the client upon initial connection 12.1540 + to the server. The server MUST present an appropriate response code 12.1541 + as a greeting to the client. This response informs the client 12.1542 + whether service is available and whether the client is permitted to 12.1543 + post. 12.1544 + 12.1545 + If the server will accept further commands from the client including 12.1546 + POST, the server MUST present a 200 greeting code. If the server 12.1547 + will accept further commands from the client, but the client is not 12.1548 + authorized to post articles using the POST command, the server MUST 12.1549 + present a 201 greeting code. 12.1550 + 12.1551 + Otherwise, the server MUST present a 400 or 502 greeting code and 12.1552 + then immediately close the connection. 400 SHOULD be used if the 12.1553 + issue is only temporary (for example, because of load) and the client 12.1554 + can expect to be able to connect successfully at some point in the 12.1555 + future without making any changes. 502 MUST be used if the client is 12.1556 + not permitted under any circumstances to interact with the server, 12.1557 + and MAY be used if the server has insufficient information to 12.1558 + determine whether the issue is temporary or permanent. 12.1559 + 12.1560 + Note: the distinction between the 200 and 201 response codes has 12.1561 + turned out in practice to be insufficient; for example, some servers 12.1562 + do not allow posting until the client has authenticated, while other 12.1563 + clients assume that a 201 response means that posting will never be 12.1564 + possible even after authentication. Therefore, clients SHOULD use 12.1565 + 12.1566 + 12.1567 + 12.1568 +Feather Standards Track [Page 28] 12.1569 + 12.1570 +RFC 3977 Network News Transfer Protocol (NNTP) October 2006 12.1571 + 12.1572 + 12.1573 + the CAPABILITIES command (Section 5.2) rather than rely on this 12.1574 + response. 12.1575 + 12.1576 +5.1.3. Examples 12.1577 + 12.1578 + Example of a normal connection from an authorized client that then 12.1579 + terminates the session (see Section 5.4): 12.1580 + 12.1581 + [Initial connection set-up completed.] 12.1582 + [S] 200 NNTP Service Ready, posting permitted 12.1583 + [C] QUIT 12.1584 + [S] 205 NNTP Service exits normally 12.1585 + [Server closes connection.] 12.1586 + 12.1587 + Example of a normal connection from an authorized client that is not 12.1588 + permitted to post, which also immediately terminates the session: 12.1589 + 12.1590 + [Initial connection set-up completed.] 12.1591 + [S] 201 NNTP Service Ready, posting prohibited 12.1592 + [C] QUIT 12.1593 + [S] 205 NNTP Service exits normally 12.1594 + [Server closes connection.] 12.1595 + 12.1596 + Example of a normal connection from an unauthorized client: 12.1597 + 12.1598 + [Initial connection set-up completed.] 12.1599 + [S] 502 NNTP Service permanently unavailable 12.1600 + [Server closes connection.] 12.1601 + 12.1602 + Example of a connection from a client if the server is unable to 12.1603 + provide service: 12.1604 + 12.1605 + [Initial connection set-up completed.] 12.1606 + [S] 400 NNTP Service temporarily unavailable 12.1607 + [Server closes connection.] 12.1608 + 12.1609 +5.2. CAPABILITIES 12.1610 + 12.1611 +5.2.1. Usage 12.1612 + 12.1613 + This command is mandatory. 12.1614 + 12.1615 + Syntax 12.1616 + CAPABILITIES [keyword] 12.1617 + 12.1618 + Responses 12.1619 + 101 Capability list follows (multi-line) 12.1620 + 12.1621 + 12.1622 + 12.1623 + 12.1624 +Feather Standards Track [Page 29] 12.1625 + 12.1626 +RFC 3977 Network News Transfer Protocol (NNTP) October 2006 12.1627 + 12.1628 + 12.1629 + Parameters 12.1630 + keyword additional feature, see description 12.1631 + 12.1632 +5.2.2. Description 12.1633 + 12.1634 + The CAPABILITIES command allows a client to determine the 12.1635 + capabilities of the server at any given time. 12.1636 + 12.1637 + This command MAY be issued at any time; the server MUST NOT require 12.1638 + it to be issued in order to make use of any capability. The response 12.1639 + generated by this command MAY change during a session because of 12.1640 + other state information (which, in turn, may be changed by the 12.1641 + effects of other commands or by external events). An NNTP client is 12.1642 + only able to get the current and correct information concerning 12.1643 + available capabilities at any point during a session by issuing a 12.1644 + CAPABILITIES command at that point of that session and processing the 12.1645 + response. 12.1646 + 12.1647 + The capability list is returned as a multi-line data block following 12.1648 + the 101 response code. Each capability is described by a separate 12.1649 + capability line. The server MUST NOT list the same capability twice 12.1650 + in the response, even with different arguments. Except that the 12.1651 + VERSION capability MUST be the first line, the order in which the 12.1652 + capability lines appears is not significant; the server need not even 12.1653 + consistently return the same order. 12.1654 + 12.1655 + While some capabilities are likely to be always available or never 12.1656 + available, others (notably extensions) will appear and disappear 12.1657 + depending on server state changes within the session or on external 12.1658 + events between sessions. An NNTP client MAY cache the results of 12.1659 + this command, but MUST NOT rely on the correctness of any cached 12.1660 + results, whether from earlier in this session or from a previous 12.1661 + session, MUST cope gracefully with the cached status being out of 12.1662 + date, and SHOULD (if caching results) provide a way to force the 12.1663 + cached information to be refreshed. Furthermore, a client MUST NOT 12.1664 + use cached results in relation to security, privacy, and 12.1665 + authentication extensions. See Section 12.6 for further discussion 12.1666 + of this topic. 12.1667 + 12.1668 + The keyword argument is not used by this specification. It is 12.1669 + provided so that extensions or revisions to this specification can 12.1670 + include extra features for this command without requiring the 12.1671 + CAPABILITIES command to be used twice (once to determine if the extra 12.1672 + features are available, and a second time to make use of them). If 12.1673 + the server does not recognise the argument (and it is a keyword), it 12.1674 + MUST respond with the 101 response code as if the argument had been 12.1675 + omitted. If an argument is provided that the server does recognise, 12.1676 + it MAY use the 101 response code or MAY use some other response code 12.1677 + 12.1678 + 12.1679 + 12.1680 +Feather Standards Track [Page 30] 12.1681 + 12.1682 +RFC 3977 Network News Transfer Protocol (NNTP) October 2006 12.1683 + 12.1684 + 12.1685 + (which will be defined in the specification of that feature). If the 12.1686 + argument is not a keyword, the 501 generic response code MUST be 12.1687 + returned. The server MUST NOT generate any other response code to 12.1688 + the CAPABILITIES command. 12.1689 + 12.1690 +5.2.3. Examples 12.1691 + 12.1692 + Example of a minimal response (a read-only server): 12.1693 + 12.1694 + [C] CAPABILITIES 12.1695 + [S] 101 Capability list: 12.1696 + [S] VERSION 2 12.1697 + [S] READER 12.1698 + [S] LIST ACTIVE NEWSGROUPS 12.1699 + [S] . 12.1700 + 12.1701 + Example of a response from a server that has a range of facilities 12.1702 + and that also describes itself: 12.1703 + 12.1704 + [C] CAPABILITIES 12.1705 + [S] 101 Capability list: 12.1706 + [S] VERSION 2 12.1707 + [S] READER 12.1708 + [S] IHAVE 12.1709 + [S] POST 12.1710 + [S] NEWNEWS 12.1711 + [S] LIST ACTIVE NEWSGROUPS ACTIVE.TIMES OVERVIEW.FMT 12.1712 + [S] IMPLEMENTATION INN 4.2 2004-12-25 12.1713 + [S] OVER MSGID 12.1714 + [S] STREAMING 12.1715 + [S] XSECRET 12.1716 + [S] . 12.1717 + 12.1718 + Example of a server that supports more than one version of NNTP: 12.1719 + 12.1720 + [C] CAPABILITIES 12.1721 + [S] 101 Capability list: 12.1722 + [S] VERSION 2 3 12.1723 + [S] READER 12.1724 + [S] LIST ACTIVE NEWSGROUPS 12.1725 + [S] . 12.1726 + 12.1727 + 12.1728 + 12.1729 + 12.1730 + 12.1731 + 12.1732 + 12.1733 + 12.1734 + 12.1735 + 12.1736 +Feather Standards Track [Page 31] 12.1737 + 12.1738 +RFC 3977 Network News Transfer Protocol (NNTP) October 2006 12.1739 + 12.1740 + 12.1741 + Example of a client attempting to use a feature of the CAPABILITIES 12.1742 + command that the server does not support: 12.1743 + 12.1744 + [C] CAPABILITIES AUTOUPDATE 12.1745 + [S] 101 Capability list: 12.1746 + [S] VERSION 2 12.1747 + [S] READER 12.1748 + [S] IHAVE 12.1749 + [S] LIST ACTIVE NEWSGROUPS OVERVIEW.FMT HEADERS 12.1750 + [S] OVER MSGID 12.1751 + [S] HDR 12.1752 + [S] NEWNEWS 12.1753 + [S] . 12.1754 + 12.1755 +5.3. MODE READER 12.1756 + 12.1757 +5.3.1. Usage 12.1758 + 12.1759 + Indicating capability: MODE-READER 12.1760 + 12.1761 + This command MUST NOT be pipelined. 12.1762 + 12.1763 + Syntax 12.1764 + MODE READER 12.1765 + 12.1766 + Responses 12.1767 + 200 Posting allowed 12.1768 + 201 Posting prohibited 12.1769 + 502 Reading service permanently unavailable [1] 12.1770 + 12.1771 + [1] Following a 502 response the server MUST immediately close the 12.1772 + connection. 12.1773 + 12.1774 +5.3.2. Description 12.1775 + 12.1776 + The MODE READER command instructs a mode-switching server to switch 12.1777 + modes, as described in Section 3.4.2. 12.1778 + 12.1779 + If the server is mode-switching, it switches from its transit mode to 12.1780 + its reader mode, indicating this by changing the capability list 12.1781 + accordingly. It MUST then return a 200 or 201 response with the same 12.1782 + meaning as for the initial greeting (as described in Section 5.1.1). 12.1783 + Note that the response need not be the same as that presented during 12.1784 + the initial greeting. The client MUST NOT issue MODE READER more 12.1785 + than once in a session or after any security or privacy commands are 12.1786 + issued. When the MODE READER command is issued, the server MAY reset 12.1787 + its state to that immediately after the initial connection before 12.1788 + switching mode. 12.1789 + 12.1790 + 12.1791 + 12.1792 +Feather Standards Track [Page 32] 12.1793 + 12.1794 +RFC 3977 Network News Transfer Protocol (NNTP) October 2006 12.1795 + 12.1796 + 12.1797 + If the server is not mode-switching, then the following apply: 12.1798 + 12.1799 + o If it advertises the READER capability, it MUST return a 200 or 12.1800 + 201 response with the same meaning as for the initial greeting; in 12.1801 + this case, the command MUST NOT affect the server state in any 12.1802 + way. 12.1803 + 12.1804 + o If it does not advertise the READER capability, it MUST return a 12.1805 + 502 response and then immediately close the connection. 12.1806 + 12.1807 +5.3.3. Examples 12.1808 + 12.1809 + Example of use of the MODE READER command on a transit-only server 12.1810 + (which therefore does not providing reading facilities): 12.1811 + 12.1812 + [C] CAPABILITIES 12.1813 + [S] 101 Capability list: 12.1814 + [S] VERSION 2 12.1815 + [S] IHAVE 12.1816 + [S] . 12.1817 + [C] MODE READER 12.1818 + [S] 502 Transit service only 12.1819 + [Server closes connection.] 12.1820 + 12.1821 + Example of use of the MODE READER command on a server that provides 12.1822 + reading facilities: 12.1823 + 12.1824 + [C] CAPABILITIES 12.1825 + [S] 101 Capability list: 12.1826 + [S] VERSION 2 12.1827 + [S] READER 12.1828 + [S] LIST ACTIVE NEWSGROUPS 12.1829 + [S] . 12.1830 + [C] MODE READER 12.1831 + [S] 200 Reader mode, posting permitted 12.1832 + [C] IHAVE <i.am.an.article.you.have@example.com> 12.1833 + [S] 500 Permission denied 12.1834 + [C] GROUP misc.test 12.1835 + [S] 211 1234 3000234 3002322 misc.test 12.1836 + 12.1837 + Note that in both of these situations, the client SHOULD NOT use MODE 12.1838 + READER. 12.1839 + 12.1840 + 12.1841 + 12.1842 + 12.1843 + 12.1844 + 12.1845 + 12.1846 + 12.1847 + 12.1848 +Feather Standards Track [Page 33] 12.1849 + 12.1850 +RFC 3977 Network News Transfer Protocol (NNTP) October 2006 12.1851 + 12.1852 + 12.1853 + Example of use of the MODE READER command on a mode-switching server: 12.1854 + 12.1855 + [C] CAPABILITIES 12.1856 + [S] 101 Capability list: 12.1857 + [S] VERSION 2 12.1858 + [S] IHAVE 12.1859 + [S] MODE-READER 12.1860 + [S] . 12.1861 + [C] MODE READER 12.1862 + [S] 200 Reader mode, posting permitted 12.1863 + [C] CAPABILITIES 12.1864 + [S] 101 Capability list: 12.1865 + [S] VERSION 2 12.1866 + [S] READER 12.1867 + [S] NEWNEWS 12.1868 + [S] LIST ACTIVE NEWSGROUPS 12.1869 + [S] STARTTLS 12.1870 + [S] . 12.1871 + 12.1872 + In this case, the server offers (but does not require) TLS privacy in 12.1873 + its reading mode but not in its transit mode. 12.1874 + 12.1875 + Example of use of the MODE READER command where the client is not 12.1876 + permitted to post: 12.1877 + 12.1878 + [C] MODE READER 12.1879 + [S] 201 NNTP Service Ready, posting prohibited 12.1880 + 12.1881 +5.4. QUIT 12.1882 + 12.1883 +5.4.1. Usage 12.1884 + 12.1885 + This command is mandatory. 12.1886 + 12.1887 + Syntax 12.1888 + QUIT 12.1889 + 12.1890 + Responses 12.1891 + 205 Connection closing 12.1892 + 12.1893 +5.4.2. Description 12.1894 + 12.1895 + The client uses the QUIT command to terminate the session. The 12.1896 + server MUST acknowledge the QUIT command and then close the 12.1897 + connection to the client. This is the preferred method for a client 12.1898 + to indicate that it has finished all of its transactions with the 12.1899 + NNTP server. 12.1900 + 12.1901 + 12.1902 + 12.1903 + 12.1904 +Feather Standards Track [Page 34] 12.1905 + 12.1906 +RFC 3977 Network News Transfer Protocol (NNTP) October 2006 12.1907 + 12.1908 + 12.1909 + If a client simply disconnects (or if the connection times out or 12.1910 + some other fault occurs), the server MUST gracefully cease its 12.1911 + attempts to service the client, disconnecting from its end if 12.1912 + necessary. 12.1913 + 12.1914 + The server MUST NOT generate any response code to the QUIT command 12.1915 + other than 205 or, if any arguments are provided, 501. 12.1916 + 12.1917 +5.4.3. Examples 12.1918 + 12.1919 + [C] QUIT 12.1920 + [S] 205 closing connection 12.1921 + [Server closes connection.] 12.1922 + 12.1923 +6. Article Posting and Retrieval 12.1924 + 12.1925 + News-reading clients have available a variety of mechanisms to 12.1926 + retrieve articles via NNTP. The news articles are stored and indexed 12.1927 + using three types of keys. The first type of key is the message-id 12.1928 + of an article and is globally unique. The second type of key is 12.1929 + composed of a newsgroup name and an article number within that 12.1930 + newsgroup. On a particular server, there MUST only be one article 12.1931 + with a given number within any newsgroup, and an article MUST NOT 12.1932 + have two different numbers in the same newsgroup. An article can be 12.1933 + cross-posted to multiple newsgroups, so there may be multiple keys 12.1934 + that point to the same article on the same server; these MAY have 12.1935 + different numbers in each newsgroup. However, this type of key is 12.1936 + not required to be globally unique, so the same key MAY refer to 12.1937 + different articles on different servers. (Note that the terms 12.1938 + "group" and "newsgroup" are equivalent.) 12.1939 + 12.1940 + The final type of key is the arrival timestamp, giving the time that 12.1941 + the article arrived at the server. The server MUST ensure that 12.1942 + article numbers are issued in order of arrival timestamp; that is, 12.1943 + articles arriving later MUST have higher numbers than those that 12.1944 + arrive earlier. The server SHOULD allocate the next sequential 12.1945 + unused number to each new article. 12.1946 + 12.1947 + Article numbers MUST lie between 1 and 2,147,483,647, inclusive. The 12.1948 + client and server MAY use leading zeroes in specifying article 12.1949 + numbers but MUST NOT use more than 16 digits. In some situations, 12.1950 + the value zero replaces an article number to show some special 12.1951 + situation. 12.1952 + 12.1953 + Note that it is likely that the article number limit of 2,147,483,647 12.1954 + will be increased by a future revision or extension to this 12.1955 + specification. While servers MUST NOT send article numbers greater 12.1956 + than this current limit, client and server developers are advised to 12.1957 + 12.1958 + 12.1959 + 12.1960 +Feather Standards Track [Page 35] 12.1961 + 12.1962 +RFC 3977 Network News Transfer Protocol (NNTP) October 2006 12.1963 + 12.1964 + 12.1965 + use internal structures and datatypes capable of handling larger 12.1966 + values in anticipation of such a change. 12.1967 + 12.1968 +6.1. Group and Article Selection 12.1969 + 12.1970 + The following commands are used to set the "currently selected 12.1971 + newsgroup" and the "current article number", which are used by 12.1972 + various commands. At the start of an NNTP session, both of these 12.1973 + values are set to the special value "invalid". 12.1974 + 12.1975 +6.1.1. GROUP 12.1976 + 12.1977 +6.1.1.1. Usage 12.1978 + 12.1979 + Indicating capability: READER 12.1980 + 12.1981 + Syntax 12.1982 + GROUP group 12.1983 + 12.1984 + Responses 12.1985 + 211 number low high group Group successfully selected 12.1986 + 411 No such newsgroup 12.1987 + 12.1988 + Parameters 12.1989 + group Name of newsgroup 12.1990 + number Estimated number of articles in the group 12.1991 + low Reported low water mark 12.1992 + high Reported high water mark 12.1993 + 12.1994 +6.1.1.2. Description 12.1995 + 12.1996 + The GROUP command selects a newsgroup as the currently selected 12.1997 + newsgroup and returns summary information about it. 12.1998 + 12.1999 + The required argument is the name of the newsgroup to be selected 12.2000 + (e.g., "news.software.nntp"). A list of valid newsgroups may be 12.2001 + obtained by using the LIST ACTIVE command (see Section 7.6.3). 12.2002 + 12.2003 + The successful selection response will return the article numbers of 12.2004 + the first and last articles in the group at the moment of selection 12.2005 + (these numbers are referred to as the "reported low water mark" and 12.2006 + the "reported high water mark") and an estimate of the number of 12.2007 + articles in the group currently available. 12.2008 + 12.2009 + If the group is not empty, the estimate MUST be at least the actual 12.2010 + number of articles available and MUST be no greater than one more 12.2011 + than the difference between the reported low and high water marks. 12.2012 + (Some implementations will actually count the number of articles 12.2013 + 12.2014 + 12.2015 + 12.2016 +Feather Standards Track [Page 36] 12.2017 + 12.2018 +RFC 3977 Network News Transfer Protocol (NNTP) October 2006 12.2019 + 12.2020 + 12.2021 + currently stored. Others will just subtract the low water mark from 12.2022 + the high water mark and add one to get an estimate.) 12.2023 + 12.2024 + If the group is empty, one of the following three situations will 12.2025 + occur. Clients MUST accept all three cases; servers MUST NOT 12.2026 + represent an empty group in any other way. 12.2027 + 12.2028 + o The high water mark will be one less than the low water mark, and 12.2029 + the estimated article count will be zero. Servers SHOULD use this 12.2030 + method to show an empty group. This is the only time that the 12.2031 + high water mark can be less than the low water mark. 12.2032 + 12.2033 + o All three numbers will be zero. 12.2034 + 12.2035 + o The high water mark is greater than or equal to the low water 12.2036 + mark. The estimated article count might be zero or non-zero; if 12.2037 + it is non-zero, the same requirements apply as for a non-empty 12.2038 + group. 12.2039 + 12.2040 + The set of articles in a group may change after the GROUP command is 12.2041 + carried out: 12.2042 + 12.2043 + o Articles may be removed from the group. 12.2044 + 12.2045 + o Articles may be reinstated in the group with the same article 12.2046 + number, but those articles MUST have numbers no less than the 12.2047 + reported low water mark (note that this is a reinstatement of the 12.2048 + previous article, not a new article reusing the number). 12.2049 + 12.2050 + o New articles may be added with article numbers greater than the 12.2051 + reported high water mark. (If an article that was the one with 12.2052 + the highest number has been removed and the high water mark has 12.2053 + been adjusted accordingly, the next new article will not have the 12.2054 + number one greater than the reported high water mark.) 12.2055 + 12.2056 + Except when the group is empty and all three numbers are zero, 12.2057 + whenever a subsequent GROUP command for the same newsgroup is issued, 12.2058 + either by the same client or a different client, the reported low 12.2059 + water mark in the response MUST be no less than that in any previous 12.2060 + response for that newsgroup in this session, and it SHOULD be no less 12.2061 + than that in any previous response for that newsgroup ever sent to 12.2062 + any client. Any failure to meet the latter condition SHOULD be 12.2063 + transient only. The client may make use of the low water mark to 12.2064 + remove all remembered information about articles with lower numbers, 12.2065 + as these will never recur. This includes the situation when the high 12.2066 + water mark is one less than the low water mark. No similar 12.2067 + assumption can be made about the high water mark, as this can 12.2068 + 12.2069 + 12.2070 + 12.2071 + 12.2072 +Feather Standards Track [Page 37] 12.2073 + 12.2074 +RFC 3977 Network News Transfer Protocol (NNTP) October 2006 12.2075 + 12.2076 + 12.2077 + decrease if an article is removed and then increase again if it is 12.2078 + reinstated or if new articles arrive. 12.2079 + 12.2080 + When a valid group is selected by means of this command, the 12.2081 + currently selected newsgroup MUST be set to that group, and the 12.2082 + current article number MUST be set to the first article in the group 12.2083 + (this applies even if the group is already the currently selected 12.2084 + newsgroup). If an empty newsgroup is selected, the current article 12.2085 + number is made invalid. If an invalid group is specified, the 12.2086 + currently selected newsgroup and current article number MUST NOT be 12.2087 + changed. 12.2088 + 12.2089 + The GROUP or LISTGROUP command (see Section 6.1.2) MUST be used by a 12.2090 + client, and a successful response received, before any other command 12.2091 + is used that depends on the value of the currently selected newsgroup 12.2092 + or current article number. 12.2093 + 12.2094 + If the group specified is not available on the server, a 411 response 12.2095 + MUST be returned. 12.2096 + 12.2097 +6.1.1.3. Examples 12.2098 + 12.2099 + Example for a group known to the server: 12.2100 + 12.2101 + [C] GROUP misc.test 12.2102 + [S] 211 1234 3000234 3002322 misc.test 12.2103 + 12.2104 + Example for a group unknown to the server: 12.2105 + 12.2106 + [C] GROUP example.is.sob.bradner.or.barber 12.2107 + [S] 411 example.is.sob.bradner.or.barber is unknown 12.2108 + 12.2109 + Example of an empty group using the preferred response: 12.2110 + 12.2111 + [C] GROUP example.currently.empty.newsgroup 12.2112 + [S] 211 0 4000 3999 example.currently.empty.newsgroup 12.2113 + 12.2114 + Example of an empty group using an alternative response: 12.2115 + 12.2116 + [C] GROUP example.currently.empty.newsgroup 12.2117 + [S] 211 0 0 0 example.currently.empty.newsgroup 12.2118 + 12.2119 + Example of an empty group using a different alternative response: 12.2120 + 12.2121 + [C] GROUP example.currently.empty.newsgroup 12.2122 + [S] 211 0 4000 4321 example.currently.empty.newsgroup 12.2123 + 12.2124 + 12.2125 + 12.2126 + 12.2127 + 12.2128 +Feather Standards Track [Page 38] 12.2129 + 12.2130 +RFC 3977 Network News Transfer Protocol (NNTP) October 2006 12.2131 + 12.2132 + 12.2133 + Example reselecting the currently selected newsgroup: 12.2134 + 12.2135 + [C] GROUP misc.test 12.2136 + [S] 211 1234 234 567 misc.test 12.2137 + [C] STAT 444 12.2138 + [S] 223 444 <123456@example.net> retrieved 12.2139 + [C] GROUP misc.test 12.2140 + [S] 211 1234 234 567 misc.test 12.2141 + [C] STAT 12.2142 + [S] 223 234 <different@example.net> retrieved 12.2143 + 12.2144 +6.1.2. LISTGROUP 12.2145 + 12.2146 +6.1.2.1. Usage 12.2147 + 12.2148 + Indicating capability: READER 12.2149 + 12.2150 + Syntax 12.2151 + LISTGROUP [group [range]] 12.2152 + 12.2153 + Responses 12.2154 + 211 number low high group Article numbers follow (multi-line) 12.2155 + 411 No such newsgroup 12.2156 + 412 No newsgroup selected [1] 12.2157 + 12.2158 + Parameters 12.2159 + group Name of newsgroup 12.2160 + range Range of articles to report 12.2161 + number Estimated number of articles in the group 12.2162 + low Reported low water mark 12.2163 + high Reported high water mark 12.2164 + 12.2165 + [1] The 412 response can only occur if no group has been specified. 12.2166 + 12.2167 +6.1.2.2. Description 12.2168 + 12.2169 + The LISTGROUP command selects a newsgroup in the same manner as the 12.2170 + GROUP command (see Section 6.1.1) but also provides a list of article 12.2171 + numbers in the newsgroup. If no group is specified, the currently 12.2172 + selected newsgroup is used. 12.2173 + 12.2174 + On success, a list of article numbers is returned as a multi-line 12.2175 + data block following the 211 response code (the arguments on the 12.2176 + initial response line are the same as for the GROUP command). The 12.2177 + list contains one number per line and is in numerical order. It 12.2178 + lists precisely those articles that exist in the group at the moment 12.2179 + of selection (therefore, an empty group produces an empty list). If 12.2180 + the optional range argument is specified, only articles within the 12.2181 + 12.2182 + 12.2183 + 12.2184 +Feather Standards Track [Page 39] 12.2185 + 12.2186 +RFC 3977 Network News Transfer Protocol (NNTP) October 2006 12.2187 + 12.2188 + 12.2189 + range are included in the list (therefore, the list MAY be empty even 12.2190 + if the group is not). 12.2191 + 12.2192 + The range argument may be any of the following: 12.2193 + 12.2194 + o An article number. 12.2195 + 12.2196 + o An article number followed by a dash to indicate all following. 12.2197 + 12.2198 + o An article number followed by a dash followed by another article 12.2199 + number. 12.2200 + 12.2201 + In the last case, if the second number is less than the first number, 12.2202 + then the range contains no articles. Omitting the range is 12.2203 + equivalent to the range 1- being specified. 12.2204 + 12.2205 + If the group specified is not available on the server, a 411 response 12.2206 + MUST be returned. If no group is specified and the currently 12.2207 + selected newsgroup is invalid, a 412 response MUST be returned. 12.2208 + 12.2209 + Except that the group argument is optional, that a range argument can 12.2210 + be specified, and that a multi-line data block follows the 211 12.2211 + response code, the LISTGROUP command is identical to the GROUP 12.2212 + command. In particular, when successful, the command sets the 12.2213 + current article number to the first article in the group, if any, 12.2214 + even if this is not within the range specified by the second 12.2215 + argument. 12.2216 + 12.2217 + Note that the range argument is a new feature in this specification 12.2218 + and servers that do not support CAPABILITIES (and therefore do not 12.2219 + conform to this specification) are unlikely to support it. 12.2220 + 12.2221 +6.1.2.3. Examples 12.2222 + 12.2223 + Example of LISTGROUP being used to select a group: 12.2224 + 12.2225 + [C] LISTGROUP misc.test 12.2226 + [S] 211 2000 3000234 3002322 misc.test list follows 12.2227 + [S] 3000234 12.2228 + [S] 3000237 12.2229 + [S] 3000238 12.2230 + [S] 3000239 12.2231 + [S] 3002322 12.2232 + [S] . 12.2233 + 12.2234 + 12.2235 + 12.2236 + 12.2237 + 12.2238 + 12.2239 + 12.2240 +Feather Standards Track [Page 40] 12.2241 + 12.2242 +RFC 3977 Network News Transfer Protocol (NNTP) October 2006 12.2243 + 12.2244 + 12.2245 + Example of LISTGROUP on an empty group: 12.2246 + 12.2247 + [C] LISTGROUP example.empty.newsgroup 12.2248 + [S] 211 0 0 0 example.empty.newsgroup list follows 12.2249 + [S] . 12.2250 + 12.2251 + Example of LISTGROUP on a valid, currently selected newsgroup: 12.2252 + 12.2253 + [C] GROUP misc.test 12.2254 + [S] 211 2000 3000234 3002322 misc.test 12.2255 + [C] LISTGROUP 12.2256 + [S] 211 2000 3000234 3002322 misc.test list follows 12.2257 + [S] 3000234 12.2258 + [S] 3000237 12.2259 + [S] 3000238 12.2260 + [S] 3000239 12.2261 + [S] 3002322 12.2262 + [S] . 12.2263 + 12.2264 + Example of LISTGROUP with a range: 12.2265 + 12.2266 + [C] LISTGROUP misc.test 3000238-3000248 12.2267 + [S] 211 2000 3000234 3002322 misc.test list follows 12.2268 + [S] 3000238 12.2269 + [S] 3000239 12.2270 + [S] . 12.2271 + 12.2272 + Example of LISTGROUP with an empty range: 12.2273 + 12.2274 + [C] LISTGROUP misc.test 12345678- 12.2275 + [S] 211 2000 3000234 3002322 misc.test list follows 12.2276 + [S] . 12.2277 + 12.2278 + Example of LISTGROUP with an invalid range: 12.2279 + 12.2280 + [C] LISTGROUP misc.test 9999-111 12.2281 + [S] 211 2000 3000234 3002322 misc.test list follows 12.2282 + [S] . 12.2283 + 12.2284 + 12.2285 + 12.2286 + 12.2287 + 12.2288 + 12.2289 + 12.2290 + 12.2291 + 12.2292 + 12.2293 + 12.2294 + 12.2295 + 12.2296 +Feather Standards Track [Page 41] 12.2297 + 12.2298 +RFC 3977 Network News Transfer Protocol (NNTP) October 2006 12.2299 + 12.2300 + 12.2301 +6.1.3. LAST 12.2302 + 12.2303 +6.1.3.1. Usage 12.2304 + 12.2305 + Indicating capability: READER 12.2306 + 12.2307 + Syntax 12.2308 + LAST 12.2309 + 12.2310 + Responses 12.2311 + 223 n message-id Article found 12.2312 + 412 No newsgroup selected 12.2313 + 420 Current article number is invalid 12.2314 + 422 No previous article in this group 12.2315 + 12.2316 + Parameters 12.2317 + n Article number 12.2318 + message-id Article message-id 12.2319 + 12.2320 +6.1.3.2. Description 12.2321 + 12.2322 + If the currently selected newsgroup is valid, the current article 12.2323 + number MUST be set to the previous article in that newsgroup (that 12.2324 + is, the highest existing article number less than the current article 12.2325 + number). If successful, a response indicating the new current 12.2326 + article number and the message-id of that article MUST be returned. 12.2327 + No article text is sent in response to this command. 12.2328 + 12.2329 + There MAY be no previous article in the group, although the current 12.2330 + article number is not the reported low water mark. There MUST NOT be 12.2331 + a previous article when the current article number is the reported 12.2332 + low water mark. 12.2333 + 12.2334 + Because articles can be removed and added, the results of multiple 12.2335 + LAST and NEXT commands MAY not be consistent over the life of a 12.2336 + particular NNTP session. 12.2337 + 12.2338 + If the current article number is already the first article of the 12.2339 + newsgroup, a 422 response MUST be returned. If the current article 12.2340 + number is invalid, a 420 response MUST be returned. If the currently 12.2341 + selected newsgroup is invalid, a 412 response MUST be returned. In 12.2342 + all three cases, the currently selected newsgroup and current article 12.2343 + number MUST NOT be altered. 12.2344 + 12.2345 + 12.2346 + 12.2347 + 12.2348 + 12.2349 + 12.2350 + 12.2351 + 12.2352 +Feather Standards Track [Page 42] 12.2353 + 12.2354 +RFC 3977 Network News Transfer Protocol (NNTP) October 2006 12.2355 + 12.2356 + 12.2357 +6.1.3.3. Examples 12.2358 + 12.2359 + Example of a successful article retrieval using LAST: 12.2360 + 12.2361 + [C] GROUP misc.test 12.2362 + [S] 211 1234 3000234 3002322 misc.test 12.2363 + [C] NEXT 12.2364 + [S] 223 3000237 <668929@example.org> retrieved 12.2365 + [C] LAST 12.2366 + [S] 223 3000234 <45223423@example.com> retrieved 12.2367 + 12.2368 + Example of an attempt to retrieve an article without having selected 12.2369 + a group (via the GROUP command) first: 12.2370 + 12.2371 + [Assumes currently selected newsgroup is invalid.] 12.2372 + [C] LAST 12.2373 + [S] 412 no newsgroup selected 12.2374 + 12.2375 + Example of an attempt to retrieve an article using the LAST command 12.2376 + when the current article number is that of the first article in the 12.2377 + group: 12.2378 + 12.2379 + [C] GROUP misc.test 12.2380 + [S] 211 1234 3000234 3002322 misc.test 12.2381 + [C] LAST 12.2382 + [S] 422 No previous article to retrieve 12.2383 + 12.2384 + Example of an attempt to retrieve an article using the LAST command 12.2385 + when the currently selected newsgroup is empty: 12.2386 + 12.2387 + [C] GROUP example.empty.newsgroup 12.2388 + [S] 211 0 0 0 example.empty.newsgroup 12.2389 + [C] LAST 12.2390 + [S] 420 No current article selected 12.2391 + 12.2392 + 12.2393 + 12.2394 + 12.2395 + 12.2396 + 12.2397 + 12.2398 + 12.2399 + 12.2400 + 12.2401 + 12.2402 + 12.2403 + 12.2404 + 12.2405 + 12.2406 + 12.2407 + 12.2408 +Feather Standards Track [Page 43] 12.2409 + 12.2410 +RFC 3977 Network News Transfer Protocol (NNTP) October 2006 12.2411 + 12.2412 + 12.2413 +6.1.4. NEXT 12.2414 + 12.2415 +6.1.4.1. Usage 12.2416 + 12.2417 + Indicating capability: READER 12.2418 + 12.2419 + Syntax 12.2420 + NEXT 12.2421 + 12.2422 + Responses 12.2423 + 223 n message-id Article found 12.2424 + 412 No newsgroup selected 12.2425 + 420 Current article number is invalid 12.2426 + 421 No next article in this group 12.2427 + 12.2428 + Parameters 12.2429 + n Article number 12.2430 + message-id Article message-id 12.2431 + 12.2432 +6.1.4.2. Description 12.2433 + 12.2434 + If the currently selected newsgroup is valid, the current article 12.2435 + number MUST be set to the next article in that newsgroup (that is, 12.2436 + the lowest existing article number greater than the current article 12.2437 + number). If successful, a response indicating the new current 12.2438 + article number and the message-id of that article MUST be returned. 12.2439 + No article text is sent in response to this command. 12.2440 + 12.2441 + If the current article number is already the last article of the 12.2442 + newsgroup, a 421 response MUST be returned. In all other aspects 12.2443 + (apart, of course, from the lack of 422 response), this command is 12.2444 + identical to the LAST command (Section 6.1.3). 12.2445 + 12.2446 +6.1.4.3. Examples 12.2447 + 12.2448 + Example of a successful article retrieval using NEXT: 12.2449 + 12.2450 + [C] GROUP misc.test 12.2451 + [S] 211 1234 3000234 3002322 misc.test 12.2452 + [C] NEXT 12.2453 + [S] 223 3000237 <668929@example.org> retrieved 12.2454 + 12.2455 + 12.2456 + 12.2457 + 12.2458 + 12.2459 + 12.2460 + 12.2461 + 12.2462 + 12.2463 + 12.2464 +Feather Standards Track [Page 44] 12.2465 + 12.2466 +RFC 3977 Network News Transfer Protocol (NNTP) October 2006 12.2467 + 12.2468 + 12.2469 + Example of an attempt to retrieve an article without having selected 12.2470 + a group (via the GROUP command) first: 12.2471 + 12.2472 + [Assumes currently selected newsgroup is invalid.] 12.2473 + [C] NEXT 12.2474 + [S] 412 no newsgroup selected 12.2475 + 12.2476 + Example of an attempt to retrieve an article using the NEXT command 12.2477 + when the current article number is that of the last article in the 12.2478 + group: 12.2479 + 12.2480 + [C] GROUP misc.test 12.2481 + [S] 211 1234 3000234 3002322 misc.test 12.2482 + [C] STAT 3002322 12.2483 + [S] 223 3002322 <411@example.net> retrieved 12.2484 + [C] NEXT 12.2485 + [S] 421 No next article to retrieve 12.2486 + 12.2487 + Example of an attempt to retrieve an article using the NEXT command 12.2488 + when the currently selected newsgroup is empty: 12.2489 + 12.2490 + [C] GROUP example.empty.newsgroup 12.2491 + [S] 211 0 0 0 example.empty.newsgroup 12.2492 + [C] NEXT 12.2493 + [S] 420 No current article selected 12.2494 + 12.2495 +6.2. Retrieval of Articles and Article Sections 12.2496 + 12.2497 + The ARTICLE, BODY, HEAD, and STAT commands are very similar. They 12.2498 + differ only in the parts of the article that are presented to the 12.2499 + client and in the successful response code. The ARTICLE command is 12.2500 + described here in full, while the other three commands are described 12.2501 + in terms of the differences. As specified in Section 3.6, an article 12.2502 + consists of two parts: the article headers and the article body. 12.2503 + 12.2504 + When responding to one of these commands, the server MUST present the 12.2505 + entire article or appropriate part and MUST NOT attempt to alter or 12.2506 + translate it in any way. 12.2507 + 12.2508 + 12.2509 + 12.2510 + 12.2511 + 12.2512 + 12.2513 + 12.2514 + 12.2515 + 12.2516 + 12.2517 + 12.2518 + 12.2519 + 12.2520 +Feather Standards Track [Page 45] 12.2521 + 12.2522 +RFC 3977 Network News Transfer Protocol (NNTP) October 2006 12.2523 + 12.2524 + 12.2525 +6.2.1. ARTICLE 12.2526 + 12.2527 +6.2.1.1. Usage 12.2528 + 12.2529 + Indicating capability: READER 12.2530 + 12.2531 + Syntax 12.2532 + ARTICLE message-id 12.2533 + ARTICLE number 12.2534 + ARTICLE 12.2535 + 12.2536 + Responses 12.2537 + 12.2538 + First form (message-id specified) 12.2539 + 220 0|n message-id Article follows (multi-line) 12.2540 + 430 No article with that message-id 12.2541 + 12.2542 + Second form (article number specified) 12.2543 + 220 n message-id Article follows (multi-line) 12.2544 + 412 No newsgroup selected 12.2545 + 423 No article with that number 12.2546 + 12.2547 + Third form (current article number used) 12.2548 + 220 n message-id Article follows (multi-line) 12.2549 + 412 No newsgroup selected 12.2550 + 420 Current article number is invalid 12.2551 + 12.2552 + Parameters 12.2553 + number Requested article number 12.2554 + n Returned article number 12.2555 + message-id Article message-id 12.2556 + 12.2557 +6.2.1.2. Description 12.2558 + 12.2559 + The ARTICLE command selects an article according to the arguments and 12.2560 + presents the entire article (that is, the headers, an empty line, and 12.2561 + the body, in that order) to the client. The command has three forms. 12.2562 + 12.2563 + In the first form, a message-id is specified, and the server presents 12.2564 + the article with that message-id. In this case, the server MUST NOT 12.2565 + alter the currently selected newsgroup or current article number. 12.2566 + This is both to facilitate the presentation of articles that may be 12.2567 + referenced within another article being read, and because of the 12.2568 + semantic difficulties of determining the proper sequence and 12.2569 + membership of an article that may have been cross-posted to more than 12.2570 + one newsgroup. 12.2571 + 12.2572 + 12.2573 + 12.2574 + 12.2575 + 12.2576 +Feather Standards Track [Page 46] 12.2577 + 12.2578 +RFC 3977 Network News Transfer Protocol (NNTP) October 2006 12.2579 + 12.2580 + 12.2581 + In the response, the article number MUST be replaced with zero, 12.2582 + unless there is a currently selected newsgroup and the article is 12.2583 + present in that group, in which case the server MAY use the article's 12.2584 + number in that group. (The server is not required to determine 12.2585 + whether the article is in the currently selected newsgroup or, if so, 12.2586 + what article number it has; the client MUST always be prepared for 12.2587 + zero to be specified.) The server MUST NOT provide an article number 12.2588 + unless use of that number in a second ARTICLE command immediately 12.2589 + following this one would return the same article. Even if the server 12.2590 + chooses to return article numbers in these circumstances, it need not 12.2591 + do so consistently; it MAY return zero to any such command (also see 12.2592 + the STAT examples, Section 6.2.4.3). 12.2593 + 12.2594 + In the second form, an article number is specified. If there is an 12.2595 + article with that number in the currently selected newsgroup, the 12.2596 + server MUST set the current article number to that number. 12.2597 + 12.2598 + In the third form, the article indicated by the current article 12.2599 + number in the currently selected newsgroup is used. 12.2600 + 12.2601 + Note that a previously valid article number MAY become invalid if the 12.2602 + article has been removed. A previously invalid article number MAY 12.2603 + become valid if the article has been reinstated, but this article 12.2604 + number MUST be no less than the reported low water mark for that 12.2605 + group. 12.2606 + 12.2607 + The server MUST NOT change the currently selected newsgroup as a 12.2608 + result of this command. The server MUST NOT change the current 12.2609 + article number except when an article number argument was provided 12.2610 + and the article exists; in particular, it MUST NOT change it 12.2611 + following an unsuccessful response. 12.2612 + 12.2613 + Since the message-id is unique for each article, it may be used by a 12.2614 + client to skip duplicate displays of articles that have been posted 12.2615 + more than once, or to more than one newsgroup. 12.2616 + 12.2617 + The article is returned as a multi-line data block following the 220 12.2618 + response code. 12.2619 + 12.2620 + If the argument is a message-id and no such article exists, a 430 12.2621 + response MUST be returned. If the argument is a number or is omitted 12.2622 + and the currently selected newsgroup is invalid, a 412 response MUST 12.2623 + be returned. If the argument is a number and that article does not 12.2624 + exist in the currently selected newsgroup, a 423 response MUST be 12.2625 + returned. If the argument is omitted and the current article number 12.2626 + is invalid, a 420 response MUST be returned. 12.2627 + 12.2628 + 12.2629 + 12.2630 + 12.2631 + 12.2632 +Feather Standards Track [Page 47] 12.2633 + 12.2634 +RFC 3977 Network News Transfer Protocol (NNTP) October 2006 12.2635 + 12.2636 + 12.2637 +6.2.1.3. Examples 12.2638 + 12.2639 + Example of a successful retrieval of an article (explicitly not using 12.2640 + an article number): 12.2641 + 12.2642 + [C] GROUP misc.test 12.2643 + [S] 211 1234 3000234 3002322 misc.test 12.2644 + [C] ARTICLE 12.2645 + [S] 220 3000234 <45223423@example.com> 12.2646 + [S] Path: pathost!demo!whitehouse!not-for-mail 12.2647 + [S] From: "Demo User" <nobody@example.net> 12.2648 + [S] Newsgroups: misc.test 12.2649 + [S] Subject: I am just a test article 12.2650 + [S] Date: 6 Oct 1998 04:38:40 -0500 12.2651 + [S] Organization: An Example Net, Uncertain, Texas 12.2652 + [S] Message-ID: <45223423@example.com> 12.2653 + [S] 12.2654 + [S] This is just a test article. 12.2655 + [S] . 12.2656 + 12.2657 + Example of a successful retrieval of an article by message-id: 12.2658 + 12.2659 + [C] ARTICLE <45223423@example.com> 12.2660 + [S] 220 0 <45223423@example.com> 12.2661 + [S] Path: pathost!demo!whitehouse!not-for-mail 12.2662 + [S] From: "Demo User" <nobody@example.net> 12.2663 + [S] Newsgroups: misc.test 12.2664 + [S] Subject: I am just a test article 12.2665 + [S] Date: 6 Oct 1998 04:38:40 -0500 12.2666 + [S] Organization: An Example Net, Uncertain, Texas 12.2667 + [S] Message-ID: <45223423@example.com> 12.2668 + [S] 12.2669 + [S] This is just a test article. 12.2670 + [S] . 12.2671 + 12.2672 + Example of an unsuccessful retrieval of an article by message-id: 12.2673 + 12.2674 + [C] ARTICLE <i.am.not.there@example.com> 12.2675 + [S] 430 No Such Article Found 12.2676 + 12.2677 + Example of an unsuccessful retrieval of an article by number: 12.2678 + 12.2679 + [C] GROUP misc.test 12.2680 + [S] 211 1234 3000234 3002322 news.groups 12.2681 + [C] ARTICLE 300256 12.2682 + [S] 423 No article with that number 12.2683 + 12.2684 + 12.2685 + 12.2686 + 12.2687 + 12.2688 +Feather Standards Track [Page 48] 12.2689 + 12.2690 +RFC 3977 Network News Transfer Protocol (NNTP) October 2006 12.2691 + 12.2692 + 12.2693 + Example of an unsuccessful retrieval of an article by number because 12.2694 + no newsgroup was selected first: 12.2695 + 12.2696 + [Assumes currently selected newsgroup is invalid.] 12.2697 + [C] ARTICLE 300256 12.2698 + [S] 412 No newsgroup selected 12.2699 + 12.2700 + Example of an attempt to retrieve an article when the currently 12.2701 + selected newsgroup is empty: 12.2702 + 12.2703 + [C] GROUP example.empty.newsgroup 12.2704 + [S] 211 0 0 0 example.empty.newsgroup 12.2705 + [C] ARTICLE 12.2706 + [S] 420 No current article selected 12.2707 + 12.2708 +6.2.2. HEAD 12.2709 + 12.2710 +6.2.2.1. Usage 12.2711 + 12.2712 + This command is mandatory. 12.2713 + 12.2714 + Syntax 12.2715 + HEAD message-id 12.2716 + HEAD number 12.2717 + HEAD 12.2718 + 12.2719 + Responses 12.2720 + 12.2721 + First form (message-id specified) 12.2722 + 221 0|n message-id Headers follow (multi-line) 12.2723 + 430 No article with that message-id 12.2724 + 12.2725 + Second form (article number specified) 12.2726 + 221 n message-id Headers follow (multi-line) 12.2727 + 412 No newsgroup selected 12.2728 + 423 No article with that number 12.2729 + 12.2730 + Third form (current article number used) 12.2731 + 221 n message-id Headers follow (multi-line) 12.2732 + 412 No newsgroup selected 12.2733 + 420 Current article number is invalid 12.2734 + 12.2735 + Parameters 12.2736 + number Requested article number 12.2737 + n Returned article number 12.2738 + message-id Article message-id 12.2739 + 12.2740 + 12.2741 + 12.2742 + 12.2743 + 12.2744 +Feather Standards Track [Page 49] 12.2745 + 12.2746 +RFC 3977 Network News Transfer Protocol (NNTP) October 2006 12.2747 + 12.2748 + 12.2749 +6.2.2.2. Description 12.2750 + 12.2751 + The HEAD command behaves identically to the ARTICLE command except 12.2752 + that, if the article exists, the response code is 221 instead of 220 12.2753 + and only the headers are presented (the empty line separating the 12.2754 + headers and body MUST NOT be included). 12.2755 + 12.2756 +6.2.2.3. Examples 12.2757 + 12.2758 + Example of a successful retrieval of the headers of an article 12.2759 + (explicitly not using an article number): 12.2760 + 12.2761 + [C] GROUP misc.test 12.2762 + [S] 211 1234 3000234 3002322 misc.test 12.2763 + [C] HEAD 12.2764 + [S] 221 3000234 <45223423@example.com> 12.2765 + [S] Path: pathost!demo!whitehouse!not-for-mail 12.2766 + [S] From: "Demo User" <nobody@example.net> 12.2767 + [S] Newsgroups: misc.test 12.2768 + [S] Subject: I am just a test article 12.2769 + [S] Date: 6 Oct 1998 04:38:40 -0500 12.2770 + [S] Organization: An Example Net, Uncertain, Texas 12.2771 + [S] Message-ID: <45223423@example.com> 12.2772 + [S] . 12.2773 + 12.2774 + Example of a successful retrieval of the headers of an article by 12.2775 + message-id: 12.2776 + 12.2777 + [C] HEAD <45223423@example.com> 12.2778 + [S] 221 0 <45223423@example.com> 12.2779 + [S] Path: pathost!demo!whitehouse!not-for-mail 12.2780 + [S] From: "Demo User" <nobody@example.net> 12.2781 + [S] Newsgroups: misc.test 12.2782 + [S] Subject: I am just a test article 12.2783 + [S] Date: 6 Oct 1998 04:38:40 -0500 12.2784 + [S] Organization: An Example Net, Uncertain, Texas 12.2785 + [S] Message-ID: <45223423@example.com> 12.2786 + [S] . 12.2787 + 12.2788 + Example of an unsuccessful retrieval of the headers of an article by 12.2789 + message-id: 12.2790 + 12.2791 + [C] HEAD <i.am.not.there@example.com> 12.2792 + [S] 430 No Such Article Found 12.2793 + 12.2794 + 12.2795 + 12.2796 + 12.2797 + 12.2798 + 12.2799 + 12.2800 +Feather Standards Track [Page 50] 12.2801 + 12.2802 +RFC 3977 Network News Transfer Protocol (NNTP) October 2006 12.2803 + 12.2804 + 12.2805 + Example of an unsuccessful retrieval of the headers of an article by 12.2806 + number: 12.2807 + 12.2808 + [C] GROUP misc.test 12.2809 + [S] 211 1234 3000234 3002322 misc.test 12.2810 + [C] HEAD 300256 12.2811 + [S] 423 No article with that number 12.2812 + 12.2813 + Example of an unsuccessful retrieval of the headers of an article by 12.2814 + number because no newsgroup was selected first: 12.2815 + 12.2816 + [Assumes currently selected newsgroup is invalid.] 12.2817 + [C] HEAD 300256 12.2818 + [S] 412 No newsgroup selected 12.2819 + 12.2820 + Example of an attempt to retrieve the headers of an article when the 12.2821 + currently selected newsgroup is empty: 12.2822 + 12.2823 + [C] GROUP example.empty.newsgroup 12.2824 + [S] 211 0 0 0 example.empty.newsgroup 12.2825 + [C] HEAD 12.2826 + [S] 420 No current article selected 12.2827 + 12.2828 +6.2.3. BODY 12.2829 + 12.2830 +6.2.3.1. Usage 12.2831 + 12.2832 + Indicating capability: READER 12.2833 + 12.2834 + Syntax 12.2835 + BODY message-id 12.2836 + BODY number 12.2837 + BODY 12.2838 + 12.2839 + Responses 12.2840 + 12.2841 + First form (message-id specified) 12.2842 + 222 0|n message-id Body follows (multi-line) 12.2843 + 430 No article with that message-id 12.2844 + 12.2845 + Second form (article number specified) 12.2846 + 222 n message-id Body follows (multi-line) 12.2847 + 412 No newsgroup selected 12.2848 + 423 No article with that number 12.2849 + 12.2850 + 12.2851 + 12.2852 + 12.2853 + 12.2854 + 12.2855 + 12.2856 +Feather Standards Track [Page 51] 12.2857 + 12.2858 +RFC 3977 Network News Transfer Protocol (NNTP) October 2006 12.2859 + 12.2860 + 12.2861 + Third form (current article number used) 12.2862 + 222 n message-id Body follows (multi-line) 12.2863 + 412 No newsgroup selected 12.2864 + 420 Current article number is invalid 12.2865 + 12.2866 + Parameters 12.2867 + number Requested article number 12.2868 + n Returned article number 12.2869 + message-id Article message-id 12.2870 + 12.2871 +6.2.3.2. Description 12.2872 + 12.2873 + The BODY command behaves identically to the ARTICLE command except 12.2874 + that, if the article exists, the response code is 222 instead of 220 12.2875 + and only the body is presented (the empty line separating the headers 12.2876 + and body MUST NOT be included). 12.2877 + 12.2878 +6.2.3.3. Examples 12.2879 + 12.2880 + Example of a successful retrieval of the body of an article 12.2881 + (explicitly not using an article number): 12.2882 + 12.2883 + [C] GROUP misc.test 12.2884 + [S] 211 1234 3000234 3002322 misc.test 12.2885 + [C] BODY 12.2886 + [S] 222 3000234 <45223423@example.com> 12.2887 + [S] This is just a test article. 12.2888 + [S] . 12.2889 + 12.2890 + Example of a successful retrieval of the body of an article by 12.2891 + message-id: 12.2892 + 12.2893 + [C] BODY <45223423@example.com> 12.2894 + [S] 222 0 <45223423@example.com> 12.2895 + [S] This is just a test article. 12.2896 + [S] . 12.2897 + 12.2898 + Example of an unsuccessful retrieval of the body of an article by 12.2899 + message-id: 12.2900 + 12.2901 + [C] BODY <i.am.not.there@example.com> 12.2902 + [S] 430 No Such Article Found 12.2903 + 12.2904 + 12.2905 + 12.2906 + 12.2907 + 12.2908 + 12.2909 + 12.2910 + 12.2911 + 12.2912 +Feather Standards Track [Page 52] 12.2913 + 12.2914 +RFC 3977 Network News Transfer Protocol (NNTP) October 2006 12.2915 + 12.2916 + 12.2917 + Example of an unsuccessful retrieval of the body of an article by 12.2918 + number: 12.2919 + 12.2920 + [C] GROUP misc.test 12.2921 + [S] 211 1234 3000234 3002322 misc.test 12.2922 + [C] BODY 300256 12.2923 + [S] 423 No article with that number 12.2924 + 12.2925 + Example of an unsuccessful retrieval of the body of an article by 12.2926 + number because no newsgroup was selected first: 12.2927 + 12.2928 + [Assumes currently selected newsgroup is invalid.] 12.2929 + [C] BODY 300256 12.2930 + [S] 412 No newsgroup selected 12.2931 + 12.2932 + Example of an attempt to retrieve the body of an article when the 12.2933 + currently selected newsgroup is empty: 12.2934 + 12.2935 + [C] GROUP example.empty.newsgroup 12.2936 + [S] 211 0 0 0 example.empty.newsgroup 12.2937 + [C] BODY 12.2938 + [S] 420 No current article selected 12.2939 + 12.2940 +6.2.4. STAT 12.2941 + 12.2942 +6.2.4.1. Usage 12.2943 + 12.2944 + This command is mandatory. 12.2945 + 12.2946 + Syntax 12.2947 + STAT message-id 12.2948 + STAT number 12.2949 + STAT 12.2950 + 12.2951 + Responses 12.2952 + 12.2953 + First form (message-id specified) 12.2954 + 223 0|n message-id Article exists 12.2955 + 430 No article with that message-id 12.2956 + 12.2957 + Second form (article number specified) 12.2958 + 223 n message-id Article exists 12.2959 + 412 No newsgroup selected 12.2960 + 423 No article with that number 12.2961 + 12.2962 + 12.2963 + 12.2964 + 12.2965 + 12.2966 + 12.2967 + 12.2968 +Feather Standards Track [Page 53] 12.2969 + 12.2970 +RFC 3977 Network News Transfer Protocol (NNTP) October 2006 12.2971 + 12.2972 + 12.2973 + Third form (current article number used) 12.2974 + 223 n message-id Article exists 12.2975 + 412 No newsgroup selected 12.2976 + 420 Current article number is invalid 12.2977 + 12.2978 + Parameters 12.2979 + number Requested article number 12.2980 + n Returned article number 12.2981 + message-id Article message-id 12.2982 + 12.2983 +6.2.4.2. Description 12.2984 + 12.2985 + The STAT command behaves identically to the ARTICLE command except 12.2986 + that, if the article exists, it is NOT presented to the client and 12.2987 + the response code is 223 instead of 220. Note that the response is 12.2988 + NOT multi-line. 12.2989 + 12.2990 + This command allows the client to determine whether an article exists 12.2991 + and, in the second and third forms, what its message-id is, without 12.2992 + having to process an arbitrary amount of text. 12.2993 + 12.2994 +6.2.4.3. Examples 12.2995 + 12.2996 + Example of STAT on an existing article (explicitly not using an 12.2997 + article number): 12.2998 + 12.2999 + [C] GROUP misc.test 12.3000 + [S] 211 1234 3000234 3002322 misc.test 12.3001 + [C] STAT 12.3002 + [S] 223 3000234 <45223423@example.com> 12.3003 + 12.3004 + Example of STAT on an existing article by message-id: 12.3005 + 12.3006 + [C] STAT <45223423@example.com> 12.3007 + [S] 223 0 <45223423@example.com> 12.3008 + 12.3009 + Example of STAT on an article not on the server by message-id: 12.3010 + 12.3011 + [C] STAT <i.am.not.there@example.com> 12.3012 + [S] 430 No Such Article Found 12.3013 + 12.3014 + Example of STAT on an article not in the server by number: 12.3015 + 12.3016 + [C] GROUP misc.test 12.3017 + [S] 211 1234 3000234 3002322 misc.test 12.3018 + [C] STAT 300256 12.3019 + [S] 423 No article with that number 12.3020 + 12.3021 + 12.3022 + 12.3023 + 12.3024 +Feather Standards Track [Page 54] 12.3025 + 12.3026 +RFC 3977 Network News Transfer Protocol (NNTP) October 2006 12.3027 + 12.3028 + 12.3029 + Example of STAT on an article by number when no newsgroup was 12.3030 + selected first: 12.3031 + 12.3032 + [Assumes currently selected newsgroup is invalid.] 12.3033 + [C] STAT 300256 12.3034 + [S] 412 No newsgroup selected 12.3035 + 12.3036 + Example of STAT on an article when the currently selected newsgroup 12.3037 + is empty: 12.3038 + 12.3039 + [C] GROUP example.empty.newsgroup 12.3040 + [S] 211 0 0 0 example.empty.newsgroup 12.3041 + [C] STAT 12.3042 + [S] 420 No current article selected 12.3043 + 12.3044 + Example of STAT by message-id on a server that sometimes reports the 12.3045 + actual article number: 12.3046 + 12.3047 + [C] GROUP misc.test 12.3048 + [S] 211 1234 3000234 3002322 misc.test 12.3049 + [C] STAT 12.3050 + [S] 223 3000234 <45223423@example.com> 12.3051 + [C] STAT <45223423@example.com> 12.3052 + [S] 223 0 <45223423@example.com> 12.3053 + [C] STAT <45223423@example.com> 12.3054 + [S] 223 3000234 <45223423@example.com> 12.3055 + [C] GROUP example.empty.newsgroup 12.3056 + [S] 211 0 0 0 example.empty.newsgroup 12.3057 + [C] STAT <45223423@example.com> 12.3058 + [S] 223 0 <45223423@example.com> 12.3059 + [C] GROUP alt.crossposts 12.3060 + [S] 211 9999 111111 222222 alt.crossposts 12.3061 + [C] STAT <45223423@example.com> 12.3062 + [S] 223 123456 <45223423@example.com> 12.3063 + [C] STAT 12.3064 + [S] 223 111111 <23894720@example.com> 12.3065 + 12.3066 + The first STAT command establishes the identity of an article in the 12.3067 + group. The second and third show that the server may, but need not, 12.3068 + give the article number when the message-id is specified. The fourth 12.3069 + STAT command shows that zero must be specified if the article isn't 12.3070 + in the currently selected newsgroup. The fifth shows that the 12.3071 + number, if provided, must be that relating to the currently selected 12.3072 + newsgroup. The last one shows that the current article number is 12.3073 + still not changed by the use of STAT with a message-id even if it 12.3074 + returns an article number. 12.3075 + 12.3076 + 12.3077 + 12.3078 + 12.3079 + 12.3080 +Feather Standards Track [Page 55] 12.3081 + 12.3082 +RFC 3977 Network News Transfer Protocol (NNTP) October 2006 12.3083 + 12.3084 + 12.3085 +6.3. Article Posting 12.3086 + 12.3087 + Article posting is done in one of two ways: individual article 12.3088 + posting from news-reading clients using POST, and article transfer 12.3089 + from other news servers using IHAVE. 12.3090 + 12.3091 +6.3.1. POST 12.3092 + 12.3093 +6.3.1.1. Usage 12.3094 + 12.3095 + Indicating capability: POST 12.3096 + 12.3097 + This command MUST NOT be pipelined. 12.3098 + 12.3099 + Syntax 12.3100 + POST 12.3101 + 12.3102 + Responses 12.3103 + 12.3104 + Initial responses 12.3105 + 340 Send article to be posted 12.3106 + 440 Posting not permitted 12.3107 + 12.3108 + Subsequent responses 12.3109 + 240 Article received OK 12.3110 + 441 Posting failed 12.3111 + 12.3112 +6.3.1.2. Description 12.3113 + 12.3114 + If posting is allowed, a 340 response MUST be returned to indicate 12.3115 + that the article to be posted should be sent. If posting is 12.3116 + prohibited for some installation-dependent reason, a 440 response 12.3117 + MUST be returned. 12.3118 + 12.3119 + If posting is permitted, the article MUST be in the format specified 12.3120 + in Section 3.6 and MUST be sent by the client to the server as a 12.3121 + multi-line data block (see Section 3.1.1). Thus a single dot (".") 12.3122 + on a line indicates the end of the text, and lines starting with a 12.3123 + dot in the original text have that dot doubled during transmission. 12.3124 + 12.3125 + Following the presentation of the termination sequence by the client, 12.3126 + the server MUST return a response indicating success or failure of 12.3127 + the article transfer. Note that response codes 340 and 440 are used 12.3128 + in direct response to the POST command while 240 and 441 are returned 12.3129 + after the article is sent. 12.3130 + 12.3131 + 12.3132 + 12.3133 + 12.3134 + 12.3135 + 12.3136 +Feather Standards Track [Page 56] 12.3137 + 12.3138 +RFC 3977 Network News Transfer Protocol (NNTP) October 2006 12.3139 + 12.3140 + 12.3141 + A response of 240 SHOULD indicate that, barring unforeseen server 12.3142 + errors, the posted article will be made available on the server 12.3143 + and/or transferred to other servers, as appropriate, possibly 12.3144 + following further processing. In other words, articles not wanted by 12.3145 + the server SHOULD be rejected with a 441 response, rather than being 12.3146 + accepted and then discarded silently. However, the client SHOULD NOT 12.3147 + assume that the article has been successfully transferred unless it 12.3148 + receives an affirmative response from the server and SHOULD NOT 12.3149 + assume that it is being made available to other clients without 12.3150 + explicitly checking (for example, using the STAT command). 12.3151 + 12.3152 + If the session is interrupted before the response is received, it is 12.3153 + possible that an affirmative response was sent but has been lost. 12.3154 + Therefore, in any subsequent session, the client SHOULD either check 12.3155 + whether the article was successfully posted before resending or 12.3156 + ensure that the server will allocate the same message-id to the new 12.3157 + attempt (see Appendix A.2). The latter approach is preferred since 12.3158 + the article might not have been made available for reading yet (for 12.3159 + example, it may have to go through a moderation process). 12.3160 + 12.3161 +6.3.1.3. Examples 12.3162 + 12.3163 + Example of a successful posting: 12.3164 + 12.3165 + [C] POST 12.3166 + [S] 340 Input article; end with <CR-LF>.<CR-LF> 12.3167 + [C] From: "Demo User" <nobody@example.net> 12.3168 + [C] Newsgroups: misc.test 12.3169 + [C] Subject: I am just a test article 12.3170 + [C] Organization: An Example Net 12.3171 + [C] 12.3172 + [C] This is just a test article. 12.3173 + [C] . 12.3174 + [S] 240 Article received OK 12.3175 + 12.3176 + Example of an unsuccessful posting: 12.3177 + 12.3178 + [C] POST 12.3179 + [S] 340 Input article; end with <CR-LF>.<CR-LF> 12.3180 + [C] From: "Demo User" <nobody@example.net> 12.3181 + [C] Newsgroups: misc.test 12.3182 + [C] Subject: I am just a test article 12.3183 + [C] Organization: An Example Net 12.3184 + [C] 12.3185 + [C] This is just a test article. 12.3186 + [C] . 12.3187 + [S] 441 Posting failed 12.3188 + 12.3189 + 12.3190 + 12.3191 + 12.3192 +Feather Standards Track [Page 57] 12.3193 + 12.3194 +RFC 3977 Network News Transfer Protocol (NNTP) October 2006 12.3195 + 12.3196 + 12.3197 + Example of an attempt to post when posting is not allowed: 12.3198 + 12.3199 + [Initial connection set-up completed.] 12.3200 + [S] 201 NNTP Service Ready, posting prohibited 12.3201 + [C] POST 12.3202 + [S] 440 Posting not permitted 12.3203 + 12.3204 +6.3.2. IHAVE 12.3205 + 12.3206 +6.3.2.1. Usage 12.3207 + 12.3208 + Indicating capability: IHAVE 12.3209 + 12.3210 + This command MUST NOT be pipelined. 12.3211 + 12.3212 + Syntax 12.3213 + IHAVE message-id 12.3214 + 12.3215 + Responses 12.3216 + 12.3217 + Initial responses 12.3218 + 335 Send article to be transferred 12.3219 + 435 Article not wanted 12.3220 + 436 Transfer not possible; try again later 12.3221 + 12.3222 + Subsequent responses 12.3223 + 235 Article transferred OK 12.3224 + 436 Transfer failed; try again later 12.3225 + 437 Transfer rejected; do not retry 12.3226 + 12.3227 + Parameters 12.3228 + message-id Article message-id 12.3229 + 12.3230 +6.3.2.2. Description 12.3231 + 12.3232 + The IHAVE command informs the server that the client has an article 12.3233 + with the specified message-id. If the server desires a copy of that 12.3234 + article, a 335 response MUST be returned, instructing the client to 12.3235 + send the entire article. If the server does not want the article 12.3236 + (if, for example, the server already has a copy of it), a 435 12.3237 + response MUST be returned, indicating that the article is not wanted. 12.3238 + Finally, if the article isn't wanted immediately but the client 12.3239 + should retry later if possible (if, for example, another client is in 12.3240 + the process of sending the same article to the server), a 436 12.3241 + response MUST be returned. 12.3242 + 12.3243 + 12.3244 + 12.3245 + 12.3246 + 12.3247 + 12.3248 +Feather Standards Track [Page 58] 12.3249 + 12.3250 +RFC 3977 Network News Transfer Protocol (NNTP) October 2006 12.3251 + 12.3252 + 12.3253 + If transmission of the article is requested, the client MUST send the 12.3254 + entire article, including headers and body, to the server as a 12.3255 + multi-line data block (see Section 3.1.1). Thus, a single dot (".") 12.3256 + on a line indicates the end of the text, and lines starting with a 12.3257 + dot in the original text have that dot doubled during transmission. 12.3258 + The server MUST return a 235 response, indicating that the article 12.3259 + was successfully transferred; a 436 response, indicating that the 12.3260 + transfer failed but should be tried again later; or a 437 response, 12.3261 + indicating that the article was rejected. 12.3262 + 12.3263 + This function differs from the POST command in that it is intended 12.3264 + for use in transferring already-posted articles between hosts. It 12.3265 + SHOULD NOT be used when the client is a personal news-reading 12.3266 + program, since use of this command indicates that the article has 12.3267 + already been posted at another site and is simply being forwarded 12.3268 + from another host. However, despite this, the server MAY elect not 12.3269 + to post or forward the article if, after further examination of the 12.3270 + article, it deems it inappropriate to do so. Reasons for such 12.3271 + subsequent rejection of an article may include problems such as 12.3272 + inappropriate newsgroups or distributions, disc space limitations, 12.3273 + article lengths, garbled headers, and the like. These are typically 12.3274 + restrictions enforced by the server host's news software and not 12.3275 + necessarily by the NNTP server itself. 12.3276 + 12.3277 + The client SHOULD NOT assume that the article has been successfully 12.3278 + transferred unless it receives an affirmative response from the 12.3279 + server. A lack of response (such as a dropped network connection or 12.3280 + a network timeout) SHOULD be treated the same as a 436 response. 12.3281 + 12.3282 + Because some news server software may not immediately be able to 12.3283 + determine whether an article is suitable for posting or forwarding, 12.3284 + an NNTP server MAY acknowledge the successful transfer of the article 12.3285 + (with a 235 response) but later silently discard it. 12.3286 + 12.3287 + 12.3288 + 12.3289 + 12.3290 + 12.3291 + 12.3292 + 12.3293 + 12.3294 + 12.3295 + 12.3296 + 12.3297 + 12.3298 + 12.3299 + 12.3300 + 12.3301 + 12.3302 + 12.3303 + 12.3304 +Feather Standards Track [Page 59] 12.3305 + 12.3306 +RFC 3977 Network News Transfer Protocol (NNTP) October 2006 12.3307 + 12.3308 + 12.3309 +6.3.2.3. Examples 12.3310 + 12.3311 + Example of successfully sending an article to another site: 12.3312 + 12.3313 + [C] IHAVE <i.am.an.article.you.will.want@example.com> 12.3314 + [S] 335 Send it; end with <CR-LF>.<CR-LF> 12.3315 + [C] Path: pathost!demo!somewhere!not-for-mail 12.3316 + [C] From: "Demo User" <nobody@example.com> 12.3317 + [C] Newsgroups: misc.test 12.3318 + [C] Subject: I am just a test article 12.3319 + [C] Date: 6 Oct 1998 04:38:40 -0500 12.3320 + [C] Organization: An Example Com, San Jose, CA 12.3321 + [C] Message-ID: <i.am.an.article.you.will.want@example.com> 12.3322 + [C] 12.3323 + [C] This is just a test article. 12.3324 + [C] . 12.3325 + [S] 235 Article transferred OK 12.3326 + 12.3327 + Example of sending an article to another site that rejects it. Note 12.3328 + that the message-id in the IHAVE command is not the same as the one 12.3329 + in the article headers; while this is bad practice and SHOULD NOT be 12.3330 + done, it is not forbidden. 12.3331 + 12.3332 + [C] IHAVE <i.am.an.article.you.will.want@example.com> 12.3333 + [S] 335 Send it; end with <CR-LF>.<CR-LF> 12.3334 + [C] Path: pathost!demo!somewhere!not-for-mail 12.3335 + [C] From: "Demo User" <nobody@example.com> 12.3336 + [C] Newsgroups: misc.test 12.3337 + [C] Subject: I am just a test article 12.3338 + [C] Date: 6 Oct 1998 04:38:40 -0500 12.3339 + [C] Organization: An Example Com, San Jose, CA 12.3340 + [C] Message-ID: <i.am.an.article.you.have@example.com> 12.3341 + [C] 12.3342 + [C] This is just a test article. 12.3343 + [C] . 12.3344 + [S] 437 Article rejected; don't send again 12.3345 + 12.3346 + 12.3347 + 12.3348 + 12.3349 + 12.3350 + 12.3351 + 12.3352 + 12.3353 + 12.3354 + 12.3355 + 12.3356 + 12.3357 + 12.3358 + 12.3359 + 12.3360 +Feather Standards Track [Page 60] 12.3361 + 12.3362 +RFC 3977 Network News Transfer Protocol (NNTP) October 2006 12.3363 + 12.3364 + 12.3365 + Example of sending an article to another site where the transfer 12.3366 + fails: 12.3367 + 12.3368 + [C] IHAVE <i.am.an.article.you.will.want@example.com> 12.3369 + [S] 335 Send it; end with <CR-LF>.<CR-LF> 12.3370 + [C] Path: pathost!demo!somewhere!not-for-mail 12.3371 + [C] From: "Demo User" <nobody@example.com> 12.3372 + [C] Newsgroups: misc.test 12.3373 + [C] Subject: I am just a test article 12.3374 + [C] Date: 6 Oct 1998 04:38:40 -0500 12.3375 + [C] Organization: An Example Com, San Jose, CA 12.3376 + [C] Message-ID: <i.am.an.article.you.will.want@example.com> 12.3377 + [C] 12.3378 + [C] This is just a test article. 12.3379 + [C] . 12.3380 + [S] 436 Transfer failed 12.3381 + 12.3382 + Example of sending an article to a site that already has it: 12.3383 + 12.3384 + [C] IHAVE <i.am.an.article.you.have@example.com> 12.3385 + [S] 435 Duplicate 12.3386 + 12.3387 + Example of sending an article to a site that requests that the 12.3388 + article be tried again later: 12.3389 + 12.3390 + [C] IHAVE <i.am.an.article.you.defer@example.com> 12.3391 + [S] 436 Retry later 12.3392 + 12.3393 +7. Information Commands 12.3394 + 12.3395 + This section lists other commands that may be used at any time 12.3396 + between the beginning of a session and its termination. Using these 12.3397 + commands does not alter any state information, but the response 12.3398 + generated from their use may provide useful information to clients. 12.3399 + 12.3400 +7.1. DATE 12.3401 + 12.3402 +7.1.1. Usage 12.3403 + 12.3404 + Indicating capability: READER 12.3405 + 12.3406 + Syntax 12.3407 + DATE 12.3408 + 12.3409 + Responses 12.3410 + 111 yyyymmddhhmmss Server date and time 12.3411 + 12.3412 + 12.3413 + 12.3414 + 12.3415 + 12.3416 +Feather Standards Track [Page 61] 12.3417 + 12.3418 +RFC 3977 Network News Transfer Protocol (NNTP) October 2006 12.3419 + 12.3420 + 12.3421 + Parameters 12.3422 + yyyymmddhhmmss Current UTC date and time on server 12.3423 + 12.3424 +7.1.2. Description 12.3425 + 12.3426 + This command exists to help clients find out the current Coordinated 12.3427 + Universal Time [TF.686-1] from the server's perspective. This 12.3428 + command SHOULD NOT be used as a substitute for NTP [RFC1305] but to 12.3429 + provide information that might be useful when using the NEWNEWS 12.3430 + command (see Section 7.4). 12.3431 + 12.3432 + The DATE command MUST return a timestamp from the same clock as is 12.3433 + used for determining article arrival and group creation times (see 12.3434 + Section 6). This clock SHOULD be monotonic, and adjustments SHOULD 12.3435 + be made by running it fast or slow compared to "real" time rather 12.3436 + than by making sudden jumps. A system providing NNTP service SHOULD 12.3437 + keep the system clock as accurate as possible, either with NTP or by 12.3438 + some other method. 12.3439 + 12.3440 + The server MUST return a 111 response specifying the date and time on 12.3441 + the server in the form yyyymmddhhmmss. This date and time is in 12.3442 + Coordinated Universal Time. 12.3443 + 12.3444 +7.1.3. Examples 12.3445 + 12.3446 + [C] DATE 12.3447 + [S] 111 19990623135624 12.3448 + 12.3449 +7.2. HELP 12.3450 + 12.3451 +7.2.1. Usage 12.3452 + 12.3453 + This command is mandatory. 12.3454 + 12.3455 + Syntax 12.3456 + HELP 12.3457 + 12.3458 + Responses 12.3459 + 100 Help text follows (multi-line) 12.3460 + 12.3461 +7.2.2. Description 12.3462 + 12.3463 + This command provides a short summary of the commands that are 12.3464 + understood by this implementation of the server. The help text will 12.3465 + be presented as a multi-line data block following the 100 response 12.3466 + code. 12.3467 + 12.3468 + 12.3469 + 12.3470 + 12.3471 + 12.3472 +Feather Standards Track [Page 62] 12.3473 + 12.3474 +RFC 3977 Network News Transfer Protocol (NNTP) October 2006 12.3475 + 12.3476 + 12.3477 + This text is not guaranteed to be in any particular format (but must 12.3478 + be UTF-8) and MUST NOT be used by clients as a replacement for the 12.3479 + CAPABILITIES command described in Section 5.2. 12.3480 + 12.3481 +7.2.3. Examples 12.3482 + 12.3483 + [C] HELP 12.3484 + [S] 100 Help text follows 12.3485 + [S] This is some help text. There is no specific 12.3486 + [S] formatting requirement for this test, though 12.3487 + [S] it is customary for it to list the valid commands 12.3488 + [S] and give a brief definition of what they do. 12.3489 + [S] . 12.3490 + 12.3491 +7.3. NEWGROUPS 12.3492 + 12.3493 +7.3.1. Usage 12.3494 + 12.3495 + Indicating capability: READER 12.3496 + 12.3497 + Syntax 12.3498 + NEWGROUPS date time [GMT] 12.3499 + 12.3500 + Responses 12.3501 + 231 List of new newsgroups follows (multi-line) 12.3502 + 12.3503 + Parameters 12.3504 + date Date in yymmdd or yyyymmdd format 12.3505 + time Time in hhmmss format 12.3506 + 12.3507 +7.3.2. Description 12.3508 + 12.3509 + This command returns a list of newsgroups created on the server since 12.3510 + the specified date and time. The results are in the same format as 12.3511 + the LIST ACTIVE command (see Section 7.6.3). However, they MAY 12.3512 + include groups not available on the server (and so not returned by 12.3513 + LIST ACTIVE) and MAY omit groups for which the creation date is not 12.3514 + available. 12.3515 + 12.3516 + The date is specified as 6 or 8 digits in the format [xx]yymmdd, 12.3517 + where xx is the first two digits of the year (19-99), yy is the last 12.3518 + two digits of the year (00-99), mm is the month (01-12), and dd is 12.3519 + the day of the month (01-31). Clients SHOULD specify all four digits 12.3520 + of the year. If the first two digits of the year are not specified 12.3521 + (this is supported only for backward compatibility), the year is to 12.3522 + be taken from the current century if yy is smaller than or equal to 12.3523 + the current year, and the previous century otherwise. 12.3524 + 12.3525 + 12.3526 + 12.3527 + 12.3528 +Feather Standards Track [Page 63] 12.3529 + 12.3530 +RFC 3977 Network News Transfer Protocol (NNTP) October 2006 12.3531 + 12.3532 + 12.3533 + The time is specified as 6 digits in the format hhmmss, where hh is 12.3534 + the hours in the 24-hour clock (00-23), mm is the minutes (00-59), 12.3535 + and ss is the seconds (00-60, to allow for leap seconds). The token 12.3536 + "GMT" specifies that the date and time are given in Coordinated 12.3537 + Universal Time [TF.686-1]; if it is omitted, then the date and time 12.3538 + are specified in the server's local timezone. Note that there is no 12.3539 + way of using the protocol specified in this document to establish the 12.3540 + server's local timezone. 12.3541 + 12.3542 + Note that an empty list is a possible valid response and indicates 12.3543 + that there are no new newsgroups since that date-time. 12.3544 + 12.3545 + Clients SHOULD make all queries using Coordinated Universal Time 12.3546 + (i.e., by including the "GMT" argument) when possible. 12.3547 + 12.3548 +7.3.3. Examples 12.3549 + 12.3550 + Example where there are new groups: 12.3551 + 12.3552 + [C] NEWGROUPS 19990624 000000 GMT 12.3553 + [S] 231 list of new newsgroups follows 12.3554 + [S] alt.rfc-writers.recovery 4 1 y 12.3555 + [S] tx.natives.recovery 89 56 y 12.3556 + [S] . 12.3557 + 12.3558 + Example where there are no new groups: 12.3559 + 12.3560 + [C] NEWGROUPS 19990624 000000 GMT 12.3561 + [S] 231 list of new newsgroups follows 12.3562 + [S] . 12.3563 + 12.3564 +7.4. NEWNEWS 12.3565 + 12.3566 +7.4.1. Usage 12.3567 + 12.3568 + Indicating capability: NEWNEWS 12.3569 + 12.3570 + Syntax 12.3571 + NEWNEWS wildmat date time [GMT] 12.3572 + 12.3573 + Responses 12.3574 + 230 List of new articles follows (multi-line) 12.3575 + 12.3576 + Parameters 12.3577 + wildmat Newsgroups of interest 12.3578 + date Date in yymmdd or yyyymmdd format 12.3579 + time Time in hhmmss format 12.3580 + 12.3581 + 12.3582 + 12.3583 + 12.3584 +Feather Standards Track [Page 64] 12.3585 + 12.3586 +RFC 3977 Network News Transfer Protocol (NNTP) October 2006 12.3587 + 12.3588 + 12.3589 +7.4.2. Description 12.3590 + 12.3591 + This command returns a list of message-ids of articles posted or 12.3592 + received on the server, in the newsgroups whose names match the 12.3593 + wildmat, since the specified date and time. One message-id is sent 12.3594 + on each line; the order of the response has no specific significance 12.3595 + and may vary from response to response in the same session. A 12.3596 + message-id MAY appear more than once; if it does, it has the same 12.3597 + meaning as if it appeared only once. 12.3598 + 12.3599 + Date and time are in the same format as the NEWGROUPS command (see 12.3600 + Section 7.3). 12.3601 + 12.3602 + Note that an empty list is a possible valid response and indicates 12.3603 + that there is currently no new news in the relevant groups. 12.3604 + 12.3605 + Clients SHOULD make all queries in Coordinated Universal Time (i.e., 12.3606 + by using the "GMT" argument) when possible. 12.3607 + 12.3608 +7.4.3. Examples 12.3609 + 12.3610 + Example where there are new articles: 12.3611 + 12.3612 + [C] NEWNEWS news.*,sci.* 19990624 000000 GMT 12.3613 + [S] 230 list of new articles by message-id follows 12.3614 + [S] <i.am.a.new.article@example.com> 12.3615 + [S] <i.am.another.new.article@example.com> 12.3616 + [S] . 12.3617 + 12.3618 + Example where there are no new articles: 12.3619 + 12.3620 + [C] NEWNEWS alt.* 19990624 000000 GMT 12.3621 + [S] 230 list of new articles by message-id follows 12.3622 + [S] . 12.3623 + 12.3624 +7.5. Time 12.3625 + 12.3626 + As described in Section 6, each article has an arrival timestamp. 12.3627 + Each newsgroup also has a creation timestamp. These timestamps are 12.3628 + used by the NEWNEWS and NEWGROUP commands to construct their 12.3629 + responses. 12.3630 + 12.3631 + Clients can ensure that they do not have gaps in lists of articles or 12.3632 + groups by using the DATE command in the following manner: 12.3633 + 12.3634 + First session: 12.3635 + Issue DATE command and record result. 12.3636 + Issue NEWNEWS command using a previously chosen timestamp. 12.3637 + 12.3638 + 12.3639 + 12.3640 +Feather Standards Track [Page 65] 12.3641 + 12.3642 +RFC 3977 Network News Transfer Protocol (NNTP) October 2006 12.3643 + 12.3644 + 12.3645 + Subsequent sessions: 12.3646 + Issue DATE command and hold result in temporary storage. 12.3647 + Issue NEWNEWS command using timestamp saved from previous session. 12.3648 + Overwrite saved timestamp with that currently in temporary 12.3649 + storage. 12.3650 + 12.3651 + In order to allow for minor errors, clients MAY want to adjust the 12.3652 + timestamp back by two or three minutes before using it in NEWNEWS. 12.3653 + 12.3654 +7.5.1. Examples 12.3655 + 12.3656 + First session: 12.3657 + 12.3658 + [C] DATE 12.3659 + [S] 111 20010203112233 12.3660 + [C] NEWNEWS local.chat 20001231 235959 GMT 12.3661 + [S] 230 list follows 12.3662 + [S] <article.1@local.service> 12.3663 + [S] <article.2@local.service> 12.3664 + [S] <article.3@local.service> 12.3665 + [S] . 12.3666 + 12.3667 + Second session (the client has subtracted 3 minutes from the 12.3668 + timestamp returned previously): 12.3669 + 12.3670 + [C] DATE 12.3671 + [S] 111 20010204003344 12.3672 + [C] NEWNEWS local.chat 20010203 111933 GMT 12.3673 + [S] 230 list follows 12.3674 + [S] <article.3@local.service> 12.3675 + [S] <article.4@local.service> 12.3676 + [S] <article.5@local.service> 12.3677 + [S] . 12.3678 + 12.3679 + Note how <article.3@local.service> arrived in the 3 minute gap and so 12.3680 + is listed in both responses. 12.3681 + 12.3682 +7.6. The LIST Commands 12.3683 + 12.3684 + The LIST family of commands all return information that is multi-line 12.3685 + and that can, in general, be expected not to change during the 12.3686 + session. Often the information is related to newsgroups, in which 12.3687 + case the response has one line per newsgroup and a wildmat MAY be 12.3688 + provided to restrict the groups for which information is returned. 12.3689 + 12.3690 + The set of available keywords (including those provided by 12.3691 + extensions) is given in the capability list with capability label 12.3692 + LIST. 12.3693 + 12.3694 + 12.3695 + 12.3696 +Feather Standards Track [Page 66] 12.3697 + 12.3698 +RFC 3977 Network News Transfer Protocol (NNTP) October 2006 12.3699 + 12.3700 + 12.3701 +7.6.1. LIST 12.3702 + 12.3703 +7.6.1.1. Usage 12.3704 + 12.3705 + Indicating capability: LIST 12.3706 + 12.3707 + Syntax 12.3708 + LIST [keyword [wildmat|argument]] 12.3709 + 12.3710 + Responses 12.3711 + 215 Information follows (multi-line) 12.3712 + 12.3713 + Parameters 12.3714 + keyword Information requested [1] 12.3715 + argument Specific to keyword 12.3716 + wildmat Groups of interest 12.3717 + 12.3718 + [1] If no keyword is provided, it defaults to ACTIVE. 12.3719 + 12.3720 +7.6.1.2. Description 12.3721 + 12.3722 + The LIST command allows the server to provide blocks of information 12.3723 + to the client. This information may be global or may be related to 12.3724 + newsgroups; in the latter case, the information may be returned 12.3725 + either for all groups or only for those matching a wildmat. Each 12.3726 + block of information is represented by a different keyword. The 12.3727 + command returns the specific information identified by the keyword. 12.3728 + 12.3729 + If the information is available, it is returned as a multi-line data 12.3730 + block following the 215 response code. The format of the information 12.3731 + depends on the keyword. The information MAY be affected by the 12.3732 + additional argument, but the format MUST NOT be. 12.3733 + 12.3734 + If the information is based on newsgroups and the optional wildmat 12.3735 + argument is specified, the response is limited to only the groups (if 12.3736 + any) whose names match the wildmat and for which the information is 12.3737 + available. 12.3738 + 12.3739 + Note that an empty list is a possible valid response; for a 12.3740 + newsgroup-based keyword, it indicates that there are no groups 12.3741 + meeting the above criteria. 12.3742 + 12.3743 + If the keyword is not recognised, or if an argument is specified and 12.3744 + the keyword does not expect one, a 501 response code MUST BE 12.3745 + returned. If the keyword is recognised but the server does not 12.3746 + maintain the information, a 503 response code MUST BE returned. 12.3747 + 12.3748 + 12.3749 + 12.3750 + 12.3751 + 12.3752 +Feather Standards Track [Page 67] 12.3753 + 12.3754 +RFC 3977 Network News Transfer Protocol (NNTP) October 2006 12.3755 + 12.3756 + 12.3757 + The LIST command MUST NOT change the visible state of the server in 12.3758 + any way; that is, the behaviour of subsequent commands MUST NOT be 12.3759 + affected by whether the LIST command was issued. For example, it 12.3760 + MUST NOT make groups available that otherwise would not have been. 12.3761 + 12.3762 +7.6.1.3. Examples 12.3763 + 12.3764 + Example of LIST with the ACTIVE keyword: 12.3765 + 12.3766 + [C] LIST ACTIVE 12.3767 + [S] 215 list of newsgroups follows 12.3768 + [S] misc.test 3002322 3000234 y 12.3769 + [S] comp.risks 442001 441099 m 12.3770 + [S] alt.rfc-writers.recovery 4 1 y 12.3771 + [S] tx.natives.recovery 89 56 y 12.3772 + [S] tx.natives.recovery.d 11 9 n 12.3773 + [S] . 12.3774 + 12.3775 + Example of LIST with no keyword: 12.3776 + 12.3777 + [C] LIST 12.3778 + [S] 215 list of newsgroups follows 12.3779 + [S] misc.test 3002322 3000234 y 12.3780 + [S] comp.risks 442001 441099 m 12.3781 + [S] alt.rfc-writers.recovery 4 1 y 12.3782 + [S] tx.natives.recovery 89 56 y 12.3783 + [S] tx.natives.recovery.d 11 9 n 12.3784 + [S] . 12.3785 + 12.3786 + The output is identical to that of the previous example. 12.3787 + 12.3788 + Example of LIST on a newsgroup-based keyword with and without 12.3789 + wildmat: 12.3790 + 12.3791 + [C] LIST ACTIVE.TIMES 12.3792 + [S] 215 information follows 12.3793 + [S] misc.test 930445408 <creatme@isc.org> 12.3794 + [S] alt.rfc-writers.recovery 930562309 <m@example.com> 12.3795 + [S] tx.natives.recovery 930678923 <sob@academ.com> 12.3796 + [S] . 12.3797 + [C] LIST ACTIVE.TIMES tx.* 12.3798 + [S] 215 information follows 12.3799 + [S] tx.natives.recovery 930678923 <sob@academ.com> 12.3800 + [S] . 12.3801 + 12.3802 + 12.3803 + 12.3804 + 12.3805 + 12.3806 + 12.3807 + 12.3808 +Feather Standards Track [Page 68] 12.3809 + 12.3810 +RFC 3977 Network News Transfer Protocol (NNTP) October 2006 12.3811 + 12.3812 + 12.3813 + Example of LIST returning an error where the keyword is recognized 12.3814 + but the software does not maintain this information: 12.3815 + 12.3816 + [C] CAPABILITIES 12.3817 + [S] 101 Capability list: 12.3818 + [S] VERSION 2 12.3819 + [S] READER 12.3820 + [S] LIST ACTIVE NEWSGROUPS ACTIVE.TIMES XTRA.DATA 12.3821 + [S] . 12.3822 + [C] LIST XTRA.DATA 12.3823 + [S] 503 Data item not stored 12.3824 + 12.3825 + Example of LIST where the keyword is not recognised: 12.3826 + 12.3827 + [C] CAPABILITIES 12.3828 + [S] 101 Capability list: 12.3829 + [S] VERSION 2 12.3830 + [S] READER 12.3831 + [S] LIST ACTIVE NEWSGROUPS ACTIVE.TIMES XTRA.DATA 12.3832 + [S] . 12.3833 + [C] LIST DISTRIB.PATS 12.3834 + [S] 501 Syntax Error 12.3835 + 12.3836 +7.6.2. Standard LIST Keywords 12.3837 + 12.3838 + This specification defines the following LIST keywords: 12.3839 + 12.3840 + +--------------+---------------+------------------------------------+ 12.3841 + | Keyword | Definition | Status | 12.3842 + +--------------+---------------+------------------------------------+ 12.3843 + | ACTIVE | Section 7.6.3 | Mandatory if the READER capability | 12.3844 + | | | is advertised | 12.3845 + | | | | 12.3846 + | ACTIVE.TIMES | Section 7.6.4 | Optional | 12.3847 + | | | | 12.3848 + | DISTRIB.PATS | Section 7.6.5 | Optional | 12.3849 + | | | | 12.3850 + | HEADERS | Section 8.6 | Mandatory if the HDR capability is | 12.3851 + | | | advertised | 12.3852 + | | | | 12.3853 + | NEWSGROUPS | Section 7.6.6 | Mandatory if the READER capability | 12.3854 + | | | is advertised | 12.3855 + | | | | 12.3856 + | OVERVIEW.FMT | Section 8.4 | Mandatory if the OVER capability | 12.3857 + | | | is advertised | 12.3858 + +--------------+---------------+------------------------------------+ 12.3859 + 12.3860 + 12.3861 + 12.3862 + 12.3863 + 12.3864 +Feather Standards Track [Page 69] 12.3865 + 12.3866 +RFC 3977 Network News Transfer Protocol (NNTP) October 2006 12.3867 + 12.3868 + 12.3869 + Where one of these LIST keywords is supported by a server, it MUST 12.3870 + have the meaning given in the relevant sub-section. 12.3871 + 12.3872 +7.6.3. LIST ACTIVE 12.3873 + 12.3874 + This keyword MUST be supported by servers advertising the READER 12.3875 + capability. 12.3876 + 12.3877 + LIST ACTIVE returns a list of valid newsgroups and associated 12.3878 + information. If no wildmat is specified, the server MUST include 12.3879 + every group that the client is permitted to select with the GROUP 12.3880 + command (Section 6.1.1). Each line of this list consists of four 12.3881 + fields separated from each other by one or more spaces: 12.3882 + 12.3883 + o The name of the newsgroup. 12.3884 + o The reported high water mark for the group. 12.3885 + o The reported low water mark for the group. 12.3886 + o The current status of the group on this server. 12.3887 + 12.3888 + The reported high and low water marks are as described in the GROUP 12.3889 + command (see Section 6.1.1), but note that they are in the opposite 12.3890 + order to the 211 response to that command. 12.3891 + 12.3892 + The status field is typically one of the following: 12.3893 + 12.3894 + "y" Posting is permitted. 12.3895 + 12.3896 + "n" Posting is not permitted. 12.3897 + 12.3898 + "m" Postings will be forwarded to the newsgroup moderator. 12.3899 + 12.3900 + The server SHOULD use these values when these meanings are required 12.3901 + and MUST NOT use them with any other meaning. Other values for the 12.3902 + status may exist; the definition of these other values and the 12.3903 + circumstances under which they are returned may be specified in an 12.3904 + extension or may be private to the server. A client SHOULD treat an 12.3905 + unrecognized status as giving no information. 12.3906 + 12.3907 + The status of a newsgroup only indicates how posts to that newsgroup 12.3908 + are normally processed and is not necessarily customised to the 12.3909 + specific client. For example, if the current client is forbidden 12.3910 + from posting, then this will apply equally to groups with status "y". 12.3911 + Conversely, a client with special privileges (not defined by this 12.3912 + specification) might be able to post to a group with status "n". 12.3913 + 12.3914 + 12.3915 + 12.3916 + 12.3917 + 12.3918 + 12.3919 + 12.3920 +Feather Standards Track [Page 70] 12.3921 + 12.3922 +RFC 3977 Network News Transfer Protocol (NNTP) October 2006 12.3923 + 12.3924 + 12.3925 + For example: 12.3926 + 12.3927 + [C] LIST ACTIVE 12.3928 + [S] 215 list of newsgroups follows 12.3929 + [S] misc.test 3002322 3000234 y 12.3930 + [S] comp.risks 442001 441099 m 12.3931 + [S] alt.rfc-writers.recovery 4 1 y 12.3932 + [S] tx.natives.recovery 89 56 y 12.3933 + [S] tx.natives.recovery.d 11 9 n 12.3934 + [S] . 12.3935 + 12.3936 + or, on an implementation that includes leading zeroes: 12.3937 + 12.3938 + [C] LIST ACTIVE 12.3939 + [S] 215 list of newsgroups follows 12.3940 + [S] misc.test 0003002322 0003000234 y 12.3941 + [S] comp.risks 0000442001 0000441099 m 12.3942 + [S] alt.rfc-writers.recovery 0000000004 0000000001 y 12.3943 + [S] tx.natives.recovery 0000000089 0000000056 y 12.3944 + [S] tx.natives.recovery.d 0000000011 0000000009 n 12.3945 + [S] . 12.3946 + 12.3947 + The information is newsgroup based, and a wildmat MAY be specified, 12.3948 + in which case the response is limited to only the groups (if any) 12.3949 + whose names match the wildmat. For example: 12.3950 + 12.3951 + [C] LIST ACTIVE *.recovery 12.3952 + [S] 215 list of newsgroups follows 12.3953 + [S] alt.rfc-writers.recovery 4 1 y 12.3954 + [S] tx.natives.recovery 89 56 y 12.3955 + [S] . 12.3956 + 12.3957 +7.6.4. LIST ACTIVE.TIMES 12.3958 + 12.3959 + This keyword is optional. 12.3960 + 12.3961 + The active.times list is maintained by some NNTP servers to contain 12.3962 + information about who created a particular newsgroup and when. Each 12.3963 + line of this list consists of three fields separated from each other 12.3964 + by one or more spaces. The first field is the name of the newsgroup. 12.3965 + The second is the time when this group was created on this news 12.3966 + server, measured in seconds since the start of January 1, 1970. The 12.3967 + third is plain text intended to describe the entity that created the 12.3968 + newsgroup; it is often a mailbox as defined in RFC 2822 [RFC2822]. 12.3969 + For example: 12.3970 + 12.3971 + 12.3972 + 12.3973 + 12.3974 + 12.3975 + 12.3976 +Feather Standards Track [Page 71] 12.3977 + 12.3978 +RFC 3977 Network News Transfer Protocol (NNTP) October 2006 12.3979 + 12.3980 + 12.3981 + [C] LIST ACTIVE.TIMES 12.3982 + [S] 215 information follows 12.3983 + [S] misc.test 930445408 <creatme@isc.org> 12.3984 + [S] alt.rfc-writers.recovery 930562309 <m@example.com> 12.3985 + [S] tx.natives.recovery 930678923 <sob@academ.com> 12.3986 + [S] . 12.3987 + 12.3988 + The list MAY omit newsgroups for which the information is unavailable 12.3989 + and MAY include groups not available on the server; in particular, it 12.3990 + MAY omit all groups created before the date and time of the oldest 12.3991 + entry. The client MUST NOT assume that the list is complete or that 12.3992 + it matches the list returned by the LIST ACTIVE command 12.3993 + (Section 7.6.3). The NEWGROUPS command (Section 7.3) may provide a 12.3994 + better way to access this information, and the results of the two 12.3995 + commands SHOULD be consistent except that, if the latter is invoked 12.3996 + with a date and time earlier than the oldest entry in active.times 12.3997 + list, its result may include extra groups. 12.3998 + 12.3999 + The information is newsgroup based, and a wildmat MAY be specified, 12.4000 + in which case the response is limited to only the groups (if any) 12.4001 + whose names match the wildmat. 12.4002 + 12.4003 +7.6.5. LIST DISTRIB.PATS 12.4004 + 12.4005 + This keyword is optional. 12.4006 + 12.4007 + The distrib.pats list is maintained by some NNTP servers to assist 12.4008 + clients to choose a value for the content of the Distribution header 12.4009 + of a news article being posted. Each line of this list consists of 12.4010 + three fields separated from each other by a colon (":"). The first 12.4011 + field is a weight, the second field is a wildmat (which may be a 12.4012 + simple newsgroup name), and the third field is a value for the 12.4013 + Distribution header content. For example: 12.4014 + 12.4015 + [C] LIST DISTRIB.PATS 12.4016 + [S] 215 information follows 12.4017 + [S] 10:local.*:local 12.4018 + [S] 5:*:world 12.4019 + [S] 20:local.here.*:thissite 12.4020 + [S] . 12.4021 + 12.4022 + The client MAY use this information to construct an appropriate 12.4023 + Distribution header given the name of a newsgroup. To do so, it 12.4024 + should determine the lines whose second field matches the newsgroup 12.4025 + name, select from among them the line with the highest weight (with 0 12.4026 + being the lowest), and use the value of the third field to construct 12.4027 + the Distribution header. 12.4028 + 12.4029 + 12.4030 + 12.4031 + 12.4032 +Feather Standards Track [Page 72] 12.4033 + 12.4034 +RFC 3977 Network News Transfer Protocol (NNTP) October 2006 12.4035 + 12.4036 + 12.4037 + The information is not newsgroup based, and an argument MUST NOT be 12.4038 + specified. 12.4039 + 12.4040 +7.6.6. LIST NEWSGROUPS 12.4041 + 12.4042 + This keyword MUST be supported by servers advertising the READER 12.4043 + capability. 12.4044 + 12.4045 + The newsgroups list is maintained by NNTP servers to contain the name 12.4046 + of each newsgroup that is available on the server and a short 12.4047 + description about the purpose of the group. Each line of this list 12.4048 + consists of two fields separated from each other by one or more space 12.4049 + or TAB characters (the usual practice is a single TAB). The first 12.4050 + field is the name of the newsgroup, and the second is a short 12.4051 + description of the group. For example: 12.4052 + 12.4053 + [C] LIST NEWSGROUPS 12.4054 + [S] 215 information follows 12.4055 + [S] misc.test General Usenet testing 12.4056 + [S] alt.rfc-writers.recovery RFC Writers Recovery 12.4057 + [S] tx.natives.recovery Texas Natives Recovery 12.4058 + [S] . 12.4059 + 12.4060 + The list MAY omit newsgroups for which the information is unavailable 12.4061 + and MAY include groups not available on the server. The client MUST 12.4062 + NOT assume that the list is complete or that it matches the list 12.4063 + returned by LIST ACTIVE. 12.4064 + 12.4065 + The description SHOULD be in UTF-8. However, servers often obtain 12.4066 + the information from external sources. These sources may have used 12.4067 + different encodings (ones that use octets in the range 128 to 255 in 12.4068 + some other manner) and, in that case, the server MAY pass it on 12.4069 + unchanged. Therefore, clients MUST be prepared to receive such 12.4070 + descriptions. 12.4071 + 12.4072 + The information is newsgroup based, and a wildmat MAY be specified, 12.4073 + in which case the response is limited to only the groups (if any) 12.4074 + whose names match the wildmat. 12.4075 + 12.4076 +8. Article Field Access Commands 12.4077 + 12.4078 + This section lists commands that may be used to access specific 12.4079 + article fields; that is, headers of articles and metadata about 12.4080 + articles. These commands typically fetch data from an "overview 12.4081 + database", which is a database of headers extracted from incoming 12.4082 + articles plus metadata determined as the article arrives. Only 12.4083 + certain fields are included in the database. 12.4084 + 12.4085 + 12.4086 + 12.4087 + 12.4088 +Feather Standards Track [Page 73] 12.4089 + 12.4090 +RFC 3977 Network News Transfer Protocol (NNTP) October 2006 12.4091 + 12.4092 + 12.4093 + This section is based on the Overview/NOV database [ROBE1995] 12.4094 + developed by Geoff Collyer. 12.4095 + 12.4096 +8.1. Article Metadata 12.4097 + 12.4098 + Article "metadata" is data about articles that does not occur within 12.4099 + the article itself. Each metadata item has a name that MUST begin 12.4100 + with a colon (and that MUST NOT contain a colon elsewhere within it). 12.4101 + As with header names, metadata item names are not case sensitive. 12.4102 + 12.4103 + When generating a metadata item, the server MUST compute it for 12.4104 + itself and MUST NOT trust any related value provided in the article. 12.4105 + (In particular, a Lines or Bytes header in the article MUST NOT be 12.4106 + assumed to specify the correct number of lines or bytes in the 12.4107 + article.) If the server has access to several non-identical copies 12.4108 + of an article, the value returned MUST be correct for any copy of 12.4109 + that article retrieved during the same session. 12.4110 + 12.4111 + This specification defines two metadata items: ":bytes" and ":lines". 12.4112 + Other metadata items may be defined by extensions. The names of 12.4113 + metadata items defined by registered extensions MUST NOT begin with 12.4114 + ":x-". To avoid the risk of a clash with a future registered 12.4115 + extension, the names of metadata items defined by private extensions 12.4116 + SHOULD begin with ":x-". 12.4117 + 12.4118 +8.1.1. The :bytes Metadata Item 12.4119 + 12.4120 + The :bytes metadata item for an article is a decimal integer. It 12.4121 + SHOULD equal the number of octets in the entire article: headers, 12.4122 + body, and separating empty line (counting a CRLF pair as two octets, 12.4123 + and excluding both the "." CRLF terminating the response and any "." 12.4124 + added for "dot-stuffing" purposes). 12.4125 + 12.4126 + Note to client implementers: some existing servers return a value 12.4127 + different from that above. The commonest reasons for this are as 12.4128 + follows: 12.4129 + 12.4130 + o Counting a CRLF pair as one octet. 12.4131 + 12.4132 + o Including the "." character used for dot-stuffing in the number. 12.4133 + 12.4134 + o Including the terminating "." CRLF in the number. 12.4135 + 12.4136 + o Using one copy of an article for counting the octets but then 12.4137 + returning another one that differs in some (permitted) manner. 12.4138 + 12.4139 + Implementations should be prepared for such variation and MUST NOT 12.4140 + rely on the value being accurate. 12.4141 + 12.4142 + 12.4143 + 12.4144 +Feather Standards Track [Page 74] 12.4145 + 12.4146 +RFC 3977 Network News Transfer Protocol (NNTP) October 2006 12.4147 + 12.4148 + 12.4149 +8.1.2. The :lines Metadata Item 12.4150 + 12.4151 + The :lines metadata item for an article is a decimal integer. It 12.4152 + MUST equal the number of lines in the article body (excluding the 12.4153 + empty line separating headers and body). Equivalently, it is two 12.4154 + less than the number of CRLF pairs that the BODY command would return 12.4155 + for that article (the extra two are those following the response code 12.4156 + and the termination octet). 12.4157 + 12.4158 +8.2. Database Consistency 12.4159 + 12.4160 + The information stored in the overview database may change over time. 12.4161 + If the database records the content or absence of a given field (that 12.4162 + is, a header or metadata item) for all articles, it is said to be 12.4163 + "consistent" for that field. If it records the content of a header 12.4164 + for some articles but not for others that nevertheless included that 12.4165 + header, or if it records a metadata item for some articles but not 12.4166 + for others to which that item applies, it is said to be 12.4167 + "inconsistent" for that field. 12.4168 + 12.4169 + The LIST OVERVIEW.FMT command SHOULD list all the fields for which 12.4170 + the database is consistent at that moment. It MAY omit such fields 12.4171 + (for example, if it is not known whether the database is consistent 12.4172 + or inconsistent). It MUST NOT include fields for which the database 12.4173 + is inconsistent or that are not stored in the database. Therefore, 12.4174 + if a header appears in the LIST OVERVIEW.FMT output but not in the 12.4175 + OVER output for a given article, that header does not appear in the 12.4176 + article (similarly for metadata items). 12.4177 + 12.4178 + These rules assume that the fields being stored in the database 12.4179 + remain constant for long periods of time, and therefore the database 12.4180 + will be consistent. When the set of fields to be stored is changed, 12.4181 + it will be inconsistent until either the database is rebuilt or the 12.4182 + only articles remaining are those received since the change. 12.4183 + Therefore, the output from LIST OVERVIEW.FMT needs to be altered 12.4184 + twice. Firstly, before any fields stop being stored they MUST be 12.4185 + removed from the output; then, when the database is once more known 12.4186 + to be consistent, the new fields SHOULD be added to the output. 12.4187 + 12.4188 + If the HDR command uses the overview database rather than taking 12.4189 + information directly from the articles, the same issues of 12.4190 + consistency and inconsistency apply, and the LIST HEADERS command 12.4191 + SHOULD take the same approach as the LIST OVERVIEW.FMT command in 12.4192 + resolving them. 12.4193 + 12.4194 + 12.4195 + 12.4196 + 12.4197 + 12.4198 + 12.4199 + 12.4200 +Feather Standards Track [Page 75] 12.4201 + 12.4202 +RFC 3977 Network News Transfer Protocol (NNTP) October 2006 12.4203 + 12.4204 + 12.4205 +8.3. OVER 12.4206 + 12.4207 +8.3.1. Usage 12.4208 + 12.4209 + Indicating capability: OVER 12.4210 + 12.4211 + Syntax 12.4212 + OVER message-id 12.4213 + OVER range 12.4214 + OVER 12.4215 + 12.4216 + Responses 12.4217 + 12.4218 + First form (message-id specified) 12.4219 + 224 Overview information follows (multi-line) 12.4220 + 430 No article with that message-id 12.4221 + 12.4222 + Second form (range specified) 12.4223 + 224 Overview information follows (multi-line) 12.4224 + 412 No newsgroup selected 12.4225 + 423 No articles in that range 12.4226 + 12.4227 + Third form (current article number used) 12.4228 + 224 Overview information follows (multi-line) 12.4229 + 412 No newsgroup selected 12.4230 + 420 Current article number is invalid 12.4231 + 12.4232 + Parameters 12.4233 + range Number(s) of articles 12.4234 + message-id Message-id of article 12.4235 + 12.4236 +8.3.2. Description 12.4237 + 12.4238 + The OVER command returns the contents of all the fields in the 12.4239 + database for an article specified by message-id, or from a specified 12.4240 + article or range of articles in the currently selected newsgroup. 12.4241 + 12.4242 + The message-id argument indicates a specific article. The range 12.4243 + argument may be any of the following: 12.4244 + 12.4245 + o An article number. 12.4246 + 12.4247 + o An article number followed by a dash to indicate all following. 12.4248 + 12.4249 + o An article number followed by a dash followed by another article 12.4250 + number. 12.4251 + 12.4252 + If neither is specified, the current article number is used. 12.4253 + 12.4254 + 12.4255 + 12.4256 +Feather Standards Track [Page 76] 12.4257 + 12.4258 +RFC 3977 Network News Transfer Protocol (NNTP) October 2006 12.4259 + 12.4260 + 12.4261 + Support for the first (message-id) form is optional. If it is 12.4262 + supported, the OVER capability line MUST include the argument 12.4263 + "MSGID". Otherwise, the capability line MUST NOT include this 12.4264 + argument, and the OVER command MUST return the generic response code 12.4265 + 503 when this form is used. 12.4266 + 12.4267 + If the information is available, it is returned as a multi-line data 12.4268 + block following the 224 response code and contains one line per 12.4269 + article, sorted in numerical order of article number. (Note that 12.4270 + unless the argument is a range including a dash, there will be 12.4271 + exactly one line in the data block.) Each line consists of a number 12.4272 + of fields separated by a TAB. A field may be empty (in which case 12.4273 + there will be two adjacent TABs), and a sequence of trailing TABs may 12.4274 + be omitted. 12.4275 + 12.4276 + The first 8 fields MUST be the following, in order: 12.4277 + 12.4278 + "0" or article number (see below) 12.4279 + Subject header content 12.4280 + From header content 12.4281 + Date header content 12.4282 + Message-ID header content 12.4283 + References header content 12.4284 + :bytes metadata item 12.4285 + :lines metadata item 12.4286 + 12.4287 + If the article is specified by message-id (the first form of the 12.4288 + command), the article number MUST be replaced with zero, except that 12.4289 + if there is a currently selected newsgroup and the article is present 12.4290 + in that group, the server MAY use the article's number in that group. 12.4291 + (See the ARTICLE command (Section 6.2.1) and STAT examples 12.4292 + (Section 6.2.4.3) for more details.) In the other two forms of the 12.4293 + command, the article number MUST be returned. 12.4294 + 12.4295 + Any subsequent fields are the contents of the other headers and 12.4296 + metadata held in the database. 12.4297 + 12.4298 + For the five mandatory headers, the content of each field MUST be 12.4299 + based on the content of the header (that is, with the header name and 12.4300 + following colon and space removed). If the article does not contain 12.4301 + that header, or if the content is empty, the field MUST be empty. 12.4302 + For the two mandatory metadata items, the content of the field MUST 12.4303 + be just the value, with no other text. 12.4304 + 12.4305 + For all subsequent fields that contain headers, the content MUST be 12.4306 + the entire header line other than the trailing CRLF. For all 12.4307 + subsequent fields that contain metadata, the field consists of the 12.4308 + metadata name, a single space, and then the value. 12.4309 + 12.4310 + 12.4311 + 12.4312 +Feather Standards Track [Page 77] 12.4313 + 12.4314 +RFC 3977 Network News Transfer Protocol (NNTP) October 2006 12.4315 + 12.4316 + 12.4317 + For all fields, the value is processed by first removing all CRLF 12.4318 + pairs (that is, undoing any folding and removing the terminating 12.4319 + CRLF) and then replacing each TAB with a single space. If there is 12.4320 + no such header in the article, no such metadata item, or no header or 12.4321 + item stored in the database for that article, the corresponding field 12.4322 + MUST be empty. 12.4323 + 12.4324 + Note that, after unfolding, the characters NUL, LF, and CR cannot 12.4325 + occur in the header of an article offered by a conformant server. 12.4326 + Nevertheless, servers SHOULD check for these characters and replace 12.4327 + each one by a single space (so that, for example, CR LF LF TAB will 12.4328 + become two spaces, since the CR and first LF will be removed by the 12.4329 + unfolding process). This will encourage robustness in the face of 12.4330 + non-conforming data; it is also possible that future versions of this 12.4331 + specification could permit these characters to appear in articles. 12.4332 + 12.4333 + The server SHOULD NOT produce output for articles that no longer 12.4334 + exist. 12.4335 + 12.4336 + If the argument is a message-id and no such article exists, a 430 12.4337 + response MUST be returned. If the argument is a range or is omitted 12.4338 + and the currently selected newsgroup is invalid, a 412 response MUST 12.4339 + be returned. If the argument is a range and no articles in that 12.4340 + number range exist in the currently selected newsgroup, including the 12.4341 + case where the second number is less than the first one, a 423 12.4342 + response MUST be returned. If the argument is omitted and the 12.4343 + current article number is invalid, a 420 response MUST be returned. 12.4344 + 12.4345 +8.3.3. Examples 12.4346 + 12.4347 + In the first four examples, TAB has been replaced by vertical bar and 12.4348 + some lines have been folded for readability. 12.4349 + 12.4350 + Example of a successful retrieval of overview information for an 12.4351 + article (explicitly not using an article number): 12.4352 + 12.4353 + [C] GROUP misc.test 12.4354 + [S] 211 1234 3000234 3002322 misc.test 12.4355 + [C] OVER 12.4356 + [S] 224 Overview information follows 12.4357 + [S] 3000234|I am just a test article|"Demo User" 12.4358 + <nobody@example.com>|6 Oct 1998 04:38:40 -0500| 12.4359 + <45223423@example.com>|<45454@example.net>|1234| 12.4360 + 17|Xref: news.example.com misc.test:3000363 12.4361 + [S] . 12.4362 + 12.4363 + 12.4364 + 12.4365 + 12.4366 + 12.4367 + 12.4368 +Feather Standards Track [Page 78] 12.4369 + 12.4370 +RFC 3977 Network News Transfer Protocol (NNTP) October 2006 12.4371 + 12.4372 + 12.4373 + Example of a successful retrieval of overview information for an 12.4374 + article by message-id: 12.4375 + 12.4376 + [C] CAPABILITIES 12.4377 + [S] 101 Capability list: 12.4378 + [S] VERSION 2 12.4379 + [S] READER 12.4380 + [S] OVER MSGID 12.4381 + [S] LIST ACTIVE NEWSGROUPS OVERVIEW.FMT 12.4382 + [S] . 12.4383 + [C] OVER <45223423@example.com> 12.4384 + [S] 224 Overview information follows 12.4385 + [S] 0|I am just a test article|"Demo User" 12.4386 + <nobody@example.com>|6 Oct 1998 04:38:40 -0500| 12.4387 + <45223423@example.com>|<45454@example.net>|1234| 12.4388 + 17|Xref: news.example.com misc.test:3000363 12.4389 + [S] . 12.4390 + 12.4391 + Note that the article number has been replaced by "0". 12.4392 + 12.4393 + Example of the same commands on a system that does not implement 12.4394 + retrieval by message-id: 12.4395 + 12.4396 + [C] CAPABILITIES 12.4397 + [S] 101 Capability list: 12.4398 + [S] VERSION 2 12.4399 + [S] READER 12.4400 + [S] OVER 12.4401 + [S] LIST ACTIVE NEWSGROUPS OVERVIEW.FMT 12.4402 + [S] . 12.4403 + [C] OVER <45223423@example.com> 12.4404 + [S] 503 Overview by message-id unsupported 12.4405 + 12.4406 + 12.4407 + 12.4408 + 12.4409 + 12.4410 + 12.4411 + 12.4412 + 12.4413 + 12.4414 + 12.4415 + 12.4416 + 12.4417 + 12.4418 + 12.4419 + 12.4420 + 12.4421 + 12.4422 + 12.4423 + 12.4424 +Feather Standards Track [Page 79] 12.4425 + 12.4426 +RFC 3977 Network News Transfer Protocol (NNTP) October 2006 12.4427 + 12.4428 + 12.4429 + Example of a successful retrieval of overview information for a range 12.4430 + of articles: 12.4431 + 12.4432 + [C] GROUP misc.test 12.4433 + [S] 211 1234 3000234 3002322 misc.test 12.4434 + [C] OVER 3000234-3000240 12.4435 + [S] 224 Overview information follows 12.4436 + [S] 3000234|I am just a test article|"Demo User" 12.4437 + <nobody@example.com>|6 Oct 1998 04:38:40 -0500| 12.4438 + <45223423@example.com>|<45454@example.net>|1234| 12.4439 + 17|Xref: news.example.com misc.test:3000363 12.4440 + [S] 3000235|Another test article|nobody@nowhere.to 12.4441 + (Demo User)|6 Oct 1998 04:38:45 -0500|<45223425@to.to>|| 12.4442 + 4818|37||Distribution: fi 12.4443 + [S] 3000238|Re: I am just a test article|somebody@elsewhere.to| 12.4444 + 7 Oct 1998 11:38:40 +1200|<kfwer3v@elsewhere.to>| 12.4445 + <45223423@to.to>|9234|51 12.4446 + [S] . 12.4447 + 12.4448 + Note the missing "References" and Xref headers in the second line, 12.4449 + the missing trailing fields in the first and last lines, and that 12.4450 + there are only results for those articles that still exist. 12.4451 + 12.4452 + Example of an unsuccessful retrieval of overview information on an 12.4453 + article by number: 12.4454 + 12.4455 + [C] GROUP misc.test 12.4456 + [S] 211 1234 3000234 3002322 misc.test 12.4457 + [C] OVER 300256 12.4458 + [S] 423 No such article in this group 12.4459 + 12.4460 + Example of an invalid range: 12.4461 + 12.4462 + [C] GROUP misc.test 12.4463 + [S] 211 1234 3000234 3002322 misc.test 12.4464 + [C] OVER 3000444-3000222 12.4465 + [S] 423 Empty range 12.4466 + 12.4467 + Example of an unsuccessful retrieval of overview information by 12.4468 + number because no newsgroup was selected first: 12.4469 + 12.4470 + [Assumes currently selected newsgroup is invalid.] 12.4471 + [C] OVER 12.4472 + [S] 412 No newsgroup selected 12.4473 + 12.4474 + 12.4475 + 12.4476 + 12.4477 + 12.4478 + 12.4479 + 12.4480 +Feather Standards Track [Page 80] 12.4481 + 12.4482 +RFC 3977 Network News Transfer Protocol (NNTP) October 2006 12.4483 + 12.4484 + 12.4485 + Example of an attempt to retrieve information when the currently 12.4486 + selected newsgroup is empty: 12.4487 + 12.4488 + [C] GROUP example.empty.newsgroup 12.4489 + [S] 211 0 0 0 example.empty.newsgroup 12.4490 + [C] OVER 12.4491 + [S] 420 No current article selected 12.4492 + 12.4493 +8.4. LIST OVERVIEW.FMT 12.4494 + 12.4495 +8.4.1. Usage 12.4496 + 12.4497 + Indicating capability: OVER 12.4498 + 12.4499 + Syntax 12.4500 + LIST OVERVIEW.FMT 12.4501 + 12.4502 + Responses 12.4503 + 215 Information follows (multi-line) 12.4504 + 12.4505 +8.4.2. Description 12.4506 + 12.4507 + See Section 7.6.1 for general requirements of the LIST command. 12.4508 + 12.4509 + The LIST OVERVIEW.FMT command returns a description of the fields in 12.4510 + the database for which it is consistent (as described above). The 12.4511 + information is returned as a multi-line data block following the 215 12.4512 + response code. The information contains one line per field in the 12.4513 + order in which they are returned by the OVER command; the first 7 12.4514 + lines MUST (except for the case of letters) be exactly as follows: 12.4515 + 12.4516 + Subject: 12.4517 + From: 12.4518 + Date: 12.4519 + Message-ID: 12.4520 + References: 12.4521 + :bytes 12.4522 + :lines 12.4523 + 12.4524 + For compatibility with existing implementations, the last two lines 12.4525 + MAY instead be: 12.4526 + 12.4527 + Bytes: 12.4528 + Lines: 12.4529 + 12.4530 + even though they refer to metadata, not headers. 12.4531 + 12.4532 + 12.4533 + 12.4534 + 12.4535 + 12.4536 +Feather Standards Track [Page 81] 12.4537 + 12.4538 +RFC 3977 Network News Transfer Protocol (NNTP) October 2006 12.4539 + 12.4540 + 12.4541 + All subsequent lines MUST consist of either a header name followed by 12.4542 + ":full", or the name of a piece of metadata. 12.4543 + 12.4544 + There are no leading or trailing spaces in the output. 12.4545 + 12.4546 + Note that the 7 fixed lines describe the 2nd to 8th fields of the 12.4547 + OVER output. The "full" suffix (which may use either uppercase, 12.4548 + lowercase, or a mix) is a reminder that the corresponding fields 12.4549 + include the header name. 12.4550 + 12.4551 + This command MAY generate different results if it is used more than 12.4552 + once in a session. 12.4553 + 12.4554 + If the OVER command is not implemented, the meaning of the output 12.4555 + from this command is not specified, but it must still meet the above 12.4556 + syntactic requirements. 12.4557 + 12.4558 +8.4.3. Examples 12.4559 + 12.4560 + Example of LIST OVERVIEW.FMT output corresponding to the example OVER 12.4561 + output above, in the preferred format: 12.4562 + 12.4563 + [C] LIST OVERVIEW.FMT 12.4564 + [S] 215 Order of fields in overview database. 12.4565 + [S] Subject: 12.4566 + [S] From: 12.4567 + [S] Date: 12.4568 + [S] Message-ID: 12.4569 + [S] References: 12.4570 + [S] :bytes 12.4571 + [S] :lines 12.4572 + [S] Xref:full 12.4573 + [S] Distribution:full 12.4574 + [S] . 12.4575 + 12.4576 + 12.4577 + 12.4578 + 12.4579 + 12.4580 + 12.4581 + 12.4582 + 12.4583 + 12.4584 + 12.4585 + 12.4586 + 12.4587 + 12.4588 + 12.4589 + 12.4590 + 12.4591 + 12.4592 +Feather Standards Track [Page 82] 12.4593 + 12.4594 +RFC 3977 Network News Transfer Protocol (NNTP) October 2006 12.4595 + 12.4596 + 12.4597 + Example of LIST OVERVIEW.FMT output corresponding to the example OVER 12.4598 + output above, in the alternative format: 12.4599 + 12.4600 + [C] LIST OVERVIEW.FMT 12.4601 + [S] 215 Order of fields in overview database. 12.4602 + [S] Subject: 12.4603 + [S] From: 12.4604 + [S] Date: 12.4605 + [S] Message-ID: 12.4606 + [S] References: 12.4607 + [S] Bytes: 12.4608 + [S] Lines: 12.4609 + [S] Xref:FULL 12.4610 + [S] Distribution:FULL 12.4611 + [S] . 12.4612 + 12.4613 +8.5. HDR 12.4614 + 12.4615 +8.5.1. Usage 12.4616 + 12.4617 + Indicating capability: HDR 12.4618 + 12.4619 + Syntax 12.4620 + HDR field message-id 12.4621 + HDR field range 12.4622 + HDR field 12.4623 + 12.4624 + Responses 12.4625 + 12.4626 + First form (message-id specified) 12.4627 + 225 Headers follow (multi-line) 12.4628 + 430 No article with that message-id 12.4629 + 12.4630 + Second form (range specified) 12.4631 + 225 Headers follow (multi-line) 12.4632 + 412 No newsgroup selected 12.4633 + 423 No articles in that range 12.4634 + 12.4635 + Third form (current article number used) 12.4636 + 225 Headers follow (multi-line) 12.4637 + 412 No newsgroup selected 12.4638 + 420 Current article number is invalid 12.4639 + 12.4640 + Parameters 12.4641 + field Name of field 12.4642 + range Number(s) of articles 12.4643 + message-id Message-id of article 12.4644 + 12.4645 + 12.4646 + 12.4647 + 12.4648 +Feather Standards Track [Page 83] 12.4649 + 12.4650 +RFC 3977 Network News Transfer Protocol (NNTP) October 2006 12.4651 + 12.4652 + 12.4653 +8.5.2. Description 12.4654 + 12.4655 + The HDR command provides access to specific fields from an article 12.4656 + specified by message-id, or from a specified article or range of 12.4657 + articles in the currently selected newsgroup. It MAY take the 12.4658 + information directly from the articles or from the overview database. 12.4659 + In the case of headers, an implementation MAY restrict the use of 12.4660 + this command to a specific list of headers or MAY allow it to be used 12.4661 + with any header; it may behave differently when it is used with a 12.4662 + message-id argument and when it is used with a range or no argument. 12.4663 + 12.4664 + The required field argument is the name of a header with the colon 12.4665 + omitted (e.g., "subject") or the name of a metadata item including 12.4666 + the leading colon (e.g., ":bytes"), and is case insensitive. 12.4667 + 12.4668 + The message-id argument indicates a specific article. The range 12.4669 + argument may be any of the following: 12.4670 + 12.4671 + o An article number. 12.4672 + 12.4673 + o An article number followed by a dash to indicate all following. 12.4674 + 12.4675 + o An article number followed by a dash followed by another article 12.4676 + number. 12.4677 + 12.4678 + If neither is specified, the current article number is used. 12.4679 + 12.4680 + If the information is available, it is returned as a multi-line data 12.4681 + block following the 225 response code and contains one line for each 12.4682 + article in the range that exists. (Note that unless the argument is 12.4683 + a range including a dash, there will be exactly one line in the data 12.4684 + block.) The line consists of the article number, a space, and then 12.4685 + the contents of the field. In the case of a header, the header name, 12.4686 + the colon, and the first space after the colon are all omitted. 12.4687 + 12.4688 + If the article is specified by message-id (the first form of the 12.4689 + command), the article number MUST be replaced with zero, except that 12.4690 + if there is a currently selected newsgroup and the article is present 12.4691 + in that group, the server MAY use the article's number in that group. 12.4692 + (See the ARTICLE command (Section 6.2.1) and STAT examples 12.4693 + (Section 6.2.4.3) for more details.) In the other two forms of the 12.4694 + command, the article number MUST be returned. 12.4695 + 12.4696 + Header contents are modified as follows: all CRLF pairs are removed, 12.4697 + and then each TAB is replaced with a single space. (Note that this 12.4698 + is the same transformation as is performed by the OVER command 12.4699 + (Section 8.3.2), and the same comment concerning NUL, CR, and LF 12.4700 + applies.) 12.4701 + 12.4702 + 12.4703 + 12.4704 +Feather Standards Track [Page 84] 12.4705 + 12.4706 +RFC 3977 Network News Transfer Protocol (NNTP) October 2006 12.4707 + 12.4708 + 12.4709 + Note the distinction between headers and metadata appearing to have 12.4710 + the same meaning. Headers are always taken unchanged from the 12.4711 + article; metadata are always calculated. For example, a request for 12.4712 + "Lines" returns the contents of the "Lines" header of the specified 12.4713 + articles, if any, no matter whether they accurately state the number 12.4714 + of lines, while a request for ":lines" returns the line count 12.4715 + metadata, which is always the actual number of lines irrespective of 12.4716 + what any header may state. 12.4717 + 12.4718 + If the requested header is not present in the article, or if it is 12.4719 + present but empty, a line for that article is included in the output, 12.4720 + but the header content portion of the line is empty (the space after 12.4721 + the article number MAY be retained or omitted). If the header occurs 12.4722 + in a given article more than once, only the content of the first 12.4723 + occurrence is returned by HDR. If any article number in the provided 12.4724 + range does not exist in the group, no line for that article number is 12.4725 + included in the output. 12.4726 + 12.4727 + If the second argument is a message-id and no such article exists, a 12.4728 + 430 response MUST be returned. If the second argument is a range or 12.4729 + is omitted and the currently selected newsgroup is invalid, a 412 12.4730 + response MUST be returned. If the second argument is a range and no 12.4731 + articles in that number range exist in the currently selected 12.4732 + newsgroup, including the case where the second number is less than 12.4733 + the first one, a 423 response MUST be returned. If the second 12.4734 + argument is omitted and the current article number is invalid, a 420 12.4735 + response MUST be returned. 12.4736 + 12.4737 + A server MAY only allow HDR commands for a limited set of fields; it 12.4738 + may behave differently in this respect for the first (message-id) 12.4739 + form from how it would for the other forms. If so, it MUST respond 12.4740 + with the generic 503 response to attempts to request other fields, 12.4741 + rather than return erroneous results, such as a successful empty 12.4742 + response. 12.4743 + 12.4744 + If HDR uses the overview database and it is inconsistent for the 12.4745 + requested field, the server MAY return what results it can, or it MAY 12.4746 + respond with the generic 503 response. In the latter case, the field 12.4747 + MUST NOT appear in the output from LIST HEADERS. 12.4748 + 12.4749 + 12.4750 + 12.4751 + 12.4752 + 12.4753 + 12.4754 + 12.4755 + 12.4756 + 12.4757 + 12.4758 + 12.4759 + 12.4760 +Feather Standards Track [Page 85] 12.4761 + 12.4762 +RFC 3977 Network News Transfer Protocol (NNTP) October 2006 12.4763 + 12.4764 + 12.4765 +8.5.3. Examples 12.4766 + 12.4767 + Example of a successful retrieval of subject lines from a range of 12.4768 + articles (3000235 has no Subject header, and 3000236 is missing): 12.4769 + 12.4770 + [C] GROUP misc.test 12.4771 + [S] 211 1234 3000234 3002322 misc.test 12.4772 + [C] HDR Subject 3000234-3000238 12.4773 + [S] 225 Headers follow 12.4774 + [S] 3000234 I am just a test article 12.4775 + [S] 3000235 12.4776 + [S] 3000237 Re: I am just a test article 12.4777 + [S] 3000238 Ditto 12.4778 + [S] . 12.4779 + 12.4780 + Example of a successful retrieval of line counts from a range of 12.4781 + articles: 12.4782 + 12.4783 + [C] GROUP misc.test 12.4784 + [S] 211 1234 3000234 3002322 misc.test 12.4785 + [C] HDR :lines 3000234-3000238 12.4786 + [S] 225 Headers follow 12.4787 + [S] 3000234 42 12.4788 + [S] 3000235 5 12.4789 + [S] 3000237 11 12.4790 + [S] 3000238 2378 12.4791 + [S] . 12.4792 + 12.4793 + Example of a successful retrieval of the subject line from an article 12.4794 + by message-id: 12.4795 + 12.4796 + [C] GROUP misc.test 12.4797 + [S] 211 1234 3000234 3002322 misc.test 12.4798 + [C] HDR subject <i.am.a.test.article@example.com> 12.4799 + [S] 225 Header information follows 12.4800 + [S] 0 I am just a test article 12.4801 + [S] . 12.4802 + 12.4803 + Example of a successful retrieval of the subject line from the 12.4804 + current article: 12.4805 + 12.4806 + [C] GROUP misc.test 12.4807 + [S] 211 1234 3000234 3002322 misc.test 12.4808 + [C] HDR subject 12.4809 + [S] 225 Header information follows 12.4810 + [S] 3000234 I am just a test article 12.4811 + [S] . 12.4812 + 12.4813 + 12.4814 + 12.4815 + 12.4816 +Feather Standards Track [Page 86] 12.4817 + 12.4818 +RFC 3977 Network News Transfer Protocol (NNTP) October 2006 12.4819 + 12.4820 + 12.4821 + Example of an unsuccessful retrieval of a header from an article by 12.4822 + message-id: 12.4823 + 12.4824 + [C] HDR subject <i.am.not.there@example.com> 12.4825 + [S] 430 No Such Article Found 12.4826 + 12.4827 + Example of an unsuccessful retrieval of headers from articles by 12.4828 + number because no newsgroup was selected first: 12.4829 + 12.4830 + [Assumes currently selected newsgroup is invalid.] 12.4831 + [C] HDR subject 300256- 12.4832 + [S] 412 No newsgroup selected 12.4833 + 12.4834 + Example of an unsuccessful retrieval of headers because the currently 12.4835 + selected newsgroup is empty: 12.4836 + 12.4837 + [C] GROUP example.empty.newsgroup 12.4838 + [S] 211 0 0 0 example.empty.newsgroup 12.4839 + [C] HDR subject 1- 12.4840 + [S] 423 No articles in that range 12.4841 + 12.4842 + Example of an unsuccessful retrieval of headers because the server 12.4843 + does not allow HDR commands for that header: 12.4844 + 12.4845 + [C] GROUP misc.test 12.4846 + [S] 211 1234 3000234 3002322 misc.test 12.4847 + [C] HDR Content-Type 3000234-3000238 12.4848 + [S] 503 HDR not permitted on Content-Type 12.4849 + 12.4850 +8.6. LIST HEADERS 12.4851 + 12.4852 +8.6.1. Usage 12.4853 + 12.4854 + Indicating capability: HDR 12.4855 + 12.4856 + Syntax 12.4857 + LIST HEADERS [MSGID|RANGE] 12.4858 + 12.4859 + Responses 12.4860 + 215 Field list follows (multi-line) 12.4861 + 12.4862 + Parameters 12.4863 + MSGID Requests list for access by message-id 12.4864 + RANGE Requests list for access by range 12.4865 + 12.4866 + 12.4867 + 12.4868 + 12.4869 + 12.4870 + 12.4871 + 12.4872 +Feather Standards Track [Page 87] 12.4873 + 12.4874 +RFC 3977 Network News Transfer Protocol (NNTP) October 2006 12.4875 + 12.4876 + 12.4877 +8.6.2. Description 12.4878 + 12.4879 + See Section 7.6.1 for general requirements of the LIST command. 12.4880 + 12.4881 + The LIST HEADERS command returns a list of fields that may be 12.4882 + retrieved using the HDR command. 12.4883 + 12.4884 + The information is returned as a multi-line data block following the 12.4885 + 215 response code and contains one line for each field name 12.4886 + (excluding the trailing colon for headers and including the leading 12.4887 + colon for metadata items). If the implementation allows any header 12.4888 + to be retrieved, it MUST NOT include any header names in the list but 12.4889 + MUST include the special entry ":" (a single colon on its own). It 12.4890 + MUST still explicitly list any metadata items that are available. 12.4891 + The order of items in the list is not significant; the server need 12.4892 + not even consistently return the same order. The list MAY be empty 12.4893 + (though in this circumstance there is little point in providing the 12.4894 + HDR command). 12.4895 + 12.4896 + An implementation that also supports the OVER command SHOULD at least 12.4897 + permit all the headers and metadata items listed in the output from 12.4898 + the LIST OVERVIEW.FMT command. 12.4899 + 12.4900 + If the server treats the first form of the HDR command (message-id 12.4901 + specified) differently from the other two forms (range specified or 12.4902 + current article number used) in respect of which headers or metadata 12.4903 + items are available, then the following apply: 12.4904 + 12.4905 + o If the MSGID argument is specified, the results MUST be those 12.4906 + available for the first form of the HDR command. 12.4907 + 12.4908 + o If the RANGE argument is specified, the results MUST be those 12.4909 + available for the second and third forms of the HDR command. 12.4910 + 12.4911 + o If no argument is specified, the results MUST be those available 12.4912 + in all forms of the HDR command (that is, it MUST only list those 12.4913 + items listed in both the previous cases). 12.4914 + 12.4915 + If the server does not treat the various forms differently, then it 12.4916 + MUST ignore any argument and always produce the same results (though 12.4917 + not necessarily always in the same order). 12.4918 + 12.4919 + If the HDR command is not implemented, the meaning of the output from 12.4920 + this command is not specified, but it must still meet the above 12.4921 + syntactic requirements. 12.4922 + 12.4923 + 12.4924 + 12.4925 + 12.4926 + 12.4927 + 12.4928 +Feather Standards Track [Page 88] 12.4929 + 12.4930 +RFC 3977 Network News Transfer Protocol (NNTP) October 2006 12.4931 + 12.4932 + 12.4933 +8.6.3. Examples 12.4934 + 12.4935 + Example of an implementation providing access to only a few headers: 12.4936 + 12.4937 + [C] LIST HEADERS 12.4938 + [S] 215 headers supported: 12.4939 + [S] Subject 12.4940 + [S] Message-ID 12.4941 + [S] Xref 12.4942 + [S] . 12.4943 + 12.4944 + Example of an implementation providing access to the same fields as 12.4945 + the first example in Section 8.4.3: 12.4946 + 12.4947 + [C] CAPABILITIES 12.4948 + [S] 101 Capability list: 12.4949 + [S] VERSION 2 12.4950 + [S] READER 12.4951 + [S] OVER 12.4952 + [S] HDR 12.4953 + [S] LIST ACTIVE NEWSGROUPS HEADERS OVERVIEW.FMT 12.4954 + [S] . 12.4955 + [C] LIST HEADERS 12.4956 + [S] 215 headers and metadata items supported: 12.4957 + [S] Date 12.4958 + [S] Distribution 12.4959 + [S] From 12.4960 + [S] Message-ID 12.4961 + [S] References 12.4962 + [S] Subject 12.4963 + [S] Xref 12.4964 + [S] :bytes 12.4965 + [S] :lines 12.4966 + [S] . 12.4967 + 12.4968 + Example of an implementation providing access to all headers: 12.4969 + 12.4970 + [C] LIST HEADERS 12.4971 + [S] 215 metadata items supported: 12.4972 + [S] : 12.4973 + [S] :lines 12.4974 + [S] :bytes 12.4975 + [S] :x-article-number 12.4976 + [S] . 12.4977 + 12.4978 + 12.4979 + 12.4980 + 12.4981 + 12.4982 + 12.4983 + 12.4984 +Feather Standards Track [Page 89] 12.4985 + 12.4986 +RFC 3977 Network News Transfer Protocol (NNTP) October 2006 12.4987 + 12.4988 + 12.4989 + Example of an implementation distinguishing the first form of the HDR 12.4990 + command from the other two forms: 12.4991 + 12.4992 + [C] LIST HEADERS RANGE 12.4993 + [S] 215 metadata items supported: 12.4994 + [S] : 12.4995 + [S] :lines 12.4996 + [S] :bytes 12.4997 + [S] . 12.4998 + [C] LIST HEADERS MSGID 12.4999 + [S] 215 headers and metadata items supported: 12.5000 + [S] Date 12.5001 + [S] Distribution 12.5002 + [S] From 12.5003 + [S] Message-ID 12.5004 + [S] References 12.5005 + [S] Subject 12.5006 + [S] :lines 12.5007 + [S] :bytes 12.5008 + [S] :x-article-number 12.5009 + [S] . 12.5010 + [C] LIST HEADERS 12.5011 + [S] 215 headers and metadata items supported: 12.5012 + [S] Date 12.5013 + [S] Distribution 12.5014 + [S] From 12.5015 + [S] Message-ID 12.5016 + [S] References 12.5017 + [S] Subject 12.5018 + [S] :lines 12.5019 + [S] :bytes 12.5020 + [S] . 12.5021 + 12.5022 + Note that :x-article-number does not appear in the last set of 12.5023 + output. 12.5024 + 12.5025 +9. Augmented BNF Syntax for NNTP 12.5026 + 12.5027 +9.1. Introduction 12.5028 + 12.5029 + Each of the following sections describes the syntax of a major 12.5030 + element of NNTP. This syntax extends and refines the descriptions 12.5031 + elsewhere in this specification and should be given precedence when 12.5032 + resolving apparent conflicts. Note that ABNF [RFC4234] strings are 12.5033 + case insensitive. Non-terminals used in several places are defined 12.5034 + in a separate section at the end. 12.5035 + 12.5036 + 12.5037 + 12.5038 + 12.5039 + 12.5040 +Feather Standards Track [Page 90] 12.5041 + 12.5042 +RFC 3977 Network News Transfer Protocol (NNTP) October 2006 12.5043 + 12.5044 + 12.5045 + Between them, the non-terminals <command-line>, <command-datastream>, 12.5046 + <command-continuation>, and <response> specify the text that flows 12.5047 + between client and server. A consistent naming scheme is used in 12.5048 + this document for the non-terminals relating to each command, and 12.5049 + SHOULD be used by the specification of registered extensions. 12.5050 + 12.5051 + For each command, the sequence is as follows: 12.5052 + 12.5053 + o The client sends an instance of <command-line>; the syntax for the 12.5054 + EXAMPLE command is <example-command>. 12.5055 + 12.5056 + o If the client is one that immediately streams data, it sends an 12.5057 + instance of <command-datastream>; the syntax for the EXAMPLE 12.5058 + command is <example-datastream>. 12.5059 + 12.5060 + o The server sends an instance of <response>. 12.5061 + 12.5062 + * The initial response line is independent of the command that 12.5063 + generated it; if the 000 response has arguments, the syntax of 12.5064 + the initial line is <response-000-content>. 12.5065 + 12.5066 + * If the response is multi-line, the initial line is followed by 12.5067 + a <multi-line-data-block>. The syntax for the contents of this 12.5068 + block after "dot-stuffing" has been removed is (for the 000 12.5069 + response to the EXAMPLE command) <example-000-ml-content> and 12.5070 + is an instance of <multi-line-response-content>. 12.5071 + 12.5072 + o While the latest response is one that indicates more data is 12.5073 + required (in general, a 3xx response): 12.5074 + 12.5075 + * the client sends an instance of <command-continuation>; the 12.5076 + syntax for the EXAMPLE continuation following a 333 response is 12.5077 + <example-333-continuation>; 12.5078 + 12.5079 + * the server sends another instance of <response>, as above. 12.5080 + 12.5081 + (There are no commands in this specification that immediately stream 12.5082 + data, but this non-terminal is defined for the convenience of 12.5083 + extensions.) 12.5084 + 12.5085 + 12.5086 + 12.5087 + 12.5088 + 12.5089 + 12.5090 + 12.5091 + 12.5092 + 12.5093 + 12.5094 + 12.5095 + 12.5096 +Feather Standards Track [Page 91] 12.5097 + 12.5098 +RFC 3977 Network News Transfer Protocol (NNTP) October 2006 12.5099 + 12.5100 + 12.5101 +9.2. Commands 12.5102 + 12.5103 + This syntax defines the non-terminal <command-line>, which represents 12.5104 + what is sent from the client to the server (see section 3.1 for 12.5105 + limits on lengths). 12.5106 + 12.5107 + command-line = command EOL 12.5108 + command = X-command 12.5109 + X-command = keyword *(WS token) 12.5110 + 12.5111 + command =/ article-command / 12.5112 + body-command / 12.5113 + capabilities-command / 12.5114 + date-command / 12.5115 + group-command / 12.5116 + hdr-command / 12.5117 + head-command / 12.5118 + help-command / 12.5119 + ihave-command / 12.5120 + last-command / 12.5121 + list-command / 12.5122 + listgroup-command / 12.5123 + mode-reader-command / 12.5124 + newgroups-command / 12.5125 + newnews-command / 12.5126 + next-command / 12.5127 + over-command / 12.5128 + post-command / 12.5129 + quit-command / 12.5130 + stat-command 12.5131 + 12.5132 + article-command = "ARTICLE" [WS article-ref] 12.5133 + body-command = "BODY" [WS article-ref] 12.5134 + capabilities-command = "CAPABILITIES" [WS keyword] 12.5135 + date-command = "DATE" 12.5136 + group-command = "GROUP" [WS newsgroup-name] 12.5137 + hdr-command = "HDR" WS header-meta-name [WS range-ref] 12.5138 + head-command = "HEAD" [WS article-ref] 12.5139 + help-command = "HELP" 12.5140 + ihave-command = "IHAVE" WS message-id 12.5141 + last-command = "LAST" 12.5142 + list-command = "LIST" [WS list-arguments] 12.5143 + listgroup-command = "LISTGROUP" [WS newsgroup-name [WS range]] 12.5144 + mode-reader-command = "MODE" WS "READER" 12.5145 + newgroups-command = "NEWGROUPS" WS date-time 12.5146 + newnews-command = "NEWNEWS" WS wildmat WS date-time 12.5147 + next-command = "NEXT" 12.5148 + over-command = "OVER" [WS range-ref] 12.5149 + 12.5150 + 12.5151 + 12.5152 +Feather Standards Track [Page 92] 12.5153 + 12.5154 +RFC 3977 Network News Transfer Protocol (NNTP) October 2006 12.5155 + 12.5156 + 12.5157 + post-command = "POST" 12.5158 + quit-command = "QUIT" 12.5159 + stat-command = "STAT" [WS article-ref] 12.5160 + 12.5161 + article-ref = article-number / message-id 12.5162 + date = date2y / date4y 12.5163 + date4y = 4DIGIT 2DIGIT 2DIGIT 12.5164 + date2y = 2DIGIT 2DIGIT 2DIGIT 12.5165 + date-time = date WS time [WS "GMT"] 12.5166 + header-meta-name = header-name / metadata-name 12.5167 + list-arguments = keyword [WS token] 12.5168 + metadata-name = ":" 1*A-NOTCOLON 12.5169 + range = article-number ["-" [article-number]] 12.5170 + range-ref = range / message-id 12.5171 + time = 2DIGIT 2DIGIT 2DIGIT 12.5172 + 12.5173 +9.3. Command Continuation 12.5174 + 12.5175 + This syntax defines the further material sent by the client in the 12.5176 + case of multi-stage commands and those that stream data. 12.5177 + 12.5178 + command-datastream = UNDEFINED 12.5179 + ; not used, provided as a hook for extensions 12.5180 + command-continuation = ihave-335-continuation / 12.5181 + post-340-continuation 12.5182 + 12.5183 + ihave-335-continuation = encoded-article 12.5184 + post-340-continuation = encoded-article 12.5185 + 12.5186 + encoded-article = multi-line-data-block 12.5187 + ; after undoing the "dot-stuffing", this MUST match <article> 12.5188 + 12.5189 +9.4. Responses 12.5190 + 12.5191 +9.4.1. Generic Responses 12.5192 + 12.5193 + This syntax defines the non-terminal <response>, which represents the 12.5194 + generic form of responses; that is, what is sent from the server to 12.5195 + the client in response to a <command> or a <command-continuation>. 12.5196 + 12.5197 + response = simple-response / multi-line-response 12.5198 + simple-response = initial-response-line 12.5199 + multi-line-response = initial-response-line multi-line-data-block 12.5200 + 12.5201 + initial-response-line = 12.5202 + initial-response-content [SP trailing-comment] CRLF 12.5203 + initial-response-content = X-initial-response-content 12.5204 + X-initial-response-content = 3DIGIT *(SP response-argument) 12.5205 + 12.5206 + 12.5207 + 12.5208 +Feather Standards Track [Page 93] 12.5209 + 12.5210 +RFC 3977 Network News Transfer Protocol (NNTP) October 2006 12.5211 + 12.5212 + 12.5213 + response-argument = 1*A-CHAR 12.5214 + trailing-comment = *U-CHAR 12.5215 + 12.5216 +9.4.2. Initial Response Line Contents 12.5217 + 12.5218 + This syntax defines the specific initial response lines for the 12.5219 + various commands in this specification (see section 3.1 for limits on 12.5220 + lengths). Only those response codes with arguments are listed. 12.5221 + 12.5222 + initial-response-content =/ response-111-content / 12.5223 + response-211-content / 12.5224 + response-220-content / 12.5225 + response-221-content / 12.5226 + response-222-content / 12.5227 + response-223-content / 12.5228 + response-401-content 12.5229 + 12.5230 + response-111-content = "111" SP date4y time 12.5231 + response-211-content = "211" 3(SP article-number) SP newsgroup-name 12.5232 + response-220-content = "220" SP article-number SP message-id 12.5233 + response-221-content = "221" SP article-number SP message-id 12.5234 + response-222-content = "222" SP article-number SP message-id 12.5235 + response-223-content = "223" SP article-number SP message-id 12.5236 + response-401-content = "401" SP capability-label 12.5237 + 12.5238 +9.4.3. Multi-line Response Contents 12.5239 + 12.5240 + This syntax defines the content of the various multi-line responses; 12.5241 + more precisely, it defines the part of the response in the multi-line 12.5242 + data block after any "dot-stuffing" has been undone. The numeric 12.5243 + portion of each non-terminal name indicates the response code that is 12.5244 + followed by this data. 12.5245 + 12.5246 + multi-line-response-content = article-220-ml-content / 12.5247 + body-222-ml-content / 12.5248 + capabilities-101-ml-content / 12.5249 + hdr-225-ml-content / 12.5250 + head-221-ml-content / 12.5251 + help-100-ml-content / 12.5252 + list-215-ml-content / 12.5253 + listgroup-211-ml-content / 12.5254 + newgroups-231-ml-content / 12.5255 + newnews-230-ml-content / 12.5256 + over-224-ml-content 12.5257 + 12.5258 + article-220-ml-content = article 12.5259 + body-222-ml-content = body 12.5260 + capabilities-101-ml-content = version-line CRLF 12.5261 + 12.5262 + 12.5263 + 12.5264 +Feather Standards Track [Page 94] 12.5265 + 12.5266 +RFC 3977 Network News Transfer Protocol (NNTP) October 2006 12.5267 + 12.5268 + 12.5269 + *(capability-line CRLF) 12.5270 + hdr-225-ml-content = *(article-number SP hdr-content CRLF) 12.5271 + head-221-ml-content = 1*header 12.5272 + help-100-ml-content = *(*U-CHAR CRLF) 12.5273 + list-215-ml-content = list-content 12.5274 + listgroup-211-ml-content = *(article-number CRLF) 12.5275 + newgroups-231-ml-content = active-groups-list 12.5276 + newnews-230-ml-content = *(message-id CRLF) 12.5277 + over-224-ml-content = *(article-number over-content CRLF) 12.5278 + 12.5279 + active-groups-list = *(newsgroup-name SPA article-number 12.5280 + SPA article-number SPA newsgroup-status CRLF) 12.5281 + hdr-content = *S-NONTAB 12.5282 + hdr-n-content = [(header-name ":" / metadata-name) SP hdr-content] 12.5283 + list-content = body 12.5284 + newsgroup-status = %x79 / %x6E / %x6D / private-status 12.5285 + over-content = 1*6(TAB hdr-content) / 12.5286 + 7(TAB hdr-content) *(TAB hdr-n-content) 12.5287 + private-status = token ; except the values in newsgroup-status 12.5288 + 12.5289 +9.5. Capability Lines 12.5290 + 12.5291 + This syntax defines the generic form of a capability line in the 12.5292 + capabilities list (see Section 3.3.1). 12.5293 + 12.5294 + capability-line = capability-entry 12.5295 + capability-entry = X-capability-entry 12.5296 + X-capability-entry = capability-label *(WS capability-argument) 12.5297 + capability-label = keyword 12.5298 + capability-argument = token 12.5299 + 12.5300 + This syntax defines the specific capability entries for the 12.5301 + capabilities in this specification. 12.5302 + 12.5303 + capability-entry =/ 12.5304 + hdr-capability / 12.5305 + ihave-capability / 12.5306 + implementation-capability / 12.5307 + list-capability / 12.5308 + mode-reader-capability / 12.5309 + newnews-capability / 12.5310 + over-capability / 12.5311 + post-capability / 12.5312 + reader-capability 12.5313 + 12.5314 + hdr-capability = "HDR" 12.5315 + ihave-capability = "IHAVE" 12.5316 + implementation-capability = "IMPLEMENTATION" *(WS token) 12.5317 + 12.5318 + 12.5319 + 12.5320 +Feather Standards Track [Page 95] 12.5321 + 12.5322 +RFC 3977 Network News Transfer Protocol (NNTP) October 2006 12.5323 + 12.5324 + 12.5325 + list-capability = "LIST" 1*(WS keyword) 12.5326 + mode-reader-capability = "MODE-READER" 12.5327 + newnews-capability = "NEWNEWS" 12.5328 + over-capability = "OVER" [WS "MSGID"] 12.5329 + post-capability = "POST" 12.5330 + reader-capability = "READER" 12.5331 + 12.5332 + version-line = "VERSION" 1*(WS version-number) 12.5333 + version-number = nzDIGIT *5DIGIT 12.5334 + 12.5335 +9.6. LIST Variants 12.5336 + 12.5337 + This section defines more specifically the keywords for the LIST 12.5338 + command and the syntax of the corresponding response contents. 12.5339 + 12.5340 + ; active 12.5341 + list-arguments =/ "ACTIVE" [WS wildmat] 12.5342 + list-content =/ list-active-content 12.5343 + list-active-content = active-groups-list 12.5344 + 12.5345 + 12.5346 + ; active.times 12.5347 + list-arguments =/ "ACTIVE.TIMES" [WS wildmat] 12.5348 + list-content =/ list-active-times-content 12.5349 + list-active-times-content = 12.5350 + *(newsgroup-name SPA 1*DIGIT SPA newsgroup-creator CRLF) 12.5351 + newsgroup-creator = U-TEXT 12.5352 + 12.5353 + 12.5354 + ; distrib.pats 12.5355 + list-arguments =/ "DISTRIB.PATS" 12.5356 + list-content =/ list-distrib-pats-content 12.5357 + list-distrib-pats-content = 12.5358 + *(1*DIGIT ":" wildmat ":" distribution CRLF) 12.5359 + distribution = token 12.5360 + 12.5361 + 12.5362 + ; headers 12.5363 + list-arguments =/ "HEADERS" [WS ("MSGID" / "RANGE")] 12.5364 + list-content =/ list-headers-content 12.5365 + list-headers-content = *(header-meta-name CRLF) / 12.5366 + *((metadata-name / ":") CRLF) 12.5367 + 12.5368 + 12.5369 + ; newsgroups 12.5370 + list-arguments =/ "NEWSGROUPS" [WS wildmat] 12.5371 + list-content =/ list-newsgroups-content 12.5372 + list-newsgroups-content = 12.5373 + 12.5374 + 12.5375 + 12.5376 +Feather Standards Track [Page 96] 12.5377 + 12.5378 +RFC 3977 Network News Transfer Protocol (NNTP) October 2006 12.5379 + 12.5380 + 12.5381 + *(newsgroup-name WS newsgroup-description CRLF) 12.5382 + newsgroup-description = S-TEXT 12.5383 + 12.5384 + 12.5385 + ; overview.fmt 12.5386 + list-arguments =/ "OVERVIEW.FMT" 12.5387 + list-content =/ list-overview-fmt-content 12.5388 + list-overview-fmt-content = "Subject:" CRLF 12.5389 + "From:" CRLF 12.5390 + "Date:" CRLF 12.5391 + "Message-ID:" CRLF 12.5392 + "References:" CRLF 12.5393 + ( ":bytes" CRLF ":lines" / "Bytes:" CRLF "Lines:") CRLF 12.5394 + *((header-name ":full" / metadata-name) CRLF) 12.5395 + 12.5396 +9.7. Articles 12.5397 + 12.5398 + This syntax defines the non-terminal <article>, which represents the 12.5399 + format of an article as described in Section 3.6. 12.5400 + 12.5401 + article = 1*header CRLF body 12.5402 + header = header-name ":" [CRLF] SP header-content CRLF 12.5403 + header-content = *(S-CHAR / [CRLF] WS) 12.5404 + body = *(*B-CHAR CRLF) 12.5405 + 12.5406 +9.8. General Non-terminals 12.5407 + 12.5408 + These non-terminals are used at various places in the syntax and are 12.5409 + collected here for convenience. A few of these non-terminals are not 12.5410 + used in this specification but are provided for the consistency and 12.5411 + convenience of extension authors. 12.5412 + 12.5413 + multi-line-data-block = content-lines termination 12.5414 + content-lines = *([content-text] CRLF) 12.5415 + content-text = (".." / B-NONDOT) *B-CHAR 12.5416 + termination = "." CRLF 12.5417 + 12.5418 + article-number = 1*16DIGIT 12.5419 + header-name = 1*A-NOTCOLON 12.5420 + keyword = ALPHA 2*(ALPHA / DIGIT / "." / "-") 12.5421 + message-id = "<" 1*248A-NOTGT ">" 12.5422 + newsgroup-name = 1*wildmat-exact 12.5423 + token = 1*P-CHAR 12.5424 + 12.5425 + wildmat = wildmat-pattern *("," ["!"] wildmat-pattern) 12.5426 + wildmat-pattern = 1*wildmat-item 12.5427 + wildmat-item = wildmat-exact / wildmat-wild 12.5428 + wildmat-exact = %x22-29 / %x2B / %x2D-3E / %x40-5A / %x5E-7E / 12.5429 + 12.5430 + 12.5431 + 12.5432 +Feather Standards Track [Page 97] 12.5433 + 12.5434 +RFC 3977 Network News Transfer Protocol (NNTP) October 2006 12.5435 + 12.5436 + 12.5437 + UTF8-non-ascii ; exclude ! * , ? [ \ ] 12.5438 + wildmat-wild = "*" / "?" 12.5439 + 12.5440 + base64 = *(4base64-char) [base64-terminal] 12.5441 + base64-char = UPPER / LOWER / DIGIT / "+" / "/" 12.5442 + base64-terminal = 2base64-char "==" / 3base64-char "=" 12.5443 + 12.5444 + ; Assorted special character sets 12.5445 + ; A- means based on US-ASCII, excluding controls and SP 12.5446 + ; P- means based on UTF-8, excluding controls and SP 12.5447 + ; U- means based on UTF-8, excluding NUL CR and LF 12.5448 + ; B- means based on bytes, excluding NUL CR and LF 12.5449 + A-CHAR = %x21-7E 12.5450 + A-NOTCOLON = %x21-39 / %x3B-7E ; exclude ":" 12.5451 + A-NOTGT = %x21-3D / %x3F-7E ; exclude ">" 12.5452 + P-CHAR = A-CHAR / UTF8-non-ascii 12.5453 + U-CHAR = CTRL / TAB / SP / A-CHAR / UTF8-non-ascii 12.5454 + U-NONTAB = CTRL / SP / A-CHAR / UTF8-non-ascii 12.5455 + U-TEXT = P-CHAR *U-CHAR 12.5456 + B-CHAR = CTRL / TAB / SP / %x21-FF 12.5457 + B-NONDOT = CTRL / TAB / SP / %x21-2D / %x2F-FF ; exclude "." 12.5458 + 12.5459 + ALPHA = UPPER / LOWER ; use only when case-insensitive 12.5460 + CR = %x0D 12.5461 + CRLF = CR LF 12.5462 + CTRL = %x01-08 / %x0B-0C / %x0E-1F 12.5463 + DIGIT = %x30-39 12.5464 + nzDIGIT = %x31-39 12.5465 + EOL = *(SP / TAB) CRLF 12.5466 + LF = %x0A 12.5467 + LOWER = %x61-7A 12.5468 + SP = %x20 12.5469 + SPA = 1*SP 12.5470 + TAB = %x09 12.5471 + UPPER = %x41-5A 12.5472 + UTF8-non-ascii = UTF8-2 / UTF8-3 / UTF8-4 12.5473 + UTF8-2 = %xC2-DF UTF8-tail 12.5474 + UTF8-3 = %xE0 %xA0-BF UTF8-tail / %xE1-EC 2UTF8-tail / 12.5475 + %xED %x80-9F UTF8-tail / %xEE-EF 2UTF8-tail 12.5476 + UTF8-4 = %xF0 %x90-BF 2UTF8-tail / %xF1-F3 3UTF8-tail / 12.5477 + %xF4 %x80-8F 2UTF8-tail 12.5478 + UTF8-tail = %x80-BF 12.5479 + WS = 1*(SP / TAB) 12.5480 + 12.5481 + The following non-terminals require special consideration. They 12.5482 + represent situations where material SHOULD be restricted to UTF-8, 12.5483 + but implementations MUST be able to cope with other character 12.5484 + encodings. Therefore, there are two sets of definitions for them. 12.5485 + 12.5486 + 12.5487 + 12.5488 +Feather Standards Track [Page 98] 12.5489 + 12.5490 +RFC 3977 Network News Transfer Protocol (NNTP) October 2006 12.5491 + 12.5492 + 12.5493 + Implementations MUST accept any content that meets this syntax: 12.5494 + 12.5495 + S-CHAR = %x21-FF 12.5496 + S-NONTAB = CTRL / SP / S-CHAR 12.5497 + S-TEXT = (CTRL / S-CHAR) *B-CHAR 12.5498 + 12.5499 + and MAY pass such content on unaltered. 12.5500 + 12.5501 + When generating new content or re-encoding existing content, 12.5502 + implementations SHOULD conform to this syntax: 12.5503 + 12.5504 + S-CHAR = P-CHAR 12.5505 + S-NONTAB = U-NONTAB 12.5506 + S-TEXT = U-TEXT 12.5507 + 12.5508 +9.9. Extensions and Validation 12.5509 + 12.5510 + The specification of a registered extension MUST include formal 12.5511 + syntax that defines additional forms for the following non-terminals: 12.5512 + 12.5513 + command 12.5514 + for each new command other than a variant of the LIST command - 12.5515 + the syntax of each command MUST be compatible with the definition 12.5516 + of <X-command>; 12.5517 + 12.5518 + command-datastream 12.5519 + for each new command that immediately streams data; 12.5520 + 12.5521 + command-continuation 12.5522 + for each new command that sends further material after the initial 12.5523 + command line - the syntax of each continuation MUST be exactly 12.5524 + what is sent to the server, including any escape mechanisms such 12.5525 + as "dot-stuffing"; 12.5526 + 12.5527 + initial-response-content 12.5528 + for each new response code that has arguments - the syntax of each 12.5529 + response MUST be compatible with the definition of <X-initial- 12.5530 + response-content>; 12.5531 + 12.5532 + multi-line-response-content 12.5533 + for each new response code that has a multi-line response - the 12.5534 + syntax MUST show the response after the lines containing the 12.5535 + response code and the terminating octet have been removed and any 12.5536 + "dot-stuffing" undone; 12.5537 + 12.5538 + capability-entry 12.5539 + for each new capability label - the syntax of each entry MUST be 12.5540 + compatible with the definition of <X-capability-entry>; 12.5541 + 12.5542 + 12.5543 + 12.5544 +Feather Standards Track [Page 99] 12.5545 + 12.5546 +RFC 3977 Network News Transfer Protocol (NNTP) October 2006 12.5547 + 12.5548 + 12.5549 + list-arguments 12.5550 + for each new variant of the LIST command - the syntax of each 12.5551 + entry MUST be compatible with the definition of <X-command>; 12.5552 + 12.5553 + list-content 12.5554 + for each new variant of the LIST command - the syntax MUST show 12.5555 + the response after the lines containing the 215 response code and 12.5556 + the terminating octet have been removed and any "dot-stuffing" 12.5557 + undone. 12.5558 + 12.5559 + The =/ notation of ABNF [RFC4234] and the naming conventions 12.5560 + described in Section 9.1 SHOULD be used for this. 12.5561 + 12.5562 + When the syntax in this specification, or syntax based on it, is 12.5563 + validated, it should be noted that: 12.5564 + 12.5565 + o the non-terminals <command-line>, <command-datastream>, 12.5566 + <command-continuation>, <response>, and 12.5567 + <multi-line-response-content> describe basic concepts of the 12.5568 + protocol and are not referred to by any other rule; 12.5569 + 12.5570 + o the non-terminal <base64> is provided for the convenience of 12.5571 + extension authors and is not referred to by any rule in this 12.5572 + specification; 12.5573 + 12.5574 + o for the reasons given above, the non-terminals <S-CHAR>, 12.5575 + <S-NONTAB>, and <S-TEXT> each have two definitions; and 12.5576 + 12.5577 + o the non-terminal <UNDEFINED> is deliberately not defined. 12.5578 + 12.5579 +10. Internationalisation Considerations 12.5580 + 12.5581 +10.1. Introduction and Historical Situation 12.5582 + 12.5583 + RFC 977 [RFC977] was written at a time when internationalisation was 12.5584 + not seen as a significant issue. As such, it was written on the 12.5585 + assumption that all communication would be in ASCII and use only a 12.5586 + 7-bit transport layer, although in practice just about all known 12.5587 + implementations are 8-bit clean. 12.5588 + 12.5589 + Since then, Usenet and NNTP have spread throughout the world. In the 12.5590 + absence of standards for handling the issues of language and 12.5591 + character sets, countries, newsgroup hierarchies, and individuals 12.5592 + have found a variety of solutions that work for them but that are not 12.5593 + necessarily appropriate elsewhere. For example, some have adopted a 12.5594 + default 8-bit character set appropriate to their needs (such as 12.5595 + ISO/IEC 8859-1 in Western Europe or KOI-8 in Russia), others have 12.5596 + used ASCII (either US-ASCII or national variants) in headers but 12.5597 + 12.5598 + 12.5599 + 12.5600 +Feather Standards Track [Page 100] 12.5601 + 12.5602 +RFC 3977 Network News Transfer Protocol (NNTP) October 2006 12.5603 + 12.5604 + 12.5605 + local 16-bit character sets in article bodies, and still others have 12.5606 + gone for a combination of MIME [RFC2045] and UTF-8. With the 12.5607 + increased use of MIME in email, it is becoming more common to find 12.5608 + NNTP articles containing MIME headers that identify the character set 12.5609 + of the body, but this is far from universal. 12.5610 + 12.5611 + The resulting confusion does not help interoperability. 12.5612 + 12.5613 + One point that has been generally accepted is that articles can 12.5614 + contain octets with the top bit set, and NNTP is only expected to 12.5615 + operate on 8-bit clean transport paths. 12.5616 + 12.5617 +10.2. This Specification 12.5618 + 12.5619 + Part of the role of this present specification is to eliminate this 12.5620 + confusion and promote interoperability as far as possible. At the 12.5621 + same time, it is necessary to accept the existence of the present 12.5622 + situation and not break existing implementations and arrangements 12.5623 + gratuitously, even if they are less than optimal. Therefore, the 12.5624 + current practice described above has been taken into consideration in 12.5625 + producing this specification. 12.5626 + 12.5627 + This specification extends NNTP from US-ASCII [ANSI1986] to UTF-8 12.5628 + [RFC3629]. Except in the two areas discussed below, UTF-8 (which is 12.5629 + a superset of US-ASCII) is mandatory, and implementations MUST NOT 12.5630 + use any other encoding. 12.5631 + 12.5632 + Firstly, the use of MIME for article headers and bodies is strongly 12.5633 + recommended. However, given widely divergent existing practices, an 12.5634 + attempt to require a particular encoding and tagging standard would 12.5635 + be premature at this time. Accordingly, this specification allows 12.5636 + the use of arbitrary 8-bit data in articles subject to the following 12.5637 + requirements and recommendations. 12.5638 + 12.5639 + o The names of headers (e.g., "From" or "Subject") MUST be in 12.5640 + US-ASCII. 12.5641 + 12.5642 + o Header values SHOULD use US-ASCII or an encoding based on it, such 12.5643 + as RFC 2047 [RFC2047], until such time as another approach has 12.5644 + been standardised. At present, 8-bit encodings (including UTF-8) 12.5645 + SHOULD NOT be used because they are likely to cause 12.5646 + interoperability problems. 12.5647 + 12.5648 + o The character set of article bodies SHOULD be indicated in the 12.5649 + article headers, and this SHOULD be done in accordance with MIME. 12.5650 + 12.5651 + o Where an article is obtained from an external source, an 12.5652 + implementation MAY pass it on and derive data from it (such as the 12.5653 + 12.5654 + 12.5655 + 12.5656 +Feather Standards Track [Page 101] 12.5657 + 12.5658 +RFC 3977 Network News Transfer Protocol (NNTP) October 2006 12.5659 + 12.5660 + 12.5661 + response to the HDR command), even though the article or the data 12.5662 + does not meet the above requirements. Implementations MUST 12.5663 + transfer such articles and data correctly and unchanged; they MUST 12.5664 + NOT attempt to convert or re-encode the article or derived data. 12.5665 + (Nevertheless, a client or server MAY elect not to post or forward 12.5666 + the article if, after further examination of the article, it deems 12.5667 + it inappropriate to do so.) 12.5668 + 12.5669 + This requirement affects the ARTICLE (Section 6.2.1), BODY 12.5670 + (Section 6.2.3), HDR (Section 8.5), HEAD (Section 6.2.2), IHAVE 12.5671 + (Section 6.3.2), OVER (Section 8.3), and POST (Section 6.3.1) 12.5672 + commands. 12.5673 + 12.5674 + Secondly, the following requirements are placed on the newsgroups 12.5675 + list returned by the LIST NEWSGROUPS command (Section 7.6.6): 12.5676 + 12.5677 + o Although this specification allows UTF-8 for newsgroup names, they 12.5678 + SHOULD be restricted to US-ASCII until a successor to RFC 1036 12.5679 + [RFC1036] standardises another approach. 8-bit encodings SHOULD 12.5680 + NOT be used because they are likely to cause interoperability 12.5681 + problems. 12.5682 + 12.5683 + o The newsgroup description SHOULD be in US-ASCII or UTF-8 unless 12.5684 + and until a successor to RFC 1036 standardises other encoding 12.5685 + arrangements. 8-bit encodings other than UTF-8 SHOULD NOT be used 12.5686 + because they are likely to cause interoperability problems. 12.5687 + 12.5688 + o Implementations that obtain this data from an external source MUST 12.5689 + handle it correctly even if it does not meet the above 12.5690 + requirements. Implementations (in particular, clients) MUST 12.5691 + handle such data correctly. 12.5692 + 12.5693 +10.3. Outstanding Issues 12.5694 + 12.5695 + While the primary use of NNTP is for transmitting articles that 12.5696 + conform to RFC 1036 (Netnews articles), it is also used for other 12.5697 + formats (see Appendix A). It is therefore most appropriate that 12.5698 + internationalisation issues related to article formats be addressed 12.5699 + in the relevant specifications. For Netnews articles, this is any 12.5700 + successor to RFC 1036. For email messages, it is RFC 2822 [RFC2822]. 12.5701 + 12.5702 + Of course, any article transmitted via NNTP needs to conform to this 12.5703 + specification as well. 12.5704 + 12.5705 + Restricting newsgroup names to UTF-8 is not a complete solution. In 12.5706 + particular, when new newsgroup names are created or a user is asked 12.5707 + to enter a newsgroup name, some scheme of canonicalisation will need 12.5708 + to take place. This specification does not attempt to define that 12.5709 + 12.5710 + 12.5711 + 12.5712 +Feather Standards Track [Page 102] 12.5713 + 12.5714 +RFC 3977 Network News Transfer Protocol (NNTP) October 2006 12.5715 + 12.5716 + 12.5717 + canonicalization; further work is needed in this area, in conjunction 12.5718 + with the article format specifications. Until such specifications 12.5719 + are published, implementations SHOULD match newsgroup names octet by 12.5720 + octet. It is anticipated that any approved scheme will be applied 12.5721 + "at the edges", and therefore octet-by-octet comparison will continue 12.5722 + to apply to most, if not all, uses of newsgroup names in NNTP. 12.5723 + 12.5724 + In the meantime, any implementation experimenting with UTF-8 12.5725 + newsgroup names is strongly cautioned that a future specification may 12.5726 + require that those names be canonicalized when used with NNTP in a 12.5727 + way that is not compatible with their experiments. 12.5728 + 12.5729 + Since the primary use of NNTP is with Netnews, and since newsgroup 12.5730 + descriptions are normally distributed through specially formatted 12.5731 + articles, it is recommended that the internationalisation issues 12.5732 + related to them be addressed in any successor to RFC 1036. 12.5733 + 12.5734 +11. IANA Considerations 12.5735 + 12.5736 + This specification requires IANA to keep a registry of capability 12.5737 + labels. The initial contents of this registry are specified in 12.5738 + Section 3.3.4. As described in Section 3.3.3, labels beginning with 12.5739 + X are reserved for private use, while all other names are expected to 12.5740 + be associated with a specification in an RFC on the standards track 12.5741 + or defining an IESG-approved experimental protocol. 12.5742 + 12.5743 + Different entries in the registry MUST use different capability 12.5744 + labels. 12.5745 + 12.5746 + Different entries in the registry MUST NOT use the same command name. 12.5747 + For this purpose, variants distinguished by a second or subsequent 12.5748 + keyword (e.g., "LIST HEADERS" and "LIST OVERVIEW.FMT") count as 12.5749 + different commands. If there is a need for two extensions to use the 12.5750 + same command, a single harmonised specification MUST be registered. 12.5751 + 12.5752 +12. Security Considerations 12.5753 + 12.5754 + This section is meant to inform application developers, information 12.5755 + providers, and users of the security limitations in NNTP as described 12.5756 + by this document. The discussion does not include definitive 12.5757 + solutions to the problems revealed, though it does make some 12.5758 + suggestions for reducing security risks. 12.5759 + 12.5760 + 12.5761 + 12.5762 + 12.5763 + 12.5764 + 12.5765 + 12.5766 + 12.5767 + 12.5768 +Feather Standards Track [Page 103] 12.5769 + 12.5770 +RFC 3977 Network News Transfer Protocol (NNTP) October 2006 12.5771 + 12.5772 + 12.5773 +12.1. Personal and Proprietary Information 12.5774 + 12.5775 + NNTP, because it was created to distribute network news articles, 12.5776 + will forward whatever information is stored in those articles. 12.5777 + Specification of that information is outside this scope of this 12.5778 + document, but it is likely that some personal and/or proprietary 12.5779 + information is available in some of those articles. It is very 12.5780 + important that designers and implementers provide informative 12.5781 + warnings to users so that personal and/or proprietary information in 12.5782 + material that is added automatically to articles (e.g., in headers) 12.5783 + is not disclosed inadvertently. Additionally, effective and easily 12.5784 + understood mechanisms to manage the distribution of news articles 12.5785 + SHOULD be provided to NNTP Server administrators, so that they are 12.5786 + able to report with confidence the likely spread of any particular 12.5787 + set of news articles. 12.5788 + 12.5789 +12.2. Abuse of Server Log Information 12.5790 + 12.5791 + A server is in the position to save session data about a user's 12.5792 + requests that might identify their reading patterns or subjects of 12.5793 + interest. This information is clearly confidential in nature, and 12.5794 + its handling can be constrained by law in certain countries. People 12.5795 + using this protocol to provide data are responsible for ensuring that 12.5796 + such material is not distributed without the permission of any 12.5797 + individuals that are identifiable by the published results. 12.5798 + 12.5799 +12.3. Weak Authentication and Access Control 12.5800 + 12.5801 + There is no user-based or token-based authentication in the basic 12.5802 + NNTP specification. Access is normally controlled by server 12.5803 + configuration files. Those files specify access by using domain 12.5804 + names or IP addresses. However, this specification does permit the 12.5805 + creation of extensions to NNTP for such purposes; one such extension 12.5806 + is [NNTP-AUTH]. While including such mechanisms is optional, doing 12.5807 + so is strongly encouraged. 12.5808 + 12.5809 + Other mechanisms are also available. For example, a proxy server 12.5810 + could be put in place that requires authentication before connecting 12.5811 + via the proxy to the NNTP server. 12.5812 + 12.5813 +12.4. DNS Spoofing 12.5814 + 12.5815 + Many existing NNTP implementations authorize incoming connections by 12.5816 + checking the IP address of that connection against the IP addresses 12.5817 + obtained via DNS lookups of lists of domain names given in local 12.5818 + configuration files. Servers that use this type of authentication 12.5819 + and clients that find a server by doing a DNS lookup of the server 12.5820 + name rely very heavily on the Domain Name Service, and are thus 12.5821 + 12.5822 + 12.5823 + 12.5824 +Feather Standards Track [Page 104] 12.5825 + 12.5826 +RFC 3977 Network News Transfer Protocol (NNTP) October 2006 12.5827 + 12.5828 + 12.5829 + generally prone to security attacks based on the deliberate 12.5830 + misassociation of IP addresses and DNS names. Clients and servers 12.5831 + need to be cautious in assuming the continuing validity of an IP 12.5832 + number/DNS name association. 12.5833 + 12.5834 + In particular, NNTP clients and servers SHOULD rely on their name 12.5835 + resolver for confirmation of an IP number/DNS name association, 12.5836 + rather than cache the result of previous host name lookups. Many 12.5837 + platforms already can cache host name lookups locally when 12.5838 + appropriate, and they SHOULD be configured to do so. It is proper 12.5839 + for these lookups to be cached, however, only when the TTL (Time To 12.5840 + Live) information reported by the name server makes it likely that 12.5841 + the cached information will remain useful. 12.5842 + 12.5843 + If NNTP clients or servers cache the results of host name lookups in 12.5844 + order to achieve a performance improvement, they MUST observe the TTL 12.5845 + information reported by DNS. If NNTP clients or servers do not 12.5846 + observe this rule, they could be spoofed when a previously accessed 12.5847 + server's IP address changes. As network renumbering is expected to 12.5848 + become increasingly common, the possibility of this form of attack 12.5849 + will increase. Observing this requirement thus reduces this 12.5850 + potential security vulnerability. 12.5851 + 12.5852 + This requirement also improves the load-balancing behaviour of 12.5853 + clients for replicated servers using the same DNS name and reduces 12.5854 + the likelihood of a user's experiencing failure in accessing sites 12.5855 + that use that strategy. 12.5856 + 12.5857 +12.5. UTF-8 Issues 12.5858 + 12.5859 + UTF-8 [RFC3629] permits only certain sequences of octets and 12.5860 + designates others as either malformed or "illegal". The Unicode 12.5861 + standard identifies a number of security issues related to illegal 12.5862 + sequences and forbids their generation by conforming implementations. 12.5863 + 12.5864 + Implementations of this specification MUST NOT generate malformed or 12.5865 + illegal sequences and SHOULD detect them and take some appropriate 12.5866 + action. This could include the following: 12.5867 + 12.5868 + o Generating a 501 response code. 12.5869 + 12.5870 + o Replacing such sequences by the sequence %xEF.BF.BD, which encodes 12.5871 + the "replacement character" U+FFFD. 12.5872 + 12.5873 + o Closing the connection. 12.5874 + 12.5875 + o Replacing such sequences by a "guessed" valid sequence (based on 12.5876 + properties of the UTF-8 encoding). 12.5877 + 12.5878 + 12.5879 + 12.5880 +Feather Standards Track [Page 105] 12.5881 + 12.5882 +RFC 3977 Network News Transfer Protocol (NNTP) October 2006 12.5883 + 12.5884 + 12.5885 + In the last case, the implementation MUST ensure that any replacement 12.5886 + cannot be used to bypass validity or security checks. For example, 12.5887 + the illegal sequence %xC0.A0 is an over-long encoding for space 12.5888 + (%x20). If it is replaced by the correct encoding in a command line, 12.5889 + this needs to happen before the command line is parsed into 12.5890 + individual arguments. If the replacement came after parsing, it 12.5891 + would be possible to generate an argument with an embedded space, 12.5892 + which is forbidden. Use of the "replacement character" does not have 12.5893 + this problem, since it is permitted wherever non-US-ASCII characters 12.5894 + are. Implementations SHOULD use one of the first two solutions where 12.5895 + the general structure of the NNTP stream remains intact and SHOULD 12.5896 + close the connection if it is no longer possible to parse it 12.5897 + sensibly. 12.5898 + 12.5899 +12.6. Caching of Capability Lists 12.5900 + 12.5901 + The CAPABILITIES command provides a capability list, which is 12.5902 + information about the current capabilities of the server. Whenever 12.5903 + there is a relevant change to the server state, the results of this 12.5904 + command are required to change accordingly. 12.5905 + 12.5906 + In most situations, the capabilities list in a given server state 12.5907 + will not change from session to session; for example, a given 12.5908 + extension will be installed permanently on a server. Some clients 12.5909 + may therefore wish to remember which extensions a server supports to 12.5910 + avoid the delay of an additional command and response, particularly 12.5911 + if they open multiple connections in the same session. 12.5912 + 12.5913 + However, information about extensions related to security and privacy 12.5914 + MUST NOT be cached, since this could allow a variety of attacks. 12.5915 + 12.5916 + For example, consider a server that permits the use of cleartext 12.5917 + passwords on links that are encrypted but not otherwise: 12.5918 + 12.5919 + [Initial connection set-up completed.] 12.5920 + [S] 200 NNTP Service Ready, posting permitted 12.5921 + [C] CAPABILITIES 12.5922 + [S] 101 Capability list: 12.5923 + [S] VERSION 2 12.5924 + [S] READER 12.5925 + [S] NEWNEWS 12.5926 + [S] POST 12.5927 + [S] XENCRYPT 12.5928 + [S] LIST ACTIVE NEWSGROUPS 12.5929 + [S] . 12.5930 + [C] XENCRYPT 12.5931 + [Client and server negotiate encryption on the link] 12.5932 + [S] 283 Encrypted link established 12.5933 + 12.5934 + 12.5935 + 12.5936 +Feather Standards Track [Page 106] 12.5937 + 12.5938 +RFC 3977 Network News Transfer Protocol (NNTP) October 2006 12.5939 + 12.5940 + 12.5941 + [C] CAPABILITIES 12.5942 + [S] 101 Capability list: 12.5943 + [S] VERSION 2 12.5944 + [S] READER 12.5945 + [S] NEWNEWS 12.5946 + [S] POST 12.5947 + [S] XSECRET 12.5948 + [S] LIST ACTIVE NEWSGROUPS 12.5949 + [S] . 12.5950 + [C] XSECRET fred flintstone 12.5951 + [S] 290 Password for fred accepted 12.5952 + 12.5953 + If the client caches the last capabilities list, then on the next 12.5954 + session it will attempt to use XSECRET on an unencrypted link: 12.5955 + 12.5956 + [Initial connection set-up completed.] 12.5957 + [S] 200 NNTP Service Ready, posting permitted 12.5958 + [C] XSECRET fred flintstone 12.5959 + [S] 483 Only permitted on secure links 12.5960 + 12.5961 + This exposes the password to any eavesdropper. While the primary 12.5962 + cause of this is passing a secret without first checking the security 12.5963 + of the link, caching of capability lists can increase the risk. 12.5964 + 12.5965 + Any security extension should include requirements to check the 12.5966 + security state of the link in a manner appropriate to that extension. 12.5967 + 12.5968 + Caching should normally only be considered for anonymous clients that 12.5969 + do not use any security or privacy extensions and for which the time 12.5970 + required for an additional command and response is a noticeable 12.5971 + issue. 12.5972 + 12.5973 +13. Acknowledgements 12.5974 + 12.5975 + This document is the result of much effort by the present and past 12.5976 + members of the NNTP Working Group, chaired by Russ Allbery and Ned 12.5977 + Freed. It could not have been produced without them. 12.5978 + 12.5979 + The author acknowledges the original authors of NNTP as documented in 12.5980 + RFC 977 [RFC977]: Brian Kantor and Phil Lapsey. 12.5981 + 12.5982 + The author gratefully acknowledges the following: 12.5983 + 12.5984 + o The work of the NNTP committee chaired by Eliot Lear. The 12.5985 + organization of this document was influenced by the last available 12.5986 + version from this working group. A special thanks to Eliot for 12.5987 + generously providing the original machine-readable sources for 12.5988 + that document. 12.5989 + 12.5990 + 12.5991 + 12.5992 +Feather Standards Track [Page 107] 12.5993 + 12.5994 +RFC 3977 Network News Transfer Protocol (NNTP) October 2006 12.5995 + 12.5996 + 12.5997 + o The work of the DRUMS working group, specifically RFC 1869 12.5998 + [RFC1869], that drove the original thinking that led to the 12.5999 + CAPABILITIES command and the extensions mechanism detailed in this 12.6000 + document. 12.6001 + 12.6002 + o The authors of RFC 2616 [RFC2616] for providing specific and 12.6003 + relevant examples of security issues that should be considered for 12.6004 + HTTP. Since many of the same considerations exist for NNTP, those 12.6005 + examples that are relevant have been included here with some minor 12.6006 + rewrites. 12.6007 + 12.6008 + o The comments and additional information provided by the following 12.6009 + individuals in preparing one or more of the progenitors of this 12.6010 + document: 12.6011 + 12.6012 + Russ Allbery <rra@stanford.edu> 12.6013 + Wayne Davison <davison@armory.com> 12.6014 + Chris Lewis <clewis@bnr.ca> 12.6015 + Tom Limoncelli <tal@mars.superlink.net> 12.6016 + Eric Schnoebelen <eric@egsner.cirr.com> 12.6017 + Rich Salz <rsalz@osf.org> 12.6018 + 12.6019 + This work was motivated by the work of various news reader authors 12.6020 + and news server authors, including those listed below: 12.6021 + 12.6022 + Rick Adams 12.6023 + Original author of the NNTP extensions to the RN news reader and 12.6024 + last maintainer of Bnews. 12.6025 + 12.6026 + Stan Barber 12.6027 + Original author of the NNTP extensions to the news readers that 12.6028 + are part of Bnews. 12.6029 + 12.6030 + Geoff Collyer 12.6031 + Original author of the OVERVIEW database proposal and one of the 12.6032 + original authors of CNEWS. 12.6033 + 12.6034 + Dan Curry 12.6035 + Original author of the xvnews news reader. 12.6036 + 12.6037 + Wayne Davison 12.6038 + Author of the first threading extensions to the RN news reader 12.6039 + (commonly called TRN). 12.6040 + 12.6041 + Geoff Huston 12.6042 + Original author of ANU NEWS. 12.6043 + 12.6044 + 12.6045 + 12.6046 + 12.6047 + 12.6048 +Feather Standards Track [Page 108] 12.6049 + 12.6050 +RFC 3977 Network News Transfer Protocol (NNTP) October 2006 12.6051 + 12.6052 + 12.6053 + Phil Lapsey 12.6054 + Original author of the UNIX reference implementation for NNTP. 12.6055 + 12.6056 + Iain Lea 12.6057 + Original maintainer of the TIN news reader. 12.6058 + 12.6059 + Chris Lewis 12.6060 + First known implementer of the AUTHINFO GENERIC extension. 12.6061 + 12.6062 + Rich Salz 12.6063 + Original author of INN. 12.6064 + 12.6065 + Henry Spencer 12.6066 + One of the original authors of CNEWS. 12.6067 + 12.6068 + Kim Storm 12.6069 + Original author of the NN news reader. 12.6070 + 12.6071 + Other people who contributed to this document include: 12.6072 + 12.6073 + Matthias Andree 12.6074 + Greg Andruk 12.6075 + Daniel Barclay 12.6076 + Maurizio Codogno 12.6077 + Mark Crispin 12.6078 + Andrew Gierth 12.6079 + Juergen Helbing 12.6080 + Scott Hollenbeck 12.6081 + Urs Janssen 12.6082 + Charles Lindsey 12.6083 + Ade Lovett 12.6084 + David Magda 12.6085 + Ken Murchison 12.6086 + Francois Petillon 12.6087 + Peter Robinson 12.6088 + Rob Siemborski 12.6089 + Howard Swinehart 12.6090 + Ruud van Tol 12.6091 + Jeffrey Vinocur 12.6092 + Erik Warmelink 12.6093 + 12.6094 + The author thanks them all and apologises to anyone omitted. 12.6095 + 12.6096 + Finally, the present author gratefully acknowledges the vast amount 12.6097 + of work put into previous versions by the previous author: 12.6098 + 12.6099 + Stan Barber <sob@academ.com> 12.6100 + 12.6101 + 12.6102 + 12.6103 + 12.6104 +Feather Standards Track [Page 109] 12.6105 + 12.6106 +RFC 3977 Network News Transfer Protocol (NNTP) October 2006 12.6107 + 12.6108 + 12.6109 +14. References 12.6110 + 12.6111 +14.1. Normative References 12.6112 + 12.6113 + [ANSI1986] American National Standards Institute, "Coded Character 12.6114 + Set - 7-bit American Standard Code for Information 12.6115 + Interchange", ANSI X3.4, 1986. 12.6116 + 12.6117 + [RFC977] Kantor, B. and P. Lapsley, "Network News Transfer 12.6118 + Protocol", RFC 977, February 1986. 12.6119 + 12.6120 + [RFC2045] Freed, N. and N. Borenstein, "Multipurpose Internet 12.6121 + Mail Extensions (MIME) Part One: Format of Internet 12.6122 + Message Bodies", RFC 2045, November 1996. 12.6123 + 12.6124 + [RFC2047] Moore, K., "MIME (Multipurpose Internet Mail 12.6125 + Extensions) Part Three: Message Header Extensions for 12.6126 + Non-ASCII Text", RFC 2047, November 1996. 12.6127 + 12.6128 + [RFC2119] Bradner, S., "Key words for use in RFCs to Indicate 12.6129 + Requirement Levels", BCP 14, RFC 2119, March 1997. 12.6130 + 12.6131 + [RFC3629] Yergeau, F., "UTF-8, a transformation format of ISO 12.6132 + 10646", STD 63, RFC 3629, November 2003. 12.6133 + 12.6134 + [RFC4234] Crocker, D., Ed. and P. Overell, "Augmented BNF for 12.6135 + Syntax Specifications: ABNF", RFC 4234, October 2005. 12.6136 + 12.6137 + [RFC4648] Josefsson, S., "The Base16, Base32, and Base64 Data 12.6138 + Encodings", RFC 4648, October 2006. 12.6139 + 12.6140 + [TF.686-1] International Telecommunications Union - Radio, 12.6141 + "Glossary, ITU-R Recommendation TF.686-1", 12.6142 + ITU-R Recommendation TF.686-1, October 1997. 12.6143 + 12.6144 +14.2. Informative References 12.6145 + 12.6146 + [NNTP-AUTH] Vinocur, J., Murchison, K., and C. Newman, "Network 12.6147 + News Transfer Protocol (NNTP) Extension for 12.6148 + Authentication", 12.6149 + RFC 4643, October 2006. 12.6150 + 12.6151 + [NNTP-STREAM] Vinocur, J. and K. Murchison, "Network News Transfer 12.6152 + Protocol (NNTP) Extension for Streaming Feeds", 12.6153 + RFC 4644, October 2006. 12.6154 + 12.6155 + 12.6156 + 12.6157 + 12.6158 + 12.6159 + 12.6160 +Feather Standards Track [Page 110] 12.6161 + 12.6162 +RFC 3977 Network News Transfer Protocol (NNTP) October 2006 12.6163 + 12.6164 + 12.6165 + [NNTP-TLS] Murchison, K., Vinocur, J., and C. Newman, "Using 12.6166 + Transport Layer Security (TLS) with Network News 12.6167 + Transfer Protocol (NNTP)", RFC 4642, October 2006. 12.6168 + 12.6169 + [RFC1036] Horton, M. and R. Adams, "Standard for interchange of 12.6170 + USENET messages", RFC 1036, December 1987. 12.6171 + 12.6172 + [RFC1305] Mills, D., "Network Time Protocol (Version 3) 12.6173 + Specification, Implementation and Analysis", RFC 1305, 12.6174 + March 1992. 12.6175 + 12.6176 + [RFC1869] Klensin, J., Freed, N., Rose, M., Stefferud, E., and D. 12.6177 + Crocker, "SMTP Service Extensions", STD 10, RFC 1869, 12.6178 + November 1995. 12.6179 + 12.6180 + [RFC2616] Fielding, R., Gettys, J., Mogul, J., Frystyk, H., 12.6181 + Masinter, L., Leach, P., and T. Berners-Lee, "Hypertext 12.6182 + Transfer Protocol -- HTTP/1.1", RFC 2616, June 1999. 12.6183 + 12.6184 + [RFC2629] Rose, M., "Writing I-Ds and RFCs using XML", RFC 2629, 12.6185 + June 1999. 12.6186 + 12.6187 + [RFC2822] Resnick, P., "Internet Message Format", RFC 2822, April 12.6188 + 2001. 12.6189 + 12.6190 + [RFC2980] Barber, S., "Common NNTP Extensions", RFC 2980, October 12.6191 + 2000. 12.6192 + 12.6193 + [ROBE1995] Robertson, R., "FAQ: Overview database / NOV General 12.6194 + Information", January 1995. 12.6195 + 12.6196 + There is no definitive copy of this document known to 12.6197 + the author. It was previously posted as the Usenet 12.6198 + article <news:nov-faq-1-930909720@agate.Berkeley.EDU> 12.6199 + 12.6200 + [SALZ1992] Salz, R., "Manual Page for wildmat(3) from the INN 1.4 12.6201 + distribution, Revision 1.10", April 1992. 12.6202 + 12.6203 + There is no definitive copy of this document known to 12.6204 + the author. 12.6205 + 12.6206 + 12.6207 + 12.6208 + 12.6209 + 12.6210 + 12.6211 + 12.6212 + 12.6213 + 12.6214 + 12.6215 + 12.6216 +Feather Standards Track [Page 111] 12.6217 + 12.6218 +RFC 3977 Network News Transfer Protocol (NNTP) October 2006 12.6219 + 12.6220 + 12.6221 +Appendix A. Interaction with Other Specifications 12.6222 + 12.6223 + NNTP is most often used for transferring articles that conform to 12.6224 + RFC 1036 [RFC1036] (such articles are called "Netnews articles" 12.6225 + here). It is also sometimes used for transferring email messages 12.6226 + that conform to RFC 2822 [RFC2822] (such articles are called "email 12.6227 + articles" here). In this situation, articles must conform both to 12.6228 + this specification and to that other one; this appendix describes 12.6229 + some relevant issues. 12.6230 + 12.6231 +A.1. Header Folding 12.6232 + 12.6233 + NNTP allows a header line to be folded (by inserting a CRLF pair) 12.6234 + before any space or TAB character. 12.6235 + 12.6236 + Both email and Netnews articles are required to have at least one 12.6237 + octet other than space or TAB on each header line. Thus, folding can 12.6238 + only happen at one point in each sequence of consecutive spaces or 12.6239 + TABs. Netnews articles are further required to have the header name, 12.6240 + colon, and following space all on the first line; folding may only 12.6241 + happen beyond that space. Finally, some non-conforming software will 12.6242 + remove trailing spaces and TABs from a line. Therefore, it might be 12.6243 + inadvisable to fold a header after a space or TAB. 12.6244 + 12.6245 + For maximum safety, header lines SHOULD conform to the following 12.6246 + syntax rather than to that in Section 9.7. 12.6247 + 12.6248 + 12.6249 + header = header-name ":" SP [header-content] CRLF 12.6250 + header-content = [WS] token *( [CRLF] WS token ) 12.6251 + 12.6252 +A.2. Message-IDs 12.6253 + 12.6254 + Every article handled by an NNTP server MUST have a unique 12.6255 + message-id. For the purposes of this specification, a message-id is 12.6256 + an arbitrary opaque string that merely needs to meet certain 12.6257 + syntactic requirements and is just a way to refer to the article. 12.6258 + 12.6259 + Because there is a significant risk that old articles will be 12.6260 + reinjected into the global Usenet system, RFC 1036 [RFC1036] requires 12.6261 + that message-ids are globally unique for all time. 12.6262 + 12.6263 + This specification states that message-ids are the same if and only 12.6264 + if they consist of the same sequence of octets. Other specifications 12.6265 + may define two different sequences as being equal because they are 12.6266 + putting an interpretation on particular characters. RFC 2822 12.6267 + [RFC2822] has a concept of "quoted" and "escaped" characters. It 12.6268 + therefore considers the three message-ids: 12.6269 + 12.6270 + 12.6271 + 12.6272 +Feather Standards Track [Page 112] 12.6273 + 12.6274 +RFC 3977 Network News Transfer Protocol (NNTP) October 2006 12.6275 + 12.6276 + 12.6277 + <ab.cd@example.com> 12.6278 + <"ab.cd"@example.com> 12.6279 + <"ab.\cd"@example.com> 12.6280 + 12.6281 + as being identical. Therefore, an NNTP implementation handing email 12.6282 + articles must ensure that only one of these three appears in the 12.6283 + protocol and that the other two are converted to it as and when 12.6284 + necessary, such as when a client checks the results of a NEWNEWS 12.6285 + command against an internal database of message-ids. Note that 12.6286 + RFC 1036 [RFC1036] never treats two different strings as being 12.6287 + identical. Its successor (as of the time of writing) restricts the 12.6288 + syntax of message-ids so that, whenever RFC 2822 would treat two 12.6289 + strings as equivalent, only one of them is valid (in the above 12.6290 + example, only the first string is valid). 12.6291 + 12.6292 + This specification does not describe how the message-id of an article 12.6293 + is determined; it may be deduced from the contents of the article or 12.6294 + derived from some external source. If the server is also conforming 12.6295 + to another specification that contains a definition of message-id 12.6296 + compatible with this one, the server SHOULD use those message-ids. A 12.6297 + common approach, and one that SHOULD be used for email and Netnews 12.6298 + articles, is to extract the message-id from the contents of a header 12.6299 + with name "Message-ID". This may not be as simple as copying the 12.6300 + entire header contents; it may be necessary to strip off comments and 12.6301 + undo quoting, or to reduce "equivalent" message-ids to a canonical 12.6302 + form. 12.6303 + 12.6304 + If an article is obtained through the IHAVE command, there will be a 12.6305 + message-id provided with the command. The server MAY either use it 12.6306 + or determine one from the article contents. However, whichever it 12.6307 + does, it SHOULD ensure that, if the IHAVE command is repeated with 12.6308 + the same argument and article, it will be recognized as a duplicate. 12.6309 + 12.6310 + If an article does not contain a message-id that the server can 12.6311 + identify, it MUST synthesize one. This could, for example, be a 12.6312 + simple sequence number or be based on the date and time when the 12.6313 + article arrived. When email or Netnews articles are handled, a 12.6314 + Message-ID header SHOULD be added to ensure global consistency and 12.6315 + uniqueness. 12.6316 + 12.6317 + Note that, because the message-id might not have been derived from 12.6318 + the Message-ID header in the article, the following example is 12.6319 + legitimate (though unusual): 12.6320 + 12.6321 + 12.6322 + 12.6323 + 12.6324 + 12.6325 + 12.6326 + 12.6327 + 12.6328 +Feather Standards Track [Page 113] 12.6329 + 12.6330 +RFC 3977 Network News Transfer Protocol (NNTP) October 2006 12.6331 + 12.6332 + 12.6333 + [C] HEAD <45223423@example.com> 12.6334 + [S] 221 0 <45223423@example.com> 12.6335 + [S] Path: pathost!demo!whitehouse!not-for-mail 12.6336 + [S] Message-ID: <1234@example.net> 12.6337 + [S] From: "Demo User" <nobody@example.net> 12.6338 + [S] Newsgroups: misc.test 12.6339 + [S] Subject: I am just a test article 12.6340 + [S] Date: 6 Oct 1998 04:38:40 -0500 12.6341 + [S] Organization: An Example Net, Uncertain, Texas 12.6342 + [S] . 12.6343 + 12.6344 +A.3. Article Posting 12.6345 + 12.6346 + As far as NNTP is concerned, the POST and IHAVE commands provide the 12.6347 + same basic facilities in a slightly different way. However, they 12.6348 + have rather different intentions. 12.6349 + 12.6350 + The IHAVE command is intended for transmitting conforming articles 12.6351 + between a system of NNTP servers, with all articles perhaps also 12.6352 + conforming to another specification (e.g., all articles are Netnews 12.6353 + articles). It is expected that the client will already have done any 12.6354 + necessary validation (or that it has in turn obtained the article 12.6355 + from a third party that has done so); therefore, the contents SHOULD 12.6356 + be left unchanged. 12.6357 + 12.6358 + In contrast, the POST command is intended for use when an end-user is 12.6359 + injecting a newly created article into a such a system. The article 12.6360 + being transferred might not be a conforming email or Netnews article, 12.6361 + and the server is expected to validate it and, if necessary, to 12.6362 + convert it to the right form for onward distribution. This is often 12.6363 + done by a separate piece of software on the server installation; if 12.6364 + so, the NNTP server SHOULD pass the incoming article to that software 12.6365 + unaltered, making no attempt to filter characters, to fold or limit 12.6366 + lines, or to process the incoming text otherwise. 12.6367 + 12.6368 + The POST command can fail in various ways, and clients should be 12.6369 + prepared to re-send an article. When doing so, however, it is often 12.6370 + important to ensure (as far as possible) that the same message-id is 12.6371 + allocated to both attempts so that the server, or other servers, can 12.6372 + recognize the two articles as duplicates. In the case of email or 12.6373 + Netnews articles, therefore, the posted article SHOULD contain a 12.6374 + header with the name "Message-ID", and the contents of this header 12.6375 + SHOULD be identical on each attempt. The server SHOULD ensure that 12.6376 + two POSTed articles with the same contents for this header are 12.6377 + recognized as identical and that the same message-id is allocated, 12.6378 + whether or not those contents are suitable for use as the message-id. 12.6379 + 12.6380 + 12.6381 + 12.6382 + 12.6383 + 12.6384 +Feather Standards Track [Page 114] 12.6385 + 12.6386 +RFC 3977 Network News Transfer Protocol (NNTP) October 2006 12.6387 + 12.6388 + 12.6389 +Appendix B. Summary of Commands 12.6390 + 12.6391 + This section contains a list of every command defined in this 12.6392 + document, ordered by command name and by indicating capability. 12.6393 + 12.6394 + Ordered by command name: 12.6395 + 12.6396 + +-------------------+-----------------------+---------------+ 12.6397 + | Command | Indicating capability | Definition | 12.6398 + +-------------------+-----------------------+---------------+ 12.6399 + | ARTICLE | READER | Section 6.2.1 | 12.6400 + | BODY | READER | Section 6.2.3 | 12.6401 + | CAPABILITIES | mandatory | Section 5.2 | 12.6402 + | DATE | READER | Section 7.1 | 12.6403 + | GROUP | READER | Section 6.1.1 | 12.6404 + | HDR | HDR | Section 8.5 | 12.6405 + | HEAD | mandatory | Section 6.2.2 | 12.6406 + | HELP | mandatory | Section 7.2 | 12.6407 + | IHAVE | IHAVE | Section 6.3.2 | 12.6408 + | LAST | READER | Section 6.1.3 | 12.6409 + | LIST | LIST | Section 7.6.1 | 12.6410 + | LIST ACTIVE.TIMES | LIST | Section 7.6.4 | 12.6411 + | LIST ACTIVE | LIST | Section 7.6.3 | 12.6412 + | LIST DISTRIB.PATS | LIST | Section 7.6.5 | 12.6413 + | LIST HEADERS | HDR | Section 8.6 | 12.6414 + | LIST NEWSGROUPS | LIST | Section 7.6.6 | 12.6415 + | LIST OVERVIEW.FMT | OVER | Section 8.4 | 12.6416 + | LISTGROUP | READER | Section 6.1.2 | 12.6417 + | MODE READER | MODE-READER | Section 5.3 | 12.6418 + | NEWGROUPS | READER | Section 7.3 | 12.6419 + | NEWNEWS | NEWNEWS | Section 7.4 | 12.6420 + | NEXT | READER | Section 6.1.4 | 12.6421 + | OVER | OVER | Section 8.3 | 12.6422 + | POST | POST | Section 6.3.1 | 12.6423 + | QUIT | mandatory | Section 5.4 | 12.6424 + | STAT | mandatory | Section 6.2.4 | 12.6425 + +-------------------+-----------------------+---------------+ 12.6426 + 12.6427 + 12.6428 + 12.6429 + 12.6430 + 12.6431 + 12.6432 + 12.6433 + 12.6434 + 12.6435 + 12.6436 + 12.6437 + 12.6438 + 12.6439 + 12.6440 +Feather Standards Track [Page 115] 12.6441 + 12.6442 +RFC 3977 Network News Transfer Protocol (NNTP) October 2006 12.6443 + 12.6444 + 12.6445 + Ordered by indicating capability: 12.6446 + 12.6447 + +-------------------+-----------------------+---------------+ 12.6448 + | Command | Indicating capability | Definition | 12.6449 + +-------------------+-----------------------+---------------+ 12.6450 + | CAPABILITIES | mandatory | Section 5.2 | 12.6451 + | HEAD | mandatory | Section 6.2.2 | 12.6452 + | HELP | mandatory | Section 7.2 | 12.6453 + | QUIT | mandatory | Section 5.4 | 12.6454 + | STAT | mandatory | Section 6.2.4 | 12.6455 + | HDR | HDR | Section 8.5 | 12.6456 + | LIST HEADERS | HDR | Section 8.6 | 12.6457 + | IHAVE | IHAVE | Section 6.3.2 | 12.6458 + | LIST | LIST | Section 7.6.1 | 12.6459 + | LIST ACTIVE | LIST | Section 7.6.3 | 12.6460 + | LIST ACTIVE.TIMES | LIST | Section 7.6.4 | 12.6461 + | LIST DISTRIB.PATS | LIST | Section 7.6.5 | 12.6462 + | LIST NEWSGROUPS | LIST | Section 7.6.6 | 12.6463 + | MODE READER | MODE-READER | Section 5.3 | 12.6464 + | NEWNEWS | NEWNEWS | Section 7.4 | 12.6465 + | OVER | OVER | Section 8.3 | 12.6466 + | LIST OVERVIEW.FMT | OVER | Section 8.4 | 12.6467 + | POST | POST | Section 6.3.1 | 12.6468 + | ARTICLE | READER | Section 6.2.1 | 12.6469 + | BODY | READER | Section 6.2.3 | 12.6470 + | DATE | READER | Section 7.1 | 12.6471 + | GROUP | READER | Section 6.1.1 | 12.6472 + | LAST | READER | Section 6.1.3 | 12.6473 + | LISTGROUP | READER | Section 6.1.2 | 12.6474 + | NEWGROUPS | READER | Section 7.3 | 12.6475 + | NEXT | READER | Section 6.1.4 | 12.6476 + +-------------------+-----------------------+---------------+ 12.6477 + 12.6478 + 12.6479 + 12.6480 + 12.6481 + 12.6482 + 12.6483 + 12.6484 + 12.6485 + 12.6486 + 12.6487 + 12.6488 + 12.6489 + 12.6490 + 12.6491 + 12.6492 + 12.6493 + 12.6494 + 12.6495 + 12.6496 +Feather Standards Track [Page 116] 12.6497 + 12.6498 +RFC 3977 Network News Transfer Protocol (NNTP) October 2006 12.6499 + 12.6500 + 12.6501 +Appendix C. Summary of Response Codes 12.6502 + 12.6503 + This section contains a list of every response code defined in this 12.6504 + document and indicates whether it is multi-line, which commands can 12.6505 + generate it, what arguments it has, and what its meaning is. 12.6506 + 12.6507 + Response code 100 (multi-line) 12.6508 + Generated by: HELP 12.6509 + Meaning: help text follows. 12.6510 + 12.6511 + Response code 101 (multi-line) 12.6512 + Generated by: CAPABILITIES 12.6513 + Meaning: capabilities list follows. 12.6514 + 12.6515 + Response code 111 12.6516 + Generated by: DATE 12.6517 + 1 argument: yyyymmddhhmmss 12.6518 + Meaning: server date and time. 12.6519 + 12.6520 + Response code 200 12.6521 + Generated by: initial connection, MODE READER 12.6522 + Meaning: service available, posting allowed. 12.6523 + 12.6524 + Response code 201 12.6525 + Generated by: initial connection, MODE READER 12.6526 + Meaning: service available, posting prohibited. 12.6527 + 12.6528 + Response code 205 12.6529 + Generated by: QUIT 12.6530 + Meaning: connection closing (the server immediately closes the 12.6531 + connection). 12.6532 + 12.6533 + Response code 211 12.6534 + The 211 response code has two completely different forms, 12.6535 + depending on which command generated it: 12.6536 + 12.6537 + (not multi-line) 12.6538 + Generated by: GROUP 12.6539 + 4 arguments: number low high group 12.6540 + Meaning: group selected. 12.6541 + 12.6542 + (multi-line) 12.6543 + Generated by: LISTGROUP 12.6544 + 4 arguments: number low high group 12.6545 + Meaning: article numbers follow. 12.6546 + 12.6547 + 12.6548 + 12.6549 + 12.6550 + 12.6551 + 12.6552 +Feather Standards Track [Page 117] 12.6553 + 12.6554 +RFC 3977 Network News Transfer Protocol (NNTP) October 2006 12.6555 + 12.6556 + 12.6557 + Response code 215 (multi-line) 12.6558 + Generated by: LIST 12.6559 + Meaning: information follows. 12.6560 + 12.6561 + Response code 220 (multi-line) 12.6562 + Generated by: ARTICLE 12.6563 + 2 arguments: n message-id 12.6564 + Meaning: article follows. 12.6565 + 12.6566 + Response code 221 (multi-line) 12.6567 + Generated by: HEAD 12.6568 + 2 arguments: n message-id 12.6569 + Meaning: article headers follow. 12.6570 + 12.6571 + Response code 222 (multi-line) 12.6572 + Generated by: BODY 12.6573 + 2 arguments: n message-id 12.6574 + Meaning: article body follows. 12.6575 + 12.6576 + Response code 223 12.6577 + Generated by: LAST, NEXT, STAT 12.6578 + 2 arguments: n message-id 12.6579 + Meaning: article exists and selected. 12.6580 + 12.6581 + Response code 224 (multi-line) 12.6582 + Generated by: OVER 12.6583 + Meaning: overview information follows. 12.6584 + 12.6585 + Response code 225 (multi-line) 12.6586 + Generated by: HDR 12.6587 + Meaning: headers follow. 12.6588 + 12.6589 + Response code 230 (multi-line) 12.6590 + Generated by: NEWNEWS 12.6591 + Meaning: list of new articles follows. 12.6592 + 12.6593 + Response code 231 (multi-line) 12.6594 + Generated by: NEWGROUPS 12.6595 + Meaning: list of new newsgroups follows. 12.6596 + 12.6597 + Response code 235 12.6598 + Generated by: IHAVE (second stage) 12.6599 + Meaning: article transferred OK. 12.6600 + 12.6601 + Response code 240 12.6602 + Generated by: POST (second stage) 12.6603 + Meaning: article received OK. 12.6604 + 12.6605 + 12.6606 + 12.6607 + 12.6608 +Feather Standards Track [Page 118] 12.6609 + 12.6610 +RFC 3977 Network News Transfer Protocol (NNTP) October 2006 12.6611 + 12.6612 + 12.6613 + Response code 335 12.6614 + Generated by: IHAVE (first stage) 12.6615 + Meaning: send article to be transferred. 12.6616 + 12.6617 + Response code 340 12.6618 + Generated by: POST (first stage) 12.6619 + Meaning: send article to be posted. 12.6620 + 12.6621 + Response code 400 12.6622 + Generic response and generated by initial connection 12.6623 + Meaning: service not available or no longer available (the server 12.6624 + immediately closes the connection). 12.6625 + 12.6626 + Response code 401 12.6627 + Generic response 12.6628 + 1 argument: capability-label 12.6629 + Meaning: the server is in the wrong mode; the indicated capability 12.6630 + should be used to change the mode. 12.6631 + 12.6632 + Response code 403 12.6633 + Generic response 12.6634 + Meaning: internal fault or problem preventing action being taken. 12.6635 + 12.6636 + Response code 411 12.6637 + Generated by: GROUP, LISTGROUP 12.6638 + Meaning: no such newsgroup. 12.6639 + 12.6640 + Response code 412 12.6641 + Generated by: ARTICLE, BODY, GROUP, HDR, HEAD, LAST, LISTGROUP, 12.6642 + NEXT, OVER, STAT 12.6643 + Meaning: no newsgroup selected. 12.6644 + 12.6645 + Response code 420 12.6646 + Generated by: ARTICLE, BODY, HDR, HEAD, LAST, NEXT, OVER, STAT 12.6647 + Meaning: current article number is invalid. 12.6648 + 12.6649 + Response code 421 12.6650 + Generated by: NEXT 12.6651 + Meaning: no next article in this group. 12.6652 + 12.6653 + Response code 422 12.6654 + Generated by: LAST 12.6655 + Meaning: no previous article in this group. 12.6656 + 12.6657 + Response code 423 12.6658 + Generated by: ARTICLE, BODY, HDR, HEAD, OVER, STAT 12.6659 + Meaning: no article with that number or in that range. 12.6660 + 12.6661 + 12.6662 + 12.6663 + 12.6664 +Feather Standards Track [Page 119] 12.6665 + 12.6666 +RFC 3977 Network News Transfer Protocol (NNTP) October 2006 12.6667 + 12.6668 + 12.6669 + Response code 430 12.6670 + Generated by: ARTICLE, BODY, HDR, HEAD, OVER, STAT 12.6671 + Meaning: no article with that message-id. 12.6672 + 12.6673 + Response code 435 12.6674 + Generated by: IHAVE (first stage) 12.6675 + Meaning: article not wanted. 12.6676 + 12.6677 + Response code 436 12.6678 + Generated by: IHAVE (either stage) 12.6679 + Meaning: transfer not possible (first stage) or failed (second 12.6680 + stage); try again later. 12.6681 + 12.6682 + Response code 437 12.6683 + Generated by: IHAVE (second stage) 12.6684 + Meaning: transfer rejected; do not retry. 12.6685 + 12.6686 + Response code 440 12.6687 + Generated by: POST (first stage) 12.6688 + Meaning: posting not permitted. 12.6689 + 12.6690 + Response code 441 12.6691 + Generated by: POST (second stage) 12.6692 + Meaning: posting failed. 12.6693 + 12.6694 + Response code 480 12.6695 + Generic response 12.6696 + Meaning: command unavailable until the client has authenticated 12.6697 + itself. 12.6698 + 12.6699 + Response code 483 12.6700 + Generic response 12.6701 + Meaning: command unavailable until suitable privacy has been 12.6702 + arranged. 12.6703 + 12.6704 + Response code 500 12.6705 + Generic response 12.6706 + Meaning: unknown command. 12.6707 + 12.6708 + Response code 501 12.6709 + Generic response 12.6710 + Meaning: syntax error in command. 12.6711 + 12.6712 + 12.6713 + 12.6714 + 12.6715 + 12.6716 + 12.6717 + 12.6718 + 12.6719 + 12.6720 +Feather Standards Track [Page 120] 12.6721 + 12.6722 +RFC 3977 Network News Transfer Protocol (NNTP) October 2006 12.6723 + 12.6724 + 12.6725 + Response code 502 12.6726 + Generic response and generated by initial connection 12.6727 + 12.6728 + Meaning for the initial connection and the MODE READER command: 12.6729 + service permanently unavailable (the server immediately closes the 12.6730 + connection). 12.6731 + 12.6732 + Meaning for all other commands: command not permitted (and there 12.6733 + is no way for the client to change this). 12.6734 + 12.6735 + Response code 503 12.6736 + Generic response 12.6737 + Meaning: feature not supported. 12.6738 + 12.6739 + Response code 504 12.6740 + Generic response 12.6741 + Meaning: error in base64-encoding [RFC4648] of an argument. 12.6742 + 12.6743 +Appendix D. Changes from RFC 977 12.6744 + 12.6745 + In general every attempt has been made to ensure that the protocol 12.6746 + specification in this document is compatible with the version 12.6747 + specified in RFC 977 [RFC977] and the various facilities adopted from 12.6748 + RFC 2980 [RFC2980]. However, there have been a number of changes, 12.6749 + some compatible and some not. 12.6750 + 12.6751 + This appendix lists these changes. It is not guaranteed to be 12.6752 + exhaustive or correct and MUST NOT be relied on. 12.6753 + 12.6754 + o A formal syntax specification (Section 9) has been added. 12.6755 + 12.6756 + o The default character set is changed from US-ASCII [ANSI1986] to 12.6757 + UTF-8 [RFC3629] (note that US-ASCII is a subset of UTF-8). This 12.6758 + matter is discussed further in Section 10. 12.6759 + 12.6760 + o All articles are required to have a message-id, eliminating the 12.6761 + "<0>" placeholder used in RFC 977 in some responses. 12.6762 + 12.6763 + o The newsgroup name matching capabilities already documented in 12.6764 + RFC 977 ("wildmats", Section 4) are clarified and extended. The 12.6765 + new facilities (e.g., the use of commas and exclamation marks) are 12.6766 + allowed wherever wildmats appear in the protocol. 12.6767 + 12.6768 + o Support for pipelining of commands (Section 3.5) is made 12.6769 + mandatory. 12.6770 + 12.6771 + 12.6772 + 12.6773 + 12.6774 + 12.6775 + 12.6776 +Feather Standards Track [Page 121] 12.6777 + 12.6778 +RFC 3977 Network News Transfer Protocol (NNTP) October 2006 12.6779 + 12.6780 + 12.6781 + o The principles behind response codes (Section 3.2) have been 12.6782 + tidied up. In particular: 12.6783 + 12.6784 + * the x8x response code family, formerly used for private 12.6785 + extensions, is now reserved for authentication and privacy 12.6786 + extensions; 12.6787 + 12.6788 + * the x9x response code family, formerly intended for debugging 12.6789 + facilities, are now reserved for private extensions; 12.6790 + 12.6791 + * the 502 and 503 generic response codes (Section 3.2.1) have 12.6792 + been redefined; 12.6793 + 12.6794 + * new 401, 403, 480, 483, and 504 generic response codes have 12.6795 + been added. 12.6796 + 12.6797 + o The rules for article numbering (Section 6) have been clarified 12.6798 + (also see Section 6.1.1.2). 12.6799 + 12.6800 + o The SLAVE command (which was ill-defined) is removed from the 12.6801 + protocol. 12.6802 + 12.6803 + o Four-digit years are permitted in the NEWNEWS (Section 7.4) and 12.6804 + NEWGROUPS (Section 7.3) commands (two-digit years are still 12.6805 + permitted). The optional distribution parameter to these commands 12.6806 + has been removed. 12.6807 + 12.6808 + o The LIST command (Section 7.6.1) is greatly extended; the original 12.6809 + is available as LIST ACTIVE, while new variants include 12.6810 + ACTIVE.TIMES, DISTRIB.PATS, and NEWSGROUPS. A new "m" status flag 12.6811 + is added to the LIST ACTIVE response. 12.6812 + 12.6813 + o A new CAPABILITIES command (Section 5.2) allows clients to 12.6814 + determine what facilities are supported by a server. 12.6815 + 12.6816 + o The DATE command (Section 7.1) is adopted from RFC 2980 12.6817 + effectively unchanged. 12.6818 + 12.6819 + o The LISTGROUP command (Section 6.1.2) is adopted from RFC 2980. 12.6820 + An optional range argument has been added, and the 211 initial 12.6821 + response line now has the same format as the 211 response from the 12.6822 + GROUP command. 12.6823 + 12.6824 + o The MODE READER command (Section 5.3) is adopted from RFC 2980 and 12.6825 + its meaning and effects clarified. 12.6826 + 12.6827 + o The XHDR command in RFC 2980 has been formalised as the new HDR 12.6828 + (Section 8.5) and LIST HEADERS (Section 8.6) commands. 12.6829 + 12.6830 + 12.6831 + 12.6832 +Feather Standards Track [Page 122] 12.6833 + 12.6834 +RFC 3977 Network News Transfer Protocol (NNTP) October 2006 12.6835 + 12.6836 + 12.6837 + o The XOVER command in RFC 2980 has been formalised as the new OVER 12.6838 + (Section 8.3) and LIST OVERVIEW.FMT (Section 8.4) commands. The 12.6839 + former can be applied to a message-id as well as to a range. 12.6840 + 12.6841 + o The concept of article metadata (Section 8.1) has been formalised, 12.6842 + allowing the Bytes and Lines pseudo-headers to be deprecated. 12.6843 + 12.6844 + Client authors should note in particular that lack of support for the 12.6845 + CAPABILITIES command is a good indication that the server does not 12.6846 + support this specification. 12.6847 + 12.6848 + 12.6849 + 12.6850 + 12.6851 + 12.6852 + 12.6853 + 12.6854 + 12.6855 + 12.6856 + 12.6857 + 12.6858 + 12.6859 + 12.6860 + 12.6861 + 12.6862 + 12.6863 + 12.6864 + 12.6865 + 12.6866 + 12.6867 + 12.6868 + 12.6869 + 12.6870 + 12.6871 + 12.6872 + 12.6873 + 12.6874 + 12.6875 + 12.6876 + 12.6877 + 12.6878 + 12.6879 + 12.6880 + 12.6881 + 12.6882 + 12.6883 + 12.6884 + 12.6885 + 12.6886 + 12.6887 + 12.6888 +Feather Standards Track [Page 123] 12.6889 + 12.6890 +RFC 3977 Network News Transfer Protocol (NNTP) October 2006 12.6891 + 12.6892 + 12.6893 +Author's Address 12.6894 + 12.6895 + Clive D.W. Feather 12.6896 + THUS plc 12.6897 + 322 Regents Park Road 12.6898 + London 12.6899 + N3 2QQ 12.6900 + United Kingdom 12.6901 + 12.6902 + Phone: +44 20 8495 6138 12.6903 + Fax: +44 870 051 9937 12.6904 + EMail: clive@demon.net 12.6905 + URI: http://www.davros.org/ 12.6906 + 12.6907 + 12.6908 + 12.6909 + 12.6910 + 12.6911 + 12.6912 + 12.6913 + 12.6914 + 12.6915 + 12.6916 + 12.6917 + 12.6918 + 12.6919 + 12.6920 + 12.6921 + 12.6922 + 12.6923 + 12.6924 + 12.6925 + 12.6926 + 12.6927 + 12.6928 + 12.6929 + 12.6930 + 12.6931 + 12.6932 + 12.6933 + 12.6934 + 12.6935 + 12.6936 + 12.6937 + 12.6938 + 12.6939 + 12.6940 + 12.6941 + 12.6942 + 12.6943 + 12.6944 +Feather Standards Track [Page 124] 12.6945 + 12.6946 +RFC 3977 Network News Transfer Protocol (NNTP) October 2006 12.6947 + 12.6948 + 12.6949 +Full Copyright Statement 12.6950 + 12.6951 +Copyright (C) The Internet Society (2006). 12.6952 + 12.6953 + This document is subject to the rights, licenses and restrictions 12.6954 + contained in BCP 78, and except as set forth therein, the authors 12.6955 + retain all their rights. 12.6956 + 12.6957 + This document and the information contained herein are provided on an 12.6958 + "AS IS" basis and THE CONTRIBUTOR, THE ORGANIZATION HE/SHE REPRESENTS 12.6959 + OR IS SPONSORED BY (IF ANY), THE INTERNET SOCIETY AND THE INTERNET 12.6960 + ENGINEERING TASK FORCE DISCLAIM ALL WARRANTIES, EXPRESS OR IMPLIED, 12.6961 + INCLUDING BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE 12.6962 + INFORMATION HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED 12.6963 + WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. 12.6964 + 12.6965 +Intellectual Property 12.6966 + 12.6967 + The IETF takes no position regarding the validity or scope of any 12.6968 + Intellectual Property Rights or other rights that might be claimed to 12.6969 + pertain to the implementation or use of the technology described in 12.6970 + this document or the extent to which any license under such rights 12.6971 + might or might not be available; nor does it represent that it has 12.6972 + made any independent effort to identify any such rights. Information 12.6973 + on the procedures with respect to rights in RFC documents can be 12.6974 + found in BCP 78 and BCP 79. 12.6975 + 12.6976 + Copies of IPR disclosures made to the IETF Secretariat and any 12.6977 + assurances of licenses to be made available, or the result of an 12.6978 + attempt made to obtain a general license or permission for the use of 12.6979 + such proprietary rights by implementers or users of this 12.6980 + specification can be obtained from the IETF on-line IPR repository at 12.6981 + http://www.ietf.org/ipr. 12.6982 + 12.6983 + The IETF invites any interested party to bring to its attention any 12.6984 + copyrights, patents or patent applications, or other proprietary 12.6985 + rights that may cover technology that may be required to implement 12.6986 + this standard. Please address the information to the IETF at ietf- 12.6987 + ipr@ietf.org. 12.6988 + 12.6989 +Acknowledgement 12.6990 + 12.6991 + Funding for the RFC Editor function is provided by the IETF 12.6992 + Administrative Support Activity (IASA). 12.6993 + 12.6994 + 12.6995 + 12.6996 + 12.6997 + 12.6998 + 12.6999 + 12.7000 +Feather Standards Track [Page 125] 12.7001 +
13.1 Binary file RFC3977.pdf has changed
14.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 14.2 +++ b/SConstruct Fri Jun 26 16:48:50 2009 +0200 14.3 @@ -0,0 +1,16 @@ 14.4 +# This file is used to build and automatically test sonews 14.5 + 14.6 +import os 14.7 +env = Environment() 14.8 + 14.9 +env['ENV']['LANG'] = 'en_GB.UTF-8' 14.10 +env['JAVACFLAGS'] = '-source 1.6 -target 1.6' 14.11 +env['JAVACLASSPATH'] = '/usr/share/java/junit4.jar:/usr/share/java/glassfish-mail.jar:/usr/share/java/servlet-api-2.5.jar:/usr/share/java/jchart2d.jar:classes' 14.12 + 14.13 +# Build Java classes 14.14 +classes = env.Java(target='classes', source=['org/sonews/']) 14.15 +test_classes = env.Java(target='classes', source=['test']) 14.16 + 14.17 +# Setting dependencies 14.18 +Depends(test_classes, classes) 14.19 +
15.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 15.2 +++ b/bin/sonews-web.sh Fri Jun 26 16:48:50 2009 +0200 15.3 @@ -0,0 +1,10 @@ 15.4 +#!/bin/bash 15.5 +SCRIPTROOT=$(dirname $0) 15.6 +CLASSPATH=$SCRIPTROOT/lib/jchart2d.jar:\ 15.7 +$SCRIPTROOT/lib/sonews.jar:\ 15.8 +$SCRIPTROOT/lib/servlet-api-2.5.jar 15.9 +ARG0=org.sonews.web.SonewsServlet@sonews 15.10 +ARG1=org.sonews.web.SonewsConfigServlet@sonews/config 15.11 +ARG2=org.sonews.web.SonewsPeerServlet@sonews/peer 15.12 +ARG3=org.sonews.web.SonewsChartServlet@sonews/chart 15.13 +java -cp $CLASSPATH org.sonews.kitten.Main -s $ARG0 -s $ARG1 -s $ARG2 -s $ARG3
16.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 16.2 +++ b/bin/sonews.sh Fri Jun 26 16:48:50 2009 +0200 16.3 @@ -0,0 +1,35 @@ 16.4 +#!/bin/bash 16.5 +SCRIPTROOT=$(pwd) 16.6 +CLASSPATH=$SCRIPTROOT/lib/sonews.jar:\ 16.7 +$SCRIPTROOT/lib/mysql-connector-java.jar:\ 16.8 +$SCRIPTROOT/lib/glassfish-mail.jar:\ 16.9 +$SCRIPTROOT/lib/postgresql.jar 16.10 + 16.11 +LOGFILE=sonews.log 16.12 +PIDFILE=sonews.pid 16.13 +ARGS=$@ 16.14 + 16.15 +MAINCLASS=org.sonews.daemon.Main 16.16 +JAVA=java 16.17 + 16.18 +case "$1" in 16.19 + start) 16.20 + echo "Starting sonews Newsserver..." 16.21 + $JAVA -classpath $CLASSPATH $MAINCLASS $ARGS &> $LOGFILE & 16.22 + echo $! > $PIDFILE 16.23 + ;; 16.24 + stop) 16.25 + echo "Stopping sonews Newsserver..." 16.26 + PID=`cat $PIDFILE` 16.27 + kill -15 $PID 16.28 + ;; 16.29 + setup) 16.30 + $JAVA -classpath $CLASSPATH org.sonews.util.DatabaseSetup 16.31 + ;; 16.32 + purge) 16.33 + $JAVA -classpath $CLASSPATH org.sonews.util.Purger 16.34 + ;; 16.35 + 16.36 + *) 16.37 + echo "Usage: sonews [start|stop|setup|purge]" 16.38 +esac
17.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 17.2 +++ b/doc/config.xsl Fri Jun 26 16:48:50 2009 +0200 17.3 @@ -0,0 +1,17 @@ 17.4 +<?xml version="1.0"?> 17.5 +<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 17.6 + xmlns:fo="http://www.w3.org/1999/XSL/Format" 17.7 + version="1.0"> 17.8 + <xsl:param name="use.id.as.filename" select="1"/> 17.9 + <xsl:param name="admon.graphics" select="1"/> 17.10 + <xsl:param name="admon.graphics.path"></xsl:param> 17.11 + <xsl:param name="chunk.section.depth" select="0"></xsl:param> 17.12 + <xsl:param name="html.stylesheet" select="'sonews.css'"/> 17.13 +<xsl:template name="user.footer.navigation"> 17.14 + <p class="copyright"> 17.15 + <a rel="license" href="http://creativecommons.org/licenses/by-sa/3.0/"><img alt="Creative Commons License" style="border-width:0" src="http://i.creativecommons.org/l/by-sa/3.0/80x15.png" /></a> This work by <span xmlns:cc="http://creativecommons.org/ns#" property="cc:attributionName">Christian Lins</span> is licensed under a <a rel="license" href="http://creativecommons.org/licenses/by-sa/3.0/">Creative Commons Attribution-Share Alike 3.0 License</a>. 17.16 + </p> 17.17 +</xsl:template> 17.18 + 17.19 +</xsl:stylesheet> 17.20 +
18.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 18.2 +++ b/doc/makedoc Fri Jun 26 16:48:50 2009 +0200 18.3 @@ -0,0 +1,1 @@ 18.4 +xmlto --skip-validation html -m config.xsl sonews.xml
19.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 19.2 +++ b/doc/sonews.css Fri Jun 26 16:48:50 2009 +0200 19.3 @@ -0,0 +1,35 @@ 19.4 +body 19.5 +{ 19.6 + font-family: Liberation Sans,Verdana,sans-serif; 19.7 + font-size: 11pt; 19.8 +} 19.9 + 19.10 +.screen { 19.11 + font-family: monospace; 19.12 + font-size: 1em; 19.13 + display: block; 19.14 + padding: 10px; 19.15 + border: 1px solid #bbb; 19.16 + background-color: #eee; 19.17 + color: #000; 19.18 + overflow: auto; 19.19 + border-radius: 2.5px; 19.20 + -moz-border-radius: 2.5px; 19.21 + margin: 0.5em 2em; 19.22 + 19.23 +} 19.24 + 19.25 +.programlisting { 19.26 + font-family: monospace; 19.27 + font-size: 1em; 19.28 + display: block; 19.29 + padding: 10px; 19.30 + border: 1px solid #bbb; 19.31 + background-color: #ddd; 19.32 + color: #000; 19.33 + overflow: auto; 19.34 + border-radius: 2.5px; 19.35 + -moz-border-radius: 2.5px; 19.36 + margin: 0.5em 2em; 19.37 +} 19.38 +
20.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 20.2 +++ b/doc/sonews.xml Fri Jun 26 16:48:50 2009 +0200 20.3 @@ -0,0 +1,254 @@ 20.4 +<?xml version="1.0"?> 20.5 +<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN" "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd" [ 20.6 + <!ENTITY tex "TeX"> 20.7 + <!ENTITY latex "LaTeX"> 20.8 +]> 20.9 +<book id="sonews.xml" lang="en"> 20.10 + <title>sonews Usenet News Server</title> 20.11 + <para> 20.12 + <emphasis role="bold">sonews</emphasis> is NNTP server than can provide 20.13 + access to both local and global Usenets newsgroups. It is written in 20.14 + <ulink url="http://java.sun.com/">Java</ulink> and uses a relational 20.15 + database as backend. 20.16 + </para> 20.17 + <para> 20.18 + <emphasis role="bold">2009/06/29</emphasis>: 20.19 + <emphasis>sonews/0.5.0</emphasis> 20.20 + (<ulink url="files/sonews-0.5.0.tar.bz2">binary tarball</ulink>, 20.21 + <ulink url="files/sonews-0.5.0-src.tar.bz2">source tarball</ulink>) final 20.22 + released. 20.23 + The setup is a little clumsy but the software is stable and works well. 20.24 + </para> 20.25 + 20.26 + <chapter> 20.27 + <title>Introduction</title> 20.28 + <para>sonews is a RCF3977 compliant NNTP Usenet server. 20.29 + It is written in Java and uses a relation database management system 20.30 + (RDBMS) as backend (currently 20.31 + <ulink url="http://www.postgresql.com/">PostgreSQL</ulink> and 20.32 + <ulink url="http://www.mysql.com/">MySQL</ulink>). 20.33 + sonews is highly multithreaded and uses Java NIO asynchronous sockets 20.34 + to handle thousands of concurrent connections.</para> 20.35 + <para>sonews is Free and Open Source Software (FOSS) licensed under the 20.36 + terms of the 20.37 + <ulink url="http://www.gnu.org/licenses/gpl.html">GNU General Public License</ulink> 20.38 + Version 3 (or later).</para> 20.39 + 20.40 + <sect1 label="1.1"> 20.41 + <title>History</title> 20.42 + <para>Ancestor of sonews is probably the Neat NNTP Daemon (n3tpd) 20.43 + although there is very little code in sonews that can be identified 20.44 + as direct derivation. 20.45 + sonews was developed as diploma thesis project of Christian Lins at 20.46 + <ulink url="http://de.sun.com/">StarOffice development</ulink> 20.47 + in Hamburg and is now a Free Software project.</para> 20.48 + </sect1> 20.49 + 20.50 + <sect1 label="1.2"> 20.51 + <title>Roadmap</title> 20.52 + <sect2 label="1.2.1"> 20.53 + <title>sonews/0.6</title> 20.54 + <para>Planned to implement the XPAT command for searching, correctly 20.55 + hashed Message-Ids and a news purging command. 20.56 + See <ulink url="http://bugs.xerxys.info/">Bugtracker</ulink> for 20.57 + issues with target sonews/0.6.x.</para> 20.58 + </sect2> 20.59 + </sect1> 20.60 + </chapter> 20.61 + 20.62 + <chapter label="2"> 20.63 + <title>Installation and initial setup</title> 20.64 + <sect1 label="2.1"> 20.65 + <title>Download & Installation</title> 20.66 + <sect2 label="2.1.1"> 20.67 + <title>Debian based systems</title> 20.68 + <para>You can install sonews with 20.69 + <ulink url="http://www.debian.org/doc/manuals/apt-howto/">APT</ulink> 20.70 + easily. 20.71 + Add the following line to /etc/apt/sources.list:</para> 20.72 + <screen>deb http://packages.xerxys.info/debian/ unstable main 20.73 + </screen> 20.74 + <para>And add the GPG-Key for package authentification, see 20.75 + <ulink url="http://packages.xerxys.info/debian/">Xerxys Debian Repository</ulink> 20.76 + for more details.</para> 20.77 + <para>Then force an update of your local package list:</para> 20.78 + <screen># apt-get update 20.79 +</screen> 20.80 + <para>To install sonews and all prerequisites issue the following command:</para> 20.81 + <screen># apt-get install sonews 20.82 + </screen> 20.83 + <para>This method should work for all recent Debian-based distributions 20.84 +(<ulink url="http://www.debian.org/">Debian</ulink>, <ulink url="http://www.ubuntu.com/">Ubuntu</ulink>, etc.).</para> 20.85 + </sect2> 20.86 + 20.87 + <sect2 label="2.1.2"> 20.88 + <title>Other *nix systems</title> 20.89 + <para>See <ulink url="files/">Files Section</ulink> for recent binary and source tarballs.</para> 20.90 + <para>Use the binary archive and extract it in a directory of your choice. Make sure your system 20.91 +provides the necessary prerequisites:</para> 20.92 + <itemizedlist> 20.93 + <listitem> 20.94 + <para>Java6 compatible runtime (JRE)</para> 20.95 + </listitem> 20.96 + <listitem> 20.97 + <para>Java Mail API implementation, e.g. <ulink url="http://java.sun.com/products/javamail/">Sun Java Mail</ulink>. 20.98 +GNU JavaMail has a broken POP3 Provider and does not work with sonews.</para> 20.99 + </listitem> 20.100 + <listitem> 20.101 + <para>JSP Servlet Container (e.g. 20.102 + <ulink url="http://kitten.sonews.org/">Kitten</ulink>) [optional]</para> 20.103 + </listitem> 20.104 + </itemizedlist> 20.105 + </sect2> 20.106 + </sect1> 20.107 + 20.108 + <sect1 label="2.2"> 20.109 + <title>Initial database setup</title> 20.110 + <para>Before you start sonews, you must prepare the database. Currently sonews is known 20.111 +to work with PostgreSQL and MySQL.</para> 20.112 + <para>It is highly recommended to create an own database for every sonews instance, e.g. 20.113 +called 'sonews'. Additionally, it is recommended to create a unique database user 20.114 +for sonews, e.g. 'sonewsuser'. Please do not use the root user for sonews! 20.115 +The sonews user needs rights for SELECT, INSERT and UPDATE statements. 20.116 +Refer to the database's manual for instructions.</para> 20.117 + <para>You will find the SQL Schema definitions in the helpers subdirectory of 20.118 +the source and binary distributions. You can create the tables manually using 20.119 +this templates or you can use the setup helper:</para> 20.120 + <screen>user@debian$ sonews setup 20.121 +</screen> 20.122 + <para>or on other *nix systems:</para> 20.123 + <screen>user@nix$ java -jar sonews.jar org.sonews.util.DatabaseSetup 20.124 +</screen> 20.125 + <para>The tool will ask for some information about your database environment, 20.126 +connect to the database, create the tables and creates a default bootstrap 20.127 +config file called sonews.conf.</para> 20.128 + </sect1> 20.129 + </chapter> 20.130 + 20.131 + <chapter label="3"> 20.132 + <title>Running sonews</title> 20.133 + <sect1 label="3.1"> 20.134 + <title>Configuration</title> 20.135 + <para>There is a bootstrap configuration in /etc/sonews/sonews.conf and a regular configuration 20.136 +in the database table config.</para> 20.137 + <para>There are various configuration values that can be adapted:</para> 20.138 + <variablelist> 20.139 + <varlistentry> 20.140 + <term>‘<literal>sonews.article.maxsize</literal>’</term> 20.141 + <listitem> 20.142 + <para>Maximum allowed body size of a news message given in kilobytes. Please note that 20.143 +for MySQL the ‘<literal>max_allowed_packet</literal>’ configuration variable must 20.144 +be set to a value higher than ‘<literal>sonews.article.maxsize</literal>’ otherwise posting 20.145 +of large mails will fail.</para> 20.146 + </listitem> 20.147 + </varlistentry> 20.148 + <varlistentry> 20.149 + <term>‘<literal>sonews.debug</literal>’</term> 20.150 + <listitem> 20.151 + <para> 20.152 + If set to true every(!) data going through sonews' socket 20.153 + is written to sonews.log. After a night the logfile can be 20.154 + several gigabytes large, so be careful with this setting. 20.155 + </para> 20.156 + </listitem> 20.157 + </varlistentry> 20.158 + <varlistentry> 20.159 + <term>‘<literal>sonews.hostname</literal>’</term> 20.160 + <listitem> 20.161 + <para>Canonical name of the server instance. This variable is part of the server's 20.162 +hello message to the client and used to generate Message-Ids.</para> 20.163 + </listitem> 20.164 + </varlistentry> 20.165 + <varlistentry> 20.166 + <term>‘<literal>sonews.timeout</literal>’</term> 20.167 + <listitem> 20.168 + <para>Socket timeout for client connections in seconds.</para> 20.169 + </listitem> 20.170 + </varlistentry> 20.171 + <varlistentry> 20.172 + <term>‘<literal>sonews.port</literal>’</term> 20.173 + <listitem> 20.174 + <para>Listening port of sonews daemon.</para> 20.175 + </listitem> 20.176 + </varlistentry> 20.177 + </variablelist> 20.178 + </sect1> 20.179 + 20.180 + <sect1 label="3.2"> 20.181 + <title>Command line arguments</title> 20.182 + <para>If you like to start sonews directly, you can use one of the following 20.183 +arguments:</para> 20.184 + <screen>java -jar sonews.jar [arguments] 20.185 + where arguments: 20.186 + -c|-config <path to config file> if custom config file preferred 20.187 + -dumpjdbcdriver Prints out a list of available JDBC drivers 20.188 + -feed Enables feed daemon for pulling news from peer servers 20.189 + -h|-help This output 20.190 + -mlgw Enables the Mailinglist Gateway poller 20.191 + -p portnumber Port on which sonews is listening for incoming connections. 20.192 + Overrides port settings in config file and database. 20.193 + 20.194 +</screen> 20.195 + </sect1> 20.196 + 20.197 + <sect1 label="3.3"> 20.198 + <title>Webinterface</title> 20.199 + <para>The package sonews-web provides an optional webinterface that can be used to 20.200 +review statistical information and configuration values of sonews.</para> 20.201 + <screen>sonews-web start|stop 20.202 +</screen> 20.203 + <para>The webinterface uses the the lightweight Servlet Container Kitten and is 20.204 +per default listening on HTTP-Port 8080 (go to http://localhost:8080/sonews).</para> 20.205 + </sect1> 20.206 + </chapter> 20.207 + 20.208 + <chapter label="4"> 20.209 + <title>Development</title> 20.210 + <para>You're welcome to create patches with bugfixes or additional features. The 20.211 +Mercurial DSCM makes this step an easy task.</para> 20.212 + <para>Just clone the public <ulink url="http://www.selenic.com/mercurial/">Mercurial</ulink> repository:</para> 20.213 + <screen>hg clone http://code.xerxys.info:8000/hg/sonews/trunk sonews-trunk 20.214 +</screen> 20.215 + <para>Then make your changes, create a bundle of changesets and send this to me via email. 20.216 +Or ask for push access to the public repository.</para> 20.217 + <para> 20.218 + There is a nightly generated <ulink url="apidoc/">Javadoc API documentation</ulink> that will help 20.219 + you to get in touch with the sonews source. 20.220 + </para> 20.221 + <para>Some debugging hints: if the server blocks and does not longer respond you 20.222 +probably found a deadlock. Do not kill the process with "kill -9 <pid>" 20.223 +but send a SIGQUIT signal with "kill -3 <pid>" and the Java VM will output 20.224 +a stracktrace of all threads. This output is the most valuable information to 20.225 +fix the deadlock.</para> 20.226 + 20.227 + <sect1 label="4.1"> 20.228 + <title>Contributors</title> 20.229 + <para>Maintainer and project lead: 20.230 +Christian Lins (contact christian.lins (at) fh-osnabrueck.de)</para> 20.231 + </sect1> 20.232 + 20.233 + <sect1 label="4.2"> 20.234 + <title>Sponsors</title> 20.235 + <para>The author thanks <ulink url="http://www.sun.com/">Sun Microsystems</ulink> for fully 20.236 +financing the first version of sonews. A really free software supporting company!</para> 20.237 + <para>If you like to support sonews with a donation of any kind (hardware, books, money, donuts,...), 20.238 + feel free to contact the project leader. 20.239 +A friendly email or a bug report is most welcome, too :-)</para> 20.240 + </sect1> 20.241 + </chapter> 20.242 + 20.243 + <chapter label="5"> 20.244 + <title>Links and further information</title> 20.245 + <itemizedlist> 20.246 + <listitem> 20.247 + <para><ulink url="http://bugs.xerxys.info/">Bugtracker</ulink>, register necessary, see project 'sonews'.</para> 20.248 + </listitem> 20.249 + <listitem> 20.250 + <para><ulink url="http://www.sun.com/">Sun Microsystems</ulink>, friendly sponsor.</para> 20.251 + </listitem> 20.252 + <listitem> 20.253 + <para><ulink url="http://www.fh-osnabrueck">University of Applied Sciences Osnabrueck</ulink></para> 20.254 + </listitem> 20.255 + </itemizedlist> 20.256 + </chapter> 20.257 +</book>
21.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 21.2 +++ b/helpers/copyright Fri Jun 26 16:48:50 2009 +0200 21.3 @@ -0,0 +1,23 @@ 21.4 +Upstream Author: 21.5 + 21.6 + Christian Lins <christian.lins@web.de> 21.7 + 21.8 +Copyright: 21.9 + 21.10 + Copyright (C) 2009 Christian Lins 21.11 + 21.12 +License: 21.13 + 21.14 + This program is free software: you can redistribute it and/or modify 21.15 + it under the terms of the GNU General Public License as published by 21.16 + the Free Software Foundation, either version 3 of the License, or 21.17 + (at your option) any later version. 21.18 + 21.19 + This program is distributed in the hope that it will be useful, 21.20 + but WITHOUT ANY WARRANTY; without even the implied warranty of 21.21 + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 21.22 + GNU General Public License for more details. 21.23 + 21.24 + You should have received a copy of the GNU General Public License 21.25 + along with this program. If not, see <http://www.gnu.org/licenses/>. 21.26 +
22.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 22.2 +++ b/helpers/database_mysql5_tmpl.sql Fri Jun 26 16:48:50 2009 +0200 22.3 @@ -0,0 +1,158 @@ 22.4 +/* 22.5 + Create a database at first: 22.6 + CREATE DATABASE sonews CHARACTER SET utf8 22.7 +*/ 22.8 + 22.9 +/* 22.10 + flags: 22.11 + If bit 0 is set, groups is a mirrorred mailing list. 22.12 + If not set default newsgroup. 22.13 + 22.14 + Normalization: 1NF, 2NF, 3NF 22.15 +*/ 22.16 +CREATE TABLE groups 22.17 +( 22.18 + group_id SERIAL, 22.19 + name VARCHAR(80) NOT NULL, 22.20 + flags TINYINT UNSIGNED DEFAULT 0, 22.21 + 22.22 + PRIMARY KEY(group_id), 22.23 + UNIQUE(name) 22.24 +) 22.25 +ENGINE = INNODB 22.26 +CHARACTER SET utf8; 22.27 + 22.28 +CREATE TABLE articles 22.29 +( 22.30 + article_id INT, 22.31 + body LONGBLOB, 22.32 + 22.33 + PRIMARY KEY(article_id) 22.34 +) 22.35 +ENGINE = INNODB 22.36 +CHARACTER SET utf8; 22.37 + 22.38 +CREATE TABLE article_ids 22.39 +( 22.40 + article_id INT REFERENCES articles.article_id ON DELETE CASCADE, 22.41 + message_id VARCHAR(255), 22.42 + 22.43 + PRIMARY KEY(article_id), 22.44 + UNIQUE(message_id) 22.45 +) 22.46 +ENGINE = INNODB 22.47 +CHARACTER SET utf8; 22.48 + 22.49 +CREATE TABLE headers 22.50 +( 22.51 + article_id INT REFERENCES articles.article_id ON DELETE CASCADE, 22.52 + header_key VARCHAR(255), 22.53 + header_value TEXT, /* Max. 64k */ 22.54 + header_index INT, 22.55 + 22.56 + PRIMARY KEY(article_id, header_key, header_index) 22.57 +) 22.58 +ENGINE = INNODB 22.59 +CHARACTER SET utf8; 22.60 + 22.61 +/* 22.62 + Normalization: 1NF, 2NF 22.63 +*/ 22.64 +CREATE TABLE postings 22.65 +( 22.66 + group_id INTEGER, 22.67 + article_id INTEGER REFERENCES articles.article_id ON DELETE CASCADE, 22.68 + article_index INTEGER NOT NULL, 22.69 + 22.70 + PRIMARY KEY(group_id, article_id) 22.71 +) 22.72 +ENGINE = INNODB 22.73 +CHARACTER SET utf8; 22.74 + 22.75 +/* 22.76 + Table for association of newsgroups and mailing-lists 22.77 + 22.78 + Normalization: 1NF, 2NF, 3NF 22.79 +*/ 22.80 +CREATE TABLE groups2list 22.81 +( 22.82 + group_id INTEGER REFERENCES groups.group_id ON DELETE CASCADE, 22.83 + listaddress VARCHAR(255), 22.84 + 22.85 + PRIMARY KEY(group_id, listaddress), 22.86 + UNIQUE(listaddress) 22.87 +) 22.88 +ENGINE = INNODB 22.89 +CHARACTER SET utf8; 22.90 + 22.91 +/* 22.92 + Configuration table, containing key/value pairs 22.93 + 22.94 + Normalization: 1NF, 2NF, 3NF 22.95 +*/ 22.96 +CREATE TABLE config 22.97 +( 22.98 + config_key VARCHAR(255), 22.99 + config_value TEXT, 22.100 + 22.101 + PRIMARY KEY(config_key) 22.102 +) 22.103 +ENGINE = INNODB 22.104 +CHARACTER SET utf8; 22.105 + 22.106 +/* 22.107 + Newsserver peers 22.108 + feedtype: 0: pullfeed 1: pushfeed 22.109 + Normalization: 1NF (atomic values), 2NF 22.110 +*/ 22.111 +CREATE TABLE peers 22.112 +( 22.113 + peer_id SERIAL, 22.114 + host VARCHAR(255), 22.115 + port SMALLINT UNSIGNED, 22.116 + 22.117 + PRIMARY KEY(peer_id), 22.118 + UNIQUE(host, port) 22.119 +) 22.120 +ENGINE = INNODB 22.121 +CHARACTER SET utf8; 22.122 + 22.123 +/* 22.124 + List of newsgroups to feed into sonews 22.125 + 22.126 + Normalization: 1NF, 2NF, 3NF 22.127 +*/ 22.128 +CREATE TABLE peer_subscriptions 22.129 +( 22.130 + peer_id INTEGER REFERENCES peers.peer_id ON DELETE CASCADE, 22.131 + group_id INTEGER REFERENCES groups.group_id ON DELETE CASCADE, 22.132 + feedtype TINYINT UNSIGNED DEFAULT 0, 22.133 + 22.134 + PRIMARY KEY(peer_id, group_id, feedtype) 22.135 +) 22.136 +ENGINE = INNODB 22.137 +CHARACTER SET utf8; 22.138 + 22.139 +/* 22.140 + Tables for server event statistics 22.141 + 22.142 + Possible statistic keys: 22.143 + 1=CONNECTIONS (active connections) 22.144 + 2=POSTED_NEWS (directly to the server posted unique messages) 22.145 + 3=GATEWAYED_NEWS (posted unique message gateways through the ML-gateway) 22.146 + 4=FEEDED_NEWS (unique messages feed via NNTP) 22.147 + 22.148 + The server will create snapshots of the above data. 22.149 + 22.150 + Normalization: 1NF, 2NF 22.151 +*/ 22.152 +CREATE TABLE events 22.153 +( 22.154 + event_time BIGINT UNSIGNED, /* time of this snapshot */ 22.155 + event_key TINYINT UNSIGNED, /* which data */ 22.156 + group_id INT REFERENCES groups.group_id ON DELETE CASCADE, 22.157 + 22.158 + PRIMARY KEY(event_time, event_key) 22.159 +) 22.160 +ENGINE = INNODB 22.161 +CHARACTER SET utf8;
23.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 23.2 +++ b/helpers/database_postgresql8_tmpl.sql Fri Jun 26 16:48:50 2009 +0200 23.3 @@ -0,0 +1,138 @@ 23.4 +/* 23.5 + Create a database at first: 23.6 + CREATE DATABASE sonews ENCODING 'UTF8'; 23.7 +*/ 23.8 + 23.9 +/* 23.10 + flags: 23.11 + If bit 0 is set, groups is a mirrorred mailing list. 23.12 + If not set default newsgroup. 23.13 + 23.14 + Normalization: 1NF, 2NF, 3NF 23.15 +*/ 23.16 +CREATE TABLE groups 23.17 +( 23.18 + group_id SERIAL, 23.19 + name VARCHAR(80) NOT NULL, 23.20 + flags SMALLINT DEFAULT 0, 23.21 + 23.22 + PRIMARY KEY(group_id), 23.23 + UNIQUE(name) 23.24 +); 23.25 + 23.26 +CREATE TABLE articles 23.27 +( 23.28 + article_id INT, 23.29 + body BYTEA, 23.30 + 23.31 + PRIMARY KEY(article_id) 23.32 +); 23.33 + 23.34 +CREATE TABLE article_ids 23.35 +( 23.36 + article_id INT REFERENCES articles(article_id) ON DELETE CASCADE, 23.37 + message_id VARCHAR(255), 23.38 + 23.39 + PRIMARY KEY(article_id), 23.40 + UNIQUE(message_id) 23.41 +); 23.42 + 23.43 +CREATE TABLE headers 23.44 +( 23.45 + article_id INT REFERENCES articles(article_id) ON DELETE CASCADE, 23.46 + header_key VARCHAR(255), 23.47 + header_value TEXT, 23.48 + header_index INT, 23.49 + 23.50 + PRIMARY KEY(article_id, header_key, header_index) 23.51 +); 23.52 + 23.53 +/* 23.54 + Normalization: 1NF, 2NF 23.55 +*/ 23.56 +CREATE TABLE postings 23.57 +( 23.58 + group_id INTEGER, 23.59 + article_id INTEGER REFERENCES articles (article_id) ON DELETE CASCADE, 23.60 + article_index INTEGER NOT NULL, 23.61 + 23.62 + PRIMARY KEY(group_id, article_id) 23.63 +); 23.64 + 23.65 +/* 23.66 + Table for association of newsgroups and mailing-lists 23.67 + 23.68 + Normalization: 1NF, 2NF, 3NF 23.69 +*/ 23.70 +CREATE TABLE groups2list 23.71 +( 23.72 + group_id INTEGER REFERENCES groups(group_id) ON DELETE CASCADE, 23.73 + listaddress VARCHAR(255), 23.74 + 23.75 + PRIMARY KEY(group_id, listaddress), 23.76 + UNIQUE(listaddress) 23.77 +); 23.78 + 23.79 +/* 23.80 + Configuration table, containing key/value pairs 23.81 + 23.82 + Normalization: 1NF, 2NF, 3NF 23.83 +*/ 23.84 +CREATE TABLE config 23.85 +( 23.86 + config_key VARCHAR(255), 23.87 + config_value TEXT, 23.88 + 23.89 + PRIMARY KEY(config_key) 23.90 +); 23.91 + 23.92 +/* 23.93 + Newsserver peers 23.94 + 23.95 + Normalization: 1NF (atomic values), 2NF 23.96 +*/ 23.97 +CREATE TABLE peers 23.98 +( 23.99 + peer_id SERIAL, 23.100 + host VARCHAR(255), 23.101 + port SMALLINT, 23.102 + 23.103 + PRIMARY KEY(peer_id), 23.104 + UNIQUE(host, port) 23.105 +); 23.106 + 23.107 +/* 23.108 + List of newsgroups to feed into sonews 23.109 + 23.110 + Normalization: 1NF, 2NF, 3NF 23.111 +*/ 23.112 +CREATE TABLE peer_subscriptions 23.113 +( 23.114 + peer_id INTEGER REFERENCES peers (peer_id) ON DELETE CASCADE, 23.115 + group_id INTEGER REFERENCES groups (group_id) ON DELETE CASCADE, 23.116 + feedtype SMALLINT DEFAULT 0, /* 0: pullfeed; 1: pushfeed */ 23.117 + 23.118 + PRIMARY KEY(peer_id, group_id, feedtype) 23.119 +); 23.120 + 23.121 +/* 23.122 + Tables for server event statistics 23.123 + 23.124 + Possible statistic keys: 23.125 + 1=CONNECTIONS (active connections) 23.126 + 2=POSTED_NEWS (directly to the server posted unique messages) 23.127 + 3=GATEWAYED_NEWS (posted unique message gateways through the ML-gateway) 23.128 + 4=FEEDED_NEWS (unique messages feed via NNTP) 23.129 + 23.130 + The server will create snapshots of the above data. 23.131 + 23.132 + Normalization: 1NF, 2NF 23.133 +*/ 23.134 +CREATE TABLE events 23.135 +( 23.136 + event_time BIGINT, /* time of this snapshot */ 23.137 + event_key SMALLINT, /* which data */ 23.138 + group_id INT REFERENCES groups(group_id) ON DELETE CASCADE, 23.139 + 23.140 + PRIMARY KEY(event_time, event_key) 23.141 +);
24.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 24.2 +++ b/helpers/helptext Fri Jun 26 16:48:50 2009 +0200 24.3 @@ -0,0 +1,12 @@ 24.4 +Welcome to sonews help system 24.5 + 24.6 +Here is a short overview of supported NNTP commands of this newsserver: 24.7 + 24.8 +ARTICLE <article-number|message-id> 24.9 + Retrieve article including its head 24.10 + 24.11 +GROUP <groupname> 24.12 + Change currently selected group 24.13 + 24.14 +POST 24.15 + Post an article to a newsgroup 24.16 \ No newline at end of file
25.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 25.2 +++ b/helpers/sonews Fri Jun 26 16:48:50 2009 +0200 25.3 @@ -0,0 +1,42 @@ 25.4 +#!/bin/bash 25.5 + 25.6 +CLASSPATH=/usr/share/java/sonews.jar:\ 25.7 +/usr/share/java/mysql-connector-java.jar:\ 25.8 +/usr/share/java/glassfish-mail.jar:\ 25.9 +/usr/share/java/postgresql.jar 25.10 + 25.11 +LOGFILE=/var/log/sonews.log 25.12 +PIDFILE=/var/run/sonews.pid 25.13 +ARGS="-mlgw -c /etc/sonews/sonews.conf -feed" 25.14 + 25.15 +MAINCLASS=org.sonews.daemon.Main 25.16 +JAVA=java 25.17 + 25.18 +case "$1" in 25.19 + start) 25.20 + echo "Starting sonews Newsserver..." 25.21 + $JAVA -classpath $CLASSPATH $MAINCLASS $ARGS &> $LOGFILE & 25.22 + PID=$! 25.23 + echo $PID > $PIDFILE 25.24 + ;; 25.25 + stop) 25.26 + echo "Stopping sonews Newsserver..." 25.27 + PID=`cat $PIDFILE` 25.28 + STOPRES=0 25.29 + while [ $STOPRES -le 0 ] 25.30 + do 25.31 + kill -15 $PID &> /dev/null 25.32 + STOPRES=$? 25.33 + sleep 1 25.34 + done 25.35 + echo "done." 25.36 + ;; 25.37 + setup) 25.38 + $JAVA -classpath $CLASSPATH org.sonews.util.DatabaseSetup 25.39 + ;; 25.40 + purge) 25.41 + $JAVA -classpath $CLASSPATH org.sonews.util.Purger 25.42 + ;; 25.43 + *) 25.44 + echo "Usage: sonews [start|stop|restart|setup|purge]" 25.45 +esac
26.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 26.2 +++ b/helpers/sonews-web Fri Jun 26 16:48:50 2009 +0200 26.3 @@ -0,0 +1,7 @@ 26.4 +#!/bin/bash 26.5 +export CLASSPATH=/usr/share/java/jchart2d.jar:/usr/share/java/sonews.jar 26.6 +ARG0=org.sonews.web.SonewsServlet@sonews 26.7 +ARG1=org.sonews.web.SonewsConfigServlet@sonews/config 26.8 +ARG2=org.sonews.web.SonewsPeerServlet@sonews/peer 26.9 +ARG3=org.sonews.web.SonewsChartServlet@sonews/chart 26.10 +/usr/bin/kitten -s $ARG0 -s $ARG1 -s $ARG2 -s $ARG3
27.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 27.2 +++ b/helpers/sonews.conf.sample Fri Jun 26 16:48:50 2009 +0200 27.3 @@ -0,0 +1,4 @@ 27.4 +sonews.storage.database=jdbc:mysql://localhost/sonews 27.5 +sonews.storage.user=sonews 27.6 +sonews.storage.dbmsdriver=com.mysql.jdbc.Driver 27.7 +sonews.storage.password=mySecret 27.8 \ No newline at end of file
28.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 28.2 +++ b/helpers/usage Fri Jun 26 16:48:50 2009 +0200 28.3 @@ -0,0 +1,8 @@ 28.4 +java -jar sonews.jar [arguments] 28.5 + where arguments: 28.6 + -c|-config <path to config file> if custom config file preferred 28.7 + -dumpjdbcdriver Prints out a list of available JDBC drivers 28.8 + -feed Enables feed daemon for pulling news from peer servers 28.9 + -h|-help This output 28.10 + -mlgw Enables the Mailinglist Gateway poller 28.11 + -useaux Enables an additional secondary port for listening
29.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 29.2 +++ b/makedeb Fri Jun 26 16:48:50 2009 +0200 29.3 @@ -0,0 +1,45 @@ 29.4 +#!/bin/bash -x 29.5 +PACKAGE_ROOT=sonews 29.6 + 29.7 +# Compile classes 29.8 +scons 29.9 + 29.10 +# Create JAR files; this cannot be done with SCons, 29.11 +# because Scons looses inner classes. 29.12 +jar -cf sonews.jar -C classes/ org/ 29.13 +jar -ufe sonews.jar org.sonews.daemon.Main 29.14 +jar -cf test.jar -C classes/ test/ 29.15 +jar -ufe test.jar test.TestBench 29.16 +jar -cf sonews-helpers.jar helpers/ 29.17 +jar -uf sonews.jar org/sonews/web/*.tmpl 29.18 + 29.19 +# Create faked root for packaging 29.20 +sudo rm -r $PACKAGE_ROOT/ 29.21 +mkdir -p $PACKAGE_ROOT/usr/share/java 29.22 +mkdir -p $PACKAGE_ROOT/usr/bin 29.23 +mkdir -p $PACKAGE_ROOT/etc/sonews 29.24 +mkdir -p $PACKAGE_ROOT/usr/share/doc/sonews/ 29.25 +cp -r DEBIAN $PACKAGE_ROOT/ 29.26 +cp helpers/sonews $PACKAGE_ROOT/usr/bin/sonews 29.27 +cp helpers/sonews.conf.sample $PACKAGE_ROOT/etc/sonews/sonews.conf 29.28 +cp helpers/copyright $PACKAGE_ROOT/usr/share/doc/sonews/ 29.29 +cp sonews*.jar $PACKAGE_ROOT/usr/share/java/ 29.30 + 29.31 +sudo chown root:root -R $PACKAGE_ROOT/ 29.32 + 29.33 +dpkg-deb --build $PACKAGE_ROOT 29.34 + 29.35 +# Cleanup 29.36 +sudo rm -r $PACKAGE_ROOT 29.37 +rm -r classes/ 29.38 + 29.39 +# Create metapackage sonews-web 29.40 +PACKAGE_ROOT=sonews-web 29.41 +mkdir $PACKAGE_ROOT 29.42 +cp -r DEBIAN-web $PACKAGE_ROOT/DEBIAN 29.43 +dpkg-deb --build $PACKAGE_ROOT 29.44 +rm -r $PACKAGE_ROOT 29.45 + 29.46 +# Check debs 29.47 +lintian sonews.deb 29.48 +lintian sonews-web.deb
30.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 30.2 +++ b/org/sonews/daemon/AbstractDaemon.java Fri Jun 26 16:48:50 2009 +0200 30.3 @@ -0,0 +1,105 @@ 30.4 +/* 30.5 + * SONEWS News Server 30.6 + * see AUTHORS for the list of contributors 30.7 + * 30.8 + * This program is free software: you can redistribute it and/or modify 30.9 + * it under the terms of the GNU General Public License as published by 30.10 + * the Free Software Foundation, either version 3 of the License, or 30.11 + * (at your option) any later version. 30.12 + * 30.13 + * This program is distributed in the hope that it will be useful, 30.14 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 30.15 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 30.16 + * GNU General Public License for more details. 30.17 + * 30.18 + * You should have received a copy of the GNU General Public License 30.19 + * along with this program. If not, see <http://www.gnu.org/licenses/>. 30.20 + */ 30.21 + 30.22 +package org.sonews.daemon; 30.23 + 30.24 +import java.sql.SQLException; 30.25 +import org.sonews.daemon.storage.Database; 30.26 +import org.sonews.util.Log; 30.27 + 30.28 +/** 30.29 + * Base class of all sonews threads. 30.30 + * Instances of this class will be automatically registered at the ShutdownHook 30.31 + * to be cleanly exited when the server is forced to exit. 30.32 + * @author Christian Lins 30.33 + * @since sonews/0.5.0 30.34 + */ 30.35 +public abstract class AbstractDaemon extends Thread 30.36 +{ 30.37 + 30.38 + /** This variable is write synchronized through setRunning */ 30.39 + private boolean isRunning = false; 30.40 + 30.41 + /** 30.42 + * Protected constructor. Will be called by derived classes. 30.43 + */ 30.44 + protected AbstractDaemon() 30.45 + { 30.46 + setDaemon(true); // VM will exit when all threads are daemons 30.47 + setName(getClass().getSimpleName()); 30.48 + } 30.49 + 30.50 + /** 30.51 + * @return true if shutdown() was not yet called. 30.52 + */ 30.53 + public boolean isRunning() 30.54 + { 30.55 + synchronized(this) 30.56 + { 30.57 + return this.isRunning; 30.58 + } 30.59 + } 30.60 + 30.61 + /** 30.62 + * Marks this thread to exit soon. Closes the associated Database connection 30.63 + * if available. 30.64 + * @throws java.sql.SQLException 30.65 + */ 30.66 + void shutdownNow() 30.67 + throws SQLException 30.68 + { 30.69 + synchronized(this) 30.70 + { 30.71 + this.isRunning = false; 30.72 + Database db = Database.getInstance(false); 30.73 + if(db != null) 30.74 + { 30.75 + db.shutdown(); 30.76 + } 30.77 + } 30.78 + } 30.79 + 30.80 + /** 30.81 + * Calls shutdownNow() but catches SQLExceptions if occurring. 30.82 + */ 30.83 + public void shutdown() 30.84 + { 30.85 + try 30.86 + { 30.87 + shutdownNow(); 30.88 + } 30.89 + catch(SQLException ex) 30.90 + { 30.91 + Log.msg(ex, true); 30.92 + } 30.93 + } 30.94 + 30.95 + /** 30.96 + * Starts this daemon. 30.97 + */ 30.98 + @Override 30.99 + public void start() 30.100 + { 30.101 + synchronized(this) 30.102 + { 30.103 + this.isRunning = true; 30.104 + } 30.105 + super.start(); 30.106 + } 30.107 + 30.108 +}
31.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 31.2 +++ b/org/sonews/daemon/BootstrapConfig.java Fri Jun 26 16:48:50 2009 +0200 31.3 @@ -0,0 +1,194 @@ 31.4 +/* 31.5 + * SONEWS News Server 31.6 + * see AUTHORS for the list of contributors 31.7 + * 31.8 + * This program is free software: you can redistribute it and/or modify 31.9 + * it under the terms of the GNU General Public License as published by 31.10 + * the Free Software Foundation, either version 3 of the License, or 31.11 + * (at your option) any later version. 31.12 + * 31.13 + * This program is distributed in the hope that it will be useful, 31.14 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 31.15 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 31.16 + * GNU General Public License for more details. 31.17 + * 31.18 + * You should have received a copy of the GNU General Public License 31.19 + * along with this program. If not, see <http://www.gnu.org/licenses/>. 31.20 + */ 31.21 + 31.22 +package org.sonews.daemon; 31.23 + 31.24 +import java.io.FileInputStream; 31.25 +import java.io.FileNotFoundException; 31.26 +import java.io.FileOutputStream; 31.27 +import java.io.IOException; 31.28 +import java.util.Properties; 31.29 +import org.sonews.util.AbstractConfig; 31.30 + 31.31 +/** 31.32 + * Manages the bootstrap configuration. It MUST contain all config values 31.33 + * that are needed to establish a database connection. 31.34 + * For further configuration values use the Config class instead as that class 31.35 + * stores its values within the database. 31.36 + * @author Christian Lins 31.37 + * @since sonews/0.5.0 31.38 + */ 31.39 +public final class BootstrapConfig extends AbstractConfig 31.40 +{ 31.41 + 31.42 + /** Key constant. If value is "true" every I/O is written to logfile 31.43 + * (which is a lot!) 31.44 + */ 31.45 + public static final String DEBUG = "sonews.debug"; 31.46 + 31.47 + /** Key constant. Value is classname of the JDBC driver */ 31.48 + public static final String STORAGE_DBMSDRIVER = "sonews.storage.dbmsdriver"; 31.49 + 31.50 + /** Key constant. Value is JDBC connect String to the database. */ 31.51 + public static final String STORAGE_DATABASE = "sonews.storage.database"; 31.52 + 31.53 + /** Key constant. Value is the username for the DBMS. */ 31.54 + public static final String STORAGE_USER = "sonews.storage.user"; 31.55 + 31.56 + /** Key constant. Value is the password for the DBMS. */ 31.57 + public static final String STORAGE_PASSWORD = "sonews.storage.password"; 31.58 + 31.59 + /** Key constant. Value is the name of the host which is allowed to use the 31.60 + * XDAEMON command; default: "localhost" */ 31.61 + public static final String XDAEMON_HOST = "sonews.xdaemon.host"; 31.62 + 31.63 + /** The config key for the filename of the logfile */ 31.64 + public static final String LOGFILE = "sonews.log"; 31.65 + 31.66 + /** The filename of the config file that is loaded on startup */ 31.67 + public static volatile String FILE = "sonews.conf"; 31.68 + 31.69 + private static final Properties defaultConfig = new Properties(); 31.70 + 31.71 + private static BootstrapConfig instance = null; 31.72 + 31.73 + static 31.74 + { 31.75 + // Set some default values 31.76 + defaultConfig.setProperty(STORAGE_DATABASE, "jdbc:mysql://localhost/sonews"); 31.77 + defaultConfig.setProperty(STORAGE_DBMSDRIVER, "com.mysql.jdbc.Driver"); 31.78 + defaultConfig.setProperty(STORAGE_USER, "sonews_user"); 31.79 + defaultConfig.setProperty(STORAGE_PASSWORD, "mysecret"); 31.80 + defaultConfig.setProperty(DEBUG, "false"); 31.81 + } 31.82 + 31.83 + /** 31.84 + * Note: this method is not thread-safe 31.85 + * @return A Config instance 31.86 + */ 31.87 + public static synchronized BootstrapConfig getInstance() 31.88 + { 31.89 + if(instance == null) 31.90 + { 31.91 + instance = new BootstrapConfig(); 31.92 + } 31.93 + return instance; 31.94 + } 31.95 + 31.96 + // Every config instance is initialized with the default values. 31.97 + private final Properties settings = (Properties)defaultConfig.clone(); 31.98 + 31.99 + /** 31.100 + * Config is a singelton class with only one instance at time. 31.101 + * So the constructor is private to prevent the creation of more 31.102 + * then one Config instance. 31.103 + * @see Config.getInstance() to retrieve an instance of Config 31.104 + */ 31.105 + private BootstrapConfig() 31.106 + { 31.107 + try 31.108 + { 31.109 + // Load settings from file 31.110 + load(); 31.111 + } 31.112 + catch(IOException ex) 31.113 + { 31.114 + ex.printStackTrace(); 31.115 + } 31.116 + } 31.117 + 31.118 + /** 31.119 + * Loads the configuration from the config file. By default this is done 31.120 + * by the (private) constructor but it can be useful to reload the config 31.121 + * by invoking this method. 31.122 + * @throws IOException 31.123 + */ 31.124 + public void load() 31.125 + throws IOException 31.126 + { 31.127 + FileInputStream in = null; 31.128 + 31.129 + try 31.130 + { 31.131 + in = new FileInputStream(FILE); 31.132 + settings.load(in); 31.133 + } 31.134 + catch (FileNotFoundException e) 31.135 + { 31.136 + // MUST NOT use Log otherwise endless loop 31.137 + System.err.println(e.getMessage()); 31.138 + save(); 31.139 + } 31.140 + finally 31.141 + { 31.142 + if(in != null) 31.143 + in.close(); 31.144 + } 31.145 + } 31.146 + 31.147 + /** 31.148 + * Saves this Config to the config file. By default this is done 31.149 + * at program end. 31.150 + * @throws FileNotFoundException 31.151 + * @throws IOException 31.152 + */ 31.153 + public void save() throws FileNotFoundException, IOException 31.154 + { 31.155 + FileOutputStream out = null; 31.156 + try 31.157 + { 31.158 + out = new FileOutputStream(FILE); 31.159 + settings.store(out, "SONEWS Config File"); 31.160 + out.flush(); 31.161 + } 31.162 + catch(IOException ex) 31.163 + { 31.164 + throw ex; 31.165 + } 31.166 + finally 31.167 + { 31.168 + if(out != null) 31.169 + out.close(); 31.170 + } 31.171 + } 31.172 + 31.173 + /** 31.174 + * Returns the value that is stored within this config 31.175 + * identified by the given key. If the key cannot be found 31.176 + * the default value is returned. 31.177 + * @param key Key to identify the value. 31.178 + * @param def The default value that is returned if the key 31.179 + * is not found in this Config. 31.180 + * @return 31.181 + */ 31.182 + public String get(String key, String def) 31.183 + { 31.184 + return settings.getProperty(key, def); 31.185 + } 31.186 + 31.187 + /** 31.188 + * Sets the value for a given key. 31.189 + * @param key 31.190 + * @param value 31.191 + */ 31.192 + public void set(final String key, final String value) 31.193 + { 31.194 + settings.setProperty(key, value); 31.195 + } 31.196 + 31.197 +}
32.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 32.2 +++ b/org/sonews/daemon/ChannelLineBuffers.java Fri Jun 26 16:48:50 2009 +0200 32.3 @@ -0,0 +1,270 @@ 32.4 +/* 32.5 + * SONEWS News Server 32.6 + * see AUTHORS for the list of contributors 32.7 + * 32.8 + * This program is free software: you can redistribute it and/or modify 32.9 + * it under the terms of the GNU General Public License as published by 32.10 + * the Free Software Foundation, either version 3 of the License, or 32.11 + * (at your option) any later version. 32.12 + * 32.13 + * This program is distributed in the hope that it will be useful, 32.14 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 32.15 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 32.16 + * GNU General Public License for more details. 32.17 + * 32.18 + * You should have received a copy of the GNU General Public License 32.19 + * along with this program. If not, see <http://www.gnu.org/licenses/>. 32.20 + */ 32.21 + 32.22 +package org.sonews.daemon; 32.23 + 32.24 +import java.nio.ByteBuffer; 32.25 +import java.nio.channels.ClosedChannelException; 32.26 +import java.util.ArrayList; 32.27 +import java.util.List; 32.28 + 32.29 +/** 32.30 + * Class holding ByteBuffers for SocketChannels/NNTPConnection. 32.31 + * Due to the complex nature of AIO/NIO we must properly handle the line 32.32 + * buffers for the input and output of the SocketChannels. 32.33 + * @author Christian Lins 32.34 + * @since sonews/0.5.0 32.35 + */ 32.36 +public class ChannelLineBuffers 32.37 +{ 32.38 + 32.39 + /** 32.40 + * Size of one small buffer; 32.41 + * per default this is 512 bytes to fit one standard line. 32.42 + */ 32.43 + public static final int BUFFER_SIZE = 512; 32.44 + 32.45 + private static int maxCachedBuffers = 2048; // Cached buffers maximum 32.46 + 32.47 + private static final List<ByteBuffer> freeSmallBuffers 32.48 + = new ArrayList<ByteBuffer>(maxCachedBuffers); 32.49 + 32.50 + /** 32.51 + * Allocates a predefined number of direct ByteBuffers (allocated via 32.52 + * ByteBuffer.allocateDirect()). This method is Thread-safe, but should only 32.53 + * called at startup. 32.54 + */ 32.55 + public static void allocateDirect() 32.56 + { 32.57 + synchronized(freeSmallBuffers) 32.58 + { 32.59 + for(int n = 0; n < maxCachedBuffers; n++) 32.60 + { 32.61 + ByteBuffer buffer = ByteBuffer.allocateDirect(BUFFER_SIZE); 32.62 + freeSmallBuffers.add(buffer); 32.63 + } 32.64 + } 32.65 + } 32.66 + 32.67 + private ByteBuffer inputBuffer = newLineBuffer(); 32.68 + private List<ByteBuffer> outputBuffers = new ArrayList<ByteBuffer>(); 32.69 + 32.70 + /** 32.71 + * Add the given ByteBuffer to the list of buffers to be send to the client. 32.72 + * This method is Thread-safe. 32.73 + * @param buffer 32.74 + * @throws java.nio.channels.ClosedChannelException If the client channel was 32.75 + * already closed. 32.76 + */ 32.77 + public void addOutputBuffer(ByteBuffer buffer) 32.78 + throws ClosedChannelException 32.79 + { 32.80 + if(outputBuffers == null) 32.81 + { 32.82 + throw new ClosedChannelException(); 32.83 + } 32.84 + 32.85 + synchronized(outputBuffers) 32.86 + { 32.87 + outputBuffers.add(buffer); 32.88 + } 32.89 + } 32.90 + 32.91 + /** 32.92 + * Currently a channel has only one input buffer. This *may* be a bottleneck 32.93 + * and should investigated in the future. 32.94 + * @param channel 32.95 + * @return The input buffer associated with given channel. 32.96 + */ 32.97 + public ByteBuffer getInputBuffer() 32.98 + { 32.99 + return inputBuffer; 32.100 + } 32.101 + 32.102 + /** 32.103 + * Returns the current output buffer for writing(!) to SocketChannel. 32.104 + * @param channel 32.105 + * @return The next input buffer that contains unprocessed data or null 32.106 + * if the connection was closed or there are no more unprocessed buffers. 32.107 + */ 32.108 + public ByteBuffer getOutputBuffer() 32.109 + { 32.110 + synchronized(outputBuffers) 32.111 + { 32.112 + if(outputBuffers == null || outputBuffers.isEmpty()) 32.113 + { 32.114 + return null; 32.115 + } 32.116 + else 32.117 + { 32.118 + ByteBuffer buffer = outputBuffers.get(0); 32.119 + if(buffer.remaining() == 0) 32.120 + { 32.121 + outputBuffers.remove(0); 32.122 + // Add old buffers to the list of free buffers 32.123 + recycleBuffer(buffer); 32.124 + buffer = getOutputBuffer(); 32.125 + } 32.126 + return buffer; 32.127 + } 32.128 + } 32.129 + } 32.130 + 32.131 + /** 32.132 + * Goes through the input buffer of the given channel and searches 32.133 + * for next line terminator. If a '\n' is found, the bytes up to the 32.134 + * line terminator are returned as array of bytes (the line terminator 32.135 + * is omitted). If none is found the method returns null. 32.136 + * @param channel 32.137 + * @return A ByteBuffer wrapping the line. 32.138 + */ 32.139 + ByteBuffer nextInputLine() 32.140 + { 32.141 + if(inputBuffer == null) 32.142 + { 32.143 + return null; 32.144 + } 32.145 + 32.146 + synchronized(inputBuffer) 32.147 + { 32.148 + ByteBuffer buffer = inputBuffer; 32.149 + 32.150 + // Mark the current write position 32.151 + int mark = buffer.position(); 32.152 + 32.153 + // Set position to 0 and limit to current position 32.154 + buffer.flip(); 32.155 + 32.156 + ByteBuffer lineBuffer = newLineBuffer(); 32.157 + 32.158 + while (buffer.position() < buffer.limit()) 32.159 + { 32.160 + byte b = buffer.get(); 32.161 + if (b == 10) // '\n' 32.162 + { 32.163 + // The bytes between the buffer's current position and its limit, 32.164 + // if any, are copied to the beginning of the buffer. That is, the 32.165 + // byte at index p = position() is copied to index zero, the byte at 32.166 + // index p + 1 is copied to index one, and so forth until the byte 32.167 + // at index limit() - 1 is copied to index n = limit() - 1 - p. 32.168 + // The buffer's position is then set to n+1 and its limit is set to 32.169 + // its capacity. 32.170 + buffer.compact(); 32.171 + 32.172 + lineBuffer.flip(); // limit to position, position to 0 32.173 + return lineBuffer; 32.174 + } 32.175 + else 32.176 + { 32.177 + lineBuffer.put(b); 32.178 + } 32.179 + } 32.180 + 32.181 + buffer.limit(BUFFER_SIZE); 32.182 + buffer.position(mark); 32.183 + 32.184 + if(buffer.hasRemaining()) 32.185 + { 32.186 + return null; 32.187 + } 32.188 + else 32.189 + { 32.190 + // In the first 512 was no newline found, so the input is not standard 32.191 + // compliant. We return the current buffer as new line and add a space 32.192 + // to the beginning of the next line which corrects some overlong header 32.193 + // lines. 32.194 + inputBuffer = newLineBuffer(); 32.195 + inputBuffer.put((byte)' '); 32.196 + buffer.flip(); 32.197 + return buffer; 32.198 + } 32.199 + } 32.200 + } 32.201 + 32.202 + /** 32.203 + * Returns a at least 512 bytes long ByteBuffer ready for usage. 32.204 + * The method first try to reuse an already allocated (cached) buffer but 32.205 + * if that fails returns a newly allocated direct buffer. 32.206 + * Use recycleBuffer() method when you do not longer use the allocated buffer. 32.207 + */ 32.208 + static ByteBuffer newLineBuffer() 32.209 + { 32.210 + ByteBuffer buf = null; 32.211 + synchronized(freeSmallBuffers) 32.212 + { 32.213 + if(!freeSmallBuffers.isEmpty()) 32.214 + { 32.215 + buf = freeSmallBuffers.remove(0); 32.216 + } 32.217 + } 32.218 + 32.219 + if(buf == null) 32.220 + { 32.221 + // Allocate a non-direct buffer 32.222 + buf = ByteBuffer.allocate(BUFFER_SIZE); 32.223 + } 32.224 + 32.225 + assert buf.position() == 0; 32.226 + assert buf.limit() >= BUFFER_SIZE; 32.227 + 32.228 + return buf; 32.229 + } 32.230 + 32.231 + /** 32.232 + * Adds the given buffer to the list of free buffers if it is a valuable 32.233 + * direct allocated buffer. 32.234 + * @param buffer 32.235 + */ 32.236 + public static void recycleBuffer(ByteBuffer buffer) 32.237 + { 32.238 + assert buffer != null; 32.239 + assert buffer.capacity() >= BUFFER_SIZE; 32.240 + 32.241 + if(buffer.isDirect()) 32.242 + { 32.243 + // Add old buffers to the list of free buffers 32.244 + synchronized(freeSmallBuffers) 32.245 + { 32.246 + buffer.clear(); // Set position to 0 and limit to capacity 32.247 + freeSmallBuffers.add(buffer); 32.248 + } 32.249 + } // if(buffer.isDirect()) 32.250 + } 32.251 + 32.252 + /** 32.253 + * Recycles all buffers of this ChannelLineBuffers object. 32.254 + */ 32.255 + public void recycleBuffers() 32.256 + { 32.257 + synchronized(inputBuffer) 32.258 + { 32.259 + recycleBuffer(inputBuffer); 32.260 + this.inputBuffer = null; 32.261 + } 32.262 + 32.263 + synchronized(outputBuffers) 32.264 + { 32.265 + for(ByteBuffer buf : outputBuffers) 32.266 + { 32.267 + recycleBuffer(buf); 32.268 + } 32.269 + outputBuffers = null; 32.270 + } 32.271 + } 32.272 + 32.273 +}
33.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 33.2 +++ b/org/sonews/daemon/ChannelReader.java Fri Jun 26 16:48:50 2009 +0200 33.3 @@ -0,0 +1,202 @@ 33.4 +/* 33.5 + * SONEWS News Server 33.6 + * see AUTHORS for the list of contributors 33.7 + * 33.8 + * This program is free software: you can redistribute it and/or modify 33.9 + * it under the terms of the GNU General Public License as published by 33.10 + * the Free Software Foundation, either version 3 of the License, or 33.11 + * (at your option) any later version. 33.12 + * 33.13 + * This program is distributed in the hope that it will be useful, 33.14 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 33.15 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 33.16 + * GNU General Public License for more details. 33.17 + * 33.18 + * You should have received a copy of the GNU General Public License 33.19 + * along with this program. If not, see <http://www.gnu.org/licenses/>. 33.20 + */ 33.21 + 33.22 +package org.sonews.daemon; 33.23 + 33.24 +import org.sonews.util.Log; 33.25 +import java.io.IOException; 33.26 +import java.nio.ByteBuffer; 33.27 +import java.nio.channels.CancelledKeyException; 33.28 +import java.nio.channels.SelectionKey; 33.29 +import java.nio.channels.Selector; 33.30 +import java.nio.channels.SocketChannel; 33.31 +import java.util.Iterator; 33.32 +import java.util.Set; 33.33 + 33.34 +/** 33.35 + * A Thread task listening for OP_READ events from SocketChannels. 33.36 + * @author Christian Lins 33.37 + * @since sonews/0.5.0 33.38 + */ 33.39 +class ChannelReader extends AbstractDaemon 33.40 +{ 33.41 + 33.42 + private static ChannelReader instance = new ChannelReader(); 33.43 + 33.44 + /** 33.45 + * @return Active ChannelReader instance. 33.46 + */ 33.47 + public static ChannelReader getInstance() 33.48 + { 33.49 + return instance; 33.50 + } 33.51 + 33.52 + private Selector selector = null; 33.53 + 33.54 + protected ChannelReader() 33.55 + { 33.56 + } 33.57 + 33.58 + /** 33.59 + * Sets the selector which is used by this reader to determine the channel 33.60 + * to read from. 33.61 + * @param selector 33.62 + */ 33.63 + public void setSelector(final Selector selector) 33.64 + { 33.65 + this.selector = selector; 33.66 + } 33.67 + 33.68 + /** 33.69 + * Run loop. Blocks until some data is available in a channel. 33.70 + */ 33.71 + @Override 33.72 + public void run() 33.73 + { 33.74 + assert selector != null; 33.75 + 33.76 + while(isRunning()) 33.77 + { 33.78 + try 33.79 + { 33.80 + // select() blocks until some SelectableChannels are ready for 33.81 + // processing. There is no need to lock the selector as we have only 33.82 + // one thread per selector. 33.83 + selector.select(); 33.84 + 33.85 + // Get list of selection keys with pending events. 33.86 + // Note: the selected key set is not thread-safe 33.87 + SocketChannel channel = null; 33.88 + NNTPConnection conn = null; 33.89 + final Set<SelectionKey> selKeys = selector.selectedKeys(); 33.90 + SelectionKey selKey = null; 33.91 + 33.92 + synchronized (selKeys) 33.93 + { 33.94 + Iterator it = selKeys.iterator(); 33.95 + 33.96 + // Process the first pending event 33.97 + while (it.hasNext()) 33.98 + { 33.99 + selKey = (SelectionKey) it.next(); 33.100 + channel = (SocketChannel) selKey.channel(); 33.101 + conn = Connections.getInstance().get(channel); 33.102 + 33.103 + // Because we cannot lock the selKey as that would cause a deadlock 33.104 + // we lock the connection. To preserve the order of the received 33.105 + // byte blocks a selection key for a connection that has pending 33.106 + // read events is skipped. 33.107 + if (conn == null || conn.tryReadLock()) 33.108 + { 33.109 + // Remove from set to indicate that it's being processed 33.110 + it.remove(); 33.111 + if (conn != null) 33.112 + { 33.113 + break; // End while loop 33.114 + } 33.115 + } 33.116 + else 33.117 + { 33.118 + selKey = null; 33.119 + channel = null; 33.120 + conn = null; 33.121 + } 33.122 + } 33.123 + } 33.124 + 33.125 + // Do not lock the selKeys while processing because this causes 33.126 + // a deadlock in sun.nio.ch.SelectorImpl.lockAndDoSelect() 33.127 + if (selKey != null && channel != null && conn != null) 33.128 + { 33.129 + processSelectionKey(conn, channel, selKey); 33.130 + conn.unlockReadLock(); 33.131 + } 33.132 + 33.133 + } 33.134 + catch(CancelledKeyException ex) 33.135 + { 33.136 + Log.msg("ChannelReader.run(): " + ex, false); 33.137 + if(Log.isDebug()) 33.138 + { 33.139 + ex.printStackTrace(); 33.140 + } 33.141 + } 33.142 + catch(Exception ex) 33.143 + { 33.144 + ex.printStackTrace(); 33.145 + } 33.146 + 33.147 + // Eventually wait for a register operation 33.148 + synchronized (NNTPDaemon.RegisterGate) 33.149 + { 33.150 + // Do nothing; FindBugs may warn about an empty synchronized 33.151 + // statement, but we cannot use a wait()/notify() mechanism here. 33.152 + // If we used something like RegisterGate.wait() we block here 33.153 + // until the NNTPDaemon calls notify(). But the daemon only 33.154 + // calls notify() if itself is NOT blocked in the listening socket. 33.155 + } 33.156 + } // while(isRunning()) 33.157 + } 33.158 + 33.159 + private void processSelectionKey(final NNTPConnection connection, 33.160 + final SocketChannel socketChannel, final SelectionKey selKey) 33.161 + throws InterruptedException, IOException 33.162 + { 33.163 + assert selKey != null; 33.164 + assert selKey.isReadable(); 33.165 + 33.166 + // Some bytes are available for reading 33.167 + if(selKey.isValid()) 33.168 + { 33.169 + // Lock the channel 33.170 + //synchronized(socketChannel) 33.171 + { 33.172 + // Read the data into the appropriate buffer 33.173 + ByteBuffer buf = connection.getInputBuffer(); 33.174 + int read = -1; 33.175 + try 33.176 + { 33.177 + read = socketChannel.read(buf); 33.178 + } 33.179 + catch(Exception ex) 33.180 + { 33.181 + Log.msg("ChannelReader.processSelectionKey(): " + ex, false); 33.182 + if(Log.isDebug()) 33.183 + { 33.184 + ex.printStackTrace(); 33.185 + } 33.186 + } 33.187 + 33.188 + if(read == -1) // End of stream 33.189 + { 33.190 + selKey.cancel(); 33.191 + } 33.192 + else if(read > 0) // If some data was read 33.193 + { 33.194 + ConnectionWorker.addChannel(socketChannel); 33.195 + } 33.196 + } 33.197 + } 33.198 + else 33.199 + { 33.200 + // Should not happen 33.201 + Log.msg(selKey, false); 33.202 + } 33.203 + } 33.204 + 33.205 +}
34.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 34.2 +++ b/org/sonews/daemon/ChannelWriter.java Fri Jun 26 16:48:50 2009 +0200 34.3 @@ -0,0 +1,207 @@ 34.4 +/* 34.5 + * SONEWS News Server 34.6 + * see AUTHORS for the list of contributors 34.7 + * 34.8 + * This program is free software: you can redistribute it and/or modify 34.9 + * it under the terms of the GNU General Public License as published by 34.10 + * the Free Software Foundation, either version 3 of the License, or 34.11 + * (at your option) any later version. 34.12 + * 34.13 + * This program is distributed in the hope that it will be useful, 34.14 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 34.15 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 34.16 + * GNU General Public License for more details. 34.17 + * 34.18 + * You should have received a copy of the GNU General Public License 34.19 + * along with this program. If not, see <http://www.gnu.org/licenses/>. 34.20 + */ 34.21 + 34.22 +package org.sonews.daemon; 34.23 + 34.24 +import org.sonews.util.Log; 34.25 +import java.io.IOException; 34.26 +import java.nio.ByteBuffer; 34.27 +import java.nio.channels.CancelledKeyException; 34.28 +import java.nio.channels.SelectionKey; 34.29 +import java.nio.channels.Selector; 34.30 +import java.nio.channels.SocketChannel; 34.31 +import java.util.Iterator; 34.32 + 34.33 +/** 34.34 + * A Thread task that processes OP_WRITE events for SocketChannels. 34.35 + * @author Christian Lins 34.36 + * @since sonews/0.5.0 34.37 + */ 34.38 +class ChannelWriter extends AbstractDaemon 34.39 +{ 34.40 + 34.41 + private static ChannelWriter instance = new ChannelWriter(); 34.42 + 34.43 + /** 34.44 + * @return Returns the active ChannelWriter instance. 34.45 + */ 34.46 + public static ChannelWriter getInstance() 34.47 + { 34.48 + return instance; 34.49 + } 34.50 + 34.51 + private Selector selector = null; 34.52 + 34.53 + protected ChannelWriter() 34.54 + { 34.55 + } 34.56 + 34.57 + /** 34.58 + * @return Selector associated with this instance. 34.59 + */ 34.60 + public Selector getSelector() 34.61 + { 34.62 + return this.selector; 34.63 + } 34.64 + 34.65 + /** 34.66 + * Sets the selector that is used by this ChannelWriter. 34.67 + * @param selector 34.68 + */ 34.69 + public void setSelector(final Selector selector) 34.70 + { 34.71 + this.selector = selector; 34.72 + } 34.73 + 34.74 + /** 34.75 + * Run loop. 34.76 + */ 34.77 + @Override 34.78 + public void run() 34.79 + { 34.80 + assert selector != null; 34.81 + 34.82 + while(isRunning()) 34.83 + { 34.84 + try 34.85 + { 34.86 + SelectionKey selKey = null; 34.87 + SocketChannel socketChannel = null; 34.88 + NNTPConnection connection = null; 34.89 + 34.90 + // select() blocks until some SelectableChannels are ready for 34.91 + // processing. There is no need to synchronize the selector as we 34.92 + // have only one thread per selector. 34.93 + selector.select(); // The return value of select can be ignored 34.94 + 34.95 + // Get list of selection keys with pending OP_WRITE events. 34.96 + // The keySET is not thread-safe whereas the keys itself are. 34.97 + Iterator it = selector.selectedKeys().iterator(); 34.98 + 34.99 + while (it.hasNext()) 34.100 + { 34.101 + // We remove the first event from the set and store it for 34.102 + // later processing. 34.103 + selKey = (SelectionKey) it.next(); 34.104 + socketChannel = (SocketChannel) selKey.channel(); 34.105 + connection = Connections.getInstance().get(socketChannel); 34.106 + 34.107 + it.remove(); 34.108 + if (connection != null) 34.109 + { 34.110 + break; 34.111 + } 34.112 + else 34.113 + { 34.114 + selKey = null; 34.115 + } 34.116 + } 34.117 + 34.118 + if (selKey != null) 34.119 + { 34.120 + try 34.121 + { 34.122 + // Process the selected key. 34.123 + // As there is only one OP_WRITE key for a given channel, we need 34.124 + // not to synchronize this processing to retain the order. 34.125 + processSelectionKey(connection, socketChannel, selKey); 34.126 + } 34.127 + catch (IOException ex) 34.128 + { 34.129 + Log.msg("Error writing to channel: " + ex, false); 34.130 + 34.131 + // Cancel write events for this channel 34.132 + selKey.cancel(); 34.133 + connection.shutdownInput(); 34.134 + connection.shutdownOutput(); 34.135 + } 34.136 + } 34.137 + 34.138 + // Eventually wait for a register operation 34.139 + synchronized(NNTPDaemon.RegisterGate) { /* do nothing */ } 34.140 + } 34.141 + catch(CancelledKeyException ex) 34.142 + { 34.143 + Log.msg("ChannelWriter.run(): " + ex, true); 34.144 + } 34.145 + catch(Exception ex) 34.146 + { 34.147 + ex.printStackTrace(); 34.148 + } 34.149 + } // while(isRunning()) 34.150 + } 34.151 + 34.152 + private void processSelectionKey(final NNTPConnection connection, 34.153 + final SocketChannel socketChannel, final SelectionKey selKey) 34.154 + throws InterruptedException, IOException 34.155 + { 34.156 + assert connection != null; 34.157 + assert socketChannel != null; 34.158 + assert selKey != null; 34.159 + assert selKey.isWritable(); 34.160 + 34.161 + // SocketChannel is ready for writing 34.162 + if(selKey.isValid()) 34.163 + { 34.164 + // Lock the socket channel 34.165 + synchronized(socketChannel) 34.166 + { 34.167 + // Get next output buffer 34.168 + ByteBuffer buf = connection.getOutputBuffer(); 34.169 + if(buf == null) 34.170 + { 34.171 + // Currently we have nothing to write, so we stop the writeable 34.172 + // events until we have something to write to the socket channel 34.173 + //selKey.cancel(); 34.174 + selKey.interestOps(0); 34.175 + return; 34.176 + } 34.177 + 34.178 + while(buf != null) // There is data to be send 34.179 + { 34.180 + // Write buffer to socket channel; this method does not block 34.181 + if(socketChannel.write(buf) <= 0) 34.182 + { 34.183 + // Perhaps there is data to be written, but the SocketChannel's 34.184 + // buffer is full, so we stop writing to until the next event. 34.185 + break; 34.186 + } 34.187 + else 34.188 + { 34.189 + // Retrieve next buffer if available; method may return the same 34.190 + // buffer instance if it still have some bytes remaining 34.191 + buf = connection.getOutputBuffer(); 34.192 + } 34.193 + } 34.194 + } 34.195 + } 34.196 + else 34.197 + { 34.198 + Log.msg("Invalid OP_WRITE key: " + selKey, false); 34.199 + 34.200 + if (socketChannel.socket().isClosed()) 34.201 + { 34.202 + connection.shutdownInput(); 34.203 + connection.shutdownOutput(); 34.204 + socketChannel.close(); 34.205 + Log.msg("Connection closed.", true); 34.206 + } 34.207 + } 34.208 + } 34.209 + 34.210 +}
35.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 35.2 +++ b/org/sonews/daemon/Config.java Fri Jun 26 16:48:50 2009 +0200 35.3 @@ -0,0 +1,149 @@ 35.4 +/* 35.5 + * SONEWS News Server 35.6 + * see AUTHORS for the list of contributors 35.7 + * 35.8 + * This program is free software: you can redistribute it and/or modify 35.9 + * it under the terms of the GNU General Public License as published by 35.10 + * the Free Software Foundation, either version 3 of the License, or 35.11 + * (at your option) any later version. 35.12 + * 35.13 + * This program is distributed in the hope that it will be useful, 35.14 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 35.15 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 35.16 + * GNU General Public License for more details. 35.17 + * 35.18 + * You should have received a copy of the GNU General Public License 35.19 + * along with this program. If not, see <http://www.gnu.org/licenses/>. 35.20 + */ 35.21 + 35.22 +package org.sonews.daemon; 35.23 + 35.24 +import org.sonews.util.Log; 35.25 +import java.sql.SQLException; 35.26 +import org.sonews.daemon.storage.Database; 35.27 +import org.sonews.util.AbstractConfig; 35.28 +import org.sonews.util.TimeoutMap; 35.29 + 35.30 +/** 35.31 + * Provides access to the program wide configuration that is stored within 35.32 + * the server's database. 35.33 + * @author Christian Lins 35.34 + * @since sonews/0.5.0 35.35 + */ 35.36 +public final class Config extends AbstractConfig 35.37 +{ 35.38 + 35.39 + /** Config key constant. Value is the maximum article size in kilobytes. */ 35.40 + public static final String ARTICLE_MAXSIZE = "sonews.article.maxsize"; 35.41 + 35.42 + /** Config key constant. Value: Amount of news that are feeded per run. */ 35.43 + public static final String FEED_NEWSPERRUN = "sonews.feed.newsperrun"; 35.44 + public static final String FEED_PULLINTERVAL = "sonews.feed.pullinterval"; 35.45 + public static final String HOSTNAME = "sonews.hostname"; 35.46 + public static final String PORT = "sonews.port"; 35.47 + public static final String TIMEOUT = "sonews.timeout"; 35.48 + public static final String MLPOLL_DELETEUNKNOWN = "sonews.mlpoll.deleteunknown"; 35.49 + public static final String MLPOLL_HOST = "sonews.mlpoll.host"; 35.50 + public static final String MLPOLL_PASSWORD = "sonews.mlpoll.password"; 35.51 + public static final String MLPOLL_USER = "sonews.mlpoll.user"; 35.52 + public static final String MLSEND_ADDRESS = "sonews.mlsend.address"; 35.53 + public static final String MLSEND_RW_FROM = "sonews.mlsend.rewrite.from"; 35.54 + public static final String MLSEND_RW_SENDER = "sonews.mlsend.rewrite.sender"; 35.55 + public static final String MLSEND_HOST = "sonews.mlsend.host"; 35.56 + public static final String MLSEND_PASSWORD = "sonews.mlsend.password"; 35.57 + public static final String MLSEND_PORT = "sonews.mlsend.port"; 35.58 + public static final String MLSEND_USER = "sonews.mlsend.user"; 35.59 + 35.60 + public static final String[] AVAILABLE_KEYS = { 35.61 + Config.ARTICLE_MAXSIZE, 35.62 + Config.FEED_NEWSPERRUN, 35.63 + Config.FEED_PULLINTERVAL, 35.64 + Config.HOSTNAME, 35.65 + Config.MLPOLL_DELETEUNKNOWN, 35.66 + Config.MLPOLL_HOST, 35.67 + Config.MLPOLL_PASSWORD, 35.68 + Config.MLPOLL_USER, 35.69 + Config.MLSEND_ADDRESS, 35.70 + Config.MLSEND_HOST, 35.71 + Config.MLSEND_PASSWORD, 35.72 + Config.MLSEND_PORT, 35.73 + Config.MLSEND_RW_FROM, 35.74 + Config.MLSEND_RW_SENDER, 35.75 + Config.MLSEND_USER, 35.76 + Config.PORT, 35.77 + Config.TIMEOUT 35.78 + }; 35.79 + 35.80 + private static Config instance = new Config(); 35.81 + 35.82 + public static Config getInstance() 35.83 + { 35.84 + return instance; 35.85 + } 35.86 + 35.87 + private final TimeoutMap<String, String> values 35.88 + = new TimeoutMap<String, String>(); 35.89 + 35.90 + private Config() 35.91 + { 35.92 + super(); 35.93 + } 35.94 + 35.95 + /** 35.96 + * Returns the config value for the given key or the defaultValue if the 35.97 + * key is not found in config. 35.98 + * @param key 35.99 + * @param defaultValue 35.100 + * @return 35.101 + */ 35.102 + public String get(String key, String defaultValue) 35.103 + { 35.104 + try 35.105 + { 35.106 + String configValue = values.get(key); 35.107 + if(configValue == null) 35.108 + { 35.109 + configValue = Database.getInstance().getConfigValue(key); 35.110 + if(configValue == null) 35.111 + { 35.112 + return defaultValue; 35.113 + } 35.114 + else 35.115 + { 35.116 + values.put(key, configValue); 35.117 + return configValue; 35.118 + } 35.119 + } 35.120 + else 35.121 + { 35.122 + return configValue; 35.123 + } 35.124 + } 35.125 + catch(SQLException ex) 35.126 + { 35.127 + Log.msg(ex.getMessage(), false); 35.128 + return defaultValue; 35.129 + } 35.130 + } 35.131 + 35.132 + /** 35.133 + * Sets the config value which is identified by the given key. 35.134 + * @param key 35.135 + * @param value 35.136 + */ 35.137 + public void set(String key, String value) 35.138 + { 35.139 + values.put(key, value); 35.140 + 35.141 + try 35.142 + { 35.143 + // Write values to database 35.144 + Database.getInstance().setConfigValue(key, value); 35.145 + } 35.146 + catch(SQLException ex) 35.147 + { 35.148 + ex.printStackTrace(); 35.149 + } 35.150 + } 35.151 + 35.152 +}
36.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 36.2 +++ b/org/sonews/daemon/ConnectionWorker.java Fri Jun 26 16:48:50 2009 +0200 36.3 @@ -0,0 +1,102 @@ 36.4 +/* 36.5 + * SONEWS News Server 36.6 + * see AUTHORS for the list of contributors 36.7 + * 36.8 + * This program is free software: you can redistribute it and/or modify 36.9 + * it under the terms of the GNU General Public License as published by 36.10 + * the Free Software Foundation, either version 3 of the License, or 36.11 + * (at your option) any later version. 36.12 + * 36.13 + * This program is distributed in the hope that it will be useful, 36.14 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 36.15 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 36.16 + * GNU General Public License for more details. 36.17 + * 36.18 + * You should have received a copy of the GNU General Public License 36.19 + * along with this program. If not, see <http://www.gnu.org/licenses/>. 36.20 + */ 36.21 + 36.22 +package org.sonews.daemon; 36.23 + 36.24 +import org.sonews.util.Log; 36.25 +import java.nio.ByteBuffer; 36.26 +import java.nio.channels.SocketChannel; 36.27 +import java.util.concurrent.ArrayBlockingQueue; 36.28 + 36.29 +/** 36.30 + * Does most of the work: parsing input, talking to client and Database. 36.31 + * @author Christian Lins 36.32 + * @since sonews/0.5.0 36.33 + */ 36.34 +class ConnectionWorker extends AbstractDaemon 36.35 +{ 36.36 + 36.37 + // 256 pending events should be enough 36.38 + private static ArrayBlockingQueue<SocketChannel> pendingChannels 36.39 + = new ArrayBlockingQueue<SocketChannel>(256, true); 36.40 + 36.41 + /** 36.42 + * Registers the given channel for further event processing. 36.43 + * @param channel 36.44 + */ 36.45 + public static void addChannel(SocketChannel channel) 36.46 + throws InterruptedException 36.47 + { 36.48 + pendingChannels.put(channel); 36.49 + } 36.50 + 36.51 + /** 36.52 + * Processing loop. 36.53 + */ 36.54 + @Override 36.55 + public void run() 36.56 + { 36.57 + while(isRunning()) 36.58 + { 36.59 + try 36.60 + { 36.61 + // Retrieve and remove if available, otherwise wait. 36.62 + SocketChannel channel = pendingChannels.take(); 36.63 + 36.64 + if(channel != null) 36.65 + { 36.66 + // Connections.getInstance().get() MAY return null 36.67 + NNTPConnection conn = Connections.getInstance().get(channel); 36.68 + 36.69 + // Try to lock the connection object 36.70 + if(conn != null && conn.tryReadLock()) 36.71 + { 36.72 + ByteBuffer buf = conn.getBuffers().nextInputLine(); 36.73 + while(buf != null) // Complete line was received 36.74 + { 36.75 + final byte[] line = new byte[buf.limit()]; 36.76 + buf.get(line); 36.77 + ChannelLineBuffers.recycleBuffer(buf); 36.78 + 36.79 + // Here is the actual work done 36.80 + conn.lineReceived(line); 36.81 + 36.82 + // Read next line as we could have already received the next line 36.83 + buf = conn.getBuffers().nextInputLine(); 36.84 + } 36.85 + conn.unlockReadLock(); 36.86 + } 36.87 + else 36.88 + { 36.89 + addChannel(channel); 36.90 + } 36.91 + } 36.92 + } 36.93 + catch(InterruptedException ex) 36.94 + { 36.95 + Log.msg("ConnectionWorker interrupted: " + ex, true); 36.96 + } 36.97 + catch(Exception ex) 36.98 + { 36.99 + Log.msg("Exception in ConnectionWorker: " + ex, false); 36.100 + ex.printStackTrace(); 36.101 + } 36.102 + } // end while(isRunning()) 36.103 + } 36.104 + 36.105 +}
37.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 37.2 +++ b/org/sonews/daemon/Connections.java Fri Jun 26 16:48:50 2009 +0200 37.3 @@ -0,0 +1,176 @@ 37.4 +/* 37.5 + * SONEWS News Server 37.6 + * see AUTHORS for the list of contributors 37.7 + * 37.8 + * This program is free software: you can redistribute it and/or modify 37.9 + * it under the terms of the GNU General Public License as published by 37.10 + * the Free Software Foundation, either version 3 of the License, or 37.11 + * (at your option) any later version. 37.12 + * 37.13 + * This program is distributed in the hope that it will be useful, 37.14 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 37.15 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 37.16 + * GNU General Public License for more details. 37.17 + * 37.18 + * You should have received a copy of the GNU General Public License 37.19 + * along with this program. If not, see <http://www.gnu.org/licenses/>. 37.20 + */ 37.21 + 37.22 +package org.sonews.daemon; 37.23 + 37.24 +import org.sonews.util.Log; 37.25 +import java.io.IOException; 37.26 +import java.net.InetSocketAddress; 37.27 +import java.net.Socket; 37.28 +import java.nio.channels.SocketChannel; 37.29 +import java.util.ArrayList; 37.30 +import java.util.HashMap; 37.31 +import java.util.List; 37.32 +import java.util.ListIterator; 37.33 +import java.util.Map; 37.34 +import org.sonews.util.Stats; 37.35 + 37.36 +/** 37.37 + * Daemon thread collecting all NNTPConnection instances. The thread 37.38 + * checks periodically if there are stale/timed out connections and 37.39 + * removes and purges them properly. 37.40 + * @author Christian Lins 37.41 + * @since sonews/0.5.0 37.42 + */ 37.43 +final class Connections extends AbstractDaemon 37.44 +{ 37.45 + 37.46 + private static final Connections instance = new Connections(); 37.47 + 37.48 + /** 37.49 + * @return Active Connections instance. 37.50 + */ 37.51 + public static Connections getInstance() 37.52 + { 37.53 + return Connections.instance; 37.54 + } 37.55 + 37.56 + private final List<NNTPConnection> connections 37.57 + = new ArrayList<NNTPConnection>(); 37.58 + private final Map<SocketChannel, NNTPConnection> connByChannel 37.59 + = new HashMap<SocketChannel, NNTPConnection>(); 37.60 + 37.61 + private Connections() 37.62 + { 37.63 + setName("Connections"); 37.64 + } 37.65 + 37.66 + /** 37.67 + * Adds the given NNTPConnection to the Connections management. 37.68 + * @param conn 37.69 + * @see org.sonews.daemon.NNTPConnection 37.70 + */ 37.71 + public void add(final NNTPConnection conn) 37.72 + { 37.73 + synchronized(this.connections) 37.74 + { 37.75 + this.connections.add(conn); 37.76 + this.connByChannel.put(conn.getChannel(), conn); 37.77 + } 37.78 + } 37.79 + 37.80 + /** 37.81 + * @param channel 37.82 + * @return NNTPConnection instance that is associated with the given 37.83 + * SocketChannel. 37.84 + */ 37.85 + public NNTPConnection get(final SocketChannel channel) 37.86 + { 37.87 + synchronized(this.connections) 37.88 + { 37.89 + return this.connByChannel.get(channel); 37.90 + } 37.91 + } 37.92 + 37.93 + int getConnectionCount(String remote) 37.94 + { 37.95 + int cnt = 0; 37.96 + synchronized(this.connections) 37.97 + { 37.98 + for(NNTPConnection conn : this.connections) 37.99 + { 37.100 + assert conn != null; 37.101 + assert conn.getChannel() != null; 37.102 + 37.103 + Socket socket = conn.getChannel().socket(); 37.104 + if(socket != null) 37.105 + { 37.106 + InetSocketAddress sockAddr = (InetSocketAddress)socket.getRemoteSocketAddress(); 37.107 + if(sockAddr != null) 37.108 + { 37.109 + if(sockAddr.getHostName().equals(remote)) 37.110 + { 37.111 + cnt++; 37.112 + } 37.113 + } 37.114 + } // if(socket != null) 37.115 + } 37.116 + } 37.117 + return cnt; 37.118 + } 37.119 + 37.120 + /** 37.121 + * Run loops. Checks periodically for timed out connections and purged them 37.122 + * from the lists. 37.123 + */ 37.124 + @Override 37.125 + public void run() 37.126 + { 37.127 + while(isRunning()) 37.128 + { 37.129 + int timeoutMillis = 1000 * Config.getInstance().get(Config.TIMEOUT, 180); 37.130 + 37.131 + synchronized (this.connections) 37.132 + { 37.133 + final ListIterator<NNTPConnection> iter = this.connections.listIterator(); 37.134 + NNTPConnection conn; 37.135 + 37.136 + while (iter.hasNext()) 37.137 + { 37.138 + conn = iter.next(); 37.139 + if((System.currentTimeMillis() - conn.getLastActivity()) > timeoutMillis) 37.140 + { 37.141 + // A connection timeout has occurred so purge the connection 37.142 + iter.remove(); 37.143 + 37.144 + // Close and remove the channel 37.145 + SocketChannel channel = conn.getChannel(); 37.146 + connByChannel.remove(channel); 37.147 + 37.148 + try 37.149 + { 37.150 + // Close the channel; implicitely cancels all selectionkeys 37.151 + channel.close(); 37.152 + Log.msg("Disconnected: " + channel.socket().getRemoteSocketAddress() + 37.153 + " (timeout)", true); 37.154 + } 37.155 + catch(IOException ex) 37.156 + { 37.157 + Log.msg("Connections.run(): " + ex, false); 37.158 + } 37.159 + 37.160 + // Recycle the used buffers 37.161 + conn.getBuffers().recycleBuffers(); 37.162 + 37.163 + Stats.getInstance().clientDisconnect(); 37.164 + } 37.165 + } 37.166 + } 37.167 + 37.168 + try 37.169 + { 37.170 + Thread.sleep(10000); // Sleep ten seconds 37.171 + } 37.172 + catch(InterruptedException ex) 37.173 + { 37.174 + Log.msg("Connections Thread was interrupted: " + ex.getMessage(), false); 37.175 + } 37.176 + } 37.177 + } 37.178 + 37.179 +}
38.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 38.2 +++ b/org/sonews/daemon/LineEncoder.java Fri Jun 26 16:48:50 2009 +0200 38.3 @@ -0,0 +1,80 @@ 38.4 +/* 38.5 + * SONEWS News Server 38.6 + * see AUTHORS for the list of contributors 38.7 + * 38.8 + * This program is free software: you can redistribute it and/or modify 38.9 + * it under the terms of the GNU General Public License as published by 38.10 + * the Free Software Foundation, either version 3 of the License, or 38.11 + * (at your option) any later version. 38.12 + * 38.13 + * This program is distributed in the hope that it will be useful, 38.14 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 38.15 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 38.16 + * GNU General Public License for more details. 38.17 + * 38.18 + * You should have received a copy of the GNU General Public License 38.19 + * along with this program. If not, see <http://www.gnu.org/licenses/>. 38.20 + */ 38.21 + 38.22 +package org.sonews.daemon; 38.23 + 38.24 +import java.nio.ByteBuffer; 38.25 +import java.nio.CharBuffer; 38.26 +import java.nio.channels.ClosedChannelException; 38.27 +import java.nio.charset.Charset; 38.28 +import java.nio.charset.CharsetEncoder; 38.29 +import java.nio.charset.CoderResult; 38.30 + 38.31 +/** 38.32 + * Encodes a line to buffers using the correct charset. 38.33 + * @author Christian Lins 38.34 + * @since sonews/0.5.0 38.35 + */ 38.36 +class LineEncoder 38.37 +{ 38.38 + 38.39 + private CharBuffer characters; 38.40 + private Charset charset; 38.41 + 38.42 + /** 38.43 + * Constructs new LineEncoder. 38.44 + * @param characters 38.45 + * @param charset 38.46 + */ 38.47 + public LineEncoder(CharBuffer characters, Charset charset) 38.48 + { 38.49 + this.characters = characters; 38.50 + this.charset = charset; 38.51 + } 38.52 + 38.53 + /** 38.54 + * Encodes the characters of this instance to the given ChannelLineBuffers 38.55 + * using the Charset of this instance. 38.56 + * @param buffer 38.57 + * @throws java.nio.channels.ClosedChannelException 38.58 + */ 38.59 + public void encode(ChannelLineBuffers buffer) 38.60 + throws ClosedChannelException 38.61 + { 38.62 + CharsetEncoder encoder = charset.newEncoder(); 38.63 + while (characters.hasRemaining()) 38.64 + { 38.65 + ByteBuffer buf = ChannelLineBuffers.newLineBuffer(); 38.66 + assert buf.position() == 0; 38.67 + assert buf.capacity() >= 512; 38.68 + 38.69 + CoderResult res = encoder.encode(characters, buf, true); 38.70 + 38.71 + // Set limit to current position and current position to 0; 38.72 + // means make ready for read from buffer 38.73 + buf.flip(); 38.74 + buffer.addOutputBuffer(buf); 38.75 + 38.76 + if (res.isUnderflow()) // All input processed 38.77 + { 38.78 + break; 38.79 + } 38.80 + } 38.81 + } 38.82 + 38.83 +}
39.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 39.2 +++ b/org/sonews/daemon/Main.java Fri Jun 26 16:48:50 2009 +0200 39.3 @@ -0,0 +1,160 @@ 39.4 +/* 39.5 + * SONEWS News Server 39.6 + * see AUTHORS for the list of contributors 39.7 + * 39.8 + * This program is free software: you can redistribute it and/or modify 39.9 + * it under the terms of the GNU General Public License as published by 39.10 + * the Free Software Foundation, either version 3 of the License, or 39.11 + * (at your option) any later version. 39.12 + * 39.13 + * This program is distributed in the hope that it will be useful, 39.14 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 39.15 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 39.16 + * GNU General Public License for more details. 39.17 + * 39.18 + * You should have received a copy of the GNU General Public License 39.19 + * along with this program. If not, see <http://www.gnu.org/licenses/>. 39.20 + */ 39.21 + 39.22 +package org.sonews.daemon; 39.23 + 39.24 +import java.sql.Driver; 39.25 +import java.sql.DriverManager; 39.26 +import java.sql.SQLException; 39.27 +import java.util.Enumeration; 39.28 +import java.util.Date; 39.29 +import org.sonews.feed.FeedManager; 39.30 +import org.sonews.mlgw.MailPoller; 39.31 +import org.sonews.daemon.storage.Database; 39.32 +import org.sonews.util.Log; 39.33 +import org.sonews.util.io.Resource; 39.34 + 39.35 +/** 39.36 + * Startup class of the daemon. 39.37 + * @author Christian Lins 39.38 + * @since sonews/0.5.0 39.39 + */ 39.40 +public final class Main 39.41 +{ 39.42 + 39.43 + private Main() 39.44 + { 39.45 + } 39.46 + 39.47 + /** Version information of the sonews daemon */ 39.48 + public static final String VERSION = "sonews/0.5.0"; 39.49 + public static final Date STARTDATE = new Date(); 39.50 + 39.51 + /** 39.52 + * The main entrypoint. 39.53 + * @param args 39.54 + * @throws Exception 39.55 + */ 39.56 + public static void main(String[] args) throws Exception 39.57 + { 39.58 + System.out.println(VERSION); 39.59 + Thread.currentThread().setName("Mainthread"); 39.60 + 39.61 + // Command line arguments 39.62 + boolean feed = false; // Enable feeding? 39.63 + boolean mlgw = false; // Enable Mailinglist gateway? 39.64 + int port = -1; 39.65 + 39.66 + for(int n = 0; n < args.length; n++) 39.67 + { 39.68 + if(args[n].equals("-c") || args[n].equals("-config")) 39.69 + { 39.70 + BootstrapConfig.FILE = args[++n]; 39.71 + System.out.println("Using config file " + args[n]); 39.72 + } 39.73 + else if(args[n].equals("-dumpjdbcdriver")) 39.74 + { 39.75 + System.out.println("Available JDBC drivers:"); 39.76 + Enumeration<Driver> drvs = DriverManager.getDrivers(); 39.77 + while(drvs.hasMoreElements()) 39.78 + { 39.79 + System.out.println(drvs.nextElement()); 39.80 + } 39.81 + return; 39.82 + } 39.83 + else if(args[n].equals("-feed")) 39.84 + { 39.85 + feed = true; 39.86 + } 39.87 + else if(args[n].equals("-h") || args[n].equals("-help")) 39.88 + { 39.89 + printArguments(); 39.90 + return; 39.91 + } 39.92 + else if(args[n].equals("-mlgw")) 39.93 + { 39.94 + mlgw = true; 39.95 + } 39.96 + else if(args[n].equals("-p")) 39.97 + { 39.98 + port = Integer.parseInt(args[++n]); 39.99 + } 39.100 + } 39.101 + 39.102 + // Try to load the Database; 39.103 + // Do NOT USE Config or Log classes before this point because they require 39.104 + // a working Database connection. 39.105 + try 39.106 + { 39.107 + Database.getInstance(); 39.108 + 39.109 + // Make sure some elementary groups are existing 39.110 + if(!Database.getInstance().isGroupExisting("control")) 39.111 + { 39.112 + Database.getInstance().addGroup("control", 0); 39.113 + Log.msg("Group 'control' created.", true); 39.114 + } 39.115 + } 39.116 + catch(SQLException ex) 39.117 + { 39.118 + ex.printStackTrace(); 39.119 + System.err.println("Database initialization failed with " + ex.toString()); 39.120 + System.err.println("Make sure you have specified the correct database" + 39.121 + " settings in sonews.conf!"); 39.122 + return; 39.123 + } 39.124 + 39.125 + ChannelLineBuffers.allocateDirect(); 39.126 + 39.127 + // Add shutdown hook 39.128 + Runtime.getRuntime().addShutdownHook(new ShutdownHook()); 39.129 + 39.130 + // Start the listening daemon 39.131 + if(port <= 0) 39.132 + { 39.133 + port = Config.getInstance().get(Config.PORT, 119); 39.134 + } 39.135 + final NNTPDaemon daemon = NNTPDaemon.createInstance(port); 39.136 + daemon.start(); 39.137 + 39.138 + // Start Connections purger thread... 39.139 + Connections.getInstance().start(); 39.140 + 39.141 + // Start mailinglist gateway... 39.142 + if(mlgw) 39.143 + { 39.144 + new MailPoller().start(); 39.145 + } 39.146 + 39.147 + // Start feeds 39.148 + if(feed) 39.149 + { 39.150 + FeedManager.startFeeding(); 39.151 + } 39.152 + 39.153 + // Wait for main thread to exit (setDaemon(false)) 39.154 + daemon.join(); 39.155 + } 39.156 + 39.157 + private static void printArguments() 39.158 + { 39.159 + String usage = Resource.getAsString("helpers/usage", true); 39.160 + System.out.println(usage); 39.161 + } 39.162 + 39.163 +}
40.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 40.2 +++ b/org/sonews/daemon/NNTPConnection.java Fri Jun 26 16:48:50 2009 +0200 40.3 @@ -0,0 +1,480 @@ 40.4 +/* 40.5 + * SONEWS News Server 40.6 + * see AUTHORS for the list of contributors 40.7 + * 40.8 + * This program is free software: you can redistribute it and/or modify 40.9 + * it under the terms of the GNU General Public License as published by 40.10 + * the Free Software Foundation, either version 3 of the License, or 40.11 + * (at your option) any later version. 40.12 + * 40.13 + * This program is distributed in the hope that it will be useful, 40.14 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 40.15 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 40.16 + * GNU General Public License for more details. 40.17 + * 40.18 + * You should have received a copy of the GNU General Public License 40.19 + * along with this program. If not, see <http://www.gnu.org/licenses/>. 40.20 + */ 40.21 + 40.22 +package org.sonews.daemon; 40.23 + 40.24 +import org.sonews.util.Log; 40.25 +import java.io.IOException; 40.26 +import java.net.InetSocketAddress; 40.27 +import java.nio.ByteBuffer; 40.28 +import java.nio.CharBuffer; 40.29 +import java.nio.channels.ClosedChannelException; 40.30 +import java.nio.channels.SelectionKey; 40.31 +import java.nio.channels.SocketChannel; 40.32 +import java.nio.charset.Charset; 40.33 +import java.util.Timer; 40.34 +import java.util.TimerTask; 40.35 +import org.sonews.daemon.command.ArticleCommand; 40.36 +import org.sonews.daemon.command.CapabilitiesCommand; 40.37 +import org.sonews.daemon.command.AbstractCommand; 40.38 +import org.sonews.daemon.command.GroupCommand; 40.39 +import org.sonews.daemon.command.HelpCommand; 40.40 +import org.sonews.daemon.command.ListCommand; 40.41 +import org.sonews.daemon.command.ListGroupCommand; 40.42 +import org.sonews.daemon.command.ModeReaderCommand; 40.43 +import org.sonews.daemon.command.NewGroupsCommand; 40.44 +import org.sonews.daemon.command.NextPrevCommand; 40.45 +import org.sonews.daemon.command.OverCommand; 40.46 +import org.sonews.daemon.command.PostCommand; 40.47 +import org.sonews.daemon.command.QuitCommand; 40.48 +import org.sonews.daemon.command.StatCommand; 40.49 +import org.sonews.daemon.command.UnsupportedCommand; 40.50 +import org.sonews.daemon.command.XDaemonCommand; 40.51 +import org.sonews.daemon.command.XPatCommand; 40.52 +import org.sonews.daemon.storage.Article; 40.53 +import org.sonews.daemon.storage.Group; 40.54 +import org.sonews.util.Stats; 40.55 + 40.56 +/** 40.57 + * For every SocketChannel (so TCP/IP connection) there is an instance of 40.58 + * this class. 40.59 + * @author Christian Lins 40.60 + * @since sonews/0.5.0 40.61 + */ 40.62 +public final class NNTPConnection 40.63 +{ 40.64 + 40.65 + public static final String NEWLINE = "\r\n"; // RFC defines this as newline 40.66 + public static final String MESSAGE_ID_PATTERN = "<[^>]+>"; 40.67 + 40.68 + private static final Timer cancelTimer = new Timer(true); // Thread-safe? True for run as daemon 40.69 + 40.70 + /** SocketChannel is generally thread-safe */ 40.71 + private SocketChannel channel = null; 40.72 + private Charset charset = Charset.forName("UTF-8"); 40.73 + private AbstractCommand command = null; 40.74 + private Article currentArticle = null; 40.75 + private Group currentGroup = null; 40.76 + private volatile long lastActivity = System.currentTimeMillis(); 40.77 + private ChannelLineBuffers lineBuffers = new ChannelLineBuffers(); 40.78 + private int readLock = 0; 40.79 + private final Object readLockGate = new Object(); 40.80 + private SelectionKey writeSelKey = null; 40.81 + 40.82 + public NNTPConnection(final SocketChannel channel) 40.83 + throws IOException 40.84 + { 40.85 + if(channel == null) 40.86 + { 40.87 + throw new IllegalArgumentException("channel is null"); 40.88 + } 40.89 + 40.90 + this.channel = channel; 40.91 + Stats.getInstance().clientConnect(); 40.92 + } 40.93 + 40.94 + /** 40.95 + * Tries to get the read lock for this NNTPConnection. This method is Thread- 40.96 + * safe and returns true of the read lock was successfully set. If the lock 40.97 + * is still hold by another Thread the method returns false. 40.98 + */ 40.99 + boolean tryReadLock() 40.100 + { 40.101 + // As synchronizing simple types may cause deadlocks, 40.102 + // we use a gate object. 40.103 + synchronized(readLockGate) 40.104 + { 40.105 + if(readLock != 0) 40.106 + { 40.107 + return false; 40.108 + } 40.109 + else 40.110 + { 40.111 + readLock = Thread.currentThread().hashCode(); 40.112 + return true; 40.113 + } 40.114 + } 40.115 + } 40.116 + 40.117 + /** 40.118 + * Releases the read lock in a Thread-safe way. 40.119 + * @throws IllegalMonitorStateException if a Thread not holding the lock 40.120 + * tries to release it. 40.121 + */ 40.122 + void unlockReadLock() 40.123 + { 40.124 + synchronized(readLockGate) 40.125 + { 40.126 + if(readLock == Thread.currentThread().hashCode()) 40.127 + { 40.128 + readLock = 0; 40.129 + } 40.130 + else 40.131 + { 40.132 + throw new IllegalMonitorStateException(); 40.133 + } 40.134 + } 40.135 + } 40.136 + 40.137 + /** 40.138 + * @return Current input buffer of this NNTPConnection instance. 40.139 + */ 40.140 + public ByteBuffer getInputBuffer() 40.141 + { 40.142 + return this.lineBuffers.getInputBuffer(); 40.143 + } 40.144 + 40.145 + /** 40.146 + * @return Output buffer of this NNTPConnection which has at least one byte 40.147 + * free storage. 40.148 + */ 40.149 + public ByteBuffer getOutputBuffer() 40.150 + { 40.151 + return this.lineBuffers.getOutputBuffer(); 40.152 + } 40.153 + 40.154 + /** 40.155 + * @return ChannelLineBuffers instance associated with this NNTPConnection. 40.156 + */ 40.157 + public ChannelLineBuffers getBuffers() 40.158 + { 40.159 + return this.lineBuffers; 40.160 + } 40.161 + 40.162 + /** 40.163 + * @return true if this connection comes from a local remote address. 40.164 + */ 40.165 + public boolean isLocalConnection() 40.166 + { 40.167 + return ((InetSocketAddress)this.channel.socket().getRemoteSocketAddress()) 40.168 + .getHostName().equalsIgnoreCase("localhost"); 40.169 + } 40.170 + 40.171 + void setWriteSelectionKey(SelectionKey selKey) 40.172 + { 40.173 + this.writeSelKey = selKey; 40.174 + } 40.175 + 40.176 + public void shutdownInput() 40.177 + { 40.178 + try 40.179 + { 40.180 + // Closes the input line of the channel's socket, so no new data 40.181 + // will be received and a timeout can be triggered. 40.182 + this.channel.socket().shutdownInput(); 40.183 + } 40.184 + catch(IOException ex) 40.185 + { 40.186 + Log.msg("Exception in NNTPConnection.shutdownInput(): " + ex, false); 40.187 + if(Log.isDebug()) 40.188 + { 40.189 + ex.printStackTrace(); 40.190 + } 40.191 + } 40.192 + } 40.193 + 40.194 + public void shutdownOutput() 40.195 + { 40.196 + cancelTimer.schedule(new TimerTask() 40.197 + { 40.198 + @Override 40.199 + public void run() 40.200 + { 40.201 + try 40.202 + { 40.203 + // Closes the output line of the channel's socket. 40.204 + channel.socket().shutdownOutput(); 40.205 + channel.close(); 40.206 + } 40.207 + catch(Exception ex) 40.208 + { 40.209 + Log.msg("NNTPConnection.shutdownOutput(): " + ex, false); 40.210 + if(Log.isDebug()) 40.211 + { 40.212 + ex.printStackTrace(); 40.213 + } 40.214 + } 40.215 + } 40.216 + }, 3000); 40.217 + } 40.218 + 40.219 + public SocketChannel getChannel() 40.220 + { 40.221 + return this.channel; 40.222 + } 40.223 + 40.224 + public Article getCurrentArticle() 40.225 + { 40.226 + return this.currentArticle; 40.227 + } 40.228 + 40.229 + public Charset getCurrentCharset() 40.230 + { 40.231 + return this.charset; 40.232 + } 40.233 + 40.234 + public Group getCurrentGroup() 40.235 + { 40.236 + return this.currentGroup; 40.237 + } 40.238 + 40.239 + public void setCurrentArticle(final Article article) 40.240 + { 40.241 + this.currentArticle = article; 40.242 + } 40.243 + 40.244 + public void setCurrentGroup(final Group group) 40.245 + { 40.246 + this.currentGroup = group; 40.247 + } 40.248 + 40.249 + public long getLastActivity() 40.250 + { 40.251 + return this.lastActivity; 40.252 + } 40.253 + 40.254 + /** 40.255 + * Due to the readLockGate there is no need to synchronize this method. 40.256 + * @param raw 40.257 + * @throws IllegalArgumentException if raw is null. 40.258 + * @throws IllegalStateException if calling thread does not own the readLock. 40.259 + */ 40.260 + void lineReceived(byte[] raw) 40.261 + { 40.262 + if(raw == null) 40.263 + { 40.264 + throw new IllegalArgumentException("raw is null"); 40.265 + } 40.266 + 40.267 + if(readLock == 0 || readLock != Thread.currentThread().hashCode()) 40.268 + { 40.269 + throw new IllegalStateException("readLock not properly set"); 40.270 + } 40.271 + 40.272 + this.lastActivity = System.currentTimeMillis(); 40.273 + 40.274 + String line = new String(raw, this.charset); 40.275 + 40.276 + // There might be a trailing \r, but trim() is a bad idea 40.277 + // as it removes also leading spaces from long header lines. 40.278 + if(line.endsWith("\r")) 40.279 + { 40.280 + line = line.substring(0, line.length() - 1); 40.281 + } 40.282 + 40.283 + Log.msg("<< " + line, true); 40.284 + 40.285 + if(command == null) 40.286 + { 40.287 + command = parseCommandLine(line); 40.288 + assert command != null; 40.289 + } 40.290 + 40.291 + try 40.292 + { 40.293 + // The command object will process the line we just received 40.294 + command.processLine(line); 40.295 + } 40.296 + catch(ClosedChannelException ex0) 40.297 + { 40.298 + try 40.299 + { 40.300 + Log.msg("Connection to " + channel.socket().getRemoteSocketAddress() 40.301 + + " closed: " + ex0, true); 40.302 + } 40.303 + catch(Exception ex0a) 40.304 + { 40.305 + ex0a.printStackTrace(); 40.306 + } 40.307 + } 40.308 + catch(Exception ex1) 40.309 + { 40.310 + try 40.311 + { 40.312 + command = null; 40.313 + ex1.printStackTrace(); 40.314 + println("500 Internal server error"); 40.315 + } 40.316 + catch(Exception ex2) 40.317 + { 40.318 + ex2.printStackTrace(); 40.319 + } 40.320 + } 40.321 + 40.322 + if(command == null || command.hasFinished()) 40.323 + { 40.324 + command = null; 40.325 + charset = Charset.forName("UTF-8"); // Reset to default 40.326 + } 40.327 + } 40.328 + 40.329 + /** 40.330 + * This method performes several if/elseif constructs to determine the 40.331 + * fitting command object. 40.332 + * TODO: This string comparisons are probably slow! 40.333 + * @param line 40.334 + * @return 40.335 + */ 40.336 + private AbstractCommand parseCommandLine(String line) 40.337 + { 40.338 + AbstractCommand cmd = new UnsupportedCommand(this); 40.339 + String cmdStr = line.split(" ")[0]; 40.340 + 40.341 + if(cmdStr.equalsIgnoreCase("ARTICLE") || 40.342 + cmdStr.equalsIgnoreCase("BODY")) 40.343 + { 40.344 + cmd = new ArticleCommand(this); 40.345 + } 40.346 + else if(cmdStr.equalsIgnoreCase("CAPABILITIES")) 40.347 + { 40.348 + cmd = new CapabilitiesCommand(this); 40.349 + } 40.350 + else if(cmdStr.equalsIgnoreCase("GROUP")) 40.351 + { 40.352 + cmd = new GroupCommand(this); 40.353 + } 40.354 + else if(cmdStr.equalsIgnoreCase("HEAD")) 40.355 + { 40.356 + cmd = new ArticleCommand(this); 40.357 + } 40.358 + else if(cmdStr.equalsIgnoreCase("HELP")) 40.359 + { 40.360 + cmd = new HelpCommand(this); 40.361 + } 40.362 + else if(cmdStr.equalsIgnoreCase("LIST")) 40.363 + { 40.364 + cmd = new ListCommand(this); 40.365 + } 40.366 + else if(cmdStr.equalsIgnoreCase("LISTGROUP")) 40.367 + { 40.368 + cmd = new ListGroupCommand(this); 40.369 + } 40.370 + else if(cmdStr.equalsIgnoreCase("MODE")) 40.371 + { 40.372 + cmd = new ModeReaderCommand(this); 40.373 + } 40.374 + else if(cmdStr.equalsIgnoreCase("NEWGROUPS")) 40.375 + { 40.376 + cmd = new NewGroupsCommand(this); 40.377 + } 40.378 + else if(cmdStr.equalsIgnoreCase("NEXT") || 40.379 + cmdStr.equalsIgnoreCase("PREV")) 40.380 + { 40.381 + cmd = new NextPrevCommand(this); 40.382 + } 40.383 + else if(cmdStr.equalsIgnoreCase("OVER") || 40.384 + cmdStr.equalsIgnoreCase("XOVER")) // for compatibility with older RFCs 40.385 + { 40.386 + cmd = new OverCommand(this); 40.387 + } 40.388 + else if(cmdStr.equalsIgnoreCase("POST")) 40.389 + { 40.390 + cmd = new PostCommand(this); 40.391 + } 40.392 + else if(cmdStr.equalsIgnoreCase("QUIT")) 40.393 + { 40.394 + cmd = new QuitCommand(this); 40.395 + } 40.396 + else if(cmdStr.equalsIgnoreCase("STAT")) 40.397 + { 40.398 + cmd = new StatCommand(this); 40.399 + } 40.400 + else if(cmdStr.equalsIgnoreCase("XDAEMON")) 40.401 + { 40.402 + cmd = new XDaemonCommand(this); 40.403 + } 40.404 + else if(cmdStr.equalsIgnoreCase("XPAT")) 40.405 + { 40.406 + cmd = new XPatCommand(this); 40.407 + } 40.408 + 40.409 + return cmd; 40.410 + } 40.411 + 40.412 + /** 40.413 + * Puts the given line into the output buffer, adds a newline character 40.414 + * and returns. The method returns immediately and does not block until 40.415 + * the line was sent. If line is longer than 510 octets it is split up in 40.416 + * several lines. Each line is terminated by \r\n (NNTPConnection.NEWLINE). 40.417 + * @param line 40.418 + */ 40.419 + public void println(final CharSequence line, final Charset charset) 40.420 + throws IOException 40.421 + { 40.422 + writeToChannel(CharBuffer.wrap(line), charset, line); 40.423 + writeToChannel(CharBuffer.wrap(NEWLINE), charset, null); 40.424 + } 40.425 + 40.426 + /** 40.427 + * Encodes the given CharBuffer using the given Charset to a bunch of 40.428 + * ByteBuffers (each 512 bytes large) and enqueues them for writing at the 40.429 + * connected SocketChannel. 40.430 + * @throws java.io.IOException 40.431 + */ 40.432 + private void writeToChannel(CharBuffer characters, final Charset charset, 40.433 + CharSequence debugLine) 40.434 + throws IOException 40.435 + { 40.436 + if(!charset.canEncode()) 40.437 + { 40.438 + Log.msg("FATAL: Charset " + charset + " cannot encode!", false); 40.439 + return; 40.440 + } 40.441 + 40.442 + // Write characters to output buffers 40.443 + LineEncoder lenc = new LineEncoder(characters, charset); 40.444 + lenc.encode(lineBuffers); 40.445 + 40.446 + // Enable OP_WRITE events so that the buffers are processed 40.447 + try 40.448 + { 40.449 + this.writeSelKey.interestOps(SelectionKey.OP_WRITE); 40.450 + ChannelWriter.getInstance().getSelector().wakeup(); 40.451 + } 40.452 + catch (Exception ex) // CancelledKeyException and ChannelCloseException 40.453 + { 40.454 + Log.msg("NNTPConnection.writeToChannel(): " + ex, false); 40.455 + return; 40.456 + } 40.457 + 40.458 + // Update last activity timestamp 40.459 + this.lastActivity = System.currentTimeMillis(); 40.460 + if(debugLine != null) 40.461 + { 40.462 + Log.msg(">> " + debugLine, true); 40.463 + } 40.464 + } 40.465 + 40.466 + public void println(final CharSequence line) 40.467 + throws IOException 40.468 + { 40.469 + println(line, charset); 40.470 + } 40.471 + 40.472 + public void print(final String line) 40.473 + throws IOException 40.474 + { 40.475 + writeToChannel(CharBuffer.wrap(line), charset, line); 40.476 + } 40.477 + 40.478 + public void setCurrentCharset(final Charset charset) 40.479 + { 40.480 + this.charset = charset; 40.481 + } 40.482 + 40.483 +}
41.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 41.2 +++ b/org/sonews/daemon/NNTPDaemon.java Fri Jun 26 16:48:50 2009 +0200 41.3 @@ -0,0 +1,195 @@ 41.4 +/* 41.5 + * SONEWS News Server 41.6 + * see AUTHORS for the list of contributors 41.7 + * 41.8 + * This program is free software: you can redistribute it and/or modify 41.9 + * it under the terms of the GNU General Public License as published by 41.10 + * the Free Software Foundation, either version 3 of the License, or 41.11 + * (at your option) any later version. 41.12 + * 41.13 + * This program is distributed in the hope that it will be useful, 41.14 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 41.15 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 41.16 + * GNU General Public License for more details. 41.17 + * 41.18 + * You should have received a copy of the GNU General Public License 41.19 + * along with this program. If not, see <http://www.gnu.org/licenses/>. 41.20 + */ 41.21 + 41.22 +package org.sonews.daemon; 41.23 + 41.24 +import org.sonews.util.Log; 41.25 +import java.io.IOException; 41.26 +import java.net.BindException; 41.27 +import java.net.InetSocketAddress; 41.28 +import java.net.ServerSocket; 41.29 +import java.nio.channels.CancelledKeyException; 41.30 +import java.nio.channels.ClosedChannelException; 41.31 +import java.nio.channels.SelectionKey; 41.32 +import java.nio.channels.Selector; 41.33 +import java.nio.channels.ServerSocketChannel; 41.34 +import java.nio.channels.SocketChannel; 41.35 + 41.36 +/** 41.37 + * NNTP daemon using SelectableChannels. 41.38 + * @author Christian Lins 41.39 + * @since sonews/0.5.0 41.40 + */ 41.41 +public final class NNTPDaemon extends AbstractDaemon 41.42 +{ 41.43 + 41.44 + public static final Object RegisterGate = new Object(); 41.45 + 41.46 + private static NNTPDaemon instance = null; 41.47 + 41.48 + public static synchronized NNTPDaemon createInstance(int port) 41.49 + { 41.50 + if(instance == null) 41.51 + { 41.52 + instance = new NNTPDaemon(port); 41.53 + return instance; 41.54 + } 41.55 + else 41.56 + { 41.57 + throw new RuntimeException("NNTPDaemon.createInstance() called twice"); 41.58 + } 41.59 + } 41.60 + 41.61 + private int port; 41.62 + 41.63 + private NNTPDaemon(final int port) 41.64 + { 41.65 + Log.msg("Server listening on port " + port, false); 41.66 + this.port = port; 41.67 + } 41.68 + 41.69 + @Override 41.70 + public void run() 41.71 + { 41.72 + try 41.73 + { 41.74 + // Create a Selector that handles the SocketChannel multiplexing 41.75 + final Selector readSelector = Selector.open(); 41.76 + final Selector writeSelector = Selector.open(); 41.77 + 41.78 + // Start working threads 41.79 + final int workerThreads = Runtime.getRuntime().availableProcessors() * 4; 41.80 + ConnectionWorker[] cworkers = new ConnectionWorker[workerThreads]; 41.81 + for(int n = 0; n < workerThreads; n++) 41.82 + { 41.83 + cworkers[n] = new ConnectionWorker(); 41.84 + cworkers[n].start(); 41.85 + } 41.86 + 41.87 + ChannelWriter.getInstance().setSelector(writeSelector); 41.88 + ChannelReader.getInstance().setSelector(readSelector); 41.89 + ChannelWriter.getInstance().start(); 41.90 + ChannelReader.getInstance().start(); 41.91 + 41.92 + final ServerSocketChannel serverSocketChannel = ServerSocketChannel.open(); 41.93 + serverSocketChannel.configureBlocking(true); // Set to blocking mode 41.94 + 41.95 + // Configure ServerSocket; bind to socket... 41.96 + final ServerSocket serverSocket = serverSocketChannel.socket(); 41.97 + serverSocket.bind(new InetSocketAddress(this.port)); 41.98 + 41.99 + while(isRunning()) 41.100 + { 41.101 + SocketChannel socketChannel; 41.102 + 41.103 + try 41.104 + { 41.105 + // As we set the server socket channel to blocking mode the accept() 41.106 + // method will block. 41.107 + socketChannel = serverSocketChannel.accept(); 41.108 + socketChannel.configureBlocking(false); 41.109 + assert socketChannel.isConnected(); 41.110 + assert socketChannel.finishConnect(); 41.111 + } 41.112 + catch(IOException ex) 41.113 + { 41.114 + // Under heavy load an IOException "Too many open files may 41.115 + // be thrown. It most cases we should slow down the connection 41.116 + // accepting, to give the worker threads some time to process work. 41.117 + Log.msg("IOException while accepting connection: " + ex.getMessage(), false); 41.118 + Log.msg("Connection accepting sleeping for seconds...", true); 41.119 + Thread.sleep(5000); // 5 seconds 41.120 + continue; 41.121 + } 41.122 + 41.123 + final NNTPConnection conn; 41.124 + try 41.125 + { 41.126 + conn = new NNTPConnection(socketChannel); 41.127 + Connections.getInstance().add(conn); 41.128 + } 41.129 + catch(IOException ex) 41.130 + { 41.131 + Log.msg(ex.getLocalizedMessage(), false); 41.132 + socketChannel.close(); 41.133 + continue; 41.134 + } 41.135 + 41.136 + try 41.137 + { 41.138 + SelectionKey selKeyWrite = 41.139 + registerSelector(writeSelector, socketChannel, SelectionKey.OP_WRITE); 41.140 + registerSelector(readSelector, socketChannel, SelectionKey.OP_READ); 41.141 + 41.142 + Log.msg("Connected: " + socketChannel.socket().getRemoteSocketAddress(), true); 41.143 + 41.144 + // Set write selection key and send hello to client 41.145 + conn.setWriteSelectionKey(selKeyWrite); 41.146 + conn.println("200 " + Config.getInstance().get(Config.HOSTNAME, "localhost") 41.147 + + " " + Main.VERSION + " news server ready - (posting ok)."); 41.148 + } 41.149 + catch(CancelledKeyException cke) 41.150 + { 41.151 + Log.msg("CancelledKeyException " + cke.getMessage() + " was thrown: " 41.152 + + socketChannel.socket(), false); 41.153 + } 41.154 + catch(ClosedChannelException cce) 41.155 + { 41.156 + Log.msg("ClosedChannelException " + cce.getMessage() + " was thrown: " 41.157 + + socketChannel.socket(), false); 41.158 + } 41.159 + } 41.160 + } 41.161 + catch(BindException ex) 41.162 + { 41.163 + // Could not bind to socket; this is a fatal problem; so perform shutdown 41.164 + ex.printStackTrace(); 41.165 + System.exit(1); 41.166 + } 41.167 + catch(IOException ex) 41.168 + { 41.169 + ex.printStackTrace(); 41.170 + } 41.171 + catch(Exception ex) 41.172 + { 41.173 + ex.printStackTrace(); 41.174 + } 41.175 + } 41.176 + 41.177 + public static SelectionKey registerSelector(final Selector selector, 41.178 + final SocketChannel channel, final int op) 41.179 + throws CancelledKeyException, ClosedChannelException 41.180 + { 41.181 + // Register the selector at the channel, so that it will be notified 41.182 + // on the socket's events 41.183 + synchronized(RegisterGate) 41.184 + { 41.185 + // Wakeup the currently blocking reader/writer thread; we have locked 41.186 + // the RegisterGate to prevent the awakened thread to block again 41.187 + selector.wakeup(); 41.188 + 41.189 + // Lock the selector to prevent the waiting worker threads going into 41.190 + // selector.select() which would block the selector. 41.191 + synchronized (selector) 41.192 + { 41.193 + return channel.register(selector, op, null); 41.194 + } 41.195 + } 41.196 + } 41.197 + 41.198 +}
42.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 42.2 +++ b/org/sonews/daemon/ShutdownHook.java Fri Jun 26 16:48:50 2009 +0200 42.3 @@ -0,0 +1,83 @@ 42.4 +/* 42.5 + * SONEWS News Server 42.6 + * see AUTHORS for the list of contributors 42.7 + * 42.8 + * This program is free software: you can redistribute it and/or modify 42.9 + * it under the terms of the GNU General Public License as published by 42.10 + * the Free Software Foundation, either version 3 of the License, or 42.11 + * (at your option) any later version. 42.12 + * 42.13 + * This program is distributed in the hope that it will be useful, 42.14 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 42.15 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 42.16 + * GNU General Public License for more details. 42.17 + * 42.18 + * You should have received a copy of the GNU General Public License 42.19 + * along with this program. If not, see <http://www.gnu.org/licenses/>. 42.20 + */ 42.21 + 42.22 +package org.sonews.daemon; 42.23 + 42.24 +import java.sql.SQLException; 42.25 +import java.util.Map; 42.26 + 42.27 +/** 42.28 + * Will force all other threads to shutdown cleanly. 42.29 + * @author Christian Lins 42.30 + * @since sonews/0.5.0 42.31 + */ 42.32 +class ShutdownHook extends Thread 42.33 +{ 42.34 + 42.35 + /** 42.36 + * Called when the JVM exits. 42.37 + */ 42.38 + @Override 42.39 + public void run() 42.40 + { 42.41 + System.out.println("sonews: Trying to shutdown all threads..."); 42.42 + 42.43 + Map<Thread, StackTraceElement[]> threadsMap = Thread.getAllStackTraces(); 42.44 + for(Thread thread : threadsMap.keySet()) 42.45 + { 42.46 + // Interrupt the thread if it's a AbstractDaemon 42.47 + AbstractDaemon daemon; 42.48 + if(thread instanceof AbstractDaemon && thread.isAlive()) 42.49 + { 42.50 + try 42.51 + { 42.52 + daemon = (AbstractDaemon)thread; 42.53 + daemon.shutdownNow(); 42.54 + } 42.55 + catch(SQLException ex) 42.56 + { 42.57 + System.out.println("sonews: " + ex); 42.58 + } 42.59 + } 42.60 + } 42.61 + 42.62 + for(Thread thread : threadsMap.keySet()) 42.63 + { 42.64 + AbstractDaemon daemon; 42.65 + if(thread instanceof AbstractDaemon && thread.isAlive()) 42.66 + { 42.67 + daemon = (AbstractDaemon)thread; 42.68 + System.out.println("sonews: Waiting for " + daemon + " to exit..."); 42.69 + try 42.70 + { 42.71 + daemon.join(500); 42.72 + } 42.73 + catch(InterruptedException ex) 42.74 + { 42.75 + System.out.println(ex.getLocalizedMessage()); 42.76 + } 42.77 + } 42.78 + } 42.79 + 42.80 + // We have notified all not-sleeping AbstractDaemons of the shutdown; 42.81 + // all other threads can be simply purged on VM shutdown 42.82 + 42.83 + System.out.println("sonews: Clean shutdown."); 42.84 + } 42.85 + 42.86 +}
43.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 43.2 +++ b/org/sonews/daemon/command/AbstractCommand.java Fri Jun 26 16:48:50 2009 +0200 43.3 @@ -0,0 +1,87 @@ 43.4 +/* 43.5 + * SONEWS News Server 43.6 + * see AUTHORS for the list of contributors 43.7 + * 43.8 + * This program is free software: you can redistribute it and/or modify 43.9 + * it under the terms of the GNU General Public License as published by 43.10 + * the Free Software Foundation, either version 3 of the License, or 43.11 + * (at your option) any later version. 43.12 + * 43.13 + * This program is distributed in the hope that it will be useful, 43.14 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 43.15 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 43.16 + * GNU General Public License for more details. 43.17 + * 43.18 + * You should have received a copy of the GNU General Public License 43.19 + * along with this program. If not, see <http://www.gnu.org/licenses/>. 43.20 + */ 43.21 + 43.22 +package org.sonews.daemon.command; 43.23 + 43.24 +import java.io.IOException; 43.25 +import java.nio.charset.Charset; 43.26 +import java.sql.SQLException; 43.27 +import org.sonews.daemon.NNTPConnection; 43.28 +import org.sonews.daemon.storage.Article; 43.29 +import org.sonews.daemon.storage.Group; 43.30 + 43.31 +/** 43.32 + * Base class for all command handling classes. 43.33 + * @author Christian Lins 43.34 + * @author Dennis Schwerdel 43.35 + * @since n3tpd/0.1 43.36 + */ 43.37 +public abstract class AbstractCommand 43.38 +{ 43.39 + 43.40 + protected NNTPConnection connection; 43.41 + 43.42 + public AbstractCommand(final NNTPConnection connection) 43.43 + { 43.44 + this.connection = connection; 43.45 + } 43.46 + 43.47 + protected Article getCurrentArticle() 43.48 + { 43.49 + return connection.getCurrentArticle(); 43.50 + } 43.51 + 43.52 + protected Group getCurrentGroup() 43.53 + { 43.54 + return connection.getCurrentGroup(); 43.55 + } 43.56 + 43.57 + protected void setCurrentArticle(final Article current) 43.58 + { 43.59 + connection.setCurrentArticle(current); 43.60 + } 43.61 + 43.62 + protected void setCurrentGroup(final Group current) 43.63 + { 43.64 + connection.setCurrentGroup(current); 43.65 + } 43.66 + 43.67 + public abstract void processLine(String line) 43.68 + throws IOException, SQLException; 43.69 + 43.70 + protected void println(final String line) 43.71 + throws IOException 43.72 + { 43.73 + connection.println(line); 43.74 + } 43.75 + 43.76 + protected void println(final String line, final Charset charset) 43.77 + throws IOException 43.78 + { 43.79 + connection.println(line, charset); 43.80 + } 43.81 + 43.82 + protected void printStatus(final int status, final String msg) 43.83 + throws IOException 43.84 + { 43.85 + println(status + " " + msg); 43.86 + } 43.87 + 43.88 + public abstract boolean hasFinished(); 43.89 + 43.90 +}
44.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 44.2 +++ b/org/sonews/daemon/command/ArticleCommand.java Fri Jun 26 16:48:50 2009 +0200 44.3 @@ -0,0 +1,164 @@ 44.4 +/* 44.5 + * SONEWS News Server 44.6 + * see AUTHORS for the list of contributors 44.7 + * 44.8 + * This program is free software: you can redistribute it and/or modify 44.9 + * it under the terms of the GNU General Public License as published by 44.10 + * the Free Software Foundation, either version 3 of the License, or 44.11 + * (at your option) any later version. 44.12 + * 44.13 + * This program is distributed in the hope that it will be useful, 44.14 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 44.15 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 44.16 + * GNU General Public License for more details. 44.17 + * 44.18 + * You should have received a copy of the GNU General Public License 44.19 + * along with this program. If not, see <http://www.gnu.org/licenses/>. 44.20 + */ 44.21 + 44.22 +package org.sonews.daemon.command; 44.23 + 44.24 +import java.io.IOException; 44.25 +import java.sql.SQLException; 44.26 +import org.sonews.daemon.storage.Article; 44.27 +import org.sonews.daemon.NNTPConnection; 44.28 +import org.sonews.daemon.storage.Group; 44.29 + 44.30 +/** 44.31 + * Class handling the ARTICLE, BODY and HEAD commands. 44.32 + * @author Christian Lins 44.33 + * @author Dennis Schwerdel 44.34 + * @since n3tpd/0.1 44.35 + */ 44.36 +public class ArticleCommand extends AbstractCommand 44.37 +{ 44.38 + 44.39 + public ArticleCommand(final NNTPConnection connection) 44.40 + { 44.41 + super(connection); 44.42 + } 44.43 + 44.44 + @Override 44.45 + public boolean hasFinished() 44.46 + { 44.47 + return true; 44.48 + } 44.49 + 44.50 + // TODO: Refactor this method to reduce its complexity! 44.51 + @Override 44.52 + public void processLine(final String line) 44.53 + throws IOException 44.54 + { 44.55 + final String[] command = line.split(" "); 44.56 + 44.57 + Article article = null; 44.58 + long artIndex = -1; 44.59 + if (command.length == 1) 44.60 + { 44.61 + article = getCurrentArticle(); 44.62 + if (article == null) 44.63 + { 44.64 + printStatus(420, "no current article has been selected"); 44.65 + return; 44.66 + } 44.67 + } 44.68 + else if (command[1].matches(NNTPConnection.MESSAGE_ID_PATTERN)) 44.69 + { 44.70 + // Message-ID 44.71 + article = Article.getByMessageID(command[1]); 44.72 + if (article == null) 44.73 + { 44.74 + printStatus(430, "no such article found"); 44.75 + return; 44.76 + } 44.77 + } 44.78 + else 44.79 + { 44.80 + // Message Number 44.81 + try 44.82 + { 44.83 + Group currentGroup = connection.getCurrentGroup(); 44.84 + if(currentGroup == null) 44.85 + { 44.86 + printStatus(400, "no group selected"); 44.87 + return; 44.88 + } 44.89 + 44.90 + artIndex = Long.parseLong(command[1]); 44.91 + article = Article.getByArticleNumber(artIndex, currentGroup); 44.92 + } 44.93 + catch(NumberFormatException ex) 44.94 + { 44.95 + ex.printStackTrace(); 44.96 + } 44.97 + catch(SQLException ex) 44.98 + { 44.99 + ex.printStackTrace(); 44.100 + } 44.101 + 44.102 + if (article == null) 44.103 + { 44.104 + printStatus(423, "no such article number in this group"); 44.105 + return; 44.106 + } 44.107 + setCurrentArticle(article); 44.108 + } 44.109 + 44.110 + if(command[0].equalsIgnoreCase("ARTICLE")) 44.111 + { 44.112 + printStatus(220, artIndex + " " + article.getMessageID() 44.113 + + " article retrieved - head and body follow"); 44.114 + 44.115 + println(article.getHeaderSource()); 44.116 + 44.117 + println(""); 44.118 + println(article.getBody(), article.getBodyCharset()); 44.119 + println("."); 44.120 + } 44.121 + else if(command[0].equalsIgnoreCase("BODY")) 44.122 + { 44.123 + printStatus(222, artIndex + " " + article.getMessageID() + " body"); 44.124 + println(article.getBody(), article.getBodyCharset()); 44.125 + println("."); 44.126 + } 44.127 + 44.128 + /* 44.129 + * HEAD: This command is mandatory. 44.130 + * 44.131 + * Syntax 44.132 + * HEAD message-id 44.133 + * HEAD number 44.134 + * HEAD 44.135 + * 44.136 + * Responses 44.137 + * 44.138 + * First form (message-id specified) 44.139 + * 221 0|n message-id Headers follow (multi-line) 44.140 + * 430 No article with that message-id 44.141 + * 44.142 + * Second form (article number specified) 44.143 + * 221 n message-id Headers follow (multi-line) 44.144 + * 412 No newsgroup selected 44.145 + * 423 No article with that number 44.146 + * 44.147 + * Third form (current article number used) 44.148 + * 221 n message-id Headers follow (multi-line) 44.149 + * 412 No newsgroup selected 44.150 + * 420 Current article number is invalid 44.151 + * 44.152 + * Parameters 44.153 + * number Requested article number 44.154 + * n Returned article number 44.155 + * message-id Article message-id 44.156 + */ 44.157 + else if(command[0].equalsIgnoreCase("HEAD")) 44.158 + { 44.159 + printStatus(221, artIndex + " " + article.getMessageID() 44.160 + + " Headers follow (multi-line)"); 44.161 + 44.162 + println(article.getHeaderSource()); 44.163 + println("."); 44.164 + } 44.165 + } 44.166 + 44.167 +}
45.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 45.2 +++ b/org/sonews/daemon/command/CapabilitiesCommand.java Fri Jun 26 16:48:50 2009 +0200 45.3 @@ -0,0 +1,80 @@ 45.4 +/* 45.5 + * SONEWS News Server 45.6 + * see AUTHORS for the list of contributors 45.7 + * 45.8 + * This program is free software: you can redistribute it and/or modify 45.9 + * it under the terms of the GNU General Public License as published by 45.10 + * the Free Software Foundation, either version 3 of the License, or 45.11 + * (at your option) any later version. 45.12 + * 45.13 + * This program is distributed in the hope that it will be useful, 45.14 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 45.15 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 45.16 + * GNU General Public License for more details. 45.17 + * 45.18 + * You should have received a copy of the GNU General Public License 45.19 + * along with this program. If not, see <http://www.gnu.org/licenses/>. 45.20 + */ 45.21 + 45.22 +package org.sonews.daemon.command; 45.23 + 45.24 +import java.io.IOException; 45.25 +import org.sonews.daemon.NNTPConnection; 45.26 + 45.27 +/** 45.28 + * <pre> 45.29 + * The CAPABILITIES command allows a client to determine the 45.30 + * capabilities of the server at any given time. 45.31 + * 45.32 + * This command MAY be issued at any time; the server MUST NOT require 45.33 + * it to be issued in order to make use of any capability. The response 45.34 + * generated by this command MAY change during a session because of 45.35 + * other state information (which, in turn, may be changed by the 45.36 + * effects of other commands or by external events). An NNTP client is 45.37 + * only able to get the current and correct information concerning 45.38 + * available capabilities at any point during a session by issuing a 45.39 + * CAPABILITIES command at that point of that session and processing the 45.40 + * response. 45.41 + * </pre> 45.42 + * @author Christian Lins 45.43 + * @since sonews/0.5.0 45.44 + */ 45.45 +public class CapabilitiesCommand extends AbstractCommand 45.46 +{ 45.47 + 45.48 + protected static final String[] CAPABILITIES = new String[] 45.49 + { 45.50 + "VERSION 2", // MUST be the first one; VERSION 2 refers to RFC3977 45.51 + "READER", // Server implements commands for reading 45.52 + "POST", // Server implements POST command 45.53 + "OVER" // Server implements OVER command 45.54 + }; 45.55 + 45.56 + public CapabilitiesCommand(final NNTPConnection conn) 45.57 + { 45.58 + super(conn); 45.59 + } 45.60 + 45.61 + /** 45.62 + * First called after one call to processLine(). 45.63 + * @return 45.64 + */ 45.65 + @Override 45.66 + public boolean hasFinished() 45.67 + { 45.68 + return true; 45.69 + } 45.70 + 45.71 + @Override 45.72 + public void processLine(final String line) 45.73 + throws IOException 45.74 + { 45.75 + printStatus(101, "Capabilities list:"); 45.76 + for(String cap : CAPABILITIES) 45.77 + { 45.78 + println(cap); 45.79 + } 45.80 + println("."); 45.81 + } 45.82 + 45.83 +}
46.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 46.2 +++ b/org/sonews/daemon/command/GroupCommand.java Fri Jun 26 16:48:50 2009 +0200 46.3 @@ -0,0 +1,90 @@ 46.4 +/* 46.5 + * SONEWS News Server 46.6 + * see AUTHORS for the list of contributors 46.7 + * 46.8 + * This program is free software: you can redistribute it and/or modify 46.9 + * it under the terms of the GNU General Public License as published by 46.10 + * the Free Software Foundation, either version 3 of the License, or 46.11 + * (at your option) any later version. 46.12 + * 46.13 + * This program is distributed in the hope that it will be useful, 46.14 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 46.15 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 46.16 + * GNU General Public License for more details. 46.17 + * 46.18 + * You should have received a copy of the GNU General Public License 46.19 + * along with this program. If not, see <http://www.gnu.org/licenses/>. 46.20 + */ 46.21 + 46.22 +package org.sonews.daemon.command; 46.23 + 46.24 +import java.io.IOException; 46.25 +import java.sql.SQLException; 46.26 +import org.sonews.daemon.NNTPConnection; 46.27 +import org.sonews.daemon.storage.Group; 46.28 + 46.29 +/** 46.30 + * Class handling the GROUP command. 46.31 + * <pre> 46.32 + * Syntax 46.33 + * GROUP group 46.34 + * 46.35 + * Responses 46.36 + * 211 number low high group Group successfully selected 46.37 + * 411 No such newsgroup 46.38 + * 46.39 + * Parameters 46.40 + * group Name of newsgroup 46.41 + * number Estimated number of articles in the group 46.42 + * low Reported low water mark 46.43 + * high Reported high water mark 46.44 + * </pre> 46.45 + * (from RFC 3977) 46.46 + * 46.47 + * @author Christian Lins 46.48 + * @author Dennis Schwerdel 46.49 + * @since n3tpd/0.1 46.50 + */ 46.51 +public class GroupCommand extends AbstractCommand 46.52 +{ 46.53 + 46.54 + public GroupCommand(final NNTPConnection conn) 46.55 + { 46.56 + super(conn); 46.57 + } 46.58 + 46.59 + @Override 46.60 + public boolean hasFinished() 46.61 + { 46.62 + return true; 46.63 + } 46.64 + 46.65 + @Override 46.66 + public void processLine(final String line) 46.67 + throws IOException, SQLException 46.68 + { 46.69 + final String[] command = line.split(" "); 46.70 + 46.71 + Group group; 46.72 + if(command.length >= 2) 46.73 + { 46.74 + group = Group.getByName(command[1]); 46.75 + if(group == null) 46.76 + { 46.77 + printStatus(411, "no such news group"); 46.78 + } 46.79 + else 46.80 + { 46.81 + setCurrentGroup(group); 46.82 + 46.83 + printStatus(211, group.getPostingsCount() + " " + group.getFirstArticleNumber() 46.84 + + " " + group.getLastArticleNumber() + " " + group.getName() + " group selected"); 46.85 + } 46.86 + } 46.87 + else 46.88 + { 46.89 + printStatus(500, "no group name given"); 46.90 + } 46.91 + } 46.92 + 46.93 +}
47.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 47.2 +++ b/org/sonews/daemon/command/HelpCommand.java Fri Jun 26 16:48:50 2009 +0200 47.3 @@ -0,0 +1,63 @@ 47.4 +/* 47.5 + * SONEWS News Server 47.6 + * see AUTHORS for the list of contributors 47.7 + * 47.8 + * This program is free software: you can redistribute it and/or modify 47.9 + * it under the terms of the GNU General Public License as published by 47.10 + * the Free Software Foundation, either version 3 of the License, or 47.11 + * (at your option) any later version. 47.12 + * 47.13 + * This program is distributed in the hope that it will be useful, 47.14 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 47.15 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 47.16 + * GNU General Public License for more details. 47.17 + * 47.18 + * You should have received a copy of the GNU General Public License 47.19 + * along with this program. If not, see <http://www.gnu.org/licenses/>. 47.20 + */ 47.21 + 47.22 +package org.sonews.daemon.command; 47.23 + 47.24 +import java.io.IOException; 47.25 +import org.sonews.daemon.NNTPConnection; 47.26 +import org.sonews.util.io.Resource; 47.27 + 47.28 +/** 47.29 + * This command provides a short summary of the commands that are 47.30 + * understood by this implementation of the server. The help text will 47.31 + * be presented as a multi-line data block following the 100 response 47.32 + * code (taken from RFC). 47.33 + * @author Christian Lins 47.34 + * @since sonews/0.5.0 47.35 + */ 47.36 +public class HelpCommand extends AbstractCommand 47.37 +{ 47.38 + 47.39 + public HelpCommand(final NNTPConnection conn) 47.40 + { 47.41 + super(conn); 47.42 + } 47.43 + 47.44 + @Override 47.45 + public boolean hasFinished() 47.46 + { 47.47 + return true; 47.48 + } 47.49 + 47.50 + @Override 47.51 + public void processLine(final String line) 47.52 + throws IOException 47.53 + { 47.54 + printStatus(100, "help text follows"); 47.55 + 47.56 + final String[] help = Resource 47.57 + .getAsString("helpers/helptext", true).split("\n"); 47.58 + for(String hstr : help) 47.59 + { 47.60 + println(hstr); 47.61 + } 47.62 + 47.63 + println("."); 47.64 + } 47.65 + 47.66 +}
48.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 48.2 +++ b/org/sonews/daemon/command/ListCommand.java Fri Jun 26 16:48:50 2009 +0200 48.3 @@ -0,0 +1,109 @@ 48.4 +/* 48.5 + * SONEWS News Server 48.6 + * see AUTHORS for the list of contributors 48.7 + * 48.8 + * This program is free software: you can redistribute it and/or modify 48.9 + * it under the terms of the GNU General Public License as published by 48.10 + * the Free Software Foundation, either version 3 of the License, or 48.11 + * (at your option) any later version. 48.12 + * 48.13 + * This program is distributed in the hope that it will be useful, 48.14 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 48.15 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 48.16 + * GNU General Public License for more details. 48.17 + * 48.18 + * You should have received a copy of the GNU General Public License 48.19 + * along with this program. If not, see <http://www.gnu.org/licenses/>. 48.20 + */ 48.21 + 48.22 +package org.sonews.daemon.command; 48.23 + 48.24 +import java.io.IOException; 48.25 +import java.sql.SQLException; 48.26 +import java.util.List; 48.27 +import org.sonews.daemon.NNTPConnection; 48.28 +import org.sonews.daemon.storage.Group; 48.29 + 48.30 +/** 48.31 + * Class handling the LIST command. 48.32 + * @author Christian Lins 48.33 + * @author Dennis Schwerdel 48.34 + * @since n3tpd/0.1 48.35 + */ 48.36 +public class ListCommand extends AbstractCommand 48.37 +{ 48.38 + 48.39 + public ListCommand(final NNTPConnection conn) 48.40 + { 48.41 + super(conn); 48.42 + } 48.43 + 48.44 + @Override 48.45 + public boolean hasFinished() 48.46 + { 48.47 + return true; 48.48 + } 48.49 + 48.50 + @Override 48.51 + public void processLine(final String line) 48.52 + throws IOException, SQLException 48.53 + { 48.54 + final String[] command = line.split(" "); 48.55 + 48.56 + if (command.length >= 2) 48.57 + { 48.58 + if (command[1].equalsIgnoreCase("OVERVIEW.FMT")) 48.59 + { 48.60 + printStatus(215, "information follows"); 48.61 + println("Subject:\nFrom:\nDate:\nMessage-ID:\nReferences:\nBytes:\nLines:\nXref"); 48.62 + println("."); 48.63 + } 48.64 + else if (command[1].equalsIgnoreCase("NEWSGROUPS")) 48.65 + { 48.66 + printStatus(215, "information follows"); 48.67 + final List<Group> list = Group.getAll(); 48.68 + for (Group g : list) 48.69 + { 48.70 + println(g.getName() + "\t" + "-"); 48.71 + } 48.72 + println("."); 48.73 + } 48.74 + else if (command[1].equalsIgnoreCase("SUBSCRIPTIONS")) 48.75 + { 48.76 + printStatus(215, "information follows"); 48.77 + println("."); 48.78 + } 48.79 + else if (command[1].equalsIgnoreCase("EXTENSIONS")) 48.80 + { 48.81 + printStatus(202, "Supported NNTP extensions."); 48.82 + println("LISTGROUP"); 48.83 + println("."); 48.84 + 48.85 + } 48.86 + else 48.87 + { 48.88 + printStatus(500, "unknown argument to LIST command"); 48.89 + } 48.90 + } 48.91 + else 48.92 + { 48.93 + final List<Group> groups = Group.getAll(); 48.94 + if(groups != null) 48.95 + { 48.96 + printStatus(215, "list of newsgroups follows"); 48.97 + for (Group g : groups) 48.98 + { 48.99 + // Indeed first the higher article number then the lower 48.100 + println(g.getName() + " " + g.getLastArticleNumber() + " " 48.101 + + g.getFirstArticleNumber() + " y"); 48.102 + } 48.103 + println("."); 48.104 + } 48.105 + else 48.106 + { 48.107 + printStatus(500, "server database malfunction"); 48.108 + } 48.109 + } 48.110 + } 48.111 + 48.112 +}
49.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 49.2 +++ b/org/sonews/daemon/command/ListGroupCommand.java Fri Jun 26 16:48:50 2009 +0200 49.3 @@ -0,0 +1,81 @@ 49.4 +/* 49.5 + * SONEWS News Server 49.6 + * see AUTHORS for the list of contributors 49.7 + * 49.8 + * This program is free software: you can redistribute it and/or modify 49.9 + * it under the terms of the GNU General Public License as published by 49.10 + * the Free Software Foundation, either version 3 of the License, or 49.11 + * (at your option) any later version. 49.12 + * 49.13 + * This program is distributed in the hope that it will be useful, 49.14 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 49.15 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 49.16 + * GNU General Public License for more details. 49.17 + * 49.18 + * You should have received a copy of the GNU General Public License 49.19 + * along with this program. If not, see <http://www.gnu.org/licenses/>. 49.20 + */ 49.21 + 49.22 +package org.sonews.daemon.command; 49.23 + 49.24 +import java.io.IOException; 49.25 +import java.sql.SQLException; 49.26 +import java.util.List; 49.27 +import org.sonews.daemon.NNTPConnection; 49.28 +import org.sonews.daemon.storage.Group; 49.29 + 49.30 +/** 49.31 + * Class handling the LISTGROUP command. 49.32 + * @author Christian Lins 49.33 + * @author Dennis Schwerdel 49.34 + * @since n3tpd/0.1 49.35 + */ 49.36 +public class ListGroupCommand extends AbstractCommand 49.37 +{ 49.38 + 49.39 + public ListGroupCommand(final NNTPConnection conn) 49.40 + { 49.41 + super(conn); 49.42 + } 49.43 + 49.44 + @Override 49.45 + public boolean hasFinished() 49.46 + { 49.47 + return true; 49.48 + } 49.49 + 49.50 + @Override 49.51 + public void processLine(final String commandName) 49.52 + throws IOException, SQLException 49.53 + { 49.54 + final String[] command = commandName.split(" "); 49.55 + 49.56 + Group group; 49.57 + if(command.length >= 2) 49.58 + { 49.59 + group = Group.getByName(command[1]); 49.60 + } 49.61 + else 49.62 + { 49.63 + group = getCurrentGroup(); 49.64 + } 49.65 + 49.66 + if (group == null) 49.67 + { 49.68 + printStatus(412, "no group selected; use GROUP <group> command"); 49.69 + return; 49.70 + } 49.71 + 49.72 + List<Long> ids = group.getArticleNumbers(); 49.73 + printStatus(211, ids.size() + " " + 49.74 + group.getFirstArticleNumber() + " " + 49.75 + group.getLastArticleNumber() + " list of article numbers follow"); 49.76 + for(long id : ids) 49.77 + { 49.78 + // One index number per line 49.79 + println(Long.toString(id)); 49.80 + } 49.81 + println("."); 49.82 + } 49.83 + 49.84 +}
50.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 50.2 +++ b/org/sonews/daemon/command/ModeReaderCommand.java Fri Jun 26 16:48:50 2009 +0200 50.3 @@ -0,0 +1,58 @@ 50.4 +/* 50.5 + * SONEWS News Server 50.6 + * see AUTHORS for the list of contributors 50.7 + * 50.8 + * This program is free software: you can redistribute it and/or modify 50.9 + * it under the terms of the GNU General Public License as published by 50.10 + * the Free Software Foundation, either version 3 of the License, or 50.11 + * (at your option) any later version. 50.12 + * 50.13 + * This program is distributed in the hope that it will be useful, 50.14 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 50.15 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 50.16 + * GNU General Public License for more details. 50.17 + * 50.18 + * You should have received a copy of the GNU General Public License 50.19 + * along with this program. If not, see <http://www.gnu.org/licenses/>. 50.20 + */ 50.21 + 50.22 +package org.sonews.daemon.command; 50.23 + 50.24 +import java.io.IOException; 50.25 +import java.sql.SQLException; 50.26 +import org.sonews.daemon.NNTPConnection; 50.27 + 50.28 +/** 50.29 + * Class handling the MODE READER command. This command actually does nothing 50.30 + * but returning a success status code. 50.31 + * @author Christian Lins 50.32 + * @since sonews/0.5.0 50.33 + */ 50.34 +public class ModeReaderCommand extends AbstractCommand 50.35 +{ 50.36 + 50.37 + public ModeReaderCommand(final NNTPConnection conn) 50.38 + { 50.39 + super(conn); 50.40 + } 50.41 + 50.42 + @Override 50.43 + public boolean hasFinished() 50.44 + { 50.45 + return true; 50.46 + } 50.47 + 50.48 + @Override 50.49 + public void processLine(final String line) throws IOException, SQLException 50.50 + { 50.51 + if(line.equalsIgnoreCase("MODE READER")) 50.52 + { 50.53 + printStatus(200, "hello you can post"); 50.54 + } 50.55 + else 50.56 + { 50.57 + printStatus(500, "I do not know this mode command"); 50.58 + } 50.59 + } 50.60 + 50.61 +}
51.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 51.2 +++ b/org/sonews/daemon/command/NewGroupsCommand.java Fri Jun 26 16:48:50 2009 +0200 51.3 @@ -0,0 +1,65 @@ 51.4 +/* 51.5 + * SONEWS News Server 51.6 + * see AUTHORS for the list of contributors 51.7 + * 51.8 + * This program is free software: you can redistribute it and/or modify 51.9 + * it under the terms of the GNU General Public License as published by 51.10 + * the Free Software Foundation, either version 3 of the License, or 51.11 + * (at your option) any later version. 51.12 + * 51.13 + * This program is distributed in the hope that it will be useful, 51.14 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 51.15 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 51.16 + * GNU General Public License for more details. 51.17 + * 51.18 + * You should have received a copy of the GNU General Public License 51.19 + * along with this program. If not, see <http://www.gnu.org/licenses/>. 51.20 + */ 51.21 + 51.22 +package org.sonews.daemon.command; 51.23 + 51.24 +import java.io.IOException; 51.25 +import java.sql.SQLException; 51.26 +import org.sonews.daemon.NNTPConnection; 51.27 + 51.28 +/** 51.29 + * Class handling the NEWGROUPS command. 51.30 + * @author Christian Lins 51.31 + * @author Dennis Schwerdel 51.32 + * @since n3tpd/0.1 51.33 + */ 51.34 +public class NewGroupsCommand extends AbstractCommand 51.35 +{ 51.36 + 51.37 + public NewGroupsCommand(final NNTPConnection conn) 51.38 + { 51.39 + super(conn); 51.40 + } 51.41 + 51.42 + @Override 51.43 + public boolean hasFinished() 51.44 + { 51.45 + return true; 51.46 + } 51.47 + 51.48 + @Override 51.49 + public void processLine(final String line) 51.50 + throws IOException, SQLException 51.51 + { 51.52 + final String[] command = line.split(" "); 51.53 + 51.54 + if(command.length == 3) 51.55 + { 51.56 + printStatus(231, "list of new newsgroups follows"); 51.57 + 51.58 + // Currently we do not store a group's creation date; 51.59 + // so we return an empty list which is a valid response 51.60 + println("."); 51.61 + } 51.62 + else 51.63 + { 51.64 + printStatus(500, "invalid command usage"); 51.65 + } 51.66 + } 51.67 + 51.68 +}
52.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 52.2 +++ b/org/sonews/daemon/command/NextPrevCommand.java Fri Jun 26 16:48:50 2009 +0200 52.3 @@ -0,0 +1,100 @@ 52.4 +/* 52.5 + * SONEWS News Server 52.6 + * see AUTHORS for the list of contributors 52.7 + * 52.8 + * This program is free software: you can redistribute it and/or modify 52.9 + * it under the terms of the GNU General Public License as published by 52.10 + * the Free Software Foundation, either version 3 of the License, or 52.11 + * (at your option) any later version. 52.12 + * 52.13 + * This program is distributed in the hope that it will be useful, 52.14 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 52.15 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 52.16 + * GNU General Public License for more details. 52.17 + * 52.18 + * You should have received a copy of the GNU General Public License 52.19 + * along with this program. If not, see <http://www.gnu.org/licenses/>. 52.20 + */ 52.21 + 52.22 +package org.sonews.daemon.command; 52.23 + 52.24 +import java.io.IOException; 52.25 +import java.sql.SQLException; 52.26 +import org.sonews.daemon.NNTPConnection; 52.27 +import org.sonews.daemon.storage.Article; 52.28 +import org.sonews.daemon.storage.Group; 52.29 + 52.30 +/** 52.31 + * Class handling the NEXT and LAST command. 52.32 + * @author Christian Lins 52.33 + * @author Dennis Schwerdel 52.34 + * @since n3tpd/0.1 52.35 + */ 52.36 +public class NextPrevCommand extends AbstractCommand 52.37 +{ 52.38 + 52.39 + public NextPrevCommand(final NNTPConnection conn) 52.40 + { 52.41 + super(conn); 52.42 + } 52.43 + 52.44 + @Override 52.45 + public boolean hasFinished() 52.46 + { 52.47 + return true; 52.48 + } 52.49 + 52.50 + @Override 52.51 + public void processLine(final String line) 52.52 + throws IOException, SQLException 52.53 + { 52.54 + final Article currA = getCurrentArticle(); 52.55 + final Group currG = getCurrentGroup(); 52.56 + 52.57 + if (currA == null) 52.58 + { 52.59 + printStatus(420, "no current article has been selected"); 52.60 + return; 52.61 + } 52.62 + 52.63 + if (currG == null) 52.64 + { 52.65 + printStatus(412, "no newsgroup selected"); 52.66 + return; 52.67 + } 52.68 + 52.69 + final String[] command = line.split(" "); 52.70 + 52.71 + if(command[0].equalsIgnoreCase("NEXT")) 52.72 + { 52.73 + selectNewArticle(currA, currG, 1); 52.74 + } 52.75 + else if(command[0].equalsIgnoreCase("PREV")) 52.76 + { 52.77 + selectNewArticle(currA, currG, -1); 52.78 + } 52.79 + else 52.80 + { 52.81 + printStatus(500, "internal server error"); 52.82 + } 52.83 + } 52.84 + 52.85 + private void selectNewArticle(Article article, Group grp, final int delta) 52.86 + throws IOException, SQLException 52.87 + { 52.88 + assert article != null; 52.89 + 52.90 + article = Article.getByArticleNumber(article.getIndexInGroup(grp) + delta, grp); 52.91 + 52.92 + if(article == null) 52.93 + { 52.94 + printStatus(421, "no next article in this group"); 52.95 + } 52.96 + else 52.97 + { 52.98 + setCurrentArticle(article); 52.99 + printStatus(223, article.getIndexInGroup(getCurrentGroup()) + " " + article.getMessageID() + " article retrieved - request text separately"); 52.100 + } 52.101 + } 52.102 + 52.103 +}
53.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 53.2 +++ b/org/sonews/daemon/command/OverCommand.java Fri Jun 26 16:48:50 2009 +0200 53.3 @@ -0,0 +1,281 @@ 53.4 +/* 53.5 + * SONEWS News Server 53.6 + * see AUTHORS for the list of contributors 53.7 + * 53.8 + * This program is free software: you can redistribute it and/or modify 53.9 + * it under the terms of the GNU General Public License as published by 53.10 + * the Free Software Foundation, either version 3 of the License, or 53.11 + * (at your option) any later version. 53.12 + * 53.13 + * This program is distributed in the hope that it will be useful, 53.14 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 53.15 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 53.16 + * GNU General Public License for more details. 53.17 + * 53.18 + * You should have received a copy of the GNU General Public License 53.19 + * along with this program. If not, see <http://www.gnu.org/licenses/>. 53.20 + */ 53.21 + 53.22 +package org.sonews.daemon.command; 53.23 + 53.24 +import java.io.IOException; 53.25 +import java.sql.SQLException; 53.26 +import java.util.List; 53.27 +import org.sonews.util.Log; 53.28 +import org.sonews.daemon.NNTPConnection; 53.29 +import org.sonews.daemon.storage.Article; 53.30 +import org.sonews.daemon.storage.ArticleHead; 53.31 +import org.sonews.daemon.storage.Headers; 53.32 +import org.sonews.util.Pair; 53.33 + 53.34 +/** 53.35 + * Class handling the OVER/XOVER command. 53.36 + * 53.37 + * Description of the XOVER command: 53.38 + * <pre> 53.39 + * XOVER [range] 53.40 + * 53.41 + * The XOVER command returns information from the overview 53.42 + * database for the article(s) specified. 53.43 + * 53.44 + * The optional range argument may be any of the following: 53.45 + * an article number 53.46 + * an article number followed by a dash to indicate 53.47 + * all following 53.48 + * an article number followed by a dash followed by 53.49 + * another article number 53.50 + * 53.51 + * If no argument is specified, then information from the 53.52 + * current article is displayed. Successful responses start 53.53 + * with a 224 response followed by the overview information 53.54 + * for all matched messages. Once the output is complete, a 53.55 + * period is sent on a line by itself. If no argument is 53.56 + * specified, the information for the current article is 53.57 + * returned. A news group must have been selected earlier, 53.58 + * else a 412 error response is returned. If no articles are 53.59 + * in the range specified, a 420 error response is returned 53.60 + * by the server. A 502 response will be returned if the 53.61 + * client only has permission to transfer articles. 53.62 + * 53.63 + * Each line of output will be formatted with the article number, 53.64 + * followed by each of the headers in the overview database or the 53.65 + * article itself (when the data is not available in the overview 53.66 + * database) for that article separated by a tab character. The 53.67 + * sequence of fields must be in this order: subject, author, 53.68 + * date, message-id, references, byte count, and line count. Other 53.69 + * optional fields may follow line count. Other optional fields may 53.70 + * follow line count. These fields are specified by examining the 53.71 + * response to the LIST OVERVIEW.FMT command. Where no data exists, 53.72 + * a null field must be provided (i.e. the output will have two tab 53.73 + * characters adjacent to each other). Servers should not output 53.74 + * fields for articles that have been removed since the XOVER database 53.75 + * was created. 53.76 + * 53.77 + * The LIST OVERVIEW.FMT command should be implemented if XOVER 53.78 + * is implemented. A client can use LIST OVERVIEW.FMT to determine 53.79 + * what optional fields and in which order all fields will be 53.80 + * supplied by the XOVER command. 53.81 + * 53.82 + * Note that any tab and end-of-line characters in any header 53.83 + * data that is returned will be converted to a space character. 53.84 + * 53.85 + * Responses: 53.86 + * 53.87 + * 224 Overview information follows 53.88 + * 412 No news group current selected 53.89 + * 420 No article(s) selected 53.90 + * 502 no permission 53.91 + * 53.92 + * OVER defines additional responses: 53.93 + * 53.94 + * First form (message-id specified) 53.95 + * 224 Overview information follows (multi-line) 53.96 + * 430 No article with that message-id 53.97 + * 53.98 + * Second form (range specified) 53.99 + * 224 Overview information follows (multi-line) 53.100 + * 412 No newsgroup selected 53.101 + * 423 No articles in that range 53.102 + * 53.103 + * Third form (current article number used) 53.104 + * 224 Overview information follows (multi-line) 53.105 + * 412 No newsgroup selected 53.106 + * 420 Current article number is invalid 53.107 + * 53.108 + * </pre> 53.109 + * @author Christian Lins 53.110 + * @since sonews/0.5.0 53.111 + */ 53.112 +public class OverCommand extends AbstractCommand 53.113 +{ 53.114 + 53.115 + public static final int MAX_LINES_PER_DBREQUEST = 100; 53.116 + 53.117 + public OverCommand(final NNTPConnection conn) 53.118 + { 53.119 + super(conn); 53.120 + } 53.121 + 53.122 + @Override 53.123 + public boolean hasFinished() 53.124 + { 53.125 + return true; 53.126 + } 53.127 + 53.128 + @Override 53.129 + public void processLine(final String line) 53.130 + throws IOException, SQLException 53.131 + { 53.132 + if(getCurrentGroup() == null) 53.133 + { 53.134 + printStatus(412, "No news group current selected"); 53.135 + } 53.136 + else 53.137 + { 53.138 + String[] command = line.split(" "); 53.139 + 53.140 + // If no parameter was specified, show information about 53.141 + // the currently selected article(s) 53.142 + if(command.length == 1) 53.143 + { 53.144 + final Article art = getCurrentArticle(); 53.145 + if(art == null) 53.146 + { 53.147 + printStatus(420, "No article(s) selected"); 53.148 + return; 53.149 + } 53.150 + 53.151 + println(buildOverview(art, -1)); 53.152 + } 53.153 + // otherwise print information about the specified range 53.154 + else 53.155 + { 53.156 + int artStart; 53.157 + int artEnd = getCurrentGroup().getLastArticleNumber(); 53.158 + String[] nums = command[1].split("-"); 53.159 + if(nums.length >= 1) 53.160 + { 53.161 + try 53.162 + { 53.163 + artStart = Integer.parseInt(nums[0]); 53.164 + } 53.165 + catch(NumberFormatException e) 53.166 + { 53.167 + Log.msg(e.getMessage(), true); 53.168 + artStart = Integer.parseInt(command[1]); 53.169 + } 53.170 + } 53.171 + else 53.172 + { 53.173 + artStart = getCurrentGroup().getFirstArticleNumber(); 53.174 + } 53.175 + 53.176 + if(nums.length >=2) 53.177 + { 53.178 + try 53.179 + { 53.180 + artEnd = Integer.parseInt(nums[1]); 53.181 + } 53.182 + catch(NumberFormatException e) 53.183 + { 53.184 + e.printStackTrace(); 53.185 + } 53.186 + } 53.187 + 53.188 + if(artStart > artEnd) 53.189 + { 53.190 + if(command[0].equalsIgnoreCase("OVER")) 53.191 + { 53.192 + printStatus(423, "No articles in that range"); 53.193 + } 53.194 + else 53.195 + { 53.196 + printStatus(224, "(empty) overview information follows:"); 53.197 + println("."); 53.198 + } 53.199 + } 53.200 + else 53.201 + { 53.202 + for(int n = artStart; n <= artEnd; n += MAX_LINES_PER_DBREQUEST) 53.203 + { 53.204 + int nEnd = Math.min(n + MAX_LINES_PER_DBREQUEST - 1, artEnd); 53.205 + List<Pair<Long, ArticleHead>> articleHeads = getCurrentGroup() 53.206 + .getArticleHeads(n, nEnd); 53.207 + if(articleHeads.isEmpty() && n == artStart 53.208 + && command[0].equalsIgnoreCase("OVER")) 53.209 + { 53.210 + // This reply is only valid for OVER, not for XOVER command 53.211 + printStatus(423, "No articles in that range"); 53.212 + return; 53.213 + } 53.214 + else if(n == artStart) 53.215 + { 53.216 + // XOVER replies this although there is no data available 53.217 + printStatus(224, "Overview information follows"); 53.218 + } 53.219 + 53.220 + for(Pair<Long, ArticleHead> article : articleHeads) 53.221 + { 53.222 + String overview = buildOverview(article.getB(), article.getA()); 53.223 + println(overview); 53.224 + } 53.225 + } // for 53.226 + println("."); 53.227 + } 53.228 + } 53.229 + } 53.230 + } 53.231 + 53.232 + private String buildOverview(ArticleHead art, long nr) 53.233 + { 53.234 + StringBuilder overview = new StringBuilder(); 53.235 + overview.append(nr); 53.236 + overview.append('\t'); 53.237 + 53.238 + String subject = art.getHeader(Headers.SUBJECT)[0]; 53.239 + if("".equals(subject)) 53.240 + { 53.241 + subject = "<empty>"; 53.242 + } 53.243 + overview.append(escapeString(subject)); 53.244 + overview.append('\t'); 53.245 + 53.246 + overview.append(escapeString(art.getHeader(Headers.FROM)[0])); 53.247 + overview.append('\t'); 53.248 + overview.append(escapeString(art.getHeader(Headers.DATE)[0])); 53.249 + overview.append('\t'); 53.250 + overview.append(escapeString(art.getHeader(Headers.MESSAGE_ID)[0])); 53.251 + overview.append('\t'); 53.252 + overview.append(escapeString(art.getHeader(Headers.REFERENCES)[0])); 53.253 + overview.append('\t'); 53.254 + 53.255 + String bytes = art.getHeader(Headers.BYTES)[0]; 53.256 + if("".equals(bytes)) 53.257 + { 53.258 + bytes = "0"; 53.259 + } 53.260 + overview.append(escapeString(bytes)); 53.261 + overview.append('\t'); 53.262 + 53.263 + String lines = art.getHeader(Headers.LINES)[0]; 53.264 + if("".equals(lines)) 53.265 + { 53.266 + lines = "0"; 53.267 + } 53.268 + overview.append(escapeString(lines)); 53.269 + overview.append('\t'); 53.270 + overview.append(escapeString(art.getHeader(Headers.XREF)[0])); 53.271 + 53.272 + // Remove trailing tabs if some data is empty 53.273 + return overview.toString().trim(); 53.274 + } 53.275 + 53.276 + private String escapeString(String str) 53.277 + { 53.278 + String nstr = str.replace("\r", ""); 53.279 + nstr = nstr.replace('\n', ' '); 53.280 + nstr = nstr.replace('\t', ' '); 53.281 + return nstr.trim(); 53.282 + } 53.283 + 53.284 +}
54.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 54.2 +++ b/org/sonews/daemon/command/PostCommand.java Fri Jun 26 16:48:50 2009 +0200 54.3 @@ -0,0 +1,350 @@ 54.4 +/* 54.5 + * SONEWS News Server 54.6 + * see AUTHORS for the list of contributors 54.7 + * 54.8 + * This program is free software: you can redistribute it and/or modify 54.9 + * it under the terms of the GNU General Public License as published by 54.10 + * the Free Software Foundation, either version 3 of the License, or 54.11 + * (at your option) any later version. 54.12 + * 54.13 + * This program is distributed in the hope that it will be useful, 54.14 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 54.15 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 54.16 + * GNU General Public License for more details. 54.17 + * 54.18 + * You should have received a copy of the GNU General Public License 54.19 + * along with this program. If not, see <http://www.gnu.org/licenses/>. 54.20 + */ 54.21 + 54.22 +package org.sonews.daemon.command; 54.23 + 54.24 +import java.io.IOException; 54.25 + 54.26 +import java.io.ByteArrayInputStream; 54.27 +import java.nio.charset.Charset; 54.28 +import java.nio.charset.IllegalCharsetNameException; 54.29 +import java.nio.charset.UnsupportedCharsetException; 54.30 +import java.sql.SQLException; 54.31 +import java.util.Locale; 54.32 +import javax.mail.MessagingException; 54.33 +import javax.mail.internet.AddressException; 54.34 +import javax.mail.internet.InternetHeaders; 54.35 +import org.sonews.daemon.Config; 54.36 +import org.sonews.util.Log; 54.37 +import org.sonews.mlgw.Dispatcher; 54.38 +import org.sonews.daemon.storage.Article; 54.39 +import org.sonews.daemon.storage.Database; 54.40 +import org.sonews.daemon.storage.Group; 54.41 +import org.sonews.daemon.NNTPConnection; 54.42 +import org.sonews.daemon.storage.Headers; 54.43 +import org.sonews.feed.FeedManager; 54.44 +import org.sonews.util.Stats; 54.45 + 54.46 +/** 54.47 + * Implementation of the POST command. This command requires multiple lines 54.48 + * from the client, so the handling of asynchronous reading is a little tricky 54.49 + * to handle. 54.50 + * @author Christian Lins 54.51 + * @since sonews/0.5.0 54.52 + */ 54.53 +public class PostCommand extends AbstractCommand 54.54 +{ 54.55 + 54.56 + private final Article article = new Article(); 54.57 + private int lineCount = 0; 54.58 + private long bodySize = 0; 54.59 + private InternetHeaders headers = null; 54.60 + private long maxBodySize = 54.61 + Config.getInstance().get(Config.ARTICLE_MAXSIZE, 128) * 1024L; // Size in bytes 54.62 + private PostState state = PostState.WaitForLineOne; 54.63 + private final StringBuilder strBody = new StringBuilder(); 54.64 + private final StringBuilder strHead = new StringBuilder(); 54.65 + 54.66 + public PostCommand(final NNTPConnection conn) 54.67 + { 54.68 + super(conn); 54.69 + } 54.70 + 54.71 + @Override 54.72 + public boolean hasFinished() 54.73 + { 54.74 + return this.state == PostState.Finished; 54.75 + } 54.76 + 54.77 + /** 54.78 + * Process the given line String. line.trim() was called by NNTPConnection. 54.79 + * @param line 54.80 + * @throws java.io.IOException 54.81 + * @throws java.sql.SQLException 54.82 + */ 54.83 + @Override // TODO: Refactor this method to reduce complexity! 54.84 + public void processLine(String line) 54.85 + throws IOException, SQLException 54.86 + { 54.87 + switch(state) 54.88 + { 54.89 + case WaitForLineOne: 54.90 + { 54.91 + if(line.equalsIgnoreCase("POST")) 54.92 + { 54.93 + printStatus(340, "send article to be posted. End with <CR-LF>.<CR-LF>"); 54.94 + state = PostState.ReadingHeaders; 54.95 + } 54.96 + else 54.97 + { 54.98 + printStatus(500, "invalid command usage"); 54.99 + } 54.100 + break; 54.101 + } 54.102 + case ReadingHeaders: 54.103 + { 54.104 + strHead.append(line); 54.105 + strHead.append(NNTPConnection.NEWLINE); 54.106 + 54.107 + if("".equals(line) || ".".equals(line)) 54.108 + { 54.109 + // we finally met the blank line 54.110 + // separating headers from body 54.111 + 54.112 + try 54.113 + { 54.114 + // Parse the header using the InternetHeader class from JavaMail API 54.115 + headers = new InternetHeaders( 54.116 + new ByteArrayInputStream(strHead.toString().trim() 54.117 + .getBytes(connection.getCurrentCharset()))); 54.118 + 54.119 + // add the header entries for the article 54.120 + article.setHeaders(headers); 54.121 + } 54.122 + catch (MessagingException e) 54.123 + { 54.124 + e.printStackTrace(); 54.125 + printStatus(500, "posting failed - invalid header"); 54.126 + state = PostState.Finished; 54.127 + break; 54.128 + } 54.129 + 54.130 + // Change charset for reading body; 54.131 + // for multipart messages UTF-8 is returned 54.132 + connection.setCurrentCharset(article.getBodyCharset()); 54.133 + 54.134 + state = PostState.ReadingBody; 54.135 + 54.136 + if(".".equals(line)) 54.137 + { 54.138 + // Post an article without body 54.139 + postArticle(article); 54.140 + state = PostState.Finished; 54.141 + } 54.142 + } 54.143 + break; 54.144 + } 54.145 + case ReadingBody: 54.146 + { 54.147 + if(".".equals(line)) 54.148 + { 54.149 + // Set some headers needed for Over command 54.150 + headers.setHeader(Headers.LINES, Integer.toString(lineCount)); 54.151 + headers.setHeader(Headers.BYTES, Long.toString(bodySize)); 54.152 + 54.153 + if(strBody.length() >= 2) 54.154 + { 54.155 + strBody.deleteCharAt(strBody.length() - 1); // Remove last newline 54.156 + strBody.deleteCharAt(strBody.length() - 1); // Remove last CR 54.157 + } 54.158 + article.setBody(strBody.toString()); // set the article body 54.159 + 54.160 + postArticle(article); 54.161 + state = PostState.Finished; 54.162 + } 54.163 + else 54.164 + { 54.165 + bodySize += line.length() + 1; 54.166 + lineCount++; 54.167 + 54.168 + // Add line to body buffer 54.169 + strBody.append(line); 54.170 + strBody.append(NNTPConnection.NEWLINE); 54.171 + 54.172 + if(bodySize > maxBodySize) 54.173 + { 54.174 + printStatus(500, "article is too long"); 54.175 + state = PostState.Finished; 54.176 + break; 54.177 + } 54.178 + 54.179 + // Check if this message is a MIME-multipart message and needs a 54.180 + // charset change 54.181 + try 54.182 + { 54.183 + line = line.toLowerCase(Locale.ENGLISH); 54.184 + if(line.startsWith(Headers.CONTENT_TYPE)) 54.185 + { 54.186 + int idxStart = line.indexOf("charset=") + "charset=".length(); 54.187 + int idxEnd = line.indexOf(";", idxStart); 54.188 + if(idxEnd < 0) 54.189 + { 54.190 + idxEnd = line.length(); 54.191 + } 54.192 + 54.193 + if(idxStart > 0) 54.194 + { 54.195 + String charsetName = line.substring(idxStart, idxEnd); 54.196 + if(charsetName.length() > 0 && charsetName.charAt(0) == '"') 54.197 + { 54.198 + charsetName = charsetName.substring(1, charsetName.length() - 1); 54.199 + } 54.200 + 54.201 + try 54.202 + { 54.203 + connection.setCurrentCharset(Charset.forName(charsetName)); 54.204 + } 54.205 + catch(IllegalCharsetNameException ex) 54.206 + { 54.207 + Log.msg("PostCommand: " + ex, false); 54.208 + } 54.209 + catch(UnsupportedCharsetException ex) 54.210 + { 54.211 + Log.msg("PostCommand: " + ex, false); 54.212 + } 54.213 + } // if(idxStart > 0) 54.214 + } 54.215 + } 54.216 + catch(Exception ex) 54.217 + { 54.218 + ex.printStackTrace(); 54.219 + } 54.220 + } 54.221 + break; 54.222 + } 54.223 + default: 54.224 + Log.msg("PostCommand::processLine(): already finished...", false); 54.225 + } 54.226 + } 54.227 + 54.228 + /** 54.229 + * Article is a control message and needs special handling. 54.230 + * @param article 54.231 + */ 54.232 + private void controlMessage(Article article) 54.233 + throws IOException 54.234 + { 54.235 + String[] ctrl = article.getHeader(Headers.CONTROL)[0].split(" "); 54.236 + if(ctrl.length == 2) // "cancel <mid>" 54.237 + { 54.238 + try 54.239 + { 54.240 + Database.getInstance().delete(ctrl[1]); 54.241 + 54.242 + // Move cancel message to "control" group 54.243 + article.setHeader(Headers.NEWSGROUPS, "control"); 54.244 + Database.getInstance().addArticle(article); 54.245 + printStatus(240, "article cancelled"); 54.246 + } 54.247 + catch(SQLException ex) 54.248 + { 54.249 + Log.msg(ex, false); 54.250 + printStatus(500, "internal server error"); 54.251 + } 54.252 + } 54.253 + else 54.254 + { 54.255 + printStatus(441, "unknown Control header"); 54.256 + } 54.257 + } 54.258 + 54.259 + private void supersedeMessage(Article article) 54.260 + throws IOException 54.261 + { 54.262 + try 54.263 + { 54.264 + String oldMsg = article.getHeader(Headers.SUPERSEDES)[0]; 54.265 + Database.getInstance().delete(oldMsg); 54.266 + Database.getInstance().addArticle(article); 54.267 + printStatus(240, "article replaced"); 54.268 + } 54.269 + catch(SQLException ex) 54.270 + { 54.271 + Log.msg(ex, false); 54.272 + printStatus(500, "internal server error"); 54.273 + } 54.274 + } 54.275 + 54.276 + private void postArticle(Article article) 54.277 + throws IOException 54.278 + { 54.279 + if(article.getHeader(Headers.CONTROL)[0].length() > 0) 54.280 + { 54.281 + controlMessage(article); 54.282 + } 54.283 + else if(article.getHeader(Headers.SUPERSEDES)[0].length() > 0) 54.284 + { 54.285 + supersedeMessage(article); 54.286 + } 54.287 + else // Post the article regularily 54.288 + { 54.289 + // Try to create the article in the database or post it to 54.290 + // appropriate mailing list 54.291 + try 54.292 + { 54.293 + boolean success = false; 54.294 + String[] groupnames = article.getHeader(Headers.NEWSGROUPS)[0].split(","); 54.295 + for(String groupname : groupnames) 54.296 + { 54.297 + Group group = Database.getInstance().getGroup(groupname); 54.298 + if(group != null) 54.299 + { 54.300 + if(group.isMailingList() && !connection.isLocalConnection()) 54.301 + { 54.302 + // Send to mailing list; the Dispatcher writes 54.303 + // statistics to database 54.304 + Dispatcher.toList(article); 54.305 + success = true; 54.306 + } 54.307 + else 54.308 + { 54.309 + // Store in database 54.310 + if(!Database.getInstance().isArticleExisting(article.getMessageID())) 54.311 + { 54.312 + Database.getInstance().addArticle(article); 54.313 + 54.314 + // Log this posting to statistics 54.315 + Stats.getInstance().mailPosted( 54.316 + article.getHeader(Headers.NEWSGROUPS)[0]); 54.317 + } 54.318 + success = true; 54.319 + } 54.320 + } 54.321 + } // end for 54.322 + 54.323 + if(success) 54.324 + { 54.325 + printStatus(240, "article posted ok"); 54.326 + FeedManager.queueForPush(article); 54.327 + } 54.328 + else 54.329 + { 54.330 + printStatus(441, "newsgroup not found"); 54.331 + } 54.332 + } 54.333 + catch(AddressException ex) 54.334 + { 54.335 + Log.msg(ex.getMessage(), true); 54.336 + printStatus(441, "invalid sender address"); 54.337 + } 54.338 + catch(MessagingException ex) 54.339 + { 54.340 + // A MessageException is thrown when the sender email address is 54.341 + // invalid or something is wrong with the SMTP server. 54.342 + System.err.println(ex.getLocalizedMessage()); 54.343 + printStatus(441, ex.getClass().getCanonicalName() + ": " + ex.getLocalizedMessage()); 54.344 + } 54.345 + catch(SQLException ex) 54.346 + { 54.347 + ex.printStackTrace(); 54.348 + printStatus(500, "internal server error"); 54.349 + } 54.350 + } 54.351 + } 54.352 + 54.353 +}
55.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 55.2 +++ b/org/sonews/daemon/command/PostState.java Fri Jun 26 16:48:50 2009 +0200 55.3 @@ -0,0 +1,29 @@ 55.4 +/* 55.5 + * SONEWS News Server 55.6 + * see AUTHORS for the list of contributors 55.7 + * 55.8 + * This program is free software: you can redistribute it and/or modify 55.9 + * it under the terms of the GNU General Public License as published by 55.10 + * the Free Software Foundation, either version 3 of the License, or 55.11 + * (at your option) any later version. 55.12 + * 55.13 + * This program is distributed in the hope that it will be useful, 55.14 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 55.15 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 55.16 + * GNU General Public License for more details. 55.17 + * 55.18 + * You should have received a copy of the GNU General Public License 55.19 + * along with this program. If not, see <http://www.gnu.org/licenses/>. 55.20 + */ 55.21 + 55.22 +package org.sonews.daemon.command; 55.23 + 55.24 +/** 55.25 + * States of the POST command's finite state machine. 55.26 + * @author Christian Lins 55.27 + * @since sonews/0.5.0 55.28 + */ 55.29 +enum PostState 55.30 +{ 55.31 + WaitForLineOne, ReadingHeaders, ReadingBody, Finished 55.32 +}
56.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 56.2 +++ b/org/sonews/daemon/command/QuitCommand.java Fri Jun 26 16:48:50 2009 +0200 56.3 @@ -0,0 +1,54 @@ 56.4 +/* 56.5 + * SONEWS News Server 56.6 + * see AUTHORS for the list of contributors 56.7 + * 56.8 + * This program is free software: you can redistribute it and/or modify 56.9 + * it under the terms of the GNU General Public License as published by 56.10 + * the Free Software Foundation, either version 3 of the License, or 56.11 + * (at your option) any later version. 56.12 + * 56.13 + * This program is distributed in the hope that it will be useful, 56.14 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 56.15 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 56.16 + * GNU General Public License for more details. 56.17 + * 56.18 + * You should have received a copy of the GNU General Public License 56.19 + * along with this program. If not, see <http://www.gnu.org/licenses/>. 56.20 + */ 56.21 + 56.22 +package org.sonews.daemon.command; 56.23 + 56.24 +import java.io.IOException; 56.25 +import java.sql.SQLException; 56.26 +import org.sonews.daemon.NNTPConnection; 56.27 + 56.28 +/** 56.29 + * Implementation of the QUIT command; client wants to shutdown the connection. 56.30 + * @author Christian Lins 56.31 + * @since sonews/0.5.0 56.32 + */ 56.33 +public class QuitCommand extends AbstractCommand 56.34 +{ 56.35 + 56.36 + public QuitCommand(final NNTPConnection conn) 56.37 + { 56.38 + super(conn); 56.39 + } 56.40 + 56.41 + @Override 56.42 + public boolean hasFinished() 56.43 + { 56.44 + return true; 56.45 + } 56.46 + 56.47 + @Override 56.48 + public void processLine(final String line) 56.49 + throws IOException, SQLException 56.50 + { 56.51 + printStatus(205, "cya"); 56.52 + 56.53 + this.connection.shutdownInput(); 56.54 + this.connection.shutdownOutput(); 56.55 + } 56.56 + 56.57 +}
57.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 57.2 +++ b/org/sonews/daemon/command/StatCommand.java Fri Jun 26 16:48:50 2009 +0200 57.3 @@ -0,0 +1,100 @@ 57.4 +/* 57.5 + * SONEWS News Server 57.6 + * see AUTHORS for the list of contributors 57.7 + * 57.8 + * This program is free software: you can redistribute it and/or modify 57.9 + * it under the terms of the GNU General Public License as published by 57.10 + * the Free Software Foundation, either version 3 of the License, or 57.11 + * (at your option) any later version. 57.12 + * 57.13 + * This program is distributed in the hope that it will be useful, 57.14 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 57.15 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 57.16 + * GNU General Public License for more details. 57.17 + * 57.18 + * You should have received a copy of the GNU General Public License 57.19 + * along with this program. If not, see <http://www.gnu.org/licenses/>. 57.20 + */ 57.21 + 57.22 +package org.sonews.daemon.command; 57.23 + 57.24 +import java.io.IOException; 57.25 +import java.sql.SQLException; 57.26 +import org.sonews.daemon.storage.Article; 57.27 +import org.sonews.daemon.NNTPConnection; 57.28 + 57.29 +/** 57.30 + * Implementation of the STAT command. 57.31 + * @author Christian Lins 57.32 + * @since sonews/0.5.0 57.33 + */ 57.34 +public class StatCommand extends AbstractCommand 57.35 +{ 57.36 + 57.37 + public StatCommand(final NNTPConnection conn) 57.38 + { 57.39 + super(conn); 57.40 + } 57.41 + 57.42 + @Override 57.43 + public boolean hasFinished() 57.44 + { 57.45 + return true; 57.46 + } 57.47 + 57.48 + // TODO: Method has various exit points => Refactor! 57.49 + @Override 57.50 + public void processLine(final String line) 57.51 + throws IOException, SQLException 57.52 + { 57.53 + final String[] command = line.split(" "); 57.54 + 57.55 + Article article = null; 57.56 + if(command.length == 1) 57.57 + { 57.58 + article = getCurrentArticle(); 57.59 + if(article == null) 57.60 + { 57.61 + printStatus(420, "no current article has been selected"); 57.62 + return; 57.63 + } 57.64 + } 57.65 + else if(command[1].matches(NNTPConnection.MESSAGE_ID_PATTERN)) 57.66 + { 57.67 + // Message-ID 57.68 + article = Article.getByMessageID(command[1]); 57.69 + if (article == null) 57.70 + { 57.71 + printStatus(430, "no such article found"); 57.72 + return; 57.73 + } 57.74 + } 57.75 + else 57.76 + { 57.77 + // Message Number 57.78 + try 57.79 + { 57.80 + long aid = Long.parseLong(command[1]); 57.81 + article = Article.getByArticleNumber(aid, getCurrentGroup()); 57.82 + } 57.83 + catch(NumberFormatException ex) 57.84 + { 57.85 + ex.printStackTrace(); 57.86 + } 57.87 + catch(SQLException ex) 57.88 + { 57.89 + ex.printStackTrace(); 57.90 + } 57.91 + if (article == null) 57.92 + { 57.93 + printStatus(423, "no such article number in this group"); 57.94 + return; 57.95 + } 57.96 + setCurrentArticle(article); 57.97 + } 57.98 + 57.99 + printStatus(223, article.getIndexInGroup(getCurrentGroup()) + " " + article.getMessageID() 57.100 + + " article retrieved - request text separately"); 57.101 + } 57.102 + 57.103 +}
58.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 58.2 +++ b/org/sonews/daemon/command/UnsupportedCommand.java Fri Jun 26 16:48:50 2009 +0200 58.3 @@ -0,0 +1,51 @@ 58.4 +/* 58.5 + * SONEWS News Server 58.6 + * see AUTHORS for the list of contributors 58.7 + * 58.8 + * This program is free software: you can redistribute it and/or modify 58.9 + * it under the terms of the GNU General Public License as published by 58.10 + * the Free Software Foundation, either version 3 of the License, or 58.11 + * (at your option) any later version. 58.12 + * 58.13 + * This program is distributed in the hope that it will be useful, 58.14 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 58.15 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 58.16 + * GNU General Public License for more details. 58.17 + * 58.18 + * You should have received a copy of the GNU General Public License 58.19 + * along with this program. If not, see <http://www.gnu.org/licenses/>. 58.20 + */ 58.21 + 58.22 +package org.sonews.daemon.command; 58.23 + 58.24 +import java.io.IOException; 58.25 +import org.sonews.daemon.NNTPConnection; 58.26 + 58.27 +/** 58.28 + * A default "Unsupported Command". Simply returns error code 500 and a 58.29 + * "command not supported" message. 58.30 + * @author Christian Lins 58.31 + * @since sonews/0.5.0 58.32 + */ 58.33 +public class UnsupportedCommand extends AbstractCommand 58.34 +{ 58.35 + 58.36 + public UnsupportedCommand(final NNTPConnection conn) 58.37 + { 58.38 + super(conn); 58.39 + } 58.40 + 58.41 + @Override 58.42 + public boolean hasFinished() 58.43 + { 58.44 + return true; 58.45 + } 58.46 + 58.47 + @Override 58.48 + public void processLine(final String line) 58.49 + throws IOException 58.50 + { 58.51 + printStatus(500, "command not supported"); 58.52 + } 58.53 + 58.54 +}
59.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 59.2 +++ b/org/sonews/daemon/command/XDaemonCommand.java Fri Jun 26 16:48:50 2009 +0200 59.3 @@ -0,0 +1,237 @@ 59.4 +/* 59.5 + * SONEWS News Server 59.6 + * see AUTHORS for the list of contributors 59.7 + * 59.8 + * This program is free software: you can redistribute it and/or modify 59.9 + * it under the terms of the GNU General Public License as published by 59.10 + * the Free Software Foundation, either version 3 of the License, or 59.11 + * (at your option) any later version. 59.12 + * 59.13 + * This program is distributed in the hope that it will be useful, 59.14 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 59.15 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 59.16 + * GNU General Public License for more details. 59.17 + * 59.18 + * You should have received a copy of the GNU General Public License 59.19 + * along with this program. If not, see <http://www.gnu.org/licenses/>. 59.20 + */ 59.21 + 59.22 +package org.sonews.daemon.command; 59.23 + 59.24 +import java.io.IOException; 59.25 +import java.net.InetSocketAddress; 59.26 +import java.sql.SQLException; 59.27 +import java.util.List; 59.28 +import org.sonews.daemon.BootstrapConfig; 59.29 +import org.sonews.daemon.Config; 59.30 +import org.sonews.daemon.NNTPConnection; 59.31 +import org.sonews.daemon.storage.Database; 59.32 +import org.sonews.daemon.storage.Group; 59.33 +import org.sonews.feed.FeedManager; 59.34 +import org.sonews.feed.Subscription; 59.35 +import org.sonews.util.Stats; 59.36 + 59.37 +/** 59.38 + * The XDAEMON command allows a client to get/set properties of the 59.39 + * running server daemon. Only locally connected clients are allowed to 59.40 + * use this command. 59.41 + * The restriction to localhost connection can be suppressed by overriding 59.42 + * the sonews.xdaemon.host bootstrap config property. 59.43 + * @author Christian Lins 59.44 + * @since sonews/0.5.0 59.45 + */ 59.46 +public class XDaemonCommand extends AbstractCommand 59.47 +{ 59.48 + 59.49 + public XDaemonCommand(NNTPConnection conn) 59.50 + { 59.51 + super(conn); 59.52 + } 59.53 + 59.54 + @Override 59.55 + public boolean hasFinished() 59.56 + { 59.57 + return true; 59.58 + } 59.59 + 59.60 + // TODO: Refactor this method to reduce complexity! 59.61 + @Override 59.62 + public void processLine(String line) throws IOException, SQLException 59.63 + { 59.64 + InetSocketAddress addr = (InetSocketAddress)connection.getChannel().socket() 59.65 + .getRemoteSocketAddress(); 59.66 + if(addr.getHostName().equals( 59.67 + BootstrapConfig.getInstance().get(BootstrapConfig.XDAEMON_HOST, "localhost"))) 59.68 + { 59.69 + String[] commands = line.split(" ", 4); 59.70 + if(commands.length == 3 && commands[1].equalsIgnoreCase("LIST")) 59.71 + { 59.72 + if(commands[2].equalsIgnoreCase("CONFIGKEYS")) 59.73 + { 59.74 + printStatus(200, "list of available config keys follows"); 59.75 + for(String key : Config.AVAILABLE_KEYS) 59.76 + { 59.77 + println(key); 59.78 + } 59.79 + println("."); 59.80 + } 59.81 + else if(commands[2].equalsIgnoreCase("PEERINGRULES")) 59.82 + { 59.83 + List<Subscription> pull = 59.84 + Database.getInstance().getSubscriptions(FeedManager.TYPE_PULL); 59.85 + List<Subscription> push = 59.86 + Database.getInstance().getSubscriptions(FeedManager.TYPE_PUSH); 59.87 + printStatus(200,"list of peering rules follows"); 59.88 + for(Subscription sub : pull) 59.89 + { 59.90 + println("PULL " + sub.getHost() + ":" + sub.getPort() 59.91 + + " " + sub.getGroup()); 59.92 + } 59.93 + for(Subscription sub : push) 59.94 + { 59.95 + println("PUSH " + sub.getHost() + ":" + sub.getPort() 59.96 + + " " + sub.getGroup()); 59.97 + } 59.98 + println("."); 59.99 + } 59.100 + else 59.101 + { 59.102 + printStatus(501, "unknown sub command"); 59.103 + } 59.104 + } 59.105 + else if(commands.length == 3 && commands[1].equalsIgnoreCase("DELETE")) 59.106 + { 59.107 + Database.getInstance().delete(commands[2]); 59.108 + printStatus(200, "article " + commands[2] + " deleted"); 59.109 + } 59.110 + else if(commands.length == 4 && commands[1].equalsIgnoreCase("GROUPADD")) 59.111 + { 59.112 + Database.getInstance().addGroup(commands[2], Integer.parseInt(commands[3])); 59.113 + printStatus(200, "group " + commands[2] + " created"); 59.114 + } 59.115 + else if(commands.length == 3 && commands[1].equalsIgnoreCase("GROUPDEL")) 59.116 + { 59.117 + Group group = Database.getInstance().getGroup(commands[2]); 59.118 + if(group == null) 59.119 + { 59.120 + printStatus(400, "group not found"); 59.121 + } 59.122 + else 59.123 + { 59.124 + group.setFlag(Group.DELETED); 59.125 + printStatus(200, "group " + commands[2] + " marked as deleted"); 59.126 + } 59.127 + } 59.128 + else if(commands.length == 4 && commands[1].equalsIgnoreCase("SET")) 59.129 + { 59.130 + String key = commands[2]; 59.131 + String val = commands[3]; 59.132 + Config.getInstance().set(key, val); 59.133 + printStatus(200, "new config value set"); 59.134 + } 59.135 + else if(commands.length == 3 && commands[1].equalsIgnoreCase("GET")) 59.136 + { 59.137 + String key = commands[2]; 59.138 + String val = Config.getInstance().get(key, null); 59.139 + if(val != null) 59.140 + { 59.141 + printStatus(200, "config value for " + key + " follows"); 59.142 + println(val); 59.143 + println("."); 59.144 + } 59.145 + else 59.146 + { 59.147 + printStatus(400, "config value not set"); 59.148 + } 59.149 + } 59.150 + else if(commands.length >= 3 && commands[1].equalsIgnoreCase("LOG")) 59.151 + { 59.152 + Group group = null; 59.153 + if(commands.length > 3) 59.154 + { 59.155 + group = Group.getByName(commands[3]); 59.156 + } 59.157 + 59.158 + if(commands[2].equalsIgnoreCase("CONNECTED_CLIENTS")) 59.159 + { 59.160 + printStatus(200, "number of connections follow"); 59.161 + println(Integer.toString(Stats.getInstance().connectedClients())); 59.162 + println("."); 59.163 + } 59.164 + else if(commands[2].equalsIgnoreCase("POSTED_NEWS")) 59.165 + { 59.166 + printStatus(200, "hourly numbers of posted news yesterday"); 59.167 + for(int n = 0; n < 24; n++) 59.168 + { 59.169 + println(n + " " + Stats.getInstance() 59.170 + .getYesterdaysEvents(Stats.POSTED_NEWS, n, group)); 59.171 + } 59.172 + println("."); 59.173 + } 59.174 + else if(commands[2].equalsIgnoreCase("GATEWAYED_NEWS")) 59.175 + { 59.176 + printStatus(200, "hourly numbers of gatewayed news yesterday"); 59.177 + for(int n = 0; n < 24; n++) 59.178 + { 59.179 + println(n + " " + Stats.getInstance() 59.180 + .getYesterdaysEvents(Stats.GATEWAYED_NEWS, n, group)); 59.181 + } 59.182 + println("."); 59.183 + } 59.184 + else if(commands[2].equalsIgnoreCase("TRANSMITTED_NEWS")) 59.185 + { 59.186 + printStatus(200, "hourly numbers of news transmitted to peers yesterday"); 59.187 + for(int n = 0; n < 24; n++) 59.188 + { 59.189 + println(n + " " + Stats.getInstance() 59.190 + .getYesterdaysEvents(Stats.FEEDED_NEWS, n, group)); 59.191 + } 59.192 + println("."); 59.193 + } 59.194 + else if(commands[2].equalsIgnoreCase("HOSTED_NEWS")) 59.195 + { 59.196 + printStatus(200, "number of overall hosted news"); 59.197 + println(Integer.toString(Stats.getInstance().getNumberOfNews())); 59.198 + println("."); 59.199 + } 59.200 + else if(commands[2].equalsIgnoreCase("HOSTED_GROUPS")) 59.201 + { 59.202 + printStatus(200, "number of hosted groups"); 59.203 + println(Integer.toString(Stats.getInstance().getNumberOfGroups())); 59.204 + println("."); 59.205 + } 59.206 + else if(commands[2].equalsIgnoreCase("POSTED_NEWS_PER_HOUR")) 59.207 + { 59.208 + printStatus(200, "posted news per hour"); 59.209 + println(Double.toString(Stats.getInstance().postedPerHour(-1))); 59.210 + println("."); 59.211 + } 59.212 + else if(commands[2].equalsIgnoreCase("FEEDED_NEWS_PER_HOUR")) 59.213 + { 59.214 + printStatus(200, "feeded news per hour"); 59.215 + println(Double.toString(Stats.getInstance().feededPerHour(-1))); 59.216 + println("."); 59.217 + } 59.218 + else if(commands[2].equalsIgnoreCase("GATEWAYED_NEWS_PER_HOUR")) 59.219 + { 59.220 + printStatus(200, "gatewayed news per hour"); 59.221 + println(Double.toString(Stats.getInstance().gatewayedPerHour(-1))); 59.222 + println("."); 59.223 + } 59.224 + else 59.225 + { 59.226 + printStatus(501, "unknown sub command"); 59.227 + } 59.228 + } 59.229 + else 59.230 + { 59.231 + printStatus(500, "invalid command usage"); 59.232 + } 59.233 + } 59.234 + else 59.235 + { 59.236 + printStatus(500, "not allowed"); 59.237 + } 59.238 + } 59.239 + 59.240 +}
60.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 60.2 +++ b/org/sonews/daemon/command/XPatCommand.java Fri Jun 26 16:48:50 2009 +0200 60.3 @@ -0,0 +1,89 @@ 60.4 +/* 60.5 + * SONEWS News Server 60.6 + * see AUTHORS for the list of contributors 60.7 + * 60.8 + * This program is free software: you can redistribute it and/or modify 60.9 + * it under the terms of the GNU General Public License as published by 60.10 + * the Free Software Foundation, either version 3 of the License, or 60.11 + * (at your option) any later version. 60.12 + * 60.13 + * This program is distributed in the hope that it will be useful, 60.14 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 60.15 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 60.16 + * GNU General Public License for more details. 60.17 + * 60.18 + * You should have received a copy of the GNU General Public License 60.19 + * along with this program. If not, see <http://www.gnu.org/licenses/>. 60.20 + */ 60.21 + 60.22 +package org.sonews.daemon.command; 60.23 + 60.24 +import java.io.IOException; 60.25 +import java.sql.SQLException; 60.26 +import org.sonews.daemon.NNTPConnection; 60.27 + 60.28 +/** 60.29 + * <pre> 60.30 + * XPAT header range|<message-id> pat [pat...] 60.31 + * 60.32 + * The XPAT command is used to retrieve specific headers from 60.33 + * specific articles, based on pattern matching on the contents of 60.34 + * the header. This command was first available in INN. 60.35 + * 60.36 + * The required header parameter is the name of a header line (e.g. 60.37 + * "subject") in a news group article. See RFC-1036 for a list 60.38 + * of valid header lines. The required range argument may be 60.39 + * any of the following: 60.40 + * an article number 60.41 + * an article number followed by a dash to indicate 60.42 + * all following 60.43 + * an article number followed by a dash followed by 60.44 + * another article number 60.45 + * 60.46 + * The required message-id argument indicates a specific 60.47 + * article. The range and message-id arguments are mutually 60.48 + * exclusive. At least one pattern in wildmat must be specified 60.49 + * as well. If there are additional arguments the are joined 60.50 + * together separated by a single space to form one complete 60.51 + * pattern. Successful responses start with a 221 response 60.52 + * followed by a the headers from all messages in which the 60.53 + * pattern matched the contents of the specified header line. This 60.54 + * includes an empty list. Once the output is complete, a period 60.55 + * is sent on a line by itself. If the optional argument is a 60.56 + * message-id and no such article exists, the 430 error response 60.57 + * is returned. A 502 response will be returned if the client only 60.58 + * has permission to transfer articles. 60.59 + * 60.60 + * Responses 60.61 + * 60.62 + * 221 Header follows 60.63 + * 430 no such article 60.64 + * 502 no permission 60.65 + * </pre> 60.66 + * [Source:"draft-ietf-nntp-imp-02.txt"] [Copyright: 1998 S. Barber] 60.67 + * 60.68 + * @author Christian Lins 60.69 + * @since sonews/0.5.0 60.70 + */ 60.71 +public class XPatCommand extends AbstractCommand 60.72 +{ 60.73 + 60.74 + public XPatCommand(final NNTPConnection conn) 60.75 + { 60.76 + super(conn); 60.77 + } 60.78 + 60.79 + @Override 60.80 + public boolean hasFinished() 60.81 + { 60.82 + return true; 60.83 + } 60.84 + 60.85 + @Override 60.86 + public void processLine(final String line) 60.87 + throws IOException, SQLException 60.88 + { 60.89 + printStatus(500, "not (yet) supported"); 60.90 + } 60.91 + 60.92 +}
61.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 61.2 +++ b/org/sonews/daemon/command/package.html Fri Jun 26 16:48:50 2009 +0200 61.3 @@ -0,0 +1,1 @@ 61.4 +Contains a class for every NNTP command. 61.5 \ No newline at end of file
62.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 62.2 +++ b/org/sonews/daemon/package.html Fri Jun 26 16:48:50 2009 +0200 62.3 @@ -0,0 +1,1 @@ 62.4 +Contains basic classes of the daemon. 62.5 \ No newline at end of file
63.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 63.2 +++ b/org/sonews/daemon/storage/Article.java Fri Jun 26 16:48:50 2009 +0200 63.3 @@ -0,0 +1,401 @@ 63.4 +/* 63.5 + * SONEWS News Server 63.6 + * see AUTHORS for the list of contributors 63.7 + * 63.8 + * This program is free software: you can redistribute it and/or modify 63.9 + * it under the terms of the GNU General Public License as published by 63.10 + * the Free Software Foundation, either version 3 of the License, or 63.11 + * (at your option) any later version. 63.12 + * 63.13 + * This program is distributed in the hope that it will be useful, 63.14 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 63.15 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 63.16 + * GNU General Public License for more details. 63.17 + * 63.18 + * You should have received a copy of the GNU General Public License 63.19 + * along with this program. If not, see <http://www.gnu.org/licenses/>. 63.20 + */ 63.21 + 63.22 +package org.sonews.daemon.storage; 63.23 + 63.24 +import org.sonews.daemon.Config; 63.25 +import java.io.BufferedReader; 63.26 +import java.io.ByteArrayInputStream; 63.27 +import java.io.IOException; 63.28 +import java.io.InputStream; 63.29 +import java.io.InputStreamReader; 63.30 +import java.nio.charset.Charset; 63.31 +import java.sql.SQLException; 63.32 +import java.util.UUID; 63.33 +import java.util.ArrayList; 63.34 +import java.util.Enumeration; 63.35 +import java.util.List; 63.36 +import javax.mail.Header; 63.37 +import javax.mail.Message; 63.38 +import javax.mail.MessagingException; 63.39 +import javax.mail.Multipart; 63.40 +import javax.mail.internet.InternetHeaders; 63.41 +import javax.mail.internet.MimeUtility; 63.42 +import org.sonews.util.Log; 63.43 + 63.44 +/** 63.45 + * Represents a newsgroup article. 63.46 + * @author Christian Lins 63.47 + * @author Denis Schwerdel 63.48 + * @since n3tpd/0.1 63.49 + */ 63.50 +public class Article extends ArticleHead 63.51 +{ 63.52 + 63.53 + /** 63.54 + * Loads the Article identified by the given ID from the Database. 63.55 + * @param messageID 63.56 + * @return null if Article is not found or if an error occurred. 63.57 + */ 63.58 + public static Article getByMessageID(final String messageID) 63.59 + { 63.60 + try 63.61 + { 63.62 + return Database.getInstance().getArticle(messageID); 63.63 + } 63.64 + catch(SQLException ex) 63.65 + { 63.66 + ex.printStackTrace(); 63.67 + return null; 63.68 + } 63.69 + } 63.70 + 63.71 + public static Article getByArticleNumber(long articleIndex, Group group) 63.72 + throws SQLException 63.73 + { 63.74 + return Database.getInstance().getArticle(articleIndex, group.getID()); 63.75 + } 63.76 + 63.77 + private String body = ""; 63.78 + private String headerSrc = null; 63.79 + 63.80 + /** 63.81 + * Default constructor. 63.82 + */ 63.83 + public Article() 63.84 + { 63.85 + } 63.86 + 63.87 + /** 63.88 + * Creates a new Article object using the date from the given 63.89 + * raw data. 63.90 + * This construction has only package visibility. 63.91 + */ 63.92 + Article(String headers, String body) 63.93 + { 63.94 + try 63.95 + { 63.96 + this.body = body; 63.97 + 63.98 + // Parse the header 63.99 + this.headers = new InternetHeaders( 63.100 + new ByteArrayInputStream(headers.getBytes())); 63.101 + 63.102 + this.headerSrc = headers; 63.103 + } 63.104 + catch(MessagingException ex) 63.105 + { 63.106 + ex.printStackTrace(); 63.107 + } 63.108 + } 63.109 + 63.110 + /** 63.111 + * Creates an Article instance using the data from the javax.mail.Message 63.112 + * object. 63.113 + * @see javax.mail.Message 63.114 + * @param msg 63.115 + * @throws IOException 63.116 + * @throws MessagingException 63.117 + */ 63.118 + public Article(final Message msg) 63.119 + throws IOException, MessagingException 63.120 + { 63.121 + this.headers = new InternetHeaders(); 63.122 + 63.123 + for(Enumeration e = msg.getAllHeaders() ; e.hasMoreElements();) 63.124 + { 63.125 + final Header header = (Header)e.nextElement(); 63.126 + this.headers.addHeader(header.getName(), header.getValue()); 63.127 + } 63.128 + 63.129 + // The "content" of the message can be a String if it's a simple text/plain 63.130 + // message, a Multipart object or an InputStream if the content is unknown. 63.131 + final Object content = msg.getContent(); 63.132 + if(content instanceof String) 63.133 + { 63.134 + this.body = (String)content; 63.135 + } 63.136 + else if(content instanceof Multipart) // probably subclass MimeMultipart 63.137 + { 63.138 + // We're are not interested in the different parts of the MultipartMessage, 63.139 + // so we simply read in all data which *can* be huge. 63.140 + InputStream in = msg.getInputStream(); 63.141 + this.body = readContent(in); 63.142 + } 63.143 + else if(content instanceof InputStream) 63.144 + { 63.145 + // The message format is unknown to the Message class, but we can 63.146 + // simply read in the whole message data. 63.147 + this.body = readContent((InputStream)content); 63.148 + } 63.149 + else 63.150 + { 63.151 + // Unknown content is probably a malformed mail we should skip. 63.152 + // On the other hand we produce an inconsistent mail mirror, but no 63.153 + // mail system must transport invalid content. 63.154 + Log.msg("Skipping message due to unknown content. Throwing exception...", true); 63.155 + throw new MessagingException("Unknown content: " + content); 63.156 + } 63.157 + 63.158 + // Validate headers 63.159 + validateHeaders(); 63.160 + } 63.161 + 63.162 + /** 63.163 + * Reads lines from the given InputString into a String object. 63.164 + * TODO: Move this generalized method to org.sonews.util.io.Resource. 63.165 + * @param in 63.166 + * @return 63.167 + * @throws IOException 63.168 + */ 63.169 + private String readContent(InputStream in) 63.170 + throws IOException 63.171 + { 63.172 + StringBuilder buf = new StringBuilder(); 63.173 + 63.174 + BufferedReader rin = new BufferedReader(new InputStreamReader(in)); 63.175 + String line = rin.readLine(); 63.176 + while(line != null) 63.177 + { 63.178 + buf.append('\n'); 63.179 + buf.append(line); 63.180 + line = rin.readLine(); 63.181 + } 63.182 + 63.183 + return buf.toString(); 63.184 + } 63.185 + 63.186 + /** 63.187 + * Removes the header identified by the given key. 63.188 + * @param headerKey 63.189 + */ 63.190 + public void removeHeader(final String headerKey) 63.191 + { 63.192 + this.headers.removeHeader(headerKey); 63.193 + this.headerSrc = null; 63.194 + } 63.195 + 63.196 + /** 63.197 + * Generates a message id for this article and sets it into 63.198 + * the header object. You have to update the Database manually to make this 63.199 + * change persistent. 63.200 + * Note: a Message-ID should never be changed and only generated once. 63.201 + */ 63.202 + private String generateMessageID() 63.203 + { 63.204 + String msgID = "<" + UUID.randomUUID() + "@" 63.205 + + Config.getInstance().get(Config.HOSTNAME, "localhost") + ">"; 63.206 + 63.207 + this.headers.setHeader(Headers.MESSAGE_ID, msgID); 63.208 + 63.209 + return msgID; 63.210 + } 63.211 + 63.212 + /** 63.213 + * Returns the body string. 63.214 + */ 63.215 + public String getBody() 63.216 + { 63.217 + return body; 63.218 + } 63.219 + 63.220 + /** 63.221 + * @return Charset of the body text 63.222 + */ 63.223 + public Charset getBodyCharset() 63.224 + { 63.225 + // We espect something like 63.226 + // Content-Type: text/plain; charset=ISO-8859-15 63.227 + String contentType = getHeader(Headers.CONTENT_TYPE)[0]; 63.228 + int idxCharsetStart = contentType.indexOf("charset=") + "charset=".length(); 63.229 + int idxCharsetEnd = contentType.indexOf(";", idxCharsetStart); 63.230 + 63.231 + String charsetName = "UTF-8"; 63.232 + if(idxCharsetStart >= 0 && idxCharsetStart < contentType.length()) 63.233 + { 63.234 + if(idxCharsetEnd < 0) 63.235 + { 63.236 + charsetName = contentType.substring(idxCharsetStart); 63.237 + } 63.238 + else 63.239 + { 63.240 + charsetName = contentType.substring(idxCharsetStart, idxCharsetEnd); 63.241 + } 63.242 + } 63.243 + 63.244 + // Sometimes there are '"' around the name 63.245 + if(charsetName.length() > 2 && 63.246 + charsetName.charAt(0) == '"' && charsetName.endsWith("\"")) 63.247 + { 63.248 + charsetName = charsetName.substring(1, charsetName.length() - 2); 63.249 + } 63.250 + 63.251 + // Create charset 63.252 + Charset charset = Charset.forName("UTF-8"); // This MUST be supported by JVM 63.253 + try 63.254 + { 63.255 + charset = Charset.forName(charsetName); 63.256 + } 63.257 + catch(Exception ex) 63.258 + { 63.259 + Log.msg(ex.getMessage(), false); 63.260 + Log.msg("Article.getBodyCharset(): Unknown charset: " + charsetName, false); 63.261 + } 63.262 + return charset; 63.263 + } 63.264 + 63.265 + /** 63.266 + * @return Numerical IDs of the newsgroups this Article belongs to. 63.267 + */ 63.268 + List<Group> getGroups() 63.269 + { 63.270 + String[] groupnames = getHeader(Headers.NEWSGROUPS)[0].split(","); 63.271 + ArrayList<Group> groups = new ArrayList<Group>(); 63.272 + 63.273 + try 63.274 + { 63.275 + for(String newsgroup : groupnames) 63.276 + { 63.277 + newsgroup = newsgroup.trim(); 63.278 + Group group = Database.getInstance().getGroup(newsgroup); 63.279 + if(group != null && // If the server does not provide the group, ignore it 63.280 + !groups.contains(group)) // Yes, there may be duplicates 63.281 + { 63.282 + groups.add(group); 63.283 + } 63.284 + } 63.285 + } 63.286 + catch (SQLException ex) 63.287 + { 63.288 + ex.printStackTrace(); 63.289 + return null; 63.290 + } 63.291 + return groups; 63.292 + } 63.293 + 63.294 + public void setBody(String body) 63.295 + { 63.296 + this.body = body; 63.297 + } 63.298 + 63.299 + /** 63.300 + * 63.301 + * @param groupname Name(s) of newsgroups 63.302 + */ 63.303 + public void setGroup(String groupname) 63.304 + { 63.305 + this.headers.setHeader(Headers.NEWSGROUPS, groupname); 63.306 + } 63.307 + 63.308 + public String getMessageID() 63.309 + { 63.310 + String[] msgID = getHeader(Headers.MESSAGE_ID); 63.311 + return msgID[0]; 63.312 + } 63.313 + 63.314 + public Enumeration getAllHeaders() 63.315 + { 63.316 + return this.headers.getAllHeaders(); 63.317 + } 63.318 + 63.319 + /** 63.320 + * @return Header source code of this Article. 63.321 + */ 63.322 + public String getHeaderSource() 63.323 + { 63.324 + if(this.headerSrc != null) 63.325 + { 63.326 + return this.headerSrc; 63.327 + } 63.328 + 63.329 + StringBuffer buf = new StringBuffer(); 63.330 + 63.331 + for(Enumeration en = this.headers.getAllHeaders(); en.hasMoreElements();) 63.332 + { 63.333 + Header entry = (Header)en.nextElement(); 63.334 + 63.335 + buf.append(entry.getName()); 63.336 + buf.append(": "); 63.337 + buf.append( 63.338 + MimeUtility.fold(entry.getName().length() + 2, entry.getValue())); 63.339 + 63.340 + if(en.hasMoreElements()) 63.341 + { 63.342 + buf.append("\r\n"); 63.343 + } 63.344 + } 63.345 + 63.346 + this.headerSrc = buf.toString(); 63.347 + return this.headerSrc; 63.348 + } 63.349 + 63.350 + public long getIndexInGroup(Group group) 63.351 + throws SQLException 63.352 + { 63.353 + return Database.getInstance().getArticleIndex(this, group); 63.354 + } 63.355 + 63.356 + /** 63.357 + * Sets the headers of this Article. If headers contain no 63.358 + * Message-Id a new one is created. 63.359 + * @param headers 63.360 + */ 63.361 + public void setHeaders(InternetHeaders headers) 63.362 + { 63.363 + this.headers = headers; 63.364 + validateHeaders(); 63.365 + } 63.366 + 63.367 + /** 63.368 + * @return String containing the Message-ID. 63.369 + */ 63.370 + @Override 63.371 + public String toString() 63.372 + { 63.373 + return getMessageID(); 63.374 + } 63.375 + 63.376 + /** 63.377 + * Checks some headers for their validity and generates an 63.378 + * appropriate Path-header for this host if not yet existing. 63.379 + * This method is called by some Article constructors and the 63.380 + * method setHeaders(). 63.381 + * @return true if something on the headers was changed. 63.382 + */ 63.383 + private void validateHeaders() 63.384 + { 63.385 + // Check for valid Path-header 63.386 + final String path = getHeader(Headers.PATH)[0]; 63.387 + final String host = Config.getInstance().get(Config.HOSTNAME, "localhost"); 63.388 + if(!path.startsWith(host)) 63.389 + { 63.390 + StringBuffer pathBuf = new StringBuffer(); 63.391 + pathBuf.append(host); 63.392 + pathBuf.append('!'); 63.393 + pathBuf.append(path); 63.394 + this.headers.setHeader(Headers.PATH, pathBuf.toString()); 63.395 + } 63.396 + 63.397 + // Generate a messageID if no one is existing 63.398 + if(getMessageID().equals("")) 63.399 + { 63.400 + generateMessageID(); 63.401 + } 63.402 + } 63.403 + 63.404 +}
64.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 64.2 +++ b/org/sonews/daemon/storage/ArticleHead.java Fri Jun 26 16:48:50 2009 +0200 64.3 @@ -0,0 +1,78 @@ 64.4 +/* 64.5 + * SONEWS News Server 64.6 + * see AUTHORS for the list of contributors 64.7 + * 64.8 + * This program is free software: you can redistribute it and/or modify 64.9 + * it under the terms of the GNU General Public License as published by 64.10 + * the Free Software Foundation, either version 3 of the License, or 64.11 + * (at your option) any later version. 64.12 + * 64.13 + * This program is distributed in the hope that it will be useful, 64.14 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 64.15 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 64.16 + * GNU General Public License for more details. 64.17 + * 64.18 + * You should have received a copy of the GNU General Public License 64.19 + * along with this program. If not, see <http://www.gnu.org/licenses/>. 64.20 + */ 64.21 + 64.22 +package org.sonews.daemon.storage; 64.23 + 64.24 +import java.io.ByteArrayInputStream; 64.25 +import javax.mail.MessagingException; 64.26 +import javax.mail.internet.InternetHeaders; 64.27 + 64.28 +/** 64.29 + * An article with no body only headers. 64.30 + * @author Christian Lins 64.31 + * @since sonews/0.5.0 64.32 + */ 64.33 +public class ArticleHead 64.34 +{ 64.35 + 64.36 + protected InternetHeaders headers; 64.37 + 64.38 + protected ArticleHead() 64.39 + { 64.40 + } 64.41 + 64.42 + public ArticleHead(String headers) 64.43 + { 64.44 + try 64.45 + { 64.46 + // Parse the header 64.47 + this.headers = new InternetHeaders( 64.48 + new ByteArrayInputStream(headers.getBytes())); 64.49 + } 64.50 + catch(MessagingException ex) 64.51 + { 64.52 + ex.printStackTrace(); 64.53 + } 64.54 + } 64.55 + 64.56 + /** 64.57 + * Returns the header field with given name. 64.58 + * @param name 64.59 + * @return Header values or empty string. 64.60 + */ 64.61 + public String[] getHeader(String name) 64.62 + { 64.63 + String[] ret = this.headers.getHeader(name); 64.64 + if(ret == null) 64.65 + { 64.66 + ret = new String[]{""}; 64.67 + } 64.68 + return ret; 64.69 + } 64.70 + 64.71 + /** 64.72 + * Sets the header value identified through the header name. 64.73 + * @param name 64.74 + * @param value 64.75 + */ 64.76 + public void setHeader(String name, String value) 64.77 + { 64.78 + this.headers.setHeader(name, value); 64.79 + } 64.80 + 64.81 +}
65.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 65.2 +++ b/org/sonews/daemon/storage/Database.java Fri Jun 26 16:48:50 2009 +0200 65.3 @@ -0,0 +1,1353 @@ 65.4 +/* 65.5 + * SONEWS News Server 65.6 + * see AUTHORS for the list of contributors 65.7 + * 65.8 + * This program is free software: you can redistribute it and/or modify 65.9 + * it under the terms of the GNU General Public License as published by 65.10 + * the Free Software Foundation, either version 3 of the License, or 65.11 + * (at your option) any later version. 65.12 + * 65.13 + * This program is distributed in the hope that it will be useful, 65.14 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 65.15 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 65.16 + * GNU General Public License for more details. 65.17 + * 65.18 + * You should have received a copy of the GNU General Public License 65.19 + * along with this program. If not, see <http://www.gnu.org/licenses/>. 65.20 + */ 65.21 + 65.22 +package org.sonews.daemon.storage; 65.23 + 65.24 +import java.sql.Connection; 65.25 +import java.sql.DriverManager; 65.26 +import java.sql.ResultSet; 65.27 +import java.sql.SQLException; 65.28 +import java.sql.Statement; 65.29 +import java.sql.PreparedStatement; 65.30 +import java.util.ArrayList; 65.31 +import java.util.Enumeration; 65.32 +import java.util.List; 65.33 +import java.util.Map; 65.34 +import java.util.concurrent.ConcurrentHashMap; 65.35 +import javax.mail.Header; 65.36 +import javax.mail.internet.InternetAddress; 65.37 +import javax.mail.internet.MimeUtility; 65.38 +import org.sonews.daemon.BootstrapConfig; 65.39 +import org.sonews.util.Log; 65.40 +import org.sonews.feed.Subscription; 65.41 +import org.sonews.util.Pair; 65.42 + 65.43 +/** 65.44 + * Database facade class. 65.45 + * @author Christian Lins 65.46 + * @since sonews/0.5.0 65.47 + */ 65.48 +// TODO: Refactor this class to reduce size (e.g. ArticleDatabase GroupDatabase) 65.49 +public class Database 65.50 +{ 65.51 + 65.52 + public static final int MAX_RESTARTS = 3; 65.53 + 65.54 + private static final Map<Thread, Database> instances 65.55 + = new ConcurrentHashMap<Thread, Database>(); 65.56 + 65.57 + /** 65.58 + * @return Instance of the current Database backend. Returns null if an error 65.59 + * has occurred. 65.60 + */ 65.61 + public static Database getInstance(boolean create) 65.62 + throws SQLException 65.63 + { 65.64 + if(!instances.containsKey(Thread.currentThread()) && create) 65.65 + { 65.66 + Database db = new Database(); 65.67 + db.arise(); 65.68 + instances.put(Thread.currentThread(), db); 65.69 + return db; 65.70 + } 65.71 + else 65.72 + { 65.73 + return instances.get(Thread.currentThread()); 65.74 + } 65.75 + } 65.76 + 65.77 + public static Database getInstance() 65.78 + throws SQLException 65.79 + { 65.80 + return getInstance(true); 65.81 + } 65.82 + 65.83 + private Connection conn = null; 65.84 + private PreparedStatement pstmtAddArticle1 = null; 65.85 + private PreparedStatement pstmtAddArticle2 = null; 65.86 + private PreparedStatement pstmtAddArticle3 = null; 65.87 + private PreparedStatement pstmtAddArticle4 = null; 65.88 + private PreparedStatement pstmtAddGroup0 = null; 65.89 + private PreparedStatement pstmtAddEvent = null; 65.90 + private PreparedStatement pstmtCountArticles = null; 65.91 + private PreparedStatement pstmtCountGroups = null; 65.92 + private PreparedStatement pstmtDeleteArticle0 = null; 65.93 + private PreparedStatement pstmtGetArticle0 = null; 65.94 + private PreparedStatement pstmtGetArticle1 = null; 65.95 + private PreparedStatement pstmtGetArticleHeaders = null; 65.96 + private PreparedStatement pstmtGetArticleHeads = null; 65.97 + private PreparedStatement pstmtGetArticleIDs = null; 65.98 + private PreparedStatement pstmtGetArticleIndex = null; 65.99 + private PreparedStatement pstmtGetConfigValue = null; 65.100 + private PreparedStatement pstmtGetEventsCount0 = null; 65.101 + private PreparedStatement pstmtGetEventsCount1 = null; 65.102 + private PreparedStatement pstmtGetGroupForList = null; 65.103 + private PreparedStatement pstmtGetGroup0 = null; 65.104 + private PreparedStatement pstmtGetGroup1 = null; 65.105 + private PreparedStatement pstmtGetFirstArticleNumber = null; 65.106 + private PreparedStatement pstmtGetListForGroup = null; 65.107 + private PreparedStatement pstmtGetLastArticleNumber = null; 65.108 + private PreparedStatement pstmtGetMaxArticleID = null; 65.109 + private PreparedStatement pstmtGetMaxArticleIndex = null; 65.110 + private PreparedStatement pstmtGetPostingsCount = null; 65.111 + private PreparedStatement pstmtGetSubscriptions = null; 65.112 + private PreparedStatement pstmtIsArticleExisting = null; 65.113 + private PreparedStatement pstmtIsGroupExisting = null; 65.114 + private PreparedStatement pstmtSetConfigValue0 = null; 65.115 + private PreparedStatement pstmtSetConfigValue1 = null; 65.116 + 65.117 + /** How many times the database connection was reinitialized */ 65.118 + private int restarts = 0; 65.119 + 65.120 + /** 65.121 + * Rises the database: reconnect and recreate all prepared statements. 65.122 + * @throws java.lang.SQLException 65.123 + */ 65.124 + private void arise() 65.125 + throws SQLException 65.126 + { 65.127 + try 65.128 + { 65.129 + // Load database driver 65.130 + Class.forName( 65.131 + BootstrapConfig.getInstance().get(BootstrapConfig.STORAGE_DBMSDRIVER, "java.lang.Object")); 65.132 + 65.133 + // Establish database connection 65.134 + this.conn = DriverManager.getConnection( 65.135 + BootstrapConfig.getInstance().get(BootstrapConfig.STORAGE_DATABASE, "<not specified>"), 65.136 + BootstrapConfig.getInstance().get(BootstrapConfig.STORAGE_USER, "root"), 65.137 + BootstrapConfig.getInstance().get(BootstrapConfig.STORAGE_PASSWORD, "")); 65.138 + 65.139 + this.conn.setTransactionIsolation(Connection.TRANSACTION_SERIALIZABLE); 65.140 + if(this.conn.getTransactionIsolation() != Connection.TRANSACTION_SERIALIZABLE) 65.141 + { 65.142 + Log.msg("Warning: Database is NOT fully serializable!", false); 65.143 + } 65.144 + 65.145 + // Prepare statements for method addArticle() 65.146 + this.pstmtAddArticle1 = conn.prepareStatement( 65.147 + "INSERT INTO articles (article_id, body) VALUES(?, ?)"); 65.148 + this.pstmtAddArticle2 = conn.prepareStatement( 65.149 + "INSERT INTO headers (article_id, header_key, header_value, header_index) " + 65.150 + "VALUES (?, ?, ?, ?)"); 65.151 + this.pstmtAddArticle3 = conn.prepareStatement( 65.152 + "INSERT INTO postings (group_id, article_id, article_index)" + 65.153 + "VALUES (?, ?, ?)"); 65.154 + this.pstmtAddArticle4 = conn.prepareStatement( 65.155 + "INSERT INTO article_ids (article_id, message_id) VALUES (?, ?)"); 65.156 + 65.157 + // Prepare statement for method addStatValue() 65.158 + this.pstmtAddEvent = conn.prepareStatement( 65.159 + "INSERT INTO events VALUES (?, ?, ?)"); 65.160 + 65.161 + // Prepare statement for method addGroup() 65.162 + this.pstmtAddGroup0 = conn.prepareStatement( 65.163 + "INSERT INTO groups (name, flags) VALUES (?, ?)"); 65.164 + 65.165 + // Prepare statement for method countArticles() 65.166 + this.pstmtCountArticles = conn.prepareStatement( 65.167 + "SELECT Count(article_id) FROM article_ids"); 65.168 + 65.169 + // Prepare statement for method countGroups() 65.170 + this.pstmtCountGroups = conn.prepareStatement( 65.171 + "SELECT Count(group_id) FROM groups WHERE " + 65.172 + "flags & " + Group.DELETED + " = 0"); 65.173 + 65.174 + // Prepare statements for method delete(article) 65.175 + this.pstmtDeleteArticle0 = conn.prepareStatement( 65.176 + "DELETE FROM articles WHERE article_id = " + 65.177 + "(SELECT article_id FROM article_ids WHERE message_id = ?)"); 65.178 + 65.179 + // Prepare statements for methods getArticle() 65.180 + this.pstmtGetArticle0 = conn.prepareStatement( 65.181 + "SELECT * FROM articles WHERE article_id = " + 65.182 + "(SELECT article_id FROM article_ids WHERE message_id = ?)"); 65.183 + this.pstmtGetArticle1 = conn.prepareStatement( 65.184 + "SELECT * FROM articles WHERE article_id = " + 65.185 + "(SELECT article_id FROM postings WHERE " + 65.186 + "article_index = ? AND group_id = ?)"); 65.187 + 65.188 + // Prepare statement for method getArticleHeaders() 65.189 + this.pstmtGetArticleHeaders = conn.prepareStatement( 65.190 + "SELECT header_key, header_value FROM headers WHERE article_id = ? " + 65.191 + "ORDER BY header_index ASC"); 65.192 + 65.193 + this.pstmtGetArticleIDs = conn.prepareStatement( 65.194 + "SELECT article_index FROM postings WHERE group_id = ?"); 65.195 + 65.196 + // Prepare statement for method getArticleIndex 65.197 + this.pstmtGetArticleIndex = conn.prepareStatement( 65.198 + "SELECT article_index FROM postings WHERE " + 65.199 + "article_id = (SELECT article_id FROM article_ids " + 65.200 + "WHERE message_id = ?) " + 65.201 + " AND group_id = ?"); 65.202 + 65.203 + // Prepare statements for method getArticleHeads() 65.204 + this.pstmtGetArticleHeads = conn.prepareStatement( 65.205 + "SELECT article_id, article_index FROM postings WHERE " + 65.206 + "postings.group_id = ? AND article_index >= ? AND " + 65.207 + "article_index <= ?"); 65.208 + 65.209 + // Prepare statements for method getConfigValue() 65.210 + this.pstmtGetConfigValue = conn.prepareStatement( 65.211 + "SELECT config_value FROM config WHERE config_key = ?"); 65.212 + 65.213 + // Prepare statements for method getEventsCount() 65.214 + this.pstmtGetEventsCount0 = conn.prepareStatement( 65.215 + "SELECT Count(*) FROM events WHERE event_key = ? AND " + 65.216 + "event_time >= ? AND event_time < ?"); 65.217 + 65.218 + this.pstmtGetEventsCount1 = conn.prepareStatement( 65.219 + "SELECT Count(*) FROM events WHERE event_key = ? AND " + 65.220 + "event_time >= ? AND event_time < ? AND group_id = ?"); 65.221 + 65.222 + // Prepare statement for method getGroupForList() 65.223 + this.pstmtGetGroupForList = conn.prepareStatement( 65.224 + "SELECT name FROM groups INNER JOIN groups2list " + 65.225 + "ON groups.group_id = groups2list.group_id " + 65.226 + "WHERE groups2list.listaddress = ?"); 65.227 + 65.228 + // Prepare statement for method getGroup() 65.229 + this.pstmtGetGroup0 = conn.prepareStatement( 65.230 + "SELECT group_id, flags FROM groups WHERE Name = ?"); 65.231 + this.pstmtGetGroup1 = conn.prepareStatement( 65.232 + "SELECT name FROM groups WHERE group_id = ?"); 65.233 + 65.234 + // Prepare statement for method getLastArticleNumber() 65.235 + this.pstmtGetLastArticleNumber = conn.prepareStatement( 65.236 + "SELECT Max(article_index) FROM postings WHERE group_id = ?"); 65.237 + 65.238 + // Prepare statement for method getListForGroup() 65.239 + this.pstmtGetListForGroup = conn.prepareStatement( 65.240 + "SELECT listaddress FROM groups2list INNER JOIN groups " + 65.241 + "ON groups.group_id = groups2list.group_id WHERE name = ?"); 65.242 + 65.243 + // Prepare statement for method getMaxArticleID() 65.244 + this.pstmtGetMaxArticleID = conn.prepareStatement( 65.245 + "SELECT Max(article_id) FROM articles"); 65.246 + 65.247 + // Prepare statement for method getMaxArticleIndex() 65.248 + this.pstmtGetMaxArticleIndex = conn.prepareStatement( 65.249 + "SELECT Max(article_index) FROM postings WHERE group_id = ?"); 65.250 + 65.251 + // Prepare statement for method getFirstArticleNumber() 65.252 + this.pstmtGetFirstArticleNumber = conn.prepareStatement( 65.253 + "SELECT Min(article_index) FROM postings WHERE group_id = ?"); 65.254 + 65.255 + // Prepare statement for method getPostingsCount() 65.256 + this.pstmtGetPostingsCount = conn.prepareStatement( 65.257 + "SELECT Count(*) FROM postings NATURAL JOIN groups " + 65.258 + "WHERE groups.name = ?"); 65.259 + 65.260 + // Prepare statement for method getSubscriptions() 65.261 + this.pstmtGetSubscriptions = conn.prepareStatement( 65.262 + "SELECT host, port, name FROM peers NATURAL JOIN " + 65.263 + "peer_subscriptions NATURAL JOIN groups WHERE feedtype = ?"); 65.264 + 65.265 + // Prepare statement for method isArticleExisting() 65.266 + this.pstmtIsArticleExisting = conn.prepareStatement( 65.267 + "SELECT Count(article_id) FROM article_ids WHERE message_id = ?"); 65.268 + 65.269 + // Prepare statement for method isGroupExisting() 65.270 + this.pstmtIsGroupExisting = conn.prepareStatement( 65.271 + "SELECT * FROM groups WHERE name = ?"); 65.272 + 65.273 + // Prepare statement for method setConfigValue() 65.274 + this.pstmtSetConfigValue0 = conn.prepareStatement( 65.275 + "DELETE FROM config WHERE config_key = ?"); 65.276 + this.pstmtSetConfigValue1 = conn.prepareStatement( 65.277 + "INSERT INTO config VALUES(?, ?)"); 65.278 + } 65.279 + catch(ClassNotFoundException ex) 65.280 + { 65.281 + throw new Error("JDBC Driver not found!", ex); 65.282 + } 65.283 + } 65.284 + 65.285 + /** 65.286 + * Adds an article to the database. 65.287 + * @param article 65.288 + * @return 65.289 + * @throws java.sql.SQLException 65.290 + */ 65.291 + public void addArticle(final Article article) 65.292 + throws SQLException 65.293 + { 65.294 + try 65.295 + { 65.296 + this.conn.setAutoCommit(false); 65.297 + 65.298 + int newArticleID = getMaxArticleID() + 1; 65.299 + 65.300 + // Fill prepared statement with values; 65.301 + // writes body to article table 65.302 + pstmtAddArticle1.setInt(1, newArticleID); 65.303 + pstmtAddArticle1.setBytes(2, article.getBody().getBytes()); 65.304 + pstmtAddArticle1.execute(); 65.305 + 65.306 + // Add headers 65.307 + Enumeration headers = article.getAllHeaders(); 65.308 + for(int n = 0; headers.hasMoreElements(); n++) 65.309 + { 65.310 + Header header = (Header)headers.nextElement(); 65.311 + pstmtAddArticle2.setInt(1, newArticleID); 65.312 + pstmtAddArticle2.setString(2, header.getName().toLowerCase()); 65.313 + pstmtAddArticle2.setString(3, 65.314 + header.getValue().replaceAll("[\r\n]", "")); 65.315 + pstmtAddArticle2.setInt(4, n); 65.316 + pstmtAddArticle2.execute(); 65.317 + } 65.318 + 65.319 + // For each newsgroup add a reference 65.320 + List<Group> groups = article.getGroups(); 65.321 + for(Group group : groups) 65.322 + { 65.323 + pstmtAddArticle3.setLong(1, group.getID()); 65.324 + pstmtAddArticle3.setInt(2, newArticleID); 65.325 + pstmtAddArticle3.setLong(3, getMaxArticleIndex(group.getID()) + 1); 65.326 + pstmtAddArticle3.execute(); 65.327 + } 65.328 + 65.329 + // Write message-id to article_ids table 65.330 + this.pstmtAddArticle4.setInt(1, newArticleID); 65.331 + this.pstmtAddArticle4.setString(2, article.getMessageID()); 65.332 + this.pstmtAddArticle4.execute(); 65.333 + 65.334 + this.conn.commit(); 65.335 + this.conn.setAutoCommit(true); 65.336 + 65.337 + this.restarts = 0; // Reset error count 65.338 + } 65.339 + catch(SQLException ex) 65.340 + { 65.341 + try 65.342 + { 65.343 + this.conn.rollback(); // Rollback changes 65.344 + } 65.345 + catch(SQLException ex2) 65.346 + { 65.347 + Log.msg("Rollback of addArticle() failed: " + ex2, false); 65.348 + } 65.349 + 65.350 + try 65.351 + { 65.352 + this.conn.setAutoCommit(true); // and release locks 65.353 + } 65.354 + catch(SQLException ex2) 65.355 + { 65.356 + Log.msg("setAutoCommit(true) of addArticle() failed: " + ex2, false); 65.357 + } 65.358 + 65.359 + restartConnection(ex); 65.360 + addArticle(article); 65.361 + } 65.362 + } 65.363 + 65.364 + /** 65.365 + * Adds a group to the Database. This method is not accessible via NNTP. 65.366 + * @param name 65.367 + * @throws java.sql.SQLException 65.368 + */ 65.369 + public void addGroup(String name, int flags) 65.370 + throws SQLException 65.371 + { 65.372 + try 65.373 + { 65.374 + this.conn.setAutoCommit(false); 65.375 + pstmtAddGroup0.setString(1, name); 65.376 + pstmtAddGroup0.setInt(2, flags); 65.377 + 65.378 + pstmtAddGroup0.executeUpdate(); 65.379 + this.conn.commit(); 65.380 + this.conn.setAutoCommit(true); 65.381 + this.restarts = 0; // Reset error count 65.382 + } 65.383 + catch(SQLException ex) 65.384 + { 65.385 + this.conn.rollback(); 65.386 + this.conn.setAutoCommit(true); 65.387 + restartConnection(ex); 65.388 + addGroup(name, flags); 65.389 + } 65.390 + } 65.391 + 65.392 + public void addEvent(long time, byte type, long gid) 65.393 + throws SQLException 65.394 + { 65.395 + try 65.396 + { 65.397 + this.conn.setAutoCommit(false); 65.398 + this.pstmtAddEvent.setLong(1, time); 65.399 + this.pstmtAddEvent.setInt(2, type); 65.400 + this.pstmtAddEvent.setLong(3, gid); 65.401 + this.pstmtAddEvent.executeUpdate(); 65.402 + this.conn.commit(); 65.403 + this.conn.setAutoCommit(true); 65.404 + this.restarts = 0; 65.405 + } 65.406 + catch(SQLException ex) 65.407 + { 65.408 + this.conn.rollback(); 65.409 + this.conn.setAutoCommit(true); 65.410 + 65.411 + restartConnection(ex); 65.412 + addEvent(time, type, gid); 65.413 + } 65.414 + } 65.415 + 65.416 + public int countArticles() 65.417 + throws SQLException 65.418 + { 65.419 + ResultSet rs = null; 65.420 + 65.421 + try 65.422 + { 65.423 + rs = this.pstmtCountArticles.executeQuery(); 65.424 + if(rs.next()) 65.425 + { 65.426 + return rs.getInt(1); 65.427 + } 65.428 + else 65.429 + { 65.430 + return -1; 65.431 + } 65.432 + } 65.433 + catch(SQLException ex) 65.434 + { 65.435 + restartConnection(ex); 65.436 + return countArticles(); 65.437 + } 65.438 + finally 65.439 + { 65.440 + if(rs != null) 65.441 + { 65.442 + rs.close(); 65.443 + restarts = 0; 65.444 + } 65.445 + } 65.446 + } 65.447 + 65.448 + public int countGroups() 65.449 + throws SQLException 65.450 + { 65.451 + ResultSet rs = null; 65.452 + 65.453 + try 65.454 + { 65.455 + rs = this.pstmtCountGroups.executeQuery(); 65.456 + if(rs.next()) 65.457 + { 65.458 + return rs.getInt(1); 65.459 + } 65.460 + else 65.461 + { 65.462 + return -1; 65.463 + } 65.464 + } 65.465 + catch(SQLException ex) 65.466 + { 65.467 + restartConnection(ex); 65.468 + return countGroups(); 65.469 + } 65.470 + finally 65.471 + { 65.472 + if(rs != null) 65.473 + { 65.474 + rs.close(); 65.475 + restarts = 0; 65.476 + } 65.477 + } 65.478 + } 65.479 + 65.480 + public void delete(final String messageID) 65.481 + throws SQLException 65.482 + { 65.483 + try 65.484 + { 65.485 + this.conn.setAutoCommit(false); 65.486 + 65.487 + this.pstmtDeleteArticle0.setString(1, messageID); 65.488 + ResultSet rs = this.pstmtDeleteArticle0.executeQuery(); 65.489 + rs.next(); 65.490 + 65.491 + // We trust the ON DELETE CASCADE functionality to delete 65.492 + // orphaned references 65.493 + 65.494 + this.conn.commit(); 65.495 + this.conn.setAutoCommit(true); 65.496 + } 65.497 + catch(SQLException ex) 65.498 + { 65.499 + throw ex; 65.500 + } 65.501 + } 65.502 + 65.503 + public Article getArticle(String messageID) 65.504 + throws SQLException 65.505 + { 65.506 + ResultSet rs = null; 65.507 + try 65.508 + { 65.509 + pstmtGetArticle0.setString(1, messageID); 65.510 + rs = pstmtGetArticle0.executeQuery(); 65.511 + 65.512 + if(!rs.next()) 65.513 + { 65.514 + return null; 65.515 + } 65.516 + else 65.517 + { 65.518 + String body = new String(rs.getBytes("body")); 65.519 + String headers = getArticleHeaders(rs.getInt("article_id")); 65.520 + return new Article(headers, body); 65.521 + } 65.522 + } 65.523 + catch(SQLException ex) 65.524 + { 65.525 + restartConnection(ex); 65.526 + return getArticle(messageID); 65.527 + } 65.528 + finally 65.529 + { 65.530 + if(rs != null) 65.531 + { 65.532 + rs.close(); 65.533 + restarts = 0; // Reset error count 65.534 + } 65.535 + } 65.536 + } 65.537 + 65.538 + /** 65.539 + * Retrieves an article by its ID. 65.540 + * @param articleID 65.541 + * @return 65.542 + * @throws java.sql.SQLException 65.543 + */ 65.544 + public Article getArticle(long articleIndex, long gid) 65.545 + throws SQLException 65.546 + { 65.547 + ResultSet rs = null; 65.548 + 65.549 + try 65.550 + { 65.551 + this.pstmtGetArticle1.setLong(1, articleIndex); 65.552 + this.pstmtGetArticle1.setLong(2, gid); 65.553 + 65.554 + rs = this.pstmtGetArticle1.executeQuery(); 65.555 + 65.556 + if(rs.next()) 65.557 + { 65.558 + String body = new String(rs.getBytes("body")); 65.559 + String headers = getArticleHeaders(rs.getInt("article_id")); 65.560 + return new Article(headers, body); 65.561 + } 65.562 + else 65.563 + { 65.564 + return null; 65.565 + } 65.566 + } 65.567 + catch(SQLException ex) 65.568 + { 65.569 + restartConnection(ex); 65.570 + return getArticle(articleIndex, gid); 65.571 + } 65.572 + finally 65.573 + { 65.574 + if(rs != null) 65.575 + { 65.576 + rs.close(); 65.577 + restarts = 0; 65.578 + } 65.579 + } 65.580 + } 65.581 + 65.582 + public String getArticleHeaders(long articleID) 65.583 + throws SQLException 65.584 + { 65.585 + ResultSet rs = null; 65.586 + 65.587 + try 65.588 + { 65.589 + this.pstmtGetArticleHeaders.setLong(1, articleID); 65.590 + rs = this.pstmtGetArticleHeaders.executeQuery(); 65.591 + 65.592 + StringBuilder buf = new StringBuilder(); 65.593 + if(rs.next()) 65.594 + { 65.595 + for(;;) 65.596 + { 65.597 + buf.append(rs.getString(1)); // key 65.598 + buf.append(": "); 65.599 + String foldedValue = MimeUtility.fold(0, rs.getString(2)); 65.600 + buf.append(foldedValue); // value 65.601 + if(rs.next()) 65.602 + { 65.603 + buf.append("\r\n"); 65.604 + } 65.605 + else 65.606 + { 65.607 + break; 65.608 + } 65.609 + } 65.610 + } 65.611 + 65.612 + return buf.toString(); 65.613 + } 65.614 + catch(SQLException ex) 65.615 + { 65.616 + restartConnection(ex); 65.617 + return getArticleHeaders(articleID); 65.618 + } 65.619 + finally 65.620 + { 65.621 + if(rs != null) 65.622 + rs.close(); 65.623 + } 65.624 + } 65.625 + 65.626 + public long getArticleIndex(Article article, Group group) 65.627 + throws SQLException 65.628 + { 65.629 + ResultSet rs = null; 65.630 + 65.631 + try 65.632 + { 65.633 + this.pstmtGetArticleIndex.setString(1, article.getMessageID()); 65.634 + this.pstmtGetArticleIndex.setLong(2, group.getID()); 65.635 + 65.636 + rs = this.pstmtGetArticleIndex.executeQuery(); 65.637 + if(rs.next()) 65.638 + { 65.639 + return rs.getLong(1); 65.640 + } 65.641 + else 65.642 + { 65.643 + return -1; 65.644 + } 65.645 + } 65.646 + catch(SQLException ex) 65.647 + { 65.648 + restartConnection(ex); 65.649 + return getArticleIndex(article, group); 65.650 + } 65.651 + finally 65.652 + { 65.653 + if(rs != null) 65.654 + rs.close(); 65.655 + } 65.656 + } 65.657 + 65.658 + /** 65.659 + * Returns a list of Long/Article Pairs. 65.660 + * @throws java.sql.SQLException 65.661 + */ 65.662 + public List<Pair<Long, ArticleHead>> getArticleHeads(Group group, int first, int last) 65.663 + throws SQLException 65.664 + { 65.665 + ResultSet rs = null; 65.666 + 65.667 + try 65.668 + { 65.669 + this.pstmtGetArticleHeads.setLong(1, group.getID()); 65.670 + this.pstmtGetArticleHeads.setInt(2, first); 65.671 + this.pstmtGetArticleHeads.setInt(3, last); 65.672 + rs = pstmtGetArticleHeads.executeQuery(); 65.673 + 65.674 + List<Pair<Long, ArticleHead>> articles 65.675 + = new ArrayList<Pair<Long, ArticleHead>>(); 65.676 + 65.677 + while (rs.next()) 65.678 + { 65.679 + long aid = rs.getLong("article_id"); 65.680 + long aidx = rs.getLong("article_index"); 65.681 + String headers = getArticleHeaders(aid); 65.682 + articles.add(new Pair<Long, ArticleHead>(aidx, 65.683 + new ArticleHead(headers))); 65.684 + } 65.685 + 65.686 + return articles; 65.687 + } 65.688 + catch(SQLException ex) 65.689 + { 65.690 + restartConnection(ex); 65.691 + return getArticleHeads(group, first, last); 65.692 + } 65.693 + finally 65.694 + { 65.695 + if(rs != null) 65.696 + rs.close(); 65.697 + } 65.698 + } 65.699 + 65.700 + public List<Long> getArticleNumbers(long gid) 65.701 + throws SQLException 65.702 + { 65.703 + ResultSet rs = null; 65.704 + try 65.705 + { 65.706 + List<Long> ids = new ArrayList<Long>(); 65.707 + this.pstmtGetArticleIDs.setLong(1, gid); 65.708 + rs = this.pstmtGetArticleIDs.executeQuery(); 65.709 + while(rs.next()) 65.710 + { 65.711 + ids.add(rs.getLong(1)); 65.712 + } 65.713 + return ids; 65.714 + } 65.715 + catch(SQLException ex) 65.716 + { 65.717 + restartConnection(ex); 65.718 + return getArticleNumbers(gid); 65.719 + } 65.720 + finally 65.721 + { 65.722 + if(rs != null) 65.723 + { 65.724 + rs.close(); 65.725 + restarts = 0; // Clear the restart count after successful request 65.726 + } 65.727 + } 65.728 + } 65.729 + 65.730 + public String getConfigValue(String key) 65.731 + throws SQLException 65.732 + { 65.733 + ResultSet rs = null; 65.734 + try 65.735 + { 65.736 + this.pstmtGetConfigValue.setString(1, key); 65.737 + 65.738 + rs = this.pstmtGetConfigValue.executeQuery(); 65.739 + if(rs.next()) 65.740 + { 65.741 + return rs.getString(1); // First data on index 1 not 0 65.742 + } 65.743 + else 65.744 + { 65.745 + return null; 65.746 + } 65.747 + } 65.748 + catch(SQLException ex) 65.749 + { 65.750 + restartConnection(ex); 65.751 + return getConfigValue(key); 65.752 + } 65.753 + finally 65.754 + { 65.755 + if(rs != null) 65.756 + { 65.757 + rs.close(); 65.758 + restarts = 0; // Clear the restart count after successful request 65.759 + } 65.760 + } 65.761 + } 65.762 + 65.763 + public int getEventsCount(byte type, long start, long end, Group group) 65.764 + throws SQLException 65.765 + { 65.766 + ResultSet rs = null; 65.767 + 65.768 + try 65.769 + { 65.770 + if(group == null) 65.771 + { 65.772 + this.pstmtGetEventsCount0.setInt(1, type); 65.773 + this.pstmtGetEventsCount0.setLong(2, start); 65.774 + this.pstmtGetEventsCount0.setLong(3, end); 65.775 + rs = this.pstmtGetEventsCount0.executeQuery(); 65.776 + } 65.777 + else 65.778 + { 65.779 + this.pstmtGetEventsCount1.setInt(1, type); 65.780 + this.pstmtGetEventsCount1.setLong(2, start); 65.781 + this.pstmtGetEventsCount1.setLong(3, end); 65.782 + this.pstmtGetEventsCount1.setLong(4, group.getID()); 65.783 + rs = this.pstmtGetEventsCount1.executeQuery(); 65.784 + } 65.785 + 65.786 + if(rs.next()) 65.787 + { 65.788 + return rs.getInt(1); 65.789 + } 65.790 + else 65.791 + { 65.792 + return -1; 65.793 + } 65.794 + } 65.795 + catch(SQLException ex) 65.796 + { 65.797 + restartConnection(ex); 65.798 + return getEventsCount(type, start, end, group); 65.799 + } 65.800 + finally 65.801 + { 65.802 + if(rs != null) 65.803 + rs.close(); 65.804 + } 65.805 + } 65.806 + 65.807 + /** 65.808 + * Reads all Groups from the Database. 65.809 + * @return 65.810 + * @throws java.sql.SQLException 65.811 + */ 65.812 + public List<Group> getGroups() 65.813 + throws SQLException 65.814 + { 65.815 + ResultSet rs; 65.816 + List<Group> buffer = new ArrayList<Group>(); 65.817 + Statement stmt = null; 65.818 + 65.819 + try 65.820 + { 65.821 + stmt = conn.createStatement(); 65.822 + rs = stmt.executeQuery("SELECT * FROM groups ORDER BY name"); 65.823 + 65.824 + while(rs.next()) 65.825 + { 65.826 + String name = rs.getString("name"); 65.827 + long id = rs.getLong("group_id"); 65.828 + int flags = rs.getInt("flags"); 65.829 + 65.830 + Group group = new Group(name, id, flags); 65.831 + buffer.add(group); 65.832 + } 65.833 + 65.834 + return buffer; 65.835 + } 65.836 + catch(SQLException ex) 65.837 + { 65.838 + restartConnection(ex); 65.839 + return getGroups(); 65.840 + } 65.841 + finally 65.842 + { 65.843 + if(stmt != null) 65.844 + stmt.close(); // Implicitely closes ResultSets 65.845 + } 65.846 + } 65.847 + 65.848 + public String getGroupForList(InternetAddress listAddress) 65.849 + throws SQLException 65.850 + { 65.851 + ResultSet rs = null; 65.852 + 65.853 + try 65.854 + { 65.855 + this.pstmtGetGroupForList.setString(1, listAddress.getAddress()); 65.856 + 65.857 + rs = this.pstmtGetGroupForList.executeQuery(); 65.858 + if (rs.next()) 65.859 + { 65.860 + return rs.getString(1); 65.861 + } 65.862 + else 65.863 + { 65.864 + return null; 65.865 + } 65.866 + } 65.867 + catch(SQLException ex) 65.868 + { 65.869 + restartConnection(ex); 65.870 + return getGroupForList(listAddress); 65.871 + } 65.872 + finally 65.873 + { 65.874 + if(rs != null) 65.875 + rs.close(); 65.876 + } 65.877 + } 65.878 + 65.879 + /** 65.880 + * Returns the Group that is identified by the name. 65.881 + * @param name 65.882 + * @return 65.883 + * @throws java.sql.SQLException 65.884 + */ 65.885 + public Group getGroup(String name) 65.886 + throws SQLException 65.887 + { 65.888 + ResultSet rs = null; 65.889 + 65.890 + try 65.891 + { 65.892 + this.pstmtGetGroup0.setString(1, name); 65.893 + rs = this.pstmtGetGroup0.executeQuery(); 65.894 + 65.895 + if (!rs.next()) 65.896 + { 65.897 + return null; 65.898 + } 65.899 + else 65.900 + { 65.901 + long id = rs.getLong("group_id"); 65.902 + int flags = rs.getInt("flags"); 65.903 + return new Group(name, id, flags); 65.904 + } 65.905 + } 65.906 + catch(SQLException ex) 65.907 + { 65.908 + restartConnection(ex); 65.909 + return getGroup(name); 65.910 + } 65.911 + finally 65.912 + { 65.913 + if(rs != null) 65.914 + rs.close(); 65.915 + } 65.916 + } 65.917 + 65.918 + public String getListForGroup(String group) 65.919 + throws SQLException 65.920 + { 65.921 + ResultSet rs = null; 65.922 + 65.923 + try 65.924 + { 65.925 + this.pstmtGetListForGroup.setString(1, group); 65.926 + rs = this.pstmtGetListForGroup.executeQuery(); 65.927 + if (rs.next()) 65.928 + { 65.929 + return rs.getString(1); 65.930 + } 65.931 + else 65.932 + { 65.933 + return null; 65.934 + } 65.935 + } 65.936 + catch(SQLException ex) 65.937 + { 65.938 + restartConnection(ex); 65.939 + return getListForGroup(group); 65.940 + } 65.941 + finally 65.942 + { 65.943 + if(rs != null) 65.944 + rs.close(); 65.945 + } 65.946 + } 65.947 + 65.948 + private int getMaxArticleIndex(long groupID) 65.949 + throws SQLException 65.950 + { 65.951 + ResultSet rs = null; 65.952 + 65.953 + try 65.954 + { 65.955 + this.pstmtGetMaxArticleIndex.setLong(1, groupID); 65.956 + rs = this.pstmtGetMaxArticleIndex.executeQuery(); 65.957 + 65.958 + int maxIndex = 0; 65.959 + if (rs.next()) 65.960 + { 65.961 + maxIndex = rs.getInt(1); 65.962 + } 65.963 + 65.964 + return maxIndex; 65.965 + } 65.966 + catch(SQLException ex) 65.967 + { 65.968 + restartConnection(ex); 65.969 + return getMaxArticleIndex(groupID); 65.970 + } 65.971 + finally 65.972 + { 65.973 + if(rs != null) 65.974 + rs.close(); 65.975 + } 65.976 + } 65.977 + 65.978 + private int getMaxArticleID() 65.979 + throws SQLException 65.980 + { 65.981 + ResultSet rs = null; 65.982 + 65.983 + try 65.984 + { 65.985 + rs = this.pstmtGetMaxArticleID.executeQuery(); 65.986 + 65.987 + int maxIndex = 0; 65.988 + if (rs.next()) 65.989 + { 65.990 + maxIndex = rs.getInt(1); 65.991 + } 65.992 + 65.993 + return maxIndex; 65.994 + } 65.995 + catch(SQLException ex) 65.996 + { 65.997 + restartConnection(ex); 65.998 + return getMaxArticleID(); 65.999 + } 65.1000 + finally 65.1001 + { 65.1002 + if(rs != null) 65.1003 + rs.close(); 65.1004 + } 65.1005 + } 65.1006 + 65.1007 + public int getLastArticleNumber(Group group) 65.1008 + throws SQLException 65.1009 + { 65.1010 + ResultSet rs = null; 65.1011 + 65.1012 + try 65.1013 + { 65.1014 + this.pstmtGetLastArticleNumber.setLong(1, group.getID()); 65.1015 + rs = this.pstmtGetLastArticleNumber.executeQuery(); 65.1016 + if (rs.next()) 65.1017 + { 65.1018 + return rs.getInt(1); 65.1019 + } 65.1020 + else 65.1021 + { 65.1022 + return 0; 65.1023 + } 65.1024 + } 65.1025 + catch(SQLException ex) 65.1026 + { 65.1027 + restartConnection(ex); 65.1028 + return getLastArticleNumber(group); 65.1029 + } 65.1030 + finally 65.1031 + { 65.1032 + if(rs != null) 65.1033 + rs.close(); 65.1034 + } 65.1035 + } 65.1036 + 65.1037 + public int getFirstArticleNumber(Group group) 65.1038 + throws SQLException 65.1039 + { 65.1040 + ResultSet rs = null; 65.1041 + try 65.1042 + { 65.1043 + this.pstmtGetFirstArticleNumber.setLong(1, group.getID()); 65.1044 + rs = this.pstmtGetFirstArticleNumber.executeQuery(); 65.1045 + if(rs.next()) 65.1046 + { 65.1047 + return rs.getInt(1); 65.1048 + } 65.1049 + else 65.1050 + { 65.1051 + return 0; 65.1052 + } 65.1053 + } 65.1054 + catch(SQLException ex) 65.1055 + { 65.1056 + restartConnection(ex); 65.1057 + return getFirstArticleNumber(group); 65.1058 + } 65.1059 + finally 65.1060 + { 65.1061 + if(rs != null) 65.1062 + rs.close(); 65.1063 + } 65.1064 + } 65.1065 + 65.1066 + /** 65.1067 + * Returns a group name identified by the given id. 65.1068 + * @param id 65.1069 + * @return 65.1070 + * @throws java.sql.SQLException 65.1071 + */ 65.1072 + public String getGroup(int id) 65.1073 + throws SQLException 65.1074 + { 65.1075 + ResultSet rs = null; 65.1076 + 65.1077 + try 65.1078 + { 65.1079 + this.pstmtGetGroup1.setInt(1, id); 65.1080 + rs = this.pstmtGetGroup1.executeQuery(); 65.1081 + 65.1082 + if (rs.next()) 65.1083 + { 65.1084 + return rs.getString(1); 65.1085 + } 65.1086 + else 65.1087 + { 65.1088 + return null; 65.1089 + } 65.1090 + } 65.1091 + catch(SQLException ex) 65.1092 + { 65.1093 + restartConnection(ex); 65.1094 + return getGroup(id); 65.1095 + } 65.1096 + finally 65.1097 + { 65.1098 + if(rs != null) 65.1099 + rs.close(); 65.1100 + } 65.1101 + } 65.1102 + 65.1103 + public double getNumberOfEventsPerHour(int key, long gid) 65.1104 + throws SQLException 65.1105 + { 65.1106 + String gidquery = ""; 65.1107 + if(gid >= 0) 65.1108 + { 65.1109 + gidquery = " AND group_id = " + gid; 65.1110 + } 65.1111 + 65.1112 + Statement stmt = null; 65.1113 + ResultSet rs = null; 65.1114 + 65.1115 + try 65.1116 + { 65.1117 + stmt = this.conn.createStatement(); 65.1118 + rs = stmt.executeQuery("SELECT Count(*) / (Max(event_time) - Min(event_time))" + 65.1119 + " * 1000 * 60 * 60 FROM events WHERE event_key = " + key + gidquery); 65.1120 + 65.1121 + if(rs.next()) 65.1122 + { 65.1123 + restarts = 0; // reset error count 65.1124 + return rs.getDouble(1); 65.1125 + } 65.1126 + else 65.1127 + { 65.1128 + return Double.NaN; 65.1129 + } 65.1130 + } 65.1131 + catch(SQLException ex) 65.1132 + { 65.1133 + restartConnection(ex); 65.1134 + return getNumberOfEventsPerHour(key, gid); 65.1135 + } 65.1136 + finally 65.1137 + { 65.1138 + if(stmt != null) 65.1139 + { 65.1140 + stmt.close(); 65.1141 + } 65.1142 + 65.1143 + if(rs != null) 65.1144 + { 65.1145 + rs.close(); 65.1146 + } 65.1147 + } 65.1148 + } 65.1149 + 65.1150 + public int getPostingsCount(String groupname) 65.1151 + throws SQLException 65.1152 + { 65.1153 + ResultSet rs = null; 65.1154 + 65.1155 + try 65.1156 + { 65.1157 + this.pstmtGetPostingsCount.setString(1, groupname); 65.1158 + rs = this.pstmtGetPostingsCount.executeQuery(); 65.1159 + if(rs.next()) 65.1160 + { 65.1161 + return rs.getInt(1); 65.1162 + } 65.1163 + else 65.1164 + { 65.1165 + Log.msg("Warning: Count on postings return nothing!", true); 65.1166 + return 0; 65.1167 + } 65.1168 + } 65.1169 + catch(SQLException ex) 65.1170 + { 65.1171 + restartConnection(ex); 65.1172 + return getPostingsCount(groupname); 65.1173 + } 65.1174 + finally 65.1175 + { 65.1176 + if(rs != null) 65.1177 + rs.close(); 65.1178 + } 65.1179 + } 65.1180 + 65.1181 + public List<Subscription> getSubscriptions(int feedtype) 65.1182 + throws SQLException 65.1183 + { 65.1184 + ResultSet rs = null; 65.1185 + 65.1186 + try 65.1187 + { 65.1188 + List<Subscription> subs = new ArrayList<Subscription>(); 65.1189 + this.pstmtGetSubscriptions.setInt(1, feedtype); 65.1190 + rs = this.pstmtGetSubscriptions.executeQuery(); 65.1191 + 65.1192 + while(rs.next()) 65.1193 + { 65.1194 + String host = rs.getString("host"); 65.1195 + String group = rs.getString("name"); 65.1196 + int port = rs.getInt("port"); 65.1197 + subs.add(new Subscription(host, port, feedtype, group)); 65.1198 + } 65.1199 + 65.1200 + return subs; 65.1201 + } 65.1202 + catch(SQLException ex) 65.1203 + { 65.1204 + restartConnection(ex); 65.1205 + return getSubscriptions(feedtype); 65.1206 + } 65.1207 + finally 65.1208 + { 65.1209 + if(rs != null) 65.1210 + rs.close(); 65.1211 + } 65.1212 + } 65.1213 + 65.1214 + /** 65.1215 + * Checks if there is an article with the given messageid in the Database. 65.1216 + * @param name 65.1217 + * @return 65.1218 + * @throws java.sql.SQLException 65.1219 + */ 65.1220 + public boolean isArticleExisting(String messageID) 65.1221 + throws SQLException 65.1222 + { 65.1223 + ResultSet rs = null; 65.1224 + 65.1225 + try 65.1226 + { 65.1227 + this.pstmtIsArticleExisting.setString(1, messageID); 65.1228 + rs = this.pstmtIsArticleExisting.executeQuery(); 65.1229 + return rs.next() && rs.getInt(1) == 1; 65.1230 + } 65.1231 + catch(SQLException ex) 65.1232 + { 65.1233 + restartConnection(ex); 65.1234 + return isArticleExisting(messageID); 65.1235 + } 65.1236 + finally 65.1237 + { 65.1238 + if(rs != null) 65.1239 + rs.close(); 65.1240 + } 65.1241 + } 65.1242 + 65.1243 + /** 65.1244 + * Checks if there is a group with the given name in the Database. 65.1245 + * @param name 65.1246 + * @return 65.1247 + * @throws java.sql.SQLException 65.1248 + */ 65.1249 + public boolean isGroupExisting(String name) 65.1250 + throws SQLException 65.1251 + { 65.1252 + ResultSet rs = null; 65.1253 + 65.1254 + try 65.1255 + { 65.1256 + this.pstmtIsGroupExisting.setString(1, name); 65.1257 + rs = this.pstmtIsGroupExisting.executeQuery(); 65.1258 + return rs.next(); 65.1259 + } 65.1260 + catch(SQLException ex) 65.1261 + { 65.1262 + restartConnection(ex); 65.1263 + return isGroupExisting(name); 65.1264 + } 65.1265 + finally 65.1266 + { 65.1267 + if(rs != null) 65.1268 + rs.close(); 65.1269 + } 65.1270 + } 65.1271 + 65.1272 + public void setConfigValue(String key, String value) 65.1273 + throws SQLException 65.1274 + { 65.1275 + try 65.1276 + { 65.1277 + conn.setAutoCommit(false); 65.1278 + this.pstmtSetConfigValue0.setString(1, key); 65.1279 + this.pstmtSetConfigValue0.execute(); 65.1280 + this.pstmtSetConfigValue1.setString(1, key); 65.1281 + this.pstmtSetConfigValue1.setString(2, value); 65.1282 + this.pstmtSetConfigValue1.execute(); 65.1283 + conn.commit(); 65.1284 + conn.setAutoCommit(true); 65.1285 + } 65.1286 + catch(SQLException ex) 65.1287 + { 65.1288 + restartConnection(ex); 65.1289 + setConfigValue(key, value); 65.1290 + } 65.1291 + } 65.1292 + 65.1293 + /** 65.1294 + * Closes the Database connection. 65.1295 + */ 65.1296 + public void shutdown() 65.1297 + throws SQLException 65.1298 + { 65.1299 + if(this.conn != null) 65.1300 + { 65.1301 + this.conn.close(); 65.1302 + } 65.1303 + } 65.1304 + 65.1305 + private void restartConnection(SQLException cause) 65.1306 + throws SQLException 65.1307 + { 65.1308 + restarts++; 65.1309 + Log.msg(Thread.currentThread() 65.1310 + + ": Database connection was closed (restart " + restarts + ").", false); 65.1311 + 65.1312 + if(restarts >= MAX_RESTARTS) 65.1313 + { 65.1314 + // Delete the current, probably broken Database instance. 65.1315 + // So no one can use the instance any more. 65.1316 + Database.instances.remove(Thread.currentThread()); 65.1317 + 65.1318 + // Throw the exception upwards 65.1319 + throw cause; 65.1320 + } 65.1321 + 65.1322 + try 65.1323 + { 65.1324 + Thread.sleep(1500L * restarts); 65.1325 + } 65.1326 + catch(InterruptedException ex) 65.1327 + { 65.1328 + Log.msg("Interrupted: " + ex.getMessage(), false); 65.1329 + } 65.1330 + 65.1331 + // Try to properly close the old database connection 65.1332 + try 65.1333 + { 65.1334 + if(this.conn != null) 65.1335 + { 65.1336 + this.conn.close(); 65.1337 + } 65.1338 + } 65.1339 + catch(SQLException ex) 65.1340 + { 65.1341 + Log.msg(ex.getMessage(), true); 65.1342 + } 65.1343 + 65.1344 + try 65.1345 + { 65.1346 + // Try to reinitialize database connection 65.1347 + arise(); 65.1348 + } 65.1349 + catch(SQLException ex) 65.1350 + { 65.1351 + Log.msg(ex.getMessage(), true); 65.1352 + restartConnection(ex); 65.1353 + } 65.1354 + } 65.1355 + 65.1356 +}
66.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 66.2 +++ b/org/sonews/daemon/storage/Group.java Fri Jun 26 16:48:50 2009 +0200 66.3 @@ -0,0 +1,186 @@ 66.4 +/* 66.5 + * SONEWS News Server 66.6 + * see AUTHORS for the list of contributors 66.7 + * 66.8 + * This program is free software: you can redistribute it and/or modify 66.9 + * it under the terms of the GNU General Public License as published by 66.10 + * the Free Software Foundation, either version 3 of the License, or 66.11 + * (at your option) any later version. 66.12 + * 66.13 + * This program is distributed in the hope that it will be useful, 66.14 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 66.15 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 66.16 + * GNU General Public License for more details. 66.17 + * 66.18 + * You should have received a copy of the GNU General Public License 66.19 + * along with this program. If not, see <http://www.gnu.org/licenses/>. 66.20 + */ 66.21 + 66.22 +package org.sonews.daemon.storage; 66.23 + 66.24 +import java.sql.SQLException; 66.25 +import java.util.List; 66.26 +import org.sonews.util.Log; 66.27 +import org.sonews.util.Pair; 66.28 + 66.29 +/** 66.30 + * Represents a logical Group within this newsserver. 66.31 + * @author Christian Lins 66.32 + * @since sonews/0.5.0 66.33 + */ 66.34 +public class Group 66.35 +{ 66.36 + 66.37 + /** 66.38 + * If this flag is set the Group is no real newsgroup but a mailing list 66.39 + * mirror. In that case every posting and receiving mails must go through 66.40 + * the mailing list gateway. 66.41 + */ 66.42 + public static final int MAILINGLIST = 0x1; 66.43 + 66.44 + /** 66.45 + * If this flag is set the Group is marked as readonly and the posting 66.46 + * is prohibited. This can be useful for groups that are synced only in 66.47 + * one direction. 66.48 + */ 66.49 + public static final int READONLY = 0x2; 66.50 + 66.51 + /** 66.52 + * If this flag is set the Group is marked as deleted and must not occur 66.53 + * in any output. The deletion is done lazily by a low priority daemon. 66.54 + */ 66.55 + public static final int DELETED = 0x128; 66.56 + 66.57 + private long id = 0; 66.58 + private int flags = -1; 66.59 + private String name = null; 66.60 + 66.61 + /** 66.62 + * Returns a Group identified by its full name. 66.63 + * @param name 66.64 + * @return 66.65 + */ 66.66 + public static Group getByName(final String name) 66.67 + { 66.68 + try 66.69 + { 66.70 + return Database.getInstance().getGroup(name); 66.71 + } 66.72 + catch(SQLException ex) 66.73 + { 66.74 + ex.printStackTrace(); 66.75 + return null; 66.76 + } 66.77 + } 66.78 + 66.79 + /** 66.80 + * @return List of all groups this server handles. 66.81 + */ 66.82 + public static List<Group> getAll() 66.83 + { 66.84 + try 66.85 + { 66.86 + return Database.getInstance().getGroups(); 66.87 + } 66.88 + catch(SQLException ex) 66.89 + { 66.90 + Log.msg(ex.getMessage(), false); 66.91 + return null; 66.92 + } 66.93 + } 66.94 + 66.95 + /** 66.96 + * Private constructor. 66.97 + * @param name 66.98 + * @param id 66.99 + */ 66.100 + Group(final String name, final long id, final int flags) 66.101 + { 66.102 + this.id = id; 66.103 + this.flags = flags; 66.104 + this.name = name; 66.105 + } 66.106 + 66.107 + @Override 66.108 + public boolean equals(Object obj) 66.109 + { 66.110 + if(obj instanceof Group) 66.111 + { 66.112 + return ((Group)obj).id == this.id; 66.113 + } 66.114 + else 66.115 + { 66.116 + return false; 66.117 + } 66.118 + } 66.119 + 66.120 + public List<Pair<Long, ArticleHead>> getArticleHeads(final int first, final int last) 66.121 + throws SQLException 66.122 + { 66.123 + return Database.getInstance().getArticleHeads(this, first, last); 66.124 + } 66.125 + 66.126 + public List<Long> getArticleNumbers() 66.127 + throws SQLException 66.128 + { 66.129 + return Database.getInstance().getArticleNumbers(id); 66.130 + } 66.131 + 66.132 + public int getFirstArticleNumber() 66.133 + throws SQLException 66.134 + { 66.135 + return Database.getInstance().getFirstArticleNumber(this); 66.136 + } 66.137 + 66.138 + /** 66.139 + * Returns the group id. 66.140 + */ 66.141 + public long getID() 66.142 + { 66.143 + assert id > 0; 66.144 + 66.145 + return id; 66.146 + } 66.147 + 66.148 + public boolean isMailingList() 66.149 + { 66.150 + return (this.flags & MAILINGLIST) != 0; 66.151 + } 66.152 + 66.153 + public int getLastArticleNumber() 66.154 + throws SQLException 66.155 + { 66.156 + return Database.getInstance().getLastArticleNumber(this); 66.157 + } 66.158 + 66.159 + public String getName() 66.160 + { 66.161 + return name; 66.162 + } 66.163 + 66.164 + /** 66.165 + * Performs this.flags |= flag to set a specified flag and updates the data 66.166 + * in the Database. 66.167 + * @param flag 66.168 + */ 66.169 + public void setFlag(final int flag) 66.170 + { 66.171 + this.flags |= flag; 66.172 + } 66.173 + 66.174 + public void setName(final String name) 66.175 + { 66.176 + this.name = name; 66.177 + } 66.178 + 66.179 + /** 66.180 + * @return Number of posted articles in this group. 66.181 + * @throws java.sql.SQLException 66.182 + */ 66.183 + public int getPostingsCount() 66.184 + throws SQLException 66.185 + { 66.186 + return Database.getInstance().getPostingsCount(this.name); 66.187 + } 66.188 + 66.189 +}
67.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 67.2 +++ b/org/sonews/daemon/storage/Headers.java Fri Jun 26 16:48:50 2009 +0200 67.3 @@ -0,0 +1,51 @@ 67.4 +/* 67.5 + * SONEWS News Server 67.6 + * see AUTHORS for the list of contributors 67.7 + * 67.8 + * This program is free software: you can redistribute it and/or modify 67.9 + * it under the terms of the GNU General Public License as published by 67.10 + * the Free Software Foundation, either version 3 of the License, or 67.11 + * (at your option) any later version. 67.12 + * 67.13 + * This program is distributed in the hope that it will be useful, 67.14 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 67.15 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 67.16 + * GNU General Public License for more details. 67.17 + * 67.18 + * You should have received a copy of the GNU General Public License 67.19 + * along with this program. If not, see <http://www.gnu.org/licenses/>. 67.20 + */ 67.21 + 67.22 +package org.sonews.daemon.storage; 67.23 + 67.24 +/** 67.25 + * Contains header constants. These header keys are no way complete but all 67.26 + * headers that are relevant for sonews. 67.27 + * @author Christian Lins 67.28 + * @since sonews/0.5.0 67.29 + */ 67.30 +public final class Headers 67.31 +{ 67.32 + 67.33 + public static final String BYTES = "bytes"; 67.34 + public static final String CONTENT_TYPE = "content-type"; 67.35 + public static final String CONTROL = "control"; 67.36 + public static final String DATE = "date"; 67.37 + public static final String FROM = "from"; 67.38 + public static final String LINES = "lines"; 67.39 + public static final String MESSAGE_ID = "message-id"; 67.40 + public static final String NEWSGROUPS = "newsgroups"; 67.41 + public static final String NNTP_POSTING_DATE = "nntp-posting-date"; 67.42 + public static final String NNTP_POSTING_HOST = "nntp-posting-host"; 67.43 + public static final String PATH = "path"; 67.44 + public static final String REFERENCES = "references"; 67.45 + public static final String SUBJECT = "subject"; 67.46 + public static final String SUPERSEDES = "subersedes"; 67.47 + public static final String X_COMPLAINTS_TO = "x-complaints-to"; 67.48 + public static final String X_TRACE = "x-trace"; 67.49 + public static final String XREF = "xref"; 67.50 + 67.51 + private Headers() 67.52 + {} 67.53 + 67.54 +}
68.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 68.2 +++ b/org/sonews/daemon/storage/package.html Fri Jun 26 16:48:50 2009 +0200 68.3 @@ -0,0 +1,2 @@ 68.4 +Contains classes of the storage backend and the Group and Article 68.5 +abstraction. 68.6 \ No newline at end of file
69.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 69.2 +++ b/org/sonews/feed/AbstractFeeder.java Fri Jun 26 16:48:50 2009 +0200 69.3 @@ -0,0 +1,41 @@ 69.4 +/* 69.5 + * SONEWS News Server 69.6 + * see AUTHORS for the list of contributors 69.7 + * 69.8 + * This program is free software: you can redistribute it and/or modify 69.9 + * it under the terms of the GNU General Public License as published by 69.10 + * the Free Software Foundation, either version 3 of the License, or 69.11 + * (at your option) any later version. 69.12 + * 69.13 + * This program is distributed in the hope that it will be useful, 69.14 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 69.15 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 69.16 + * GNU General Public License for more details. 69.17 + * 69.18 + * You should have received a copy of the GNU General Public License 69.19 + * along with this program. If not, see <http://www.gnu.org/licenses/>. 69.20 + */ 69.21 + 69.22 +package org.sonews.feed; 69.23 + 69.24 +import java.util.ArrayList; 69.25 +import java.util.List; 69.26 +import org.sonews.daemon.AbstractDaemon; 69.27 + 69.28 +/** 69.29 + * Base class for PullFeeder and PushFeeder. 69.30 + * @author Christian Lins 69.31 + * @since sonews/0.5.0 69.32 + */ 69.33 +abstract class AbstractFeeder extends AbstractDaemon 69.34 +{ 69.35 + 69.36 + /** List of subscriptions that is processed by this feeder */ 69.37 + protected List<Subscription> subscriptions = new ArrayList<Subscription>(); 69.38 + 69.39 + public void addSubscription(final Subscription sub) 69.40 + { 69.41 + this.subscriptions.add(sub); 69.42 + } 69.43 + 69.44 +}
70.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 70.2 +++ b/org/sonews/feed/FeedManager.java Fri Jun 26 16:48:50 2009 +0200 70.3 @@ -0,0 +1,71 @@ 70.4 +/* 70.5 + * SONEWS News Server 70.6 + * see AUTHORS for the list of contributors 70.7 + * 70.8 + * This program is free software: you can redistribute it and/or modify 70.9 + * it under the terms of the GNU General Public License as published by 70.10 + * the Free Software Foundation, either version 3 of the License, or 70.11 + * (at your option) any later version. 70.12 + * 70.13 + * This program is distributed in the hope that it will be useful, 70.14 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 70.15 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 70.16 + * GNU General Public License for more details. 70.17 + * 70.18 + * You should have received a copy of the GNU General Public License 70.19 + * along with this program. If not, see <http://www.gnu.org/licenses/>. 70.20 + */ 70.21 + 70.22 +package org.sonews.feed; 70.23 + 70.24 +import java.sql.SQLException; 70.25 +import java.util.List; 70.26 +import org.sonews.daemon.storage.Article; 70.27 +import org.sonews.daemon.storage.Database; 70.28 + 70.29 +/** 70.30 + * Controlls push and pull feeder. 70.31 + * @author Christian Lins 70.32 + * @since sonews/0.5.0 70.33 + */ 70.34 +public final class FeedManager 70.35 +{ 70.36 + 70.37 + public static final int TYPE_PULL = 0; 70.38 + public static final int TYPE_PUSH = 1; 70.39 + 70.40 + private static PullFeeder pullFeeder = new PullFeeder(); 70.41 + private static PushFeeder pushFeeder = new PushFeeder(); 70.42 + 70.43 + /** 70.44 + * Reads the peer subscriptions from database and starts the appropriate 70.45 + * PullFeeder or PushFeeder. 70.46 + */ 70.47 + public static synchronized void startFeeding() 70.48 + throws SQLException 70.49 + { 70.50 + List<Subscription> subsPull = Database.getInstance() 70.51 + .getSubscriptions(TYPE_PULL); 70.52 + for(Subscription sub : subsPull) 70.53 + { 70.54 + pullFeeder.addSubscription(sub); 70.55 + } 70.56 + pullFeeder.start(); 70.57 + 70.58 + List<Subscription> subsPush = Database.getInstance() 70.59 + .getSubscriptions(TYPE_PUSH); 70.60 + for(Subscription sub : subsPush) 70.61 + { 70.62 + pushFeeder.addSubscription(sub); 70.63 + } 70.64 + pushFeeder.start(); 70.65 + } 70.66 + 70.67 + public static void queueForPush(Article article) 70.68 + { 70.69 + pushFeeder.queueForPush(article); 70.70 + } 70.71 + 70.72 + private FeedManager() {} 70.73 + 70.74 +}
71.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 71.2 +++ b/org/sonews/feed/PullFeeder.java Fri Jun 26 16:48:50 2009 +0200 71.3 @@ -0,0 +1,250 @@ 71.4 +/* 71.5 + * SONEWS News Server 71.6 + * see AUTHORS for the list of contributors 71.7 + * 71.8 + * This program is free software: you can redistribute it and/or modify 71.9 + * it under the terms of the GNU General Public License as published by 71.10 + * the Free Software Foundation, either version 3 of the License, or 71.11 + * (at your option) any later version. 71.12 + * 71.13 + * This program is distributed in the hope that it will be useful, 71.14 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 71.15 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 71.16 + * GNU General Public License for more details. 71.17 + * 71.18 + * You should have received a copy of the GNU General Public License 71.19 + * along with this program. If not, see <http://www.gnu.org/licenses/>. 71.20 + */ 71.21 + 71.22 +package org.sonews.feed; 71.23 + 71.24 +import java.io.BufferedReader; 71.25 +import java.io.IOException; 71.26 +import java.io.InputStreamReader; 71.27 +import java.io.PrintWriter; 71.28 +import java.net.Socket; 71.29 +import java.net.SocketException; 71.30 +import java.net.UnknownHostException; 71.31 +import java.sql.SQLException; 71.32 +import java.util.ArrayList; 71.33 +import java.util.HashMap; 71.34 +import java.util.List; 71.35 +import java.util.Map; 71.36 +import org.sonews.daemon.Config; 71.37 +import org.sonews.util.Log; 71.38 +import org.sonews.daemon.storage.Database; 71.39 +import org.sonews.util.Stats; 71.40 +import org.sonews.util.io.ArticleReader; 71.41 +import org.sonews.util.io.ArticleWriter; 71.42 + 71.43 +/** 71.44 + * The PullFeeder class regularily checks another Newsserver for new 71.45 + * messages. 71.46 + * @author Christian Lins 71.47 + * @since sonews/0.5.0 71.48 + */ 71.49 +class PullFeeder extends AbstractFeeder 71.50 +{ 71.51 + 71.52 + private Map<Subscription, Integer> highMarks = new HashMap<Subscription, Integer>(); 71.53 + private BufferedReader in; 71.54 + private PrintWriter out; 71.55 + 71.56 + @Override 71.57 + public void addSubscription(final Subscription sub) 71.58 + { 71.59 + super.addSubscription(sub); 71.60 + 71.61 + // Set a initial highMark 71.62 + this.highMarks.put(sub, 0); 71.63 + } 71.64 + 71.65 + /** 71.66 + * Changes to the given group and returns its high mark. 71.67 + * @param groupName 71.68 + * @return 71.69 + */ 71.70 + private int changeGroup(String groupName) 71.71 + throws IOException 71.72 + { 71.73 + this.out.print("GROUP " + groupName + "\r\n"); 71.74 + this.out.flush(); 71.75 + 71.76 + String line = this.in.readLine(); 71.77 + if(line.startsWith("211 ")) 71.78 + { 71.79 + int highmark = Integer.parseInt(line.split(" ")[3]); 71.80 + return highmark; 71.81 + } 71.82 + else 71.83 + { 71.84 + throw new IOException("GROUP " + groupName + " returned: " + line); 71.85 + } 71.86 + } 71.87 + 71.88 + private void connectTo(final String host, final int port) 71.89 + throws IOException, UnknownHostException 71.90 + { 71.91 + Socket socket = new Socket(host, port); 71.92 + this.out = new PrintWriter(socket.getOutputStream()); 71.93 + this.in = new BufferedReader(new InputStreamReader(socket.getInputStream())); 71.94 + 71.95 + String line = in.readLine(); 71.96 + if(!(line.charAt(0) == '2')) // Could be 200 or 2xx if posting is not allowed 71.97 + { 71.98 + throw new IOException(line); 71.99 + } 71.100 + } 71.101 + 71.102 + private void disconnect() 71.103 + throws IOException 71.104 + { 71.105 + this.out.print("QUIT\r\n"); 71.106 + this.out.flush(); 71.107 + this.out.close(); 71.108 + this.in.close(); 71.109 + 71.110 + this.out = null; 71.111 + this.in = null; 71.112 + } 71.113 + 71.114 + /** 71.115 + * Uses the OVER or XOVER command to get a list of message overviews that 71.116 + * may be unknown to this feeder and are about to be peered. 71.117 + * @param start 71.118 + * @param end 71.119 + * @return A list of message ids with potentially interesting messages. 71.120 + */ 71.121 + private List<String> over(int start, int end) 71.122 + throws IOException 71.123 + { 71.124 + this.out.print("OVER " + start + "-" + end + "\r\n"); 71.125 + this.out.flush(); 71.126 + 71.127 + String line = this.in.readLine(); 71.128 + if(line.startsWith("500 ")) // OVER not supported 71.129 + { 71.130 + this.out.print("XOVER " + start + "-" + end + "\r\n"); 71.131 + this.out.flush(); 71.132 + 71.133 + line = this.in.readLine(); 71.134 + } 71.135 + 71.136 + if(line.startsWith("224 ")) 71.137 + { 71.138 + List<String> messages = new ArrayList<String>(); 71.139 + line = this.in.readLine(); 71.140 + while(!".".equals(line)) 71.141 + { 71.142 + String mid = line.split("\t")[4]; // 5th should be the Message-ID 71.143 + messages.add(mid); 71.144 + line = this.in.readLine(); 71.145 + } 71.146 + return messages; 71.147 + } 71.148 + else 71.149 + { 71.150 + throw new IOException("Server return for OVER/XOVER: " + line); 71.151 + } 71.152 + } 71.153 + 71.154 + @Override 71.155 + public void run() 71.156 + { 71.157 + while(isRunning()) 71.158 + { 71.159 + int pullInterval = 1000 * 71.160 + Config.getInstance().get(Config.FEED_PULLINTERVAL, 3600); 71.161 + String host = "localhost"; 71.162 + int port = 119; 71.163 + 71.164 + Log.msg("Start PullFeeder run...", true); 71.165 + 71.166 + try 71.167 + { 71.168 + for(Subscription sub : this.subscriptions) 71.169 + { 71.170 + host = sub.getHost(); 71.171 + port = sub.getPort(); 71.172 + 71.173 + try 71.174 + { 71.175 + Log.msg("Feeding " + sub.getGroup() + " from " + sub.getHost(), true); 71.176 + try 71.177 + { 71.178 + connectTo(host, port); 71.179 + } 71.180 + catch(SocketException ex) 71.181 + { 71.182 + Log.msg("Skipping " + sub.getHost() + ": " + ex, false); 71.183 + continue; 71.184 + } 71.185 + 71.186 + int oldMark = this.highMarks.get(sub); 71.187 + int newMark = changeGroup(sub.getGroup()); 71.188 + 71.189 + if(oldMark != newMark) 71.190 + { 71.191 + List<String> messageIDs = over(oldMark, newMark); 71.192 + 71.193 + for(String messageID : messageIDs) 71.194 + { 71.195 + if(Database.getInstance().isArticleExisting(messageID)) 71.196 + { 71.197 + continue; 71.198 + } 71.199 + 71.200 + try 71.201 + { 71.202 + // Post the message via common socket connection 71.203 + ArticleReader aread = 71.204 + new ArticleReader(sub.getHost(), sub.getPort(), messageID); 71.205 + byte[] abuf = aread.getArticleData(); 71.206 + if (abuf == null) 71.207 + { 71.208 + Log.msg("Could not feed " + messageID + " from " + sub.getHost(), true); 71.209 + } 71.210 + else 71.211 + { 71.212 + Log.msg("Feeding " + messageID, true); 71.213 + ArticleWriter awrite = new ArticleWriter( 71.214 + "localhost", Config.getInstance().get(Config.PORT, 119)); 71.215 + awrite.writeArticle(abuf); 71.216 + awrite.close(); 71.217 + } 71.218 + Stats.getInstance().mailFeeded(sub.getGroup()); 71.219 + } 71.220 + catch(IOException ex) 71.221 + { 71.222 + // There may be a temporary network failure 71.223 + ex.printStackTrace(); 71.224 + Log.msg("Skipping mail " + messageID + " due to exception.", false); 71.225 + } 71.226 + } // for(;;) 71.227 + this.highMarks.put(sub, newMark); 71.228 + } 71.229 + 71.230 + disconnect(); 71.231 + } 71.232 + catch(SQLException ex) 71.233 + { 71.234 + ex.printStackTrace(); 71.235 + } 71.236 + catch(IOException ex) 71.237 + { 71.238 + ex.printStackTrace(); 71.239 + Log.msg("PullFeeder run stopped due to exception.", false); 71.240 + } 71.241 + } // for(Subscription sub : subscriptions) 71.242 + 71.243 + Log.msg("PullFeeder run ended. Waiting " + pullInterval / 1000 + "s", true); 71.244 + Thread.sleep(pullInterval); 71.245 + } 71.246 + catch(InterruptedException ex) 71.247 + { 71.248 + Log.msg(ex.getMessage(), false); 71.249 + } 71.250 + } 71.251 + } 71.252 + 71.253 +}
72.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 72.2 +++ b/org/sonews/feed/PushFeeder.java Fri Jun 26 16:48:50 2009 +0200 72.3 @@ -0,0 +1,107 @@ 72.4 +/* 72.5 + * SONEWS News Server 72.6 + * see AUTHORS for the list of contributors 72.7 + * 72.8 + * This program is free software: you can redistribute it and/or modify 72.9 + * it under the terms of the GNU General Public License as published by 72.10 + * the Free Software Foundation, either version 3 of the License, or 72.11 + * (at your option) any later version. 72.12 + * 72.13 + * This program is distributed in the hope that it will be useful, 72.14 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 72.15 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 72.16 + * GNU General Public License for more details. 72.17 + * 72.18 + * You should have received a copy of the GNU General Public License 72.19 + * along with this program. If not, see <http://www.gnu.org/licenses/>. 72.20 + */ 72.21 + 72.22 +package org.sonews.feed; 72.23 + 72.24 +import java.io.IOException; 72.25 +import java.util.concurrent.ConcurrentLinkedQueue; 72.26 +import org.sonews.daemon.storage.Article; 72.27 +import org.sonews.daemon.storage.Headers; 72.28 +import org.sonews.util.Log; 72.29 +import org.sonews.util.io.ArticleWriter; 72.30 + 72.31 +/** 72.32 + * Pushes new articles to remote newsservers. This feeder sleeps until a new 72.33 + * message is posted to the sonews instance. 72.34 + * @author Christian Lins 72.35 + * @since sonews/0.5.0 72.36 + */ 72.37 +class PushFeeder extends AbstractFeeder 72.38 +{ 72.39 + 72.40 + private ConcurrentLinkedQueue<Article> articleQueue = 72.41 + new ConcurrentLinkedQueue<Article>(); 72.42 + 72.43 + @Override 72.44 + public void run() 72.45 + { 72.46 + while(isRunning()) 72.47 + { 72.48 + try 72.49 + { 72.50 + synchronized(this) 72.51 + { 72.52 + this.wait(); 72.53 + } 72.54 + 72.55 + Article article = this.articleQueue.poll(); 72.56 + String[] groups = article.getHeader(Headers.NEWSGROUPS)[0].split(","); 72.57 + Log.msg("PushFeed: " + article.getMessageID(), true); 72.58 + for(Subscription sub : this.subscriptions) 72.59 + { 72.60 + // Circle check 72.61 + if(article.getHeader(Headers.PATH)[0].contains(sub.getHost())) 72.62 + { 72.63 + Log.msg(article.getMessageID() + " skipped for host " 72.64 + + sub.getHost(), true); 72.65 + continue; 72.66 + } 72.67 + 72.68 + try 72.69 + { 72.70 + for(String group : groups) 72.71 + { 72.72 + if(sub.getGroup().equals(group)) 72.73 + { 72.74 + // Delete headers that may cause problems 72.75 + article.removeHeader(Headers.NNTP_POSTING_DATE); 72.76 + article.removeHeader(Headers.NNTP_POSTING_HOST); 72.77 + article.removeHeader(Headers.X_COMPLAINTS_TO); 72.78 + article.removeHeader(Headers.X_TRACE); 72.79 + article.removeHeader(Headers.XREF); 72.80 + 72.81 + // POST the message to remote server 72.82 + ArticleWriter awriter = new ArticleWriter(sub.getHost(), sub.getPort()); 72.83 + awriter.writeArticle(article); 72.84 + break; 72.85 + } 72.86 + } 72.87 + } 72.88 + catch(IOException ex) 72.89 + { 72.90 + Log.msg(ex, false); 72.91 + } 72.92 + } 72.93 + } 72.94 + catch(InterruptedException ex) 72.95 + { 72.96 + Log.msg("PushFeeder interrupted.", true); 72.97 + } 72.98 + } 72.99 + } 72.100 + 72.101 + public void queueForPush(Article article) 72.102 + { 72.103 + this.articleQueue.add(article); 72.104 + synchronized(this) 72.105 + { 72.106 + this.notifyAll(); 72.107 + } 72.108 + } 72.109 + 72.110 +}
73.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 73.2 +++ b/org/sonews/feed/Subscription.java Fri Jun 26 16:48:50 2009 +0200 73.3 @@ -0,0 +1,63 @@ 73.4 +/* 73.5 + * SONEWS News Server 73.6 + * see AUTHORS for the list of contributors 73.7 + * 73.8 + * This program is free software: you can redistribute it and/or modify 73.9 + * it under the terms of the GNU General Public License as published by 73.10 + * the Free Software Foundation, either version 3 of the License, or 73.11 + * (at your option) any later version. 73.12 + * 73.13 + * This program is distributed in the hope that it will be useful, 73.14 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 73.15 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 73.16 + * GNU General Public License for more details. 73.17 + * 73.18 + * You should have received a copy of the GNU General Public License 73.19 + * along with this program. If not, see <http://www.gnu.org/licenses/>. 73.20 + */ 73.21 + 73.22 +package org.sonews.feed; 73.23 + 73.24 +/** 73.25 + * For every group that is synchronized with or from a remote newsserver 73.26 + * a Subscription instance exists. 73.27 + * @author Christian Lins 73.28 + * @since sonews/0.5.0 73.29 + */ 73.30 +public class Subscription 73.31 +{ 73.32 + 73.33 + private String host; 73.34 + private int port; 73.35 + private int feedtype; 73.36 + private String group; 73.37 + 73.38 + public Subscription(String host, int port, int feedtype, String group) 73.39 + { 73.40 + this.host = host; 73.41 + this.port = port; 73.42 + this.feedtype = feedtype; 73.43 + this.group = group; 73.44 + } 73.45 + 73.46 + public int getFeedtype() 73.47 + { 73.48 + return feedtype; 73.49 + } 73.50 + 73.51 + public String getGroup() 73.52 + { 73.53 + return group; 73.54 + } 73.55 + 73.56 + public String getHost() 73.57 + { 73.58 + return host; 73.59 + } 73.60 + 73.61 + public int getPort() 73.62 + { 73.63 + return port; 73.64 + } 73.65 + 73.66 +}
74.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 74.2 +++ b/org/sonews/feed/package.html Fri Jun 26 16:48:50 2009 +0200 74.3 @@ -0,0 +1,2 @@ 74.4 +Contains classes for the peering functionality, e.g. pulling and pushing 74.5 +mails from and to remote newsservers. 74.6 \ No newline at end of file
75.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 75.2 +++ b/org/sonews/mlgw/Dispatcher.java Fri Jun 26 16:48:50 2009 +0200 75.3 @@ -0,0 +1,251 @@ 75.4 +/* 75.5 + * SONEWS News Server 75.6 + * see AUTHORS for the list of contributors 75.7 + * 75.8 + * This program is free software: you can redistribute it and/or modify 75.9 + * it under the terms of the GNU General Public License as published by 75.10 + * the Free Software Foundation, either version 3 of the License, or 75.11 + * (at your option) any later version. 75.12 + * 75.13 + * This program is distributed in the hope that it will be useful, 75.14 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 75.15 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 75.16 + * GNU General Public License for more details. 75.17 + * 75.18 + * You should have received a copy of the GNU General Public License 75.19 + * along with this program. If not, see <http://www.gnu.org/licenses/>. 75.20 + */ 75.21 + 75.22 +package org.sonews.mlgw; 75.23 + 75.24 +import java.io.IOException; 75.25 +import org.sonews.daemon.Config; 75.26 +import org.sonews.daemon.storage.Article; 75.27 +import org.sonews.util.io.ArticleInputStream; 75.28 +import org.sonews.daemon.storage.Database; 75.29 +import java.sql.SQLException; 75.30 +import java.util.ArrayList; 75.31 +import java.util.List; 75.32 +import java.util.Properties; 75.33 +import javax.mail.Address; 75.34 +import javax.mail.Authenticator; 75.35 +import javax.mail.Message; 75.36 +import javax.mail.MessagingException; 75.37 +import javax.mail.PasswordAuthentication; 75.38 +import javax.mail.Session; 75.39 +import javax.mail.Transport; 75.40 +import javax.mail.internet.InternetAddress; 75.41 +import javax.mail.internet.MimeMessage; 75.42 +import org.sonews.daemon.storage.Headers; 75.43 +import org.sonews.util.Log; 75.44 +import org.sonews.util.Stats; 75.45 + 75.46 +/** 75.47 + * Dispatches messages from mailing list or newsserver or vice versa. 75.48 + * @author Christian Lins 75.49 + * @since sonews/0.5.0 75.50 + */ 75.51 +public class Dispatcher 75.52 +{ 75.53 + 75.54 + static class PasswordAuthenticator extends Authenticator 75.55 + { 75.56 + 75.57 + @Override 75.58 + public PasswordAuthentication getPasswordAuthentication() 75.59 + { 75.60 + final String username = 75.61 + Config.getInstance().get(Config.MLSEND_USER, "user"); 75.62 + final String password = 75.63 + Config.getInstance().get(Config.MLSEND_PASSWORD, "mysecret"); 75.64 + 75.65 + return new PasswordAuthentication(username, password); 75.66 + } 75.67 + 75.68 + } 75.69 + 75.70 + /** 75.71 + * Posts a message that was received from a mailing list to the 75.72 + * appropriate newsgroup. 75.73 + * @param msg 75.74 + */ 75.75 + public static boolean toGroup(final Message msg) 75.76 + { 75.77 + try 75.78 + { 75.79 + Address[] to = msg.getAllRecipients(); // includes TO/CC/BCC 75.80 + if(to == null || to.length <= 0) 75.81 + { 75.82 + Log.msg("Skipping message because no receipient!", true); 75.83 + return false; 75.84 + } 75.85 + else 75.86 + { 75.87 + boolean posted = false; 75.88 + for(Address toa : to) // Address can have '<' '>' around 75.89 + { 75.90 + if(!(toa instanceof InternetAddress)) 75.91 + { 75.92 + continue; 75.93 + } 75.94 + String group = Database.getInstance() 75.95 + .getGroupForList((InternetAddress)toa); 75.96 + if(group != null) 75.97 + { 75.98 + Log.msg("Posting to group " + group, true); 75.99 + 75.100 + // Create new Article object 75.101 + Article article = new Article(msg); 75.102 + article.setGroup(group); 75.103 + 75.104 + // Write article to database 75.105 + if(!Database.getInstance().isArticleExisting(article.getMessageID())) 75.106 + { 75.107 + Database.getInstance().addArticle(article); 75.108 + Stats.getInstance().mailGatewayed( 75.109 + article.getHeader(Headers.NEWSGROUPS)[0]); 75.110 + } 75.111 + else 75.112 + { 75.113 + Log.msg("Article " + article.getMessageID() + " already existing.", true); 75.114 + // TODO: It may be possible that a ML mail is posted to several 75.115 + // ML addresses... 75.116 + } 75.117 + posted = true; 75.118 + } 75.119 + else 75.120 + { 75.121 + Log.msg("No group for " + toa, true); 75.122 + } 75.123 + } // end for 75.124 + return posted; 75.125 + } 75.126 + } 75.127 + catch(Exception ex) 75.128 + { 75.129 + ex.printStackTrace(); 75.130 + return false; 75.131 + } 75.132 + } 75.133 + 75.134 + /** 75.135 + * Mails a message received through NNTP to the appropriate mailing list. 75.136 + */ 75.137 + public static void toList(Article article) 75.138 + throws IOException, MessagingException, SQLException 75.139 + { 75.140 + // Get mailing lists for the group of this article 75.141 + List<String> listAddresses = new ArrayList<String>(); 75.142 + String[] groupnames = article.getHeader(Headers.NEWSGROUPS)[0].split(","); 75.143 + 75.144 + for(String groupname : groupnames) 75.145 + { 75.146 + String listAddress = Database.getInstance().getListForGroup(groupname); 75.147 + if(listAddress != null) 75.148 + { 75.149 + listAddresses.add(listAddress); 75.150 + } 75.151 + } 75.152 + 75.153 + for(String listAddress : listAddresses) 75.154 + { 75.155 + // Compose message and send it via given SMTP-Host 75.156 + String smtpHost = Config.getInstance().get(Config.MLSEND_HOST, "localhost"); 75.157 + int smtpPort = Config.getInstance().get(Config.MLSEND_PORT, 25); 75.158 + String smtpUser = Config.getInstance().get(Config.MLSEND_USER, "user"); 75.159 + String smtpPw = Config.getInstance().get(Config.MLSEND_PASSWORD, "mysecret"); 75.160 + 75.161 + Properties props = System.getProperties(); 75.162 + props.put("mail.smtp.localhost", 75.163 + Config.getInstance().get(Config.HOSTNAME, "localhost")); 75.164 + props.put("mail.smtp.from", // Used for MAIL FROM command 75.165 + Config.getInstance().get( 75.166 + Config.MLSEND_ADDRESS, article.getHeader(Headers.FROM)[0])); 75.167 + props.put("mail.smtp.host", smtpHost); 75.168 + props.put("mail.smtp.port", smtpPort); 75.169 + props.put("mail.smtp.auth", "true"); 75.170 + 75.171 + Address[] address = new Address[1]; 75.172 + address[0] = new InternetAddress(listAddress); 75.173 + 75.174 + ArticleInputStream in = new ArticleInputStream(article); 75.175 + Session session = Session.getDefaultInstance(props, new PasswordAuthenticator()); 75.176 + MimeMessage msg = new MimeMessage(session, in); 75.177 + msg.setRecipient(Message.RecipientType.TO, address[0]); 75.178 + msg.setReplyTo(address); 75.179 + msg.removeHeader(Headers.NEWSGROUPS); 75.180 + msg.removeHeader(Headers.PATH); 75.181 + msg.removeHeader(Headers.LINES); 75.182 + msg.removeHeader(Headers.BYTES); 75.183 + 75.184 + if(Config.getInstance().get(Config.MLSEND_RW_SENDER, false)) 75.185 + { 75.186 + rewriteSenderAddress(msg); // Set the SENDER address 75.187 + } 75.188 + 75.189 + if(Config.getInstance().get(Config.MLSEND_RW_FROM, false)) 75.190 + { 75.191 + rewriteFromAddress(msg); // Set the FROM address 75.192 + } 75.193 + 75.194 + msg.saveChanges(); 75.195 + 75.196 + // Send the mail 75.197 + Transport transport = session.getTransport("smtp"); 75.198 + transport.connect(smtpHost, smtpPort, smtpUser, smtpPw); 75.199 + transport.sendMessage(msg, msg.getAllRecipients()); 75.200 + transport.close(); 75.201 + 75.202 + Stats.getInstance().mailGatewayed(article.getHeader(Headers.NEWSGROUPS)[0]); 75.203 + Log.msg("MLGateway: Mail " + article.getHeader("Subject")[0] 75.204 + + " was delivered to " + listAddress + ".", true); 75.205 + } 75.206 + } 75.207 + 75.208 + /** 75.209 + * Sets the SENDER header of the given MimeMessage. This might be necessary 75.210 + * for moderated groups that does not allow the "normal" FROM sender. 75.211 + * @param msg 75.212 + * @throws javax.mail.MessagingException 75.213 + */ 75.214 + private static void rewriteSenderAddress(MimeMessage msg) 75.215 + throws MessagingException 75.216 + { 75.217 + String mlAddress = Config.getInstance().get(Config.MLSEND_ADDRESS, null); 75.218 + 75.219 + if(mlAddress != null) 75.220 + { 75.221 + msg.setSender(new InternetAddress(mlAddress)); 75.222 + } 75.223 + else 75.224 + { 75.225 + throw new MessagingException("Cannot rewrite SENDER header!"); 75.226 + } 75.227 + } 75.228 + 75.229 + /** 75.230 + * Sets the FROM header of the given MimeMessage. This might be necessary 75.231 + * for moderated groups that does not allow the "normal" FROM sender. 75.232 + * @param msg 75.233 + * @throws javax.mail.MessagingException 75.234 + */ 75.235 + private static void rewriteFromAddress(MimeMessage msg) 75.236 + throws MessagingException 75.237 + { 75.238 + Address[] froms = msg.getFrom(); 75.239 + String mlAddress = Config.getInstance().get(Config.MLSEND_ADDRESS, null); 75.240 + 75.241 + if(froms.length > 0 && froms[0] instanceof InternetAddress 75.242 + && mlAddress != null) 75.243 + { 75.244 + InternetAddress from = (InternetAddress)froms[0]; 75.245 + from.setAddress(mlAddress); 75.246 + msg.setFrom(from); 75.247 + } 75.248 + else 75.249 + { 75.250 + throw new MessagingException("Cannot rewrite FROM header!"); 75.251 + } 75.252 + } 75.253 + 75.254 +}
76.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 76.2 +++ b/org/sonews/mlgw/MailPoller.java Fri Jun 26 16:48:50 2009 +0200 76.3 @@ -0,0 +1,152 @@ 76.4 +/* 76.5 + * SONEWS News Server 76.6 + * see AUTHORS for the list of contributors 76.7 + * 76.8 + * This program is free software: you can redistribute it and/or modify 76.9 + * it under the terms of the GNU General Public License as published by 76.10 + * the Free Software Foundation, either version 3 of the License, or 76.11 + * (at your option) any later version. 76.12 + * 76.13 + * This program is distributed in the hope that it will be useful, 76.14 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 76.15 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 76.16 + * GNU General Public License for more details. 76.17 + * 76.18 + * You should have received a copy of the GNU General Public License 76.19 + * along with this program. If not, see <http://www.gnu.org/licenses/>. 76.20 + */ 76.21 + 76.22 +package org.sonews.mlgw; 76.23 + 76.24 +import java.util.Properties; 76.25 +import javax.mail.AuthenticationFailedException; 76.26 +import javax.mail.Authenticator; 76.27 +import javax.mail.Flags.Flag; 76.28 +import javax.mail.Folder; 76.29 +import javax.mail.Message; 76.30 +import javax.mail.MessagingException; 76.31 +import javax.mail.NoSuchProviderException; 76.32 +import javax.mail.PasswordAuthentication; 76.33 +import javax.mail.Session; 76.34 +import javax.mail.Store; 76.35 +import org.sonews.daemon.Config; 76.36 +import org.sonews.daemon.AbstractDaemon; 76.37 +import org.sonews.util.Log; 76.38 +import org.sonews.util.Stats; 76.39 + 76.40 +/** 76.41 + * Daemon polling for new mails in a POP3 account to be delivered to newsgroups. 76.42 + * @author Christian Lins 76.43 + * @since sonews/0.5.0 76.44 + */ 76.45 +public class MailPoller extends AbstractDaemon 76.46 +{ 76.47 + 76.48 + static class PasswordAuthenticator extends Authenticator 76.49 + { 76.50 + 76.51 + @Override 76.52 + public PasswordAuthentication getPasswordAuthentication() 76.53 + { 76.54 + final String username = 76.55 + Config.getInstance().get(Config.MLPOLL_USER, "user"); 76.56 + final String password = 76.57 + Config.getInstance().get(Config.MLPOLL_PASSWORD, "mysecret"); 76.58 + 76.59 + return new PasswordAuthentication(username, password); 76.60 + } 76.61 + 76.62 + } 76.63 + 76.64 + @Override 76.65 + public void run() 76.66 + { 76.67 + Log.msg("Starting Mailinglist Poller...", false); 76.68 + int errors = 0; 76.69 + while(isRunning() && errors < 5) 76.70 + { 76.71 + try 76.72 + { 76.73 + // Wait some time between runs. At the beginning has advantages, 76.74 + // because the wait is not skipped if an exception occurs. 76.75 + Thread.sleep(60000 * (errors + 1)); // one minute * errors 76.76 + 76.77 + final String host = 76.78 + Config.getInstance().get(Config.MLPOLL_HOST, "samplehost"); 76.79 + final String username = 76.80 + Config.getInstance().get(Config.MLPOLL_USER, "user"); 76.81 + final String password = 76.82 + Config.getInstance().get(Config.MLPOLL_PASSWORD, "mysecret"); 76.83 + 76.84 + Stats.getInstance().mlgwRunStart(); 76.85 + 76.86 + // Create empty properties 76.87 + Properties props = System.getProperties(); 76.88 + props.put("mail.pop3.host", host); 76.89 + 76.90 + // Get session 76.91 + Session session = Session.getInstance(props); 76.92 + 76.93 + // Get the store 76.94 + Store store = session.getStore("pop3"); 76.95 + store.connect(host, 110, username, password); 76.96 + 76.97 + // Get folder 76.98 + Folder folder = store.getFolder("INBOX"); 76.99 + folder.open(Folder.READ_WRITE); 76.100 + 76.101 + // Get directory 76.102 + Message[] messages = folder.getMessages(); 76.103 + 76.104 + // Dispatch messages and delete it afterwards on the inbox 76.105 + for(Message message : messages) 76.106 + { 76.107 + String subject = message.getSubject(); 76.108 + System.out.println("MLGateway: message with subject \"" + subject + "\" received."); 76.109 + if(Dispatcher.toGroup(message) 76.110 + || Config.getInstance().get(Config.MLPOLL_DELETEUNKNOWN, false)) 76.111 + { 76.112 + // Delete the message 76.113 + message.setFlag(Flag.DELETED, true); 76.114 + } 76.115 + } 76.116 + 76.117 + // Close connection 76.118 + folder.close(true); // true to expunge deleted messages 76.119 + store.close(); 76.120 + errors = 0; 76.121 + 76.122 + Stats.getInstance().mlgwRunEnd(); 76.123 + } 76.124 + catch(NoSuchProviderException ex) 76.125 + { 76.126 + Log.msg(ex.toString(), false); 76.127 + shutdown(); 76.128 + } 76.129 + catch(AuthenticationFailedException ex) 76.130 + { 76.131 + // AuthentificationFailedException may be thrown if credentials are 76.132 + // bad or if the Mailbox is in use (locked). 76.133 + ex.printStackTrace(); 76.134 + errors++; 76.135 + } 76.136 + catch(InterruptedException ex) 76.137 + { 76.138 + System.out.println("sonews: " + this + " returns."); 76.139 + return; 76.140 + } 76.141 + catch(MessagingException ex) 76.142 + { 76.143 + ex.printStackTrace(); 76.144 + errors++; 76.145 + } 76.146 + catch(Exception ex) 76.147 + { 76.148 + ex.printStackTrace(); 76.149 + errors++; 76.150 + } 76.151 + } 76.152 + Log.msg("MailPoller exited.", false); 76.153 + } 76.154 + 76.155 +}
77.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 77.2 +++ b/org/sonews/mlgw/package.html Fri Jun 26 16:48:50 2009 +0200 77.3 @@ -0,0 +1,1 @@ 77.4 +Contains classes of the Mailinglist Gateway. 77.5 \ No newline at end of file
78.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 78.2 +++ b/org/sonews/util/AbstractConfig.java Fri Jun 26 16:48:50 2009 +0200 78.3 @@ -0,0 +1,43 @@ 78.4 +/* 78.5 + * SONEWS News Server 78.6 + * see AUTHORS for the list of contributors 78.7 + * 78.8 + * This program is free software: you can redistribute it and/or modify 78.9 + * it under the terms of the GNU General Public License as published by 78.10 + * the Free Software Foundation, either version 3 of the License, or 78.11 + * (at your option) any later version. 78.12 + * 78.13 + * This program is distributed in the hope that it will be useful, 78.14 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 78.15 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 78.16 + * GNU General Public License for more details. 78.17 + * 78.18 + * You should have received a copy of the GNU General Public License 78.19 + * along with this program. If not, see <http://www.gnu.org/licenses/>. 78.20 + */ 78.21 + 78.22 +package org.sonews.util; 78.23 + 78.24 +/** 78.25 + * Base class for Config and BootstrapConfig. 78.26 + * @author Christian Lins 78.27 + * @since sonews/0.5.0 78.28 + */ 78.29 +public abstract class AbstractConfig 78.30 +{ 78.31 + 78.32 + public abstract String get(String key, String defVal); 78.33 + 78.34 + public int get(final String key, final int defVal) 78.35 + { 78.36 + return Integer.parseInt( 78.37 + get(key, Integer.toString(defVal))); 78.38 + } 78.39 + 78.40 + public boolean get(String key, boolean defVal) 78.41 + { 78.42 + String val = get(key, Boolean.toString(defVal)); 78.43 + return Boolean.parseBoolean(val); 78.44 + } 78.45 + 78.46 +}
79.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 79.2 +++ b/org/sonews/util/DatabaseSetup.java Fri Jun 26 16:48:50 2009 +0200 79.3 @@ -0,0 +1,130 @@ 79.4 +/* 79.5 + * SONEWS News Server 79.6 + * see AUTHORS for the list of contributors 79.7 + * 79.8 + * This program is free software: you can redistribute it and/or modify 79.9 + * it under the terms of the GNU General Public License as published by 79.10 + * the Free Software Foundation, either version 3 of the License, or 79.11 + * (at your option) any later version. 79.12 + * 79.13 + * This program is distributed in the hope that it will be useful, 79.14 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 79.15 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 79.16 + * GNU General Public License for more details. 79.17 + * 79.18 + * You should have received a copy of the GNU General Public License 79.19 + * along with this program. If not, see <http://www.gnu.org/licenses/>. 79.20 + */ 79.21 + 79.22 +package org.sonews.util; 79.23 + 79.24 +import java.io.BufferedReader; 79.25 +import java.io.InputStreamReader; 79.26 +import java.sql.Connection; 79.27 +import java.sql.DriverManager; 79.28 +import java.sql.Statement; 79.29 +import java.util.HashMap; 79.30 +import java.util.Map; 79.31 +import org.sonews.daemon.BootstrapConfig; 79.32 +import org.sonews.util.io.Resource; 79.33 + 79.34 +/** 79.35 + * Database setup utility class. 79.36 + * @author Christian Lins 79.37 + * @since sonews/0.5.0 79.38 + */ 79.39 +public final class DatabaseSetup 79.40 +{ 79.41 + 79.42 + private static final Map<String, String> templateMap 79.43 + = new HashMap<String, String>(); 79.44 + private static final Map<String, StringTemplate> urlMap 79.45 + = new HashMap<String, StringTemplate>(); 79.46 + private static final Map<String, String> driverMap 79.47 + = new HashMap<String, String>(); 79.48 + 79.49 + static 79.50 + { 79.51 + templateMap.put("1", "helpers/database_mysql5_tmpl.sql"); 79.52 + templateMap.put("2", "helpers/database_postgresql8_tmpl.sql"); 79.53 + 79.54 + urlMap.put("1", new StringTemplate("jdbc:mysql://%HOSTNAME/%DB")); 79.55 + urlMap.put("2", new StringTemplate("jdbc:postgresql://%HOSTNAME/%DB")); 79.56 + 79.57 + driverMap.put("1", "com.mysql.jdbc.Driver"); 79.58 + driverMap.put("2", "org.postgresql.Driver"); 79.59 + } 79.60 + 79.61 + public static void main(String[] args) 79.62 + throws Exception 79.63 + { 79.64 + System.out.println("sonews Database setup helper"); 79.65 + System.out.println("This program will create a initial database table structure"); 79.66 + System.out.println("for the sonews Newsserver."); 79.67 + System.out.println("You need to create a database and a db user manually before!"); 79.68 + 79.69 + System.out.println("Select DBMS type:"); 79.70 + System.out.println("[1] MySQL 5.x or higher"); 79.71 + System.out.println("[2] PostgreSQL 8.x or higher"); 79.72 + System.out.print("Your choice: "); 79.73 + 79.74 + BufferedReader in = new BufferedReader(new InputStreamReader(System.in)); 79.75 + String dbmsType = in.readLine(); 79.76 + String tmplName = templateMap.get(dbmsType); 79.77 + if(tmplName == null) 79.78 + { 79.79 + System.err.println("Invalid choice. Try again you fool!"); 79.80 + main(args); 79.81 + return; 79.82 + } 79.83 + 79.84 + // Load JDBC Driver class 79.85 + Class.forName(driverMap.get(dbmsType)); 79.86 + 79.87 + String tmpl = Resource.getAsString(tmplName, true); 79.88 + 79.89 + System.out.print("Database server hostname (e.g. localhost): "); 79.90 + String dbHostname = in.readLine(); 79.91 + 79.92 + System.out.print("Database name: "); 79.93 + String dbName = in.readLine(); 79.94 + 79.95 + System.out.print("Give name of DB user that can create tables: "); 79.96 + String dbUser = in.readLine(); 79.97 + 79.98 + System.out.print("Password: "); 79.99 + String dbPassword = in.readLine(); 79.100 + 79.101 + String url = urlMap.get(dbmsType) 79.102 + .set("HOSTNAME", dbHostname) 79.103 + .set("DB", dbName).toString(); 79.104 + 79.105 + Connection conn = 79.106 + DriverManager.getConnection(url, dbUser, dbPassword); 79.107 + conn.setAutoCommit(false); 79.108 + 79.109 + String[] tmplChunks = tmpl.split(";"); 79.110 + 79.111 + for(String chunk : tmplChunks) 79.112 + { 79.113 + if(chunk.trim().equals("")) 79.114 + continue; 79.115 + 79.116 + Statement stmt = conn.createStatement(); 79.117 + stmt.execute(chunk); 79.118 + } 79.119 + 79.120 + conn.commit(); 79.121 + conn.setAutoCommit(true); 79.122 + 79.123 + BootstrapConfig config = BootstrapConfig.getInstance(); 79.124 + config.set(BootstrapConfig.STORAGE_DATABASE, url); 79.125 + config.set(BootstrapConfig.STORAGE_DBMSDRIVER, driverMap.get(dbmsType)); 79.126 + config.set(BootstrapConfig.STORAGE_PASSWORD, dbPassword); 79.127 + config.set(BootstrapConfig.STORAGE_USER, dbUser); 79.128 + config.save(); 79.129 + 79.130 + System.out.println("Ok"); 79.131 + } 79.132 + 79.133 +}
80.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 80.2 +++ b/org/sonews/util/Log.java Fri Jun 26 16:48:50 2009 +0200 80.3 @@ -0,0 +1,59 @@ 80.4 +/* 80.5 + * SONEWS News Server 80.6 + * see AUTHORS for the list of contributors 80.7 + * 80.8 + * This program is free software: you can redistribute it and/or modify 80.9 + * it under the terms of the GNU General Public License as published by 80.10 + * the Free Software Foundation, either version 3 of the License, or 80.11 + * (at your option) any later version. 80.12 + * 80.13 + * This program is distributed in the hope that it will be useful, 80.14 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 80.15 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 80.16 + * GNU General Public License for more details. 80.17 + * 80.18 + * You should have received a copy of the GNU General Public License 80.19 + * along with this program. If not, see <http://www.gnu.org/licenses/>. 80.20 + */ 80.21 + 80.22 +package org.sonews.util; 80.23 + 80.24 +import org.sonews.daemon.*; 80.25 +import java.util.Date; 80.26 + 80.27 +/** 80.28 + * Provides logging and debugging methods. 80.29 + * @author Christian Lins 80.30 + * @since sonews/0.5.0 80.31 + */ 80.32 +public class Log 80.33 +{ 80.34 + 80.35 + public static boolean isDebug() 80.36 + { 80.37 + // We must use BootstrapConfig here otherwise we come 80.38 + // into hell's kittchen when using the Logger within the 80.39 + // Database class. 80.40 + return BootstrapConfig.getInstance().get(BootstrapConfig.DEBUG, false); 80.41 + } 80.42 + 80.43 + /** 80.44 + * Writes the given message to the debug output. 80.45 + * @param msg A String message or an object. 80.46 + * @param If true this message is only shown if debug mode is enabled. 80.47 + */ 80.48 + public static void msg(final Object msg, boolean debug) 80.49 + { 80.50 + if(isDebug() || !debug) 80.51 + { 80.52 + synchronized(System.out) 80.53 + { 80.54 + System.out.print(new Date().toString()); 80.55 + System.out.print(": "); 80.56 + System.out.println(msg); 80.57 + System.out.flush(); 80.58 + } 80.59 + } 80.60 + } 80.61 + 80.62 +}
81.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 81.2 +++ b/org/sonews/util/Pair.java Fri Jun 26 16:48:50 2009 +0200 81.3 @@ -0,0 +1,48 @@ 81.4 +/* 81.5 + * SONEWS News Server 81.6 + * see AUTHORS for the list of contributors 81.7 + * 81.8 + * This program is free software: you can redistribute it and/or modify 81.9 + * it under the terms of the GNU General Public License as published by 81.10 + * the Free Software Foundation, either version 3 of the License, or 81.11 + * (at your option) any later version. 81.12 + * 81.13 + * This program is distributed in the hope that it will be useful, 81.14 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 81.15 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 81.16 + * GNU General Public License for more details. 81.17 + * 81.18 + * You should have received a copy of the GNU General Public License 81.19 + * along with this program. If not, see <http://www.gnu.org/licenses/>. 81.20 + */ 81.21 + 81.22 +package org.sonews.util; 81.23 + 81.24 +/** 81.25 + * A pair of two objects. 81.26 + * @author Christian Lins 81.27 + * @since sonews/0.5.0 81.28 + */ 81.29 +public class Pair<T1, T2> 81.30 +{ 81.31 + 81.32 + private T1 a; 81.33 + private T2 b; 81.34 + 81.35 + public Pair(T1 a, T2 b) 81.36 + { 81.37 + this.a = a; 81.38 + this.b = b; 81.39 + } 81.40 + 81.41 + public T1 getA() 81.42 + { 81.43 + return a; 81.44 + } 81.45 + 81.46 + public T2 getB() 81.47 + { 81.48 + return b; 81.49 + } 81.50 + 81.51 +}
82.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 82.2 +++ b/org/sonews/util/Purger.java Fri Jun 26 16:48:50 2009 +0200 82.3 @@ -0,0 +1,88 @@ 82.4 +/* 82.5 + * SONEWS News Server 82.6 + * see AUTHORS for the list of contributors 82.7 + * 82.8 + * This program is free software: you can redistribute it and/or modify 82.9 + * it under the terms of the GNU General Public License as published by 82.10 + * the Free Software Foundation, either version 3 of the License, or 82.11 + * (at your option) any later version. 82.12 + * 82.13 + * This program is distributed in the hope that it will be useful, 82.14 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 82.15 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 82.16 + * GNU General Public License for more details. 82.17 + * 82.18 + * You should have received a copy of the GNU General Public License 82.19 + * along with this program. If not, see <http://www.gnu.org/licenses/>. 82.20 + */ 82.21 + 82.22 +package org.sonews.util; 82.23 + 82.24 +import org.sonews.daemon.Config; 82.25 +import org.sonews.daemon.storage.Database; 82.26 +import org.sonews.daemon.storage.Article; 82.27 +import java.util.Date; 82.28 + 82.29 +/** 82.30 + * The purger is started in configurable intervals to search 82.31 + * for old messages that can be purged. 82.32 + * @author Christian Lins 82.33 + * @since sonews/0.5.0 82.34 + */ 82.35 +public class Purger 82.36 +{ 82.37 + 82.38 + private long lifetime; 82.39 + 82.40 + public Purger() 82.41 + { 82.42 + this.lifetime = Config.getInstance().get("sonews.article.lifetime", 30) 82.43 + * 24L * 60L * 60L * 1000L; // in Milliseconds 82.44 + } 82.45 + 82.46 + /** 82.47 + * Loops through all messages and deletes them if their time 82.48 + * has come. 82.49 + */ 82.50 + void purge() 82.51 + throws Exception 82.52 + { 82.53 + System.out.println("Purging old messages..."); 82.54 + 82.55 + for (;;) 82.56 + { 82.57 + // TODO: Delete articles directly in database 82.58 + Article art = null; //Database.getInstance().getOldestArticle(); 82.59 + if (art == null) // No articles in the database 82.60 + { 82.61 + break; 82.62 + } 82.63 + 82.64 +/* if (art.getDate().getTime() < (new Date().getTime() + this.lifetime)) 82.65 + { 82.66 + // Database.getInstance().delete(art); 82.67 + System.out.println("Deleted: " + art); 82.68 + } 82.69 + else 82.70 + { 82.71 + break; 82.72 + }*/ 82.73 + } 82.74 + } 82.75 + 82.76 + public static void main(String[] args) 82.77 + { 82.78 + try 82.79 + { 82.80 + Purger purger = new Purger(); 82.81 + purger.purge(); 82.82 + System.exit(0); 82.83 + } 82.84 + catch(Exception ex) 82.85 + { 82.86 + ex.printStackTrace(); 82.87 + System.exit(1); 82.88 + } 82.89 + } 82.90 + 82.91 +}
83.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 83.2 +++ b/org/sonews/util/Stats.java Fri Jun 26 16:48:50 2009 +0200 83.3 @@ -0,0 +1,194 @@ 83.4 +/* 83.5 + * SONEWS News Server 83.6 + * see AUTHORS for the list of contributors 83.7 + * 83.8 + * This program is free software: you can redistribute it and/or modify 83.9 + * it under the terms of the GNU General Public License as published by 83.10 + * the Free Software Foundation, either version 3 of the License, or 83.11 + * (at your option) any later version. 83.12 + * 83.13 + * This program is distributed in the hope that it will be useful, 83.14 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 83.15 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 83.16 + * GNU General Public License for more details. 83.17 + * 83.18 + * You should have received a copy of the GNU General Public License 83.19 + * along with this program. If not, see <http://www.gnu.org/licenses/>. 83.20 + */ 83.21 + 83.22 +package org.sonews.util; 83.23 + 83.24 +import java.sql.SQLException; 83.25 +import java.util.Calendar; 83.26 +import org.sonews.daemon.storage.Database; 83.27 +import org.sonews.daemon.storage.Group; 83.28 + 83.29 +/** 83.30 + * Class that capsulates statistical data gathering. 83.31 + * @author Christian Lins 83.32 + * @since sonews/0.5.0 83.33 + */ 83.34 +public final class Stats 83.35 +{ 83.36 + 83.37 + public static final byte CONNECTIONS = 1; 83.38 + public static final byte POSTED_NEWS = 2; 83.39 + public static final byte GATEWAYED_NEWS = 3; 83.40 + public static final byte FEEDED_NEWS = 4; 83.41 + public static final byte MLGW_RUNSTART = 5; 83.42 + public static final byte MLGW_RUNEND = 6; 83.43 + 83.44 + private static Stats instance = new Stats(); 83.45 + 83.46 + public static Stats getInstance() 83.47 + { 83.48 + return Stats.instance; 83.49 + } 83.50 + 83.51 + private Stats() {} 83.52 + 83.53 + private volatile int connectedClients = 0; 83.54 + 83.55 + private void addEvent(byte type, String groupname) 83.56 + { 83.57 + Group group = Group.getByName(groupname); 83.58 + if(group != null) 83.59 + { 83.60 + try 83.61 + { 83.62 + Database.getInstance().addEvent( 83.63 + System.currentTimeMillis(), type, group.getID()); 83.64 + } 83.65 + catch(SQLException ex) 83.66 + { 83.67 + ex.printStackTrace(); 83.68 + } 83.69 + } 83.70 + else 83.71 + { 83.72 + Log.msg("Group " + groupname + " does not exist.", true); 83.73 + } 83.74 + } 83.75 + 83.76 + public void clientConnect() 83.77 + { 83.78 + this.connectedClients++; 83.79 + } 83.80 + 83.81 + public void clientDisconnect() 83.82 + { 83.83 + this.connectedClients--; 83.84 + } 83.85 + 83.86 + public int connectedClients() 83.87 + { 83.88 + return this.connectedClients; 83.89 + } 83.90 + 83.91 + public int getNumberOfGroups() 83.92 + { 83.93 + try 83.94 + { 83.95 + return Database.getInstance().countGroups(); 83.96 + } 83.97 + catch(SQLException ex) 83.98 + { 83.99 + ex.printStackTrace(); 83.100 + return -1; 83.101 + } 83.102 + } 83.103 + 83.104 + public int getNumberOfNews() 83.105 + { 83.106 + try 83.107 + { 83.108 + return Database.getInstance().countArticles(); 83.109 + } 83.110 + catch(SQLException ex) 83.111 + { 83.112 + ex.printStackTrace(); 83.113 + return -1; 83.114 + } 83.115 + } 83.116 + 83.117 + public int getYesterdaysEvents(final byte eventType, final int hour, 83.118 + final Group group) 83.119 + { 83.120 + // Determine the timestamp values for yesterday and the given hour 83.121 + Calendar cal = Calendar.getInstance(); 83.122 + int year = cal.get(Calendar.YEAR); 83.123 + int month = cal.get(Calendar.MONTH); 83.124 + int dayom = cal.get(Calendar.DAY_OF_MONTH) - 1; // Yesterday 83.125 + 83.126 + cal.set(year, month, dayom, hour, 0, 0); 83.127 + long startTimestamp = cal.getTimeInMillis(); 83.128 + 83.129 + cal.set(year, month, dayom, hour + 1, 0, 0); 83.130 + long endTimestamp = cal.getTimeInMillis(); 83.131 + 83.132 + try 83.133 + { 83.134 + return Database.getInstance() 83.135 + .getEventsCount(eventType, startTimestamp, endTimestamp, group); 83.136 + } 83.137 + catch(SQLException ex) 83.138 + { 83.139 + ex.printStackTrace(); 83.140 + return -1; 83.141 + } 83.142 + } 83.143 + 83.144 + public void mailPosted(String groupname) 83.145 + { 83.146 + addEvent(POSTED_NEWS, groupname); 83.147 + } 83.148 + 83.149 + public void mailGatewayed(String groupname) 83.150 + { 83.151 + addEvent(GATEWAYED_NEWS, groupname); 83.152 + } 83.153 + 83.154 + public void mailFeeded(String groupname) 83.155 + { 83.156 + addEvent(FEEDED_NEWS, groupname); 83.157 + } 83.158 + 83.159 + public void mlgwRunStart() 83.160 + { 83.161 + addEvent(MLGW_RUNSTART, "control"); 83.162 + } 83.163 + 83.164 + public void mlgwRunEnd() 83.165 + { 83.166 + addEvent(MLGW_RUNEND, "control"); 83.167 + } 83.168 + 83.169 + private double perHour(int key, long gid) 83.170 + { 83.171 + try 83.172 + { 83.173 + return Database.getInstance().getNumberOfEventsPerHour(key, gid); 83.174 + } 83.175 + catch(SQLException ex) 83.176 + { 83.177 + ex.printStackTrace(); 83.178 + return -1; 83.179 + } 83.180 + } 83.181 + 83.182 + public double postedPerHour(long gid) 83.183 + { 83.184 + return perHour(POSTED_NEWS, gid); 83.185 + } 83.186 + 83.187 + public double gatewayedPerHour(long gid) 83.188 + { 83.189 + return perHour(GATEWAYED_NEWS, gid); 83.190 + } 83.191 + 83.192 + public double feededPerHour(long gid) 83.193 + { 83.194 + return perHour(FEEDED_NEWS, gid); 83.195 + } 83.196 + 83.197 +}
84.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 84.2 +++ b/org/sonews/util/StringTemplate.java Fri Jun 26 16:48:50 2009 +0200 84.3 @@ -0,0 +1,97 @@ 84.4 +/* 84.5 + * SONEWS News Server 84.6 + * see AUTHORS for the list of contributors 84.7 + * 84.8 + * This program is free software: you can redistribute it and/or modify 84.9 + * it under the terms of the GNU General Public License as published by 84.10 + * the Free Software Foundation, either version 3 of the License, or 84.11 + * (at your option) any later version. 84.12 + * 84.13 + * This program is distributed in the hope that it will be useful, 84.14 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 84.15 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 84.16 + * GNU General Public License for more details. 84.17 + * 84.18 + * You should have received a copy of the GNU General Public License 84.19 + * along with this program. If not, see <http://www.gnu.org/licenses/>. 84.20 + */ 84.21 + 84.22 +package org.sonews.util; 84.23 + 84.24 +import java.util.HashMap; 84.25 +import java.util.Map; 84.26 + 84.27 +/** 84.28 + * Class that allows simple String template handling. 84.29 + * @author Christian Lins 84.30 + * @since sonews/0.5.0 84.31 + */ 84.32 +public class StringTemplate 84.33 +{ 84.34 + 84.35 + private String str = null; 84.36 + private String templateDelimiter = "%"; 84.37 + private Map<String, String> templateValues = new HashMap<String, String>(); 84.38 + 84.39 + public StringTemplate(String str, final String templateDelimiter) 84.40 + { 84.41 + if(str == null || templateDelimiter == null) 84.42 + { 84.43 + throw new IllegalArgumentException("null arguments not allowed"); 84.44 + } 84.45 + 84.46 + this.str = str; 84.47 + this.templateDelimiter = templateDelimiter; 84.48 + } 84.49 + 84.50 + public StringTemplate(String str) 84.51 + { 84.52 + this(str, "%"); 84.53 + } 84.54 + 84.55 + public StringTemplate set(String template, String value) 84.56 + { 84.57 + if(template == null || value == null) 84.58 + { 84.59 + throw new IllegalArgumentException("null arguments not allowed"); 84.60 + } 84.61 + 84.62 + this.templateValues.put(template, value); 84.63 + return this; 84.64 + } 84.65 + 84.66 + public StringTemplate set(String template, long value) 84.67 + { 84.68 + return set(template, Long.toString(value)); 84.69 + } 84.70 + 84.71 + public StringTemplate set(String template, double value) 84.72 + { 84.73 + return set(template, Double.toString(value)); 84.74 + } 84.75 + 84.76 + public StringTemplate set(String template, Object obj) 84.77 + { 84.78 + if(template == null || obj == null) 84.79 + { 84.80 + throw new IllegalArgumentException("null arguments not allowed"); 84.81 + } 84.82 + 84.83 + return set(template, obj.toString()); 84.84 + } 84.85 + 84.86 + @Override 84.87 + public String toString() 84.88 + { 84.89 + String ret = str; 84.90 + 84.91 + for(String key : this.templateValues.keySet()) 84.92 + { 84.93 + String value = this.templateValues.get(key); 84.94 + ret = ret.replace(templateDelimiter + key, value); 84.95 + } 84.96 + 84.97 + return ret; 84.98 + } 84.99 + 84.100 +}
85.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 85.2 +++ b/org/sonews/util/TimeoutMap.java Fri Jun 26 16:48:50 2009 +0200 85.3 @@ -0,0 +1,145 @@ 85.4 +/* 85.5 + * SONEWS News Server 85.6 + * see AUTHORS for the list of contributors 85.7 + * 85.8 + * This program is free software: you can redistribute it and/or modify 85.9 + * it under the terms of the GNU General Public License as published by 85.10 + * the Free Software Foundation, either version 3 of the License, or 85.11 + * (at your option) any later version. 85.12 + * 85.13 + * This program is distributed in the hope that it will be useful, 85.14 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 85.15 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 85.16 + * GNU General Public License for more details. 85.17 + * 85.18 + * You should have received a copy of the GNU General Public License 85.19 + * along with this program. If not, see <http://www.gnu.org/licenses/>. 85.20 + */ 85.21 + 85.22 +package org.sonews.util; 85.23 + 85.24 +import java.util.HashMap; 85.25 +import java.util.HashSet; 85.26 +import java.util.Map; 85.27 +import java.util.Set; 85.28 +import java.util.concurrent.ConcurrentHashMap; 85.29 + 85.30 +/** 85.31 + * Implementation of a Map that will loose its stored values after a 85.32 + * configurable amount of time. 85.33 + * This class may be used to cache config values for example. 85.34 + * @author Christian Lins 85.35 + * @since sonews/0.5.0 85.36 + */ 85.37 +public class TimeoutMap<K,V> extends ConcurrentHashMap<K, V> 85.38 +{ 85.39 + 85.40 + private static final long serialVersionUID = 453453467700345L; 85.41 + 85.42 + private int timeout = 60000; // 60 sec 85.43 + private transient Map<K, Long> timeoutMap = new HashMap<K, Long>(); 85.44 + 85.45 + /** 85.46 + * Constructor. 85.47 + * @param timeout Timeout in milliseconds 85.48 + */ 85.49 + public TimeoutMap(final int timeout) 85.50 + { 85.51 + this.timeout = timeout; 85.52 + } 85.53 + 85.54 + /** 85.55 + * Uses default timeout (60 sec). 85.56 + */ 85.57 + public TimeoutMap() 85.58 + { 85.59 + } 85.60 + 85.61 + /** 85.62 + * 85.63 + * @param key 85.64 + * @return true if key is still valid. 85.65 + */ 85.66 + protected boolean checkTimeOut(Object key) 85.67 + { 85.68 + synchronized(this.timeoutMap) 85.69 + { 85.70 + if(this.timeoutMap.containsKey(key)) 85.71 + { 85.72 + long keytime = this.timeoutMap.get(key); 85.73 + if((System.currentTimeMillis() - keytime) < this.timeout) 85.74 + { 85.75 + return true; 85.76 + } 85.77 + else 85.78 + { 85.79 + remove(key); 85.80 + return false; 85.81 + } 85.82 + } 85.83 + else 85.84 + { 85.85 + return false; 85.86 + } 85.87 + } 85.88 + } 85.89 + 85.90 + @Override 85.91 + public boolean containsKey(Object key) 85.92 + { 85.93 + return checkTimeOut(key); 85.94 + } 85.95 + 85.96 + @Override 85.97 + public synchronized V get(Object key) 85.98 + { 85.99 + if(checkTimeOut(key)) 85.100 + { 85.101 + return super.get(key); 85.102 + } 85.103 + else 85.104 + { 85.105 + return null; 85.106 + } 85.107 + } 85.108 + 85.109 + @Override 85.110 + public V put(K key, V value) 85.111 + { 85.112 + synchronized(this.timeoutMap) 85.113 + { 85.114 + removeStaleKeys(); 85.115 + this.timeoutMap.put(key, System.currentTimeMillis()); 85.116 + return super.put(key, value); 85.117 + } 85.118 + } 85.119 + 85.120 + /** 85.121 + * @param arg0 85.122 + * @return 85.123 + */ 85.124 + @Override 85.125 + public V remove(Object arg0) 85.126 + { 85.127 + synchronized(this.timeoutMap) 85.128 + { 85.129 + this.timeoutMap.remove(arg0); 85.130 + V val = super.remove(arg0); 85.131 + return val; 85.132 + } 85.133 + } 85.134 + 85.135 + protected void removeStaleKeys() 85.136 + { 85.137 + synchronized(this.timeoutMap) 85.138 + { 85.139 + Set<Object> keySet = new HashSet<Object>(this.timeoutMap.keySet()); 85.140 + for(Object key : keySet) 85.141 + { 85.142 + // The key/value is removed by the checkTimeOut() method if true 85.143 + checkTimeOut(key); 85.144 + } 85.145 + } 85.146 + } 85.147 + 85.148 +}
86.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 86.2 +++ b/org/sonews/util/io/ArticleInputStream.java Fri Jun 26 16:48:50 2009 +0200 86.3 @@ -0,0 +1,61 @@ 86.4 +/* 86.5 + * SONEWS News Server 86.6 + * see AUTHORS for the list of contributors 86.7 + * 86.8 + * This program is free software: you can redistribute it and/or modify 86.9 + * it under the terms of the GNU General Public License as published by 86.10 + * the Free Software Foundation, either version 3 of the License, or 86.11 + * (at your option) any later version. 86.12 + * 86.13 + * This program is distributed in the hope that it will be useful, 86.14 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 86.15 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 86.16 + * GNU General Public License for more details. 86.17 + * 86.18 + * You should have received a copy of the GNU General Public License 86.19 + * along with this program. If not, see <http://www.gnu.org/licenses/>. 86.20 + */ 86.21 + 86.22 +package org.sonews.util.io; 86.23 + 86.24 +import java.io.ByteArrayOutputStream; 86.25 +import java.io.IOException; 86.26 +import org.sonews.daemon.storage.*; 86.27 +import java.io.InputStream; 86.28 +import java.io.UnsupportedEncodingException; 86.29 + 86.30 +/** 86.31 + * Capsulates an Article to provide a raw InputStream. 86.32 + * @author Christian Lins 86.33 + * @since sonews/0.5.0 86.34 + */ 86.35 +public class ArticleInputStream extends InputStream 86.36 +{ 86.37 + 86.38 + private byte[] buffer; 86.39 + private int offset = 0; 86.40 + 86.41 + public ArticleInputStream(final Article art) 86.42 + throws IOException, UnsupportedEncodingException 86.43 + { 86.44 + final ByteArrayOutputStream out = new ByteArrayOutputStream(); 86.45 + out.write(art.getHeaderSource().getBytes("UTF-8")); 86.46 + out.write("\r\n\r\n".getBytes()); 86.47 + out.write(art.getBody().getBytes(art.getBodyCharset())); 86.48 + out.flush(); 86.49 + this.buffer = out.toByteArray(); 86.50 + } 86.51 + 86.52 + public int read() 86.53 + { 86.54 + if(offset >= buffer.length) 86.55 + { 86.56 + return -1; 86.57 + } 86.58 + else 86.59 + { 86.60 + return buffer[offset++]; 86.61 + } 86.62 + } 86.63 + 86.64 +}
87.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 87.2 +++ b/org/sonews/util/io/ArticleReader.java Fri Jun 26 16:48:50 2009 +0200 87.3 @@ -0,0 +1,127 @@ 87.4 +/* 87.5 + * SONEWS News Server 87.6 + * see AUTHORS for the list of contributors 87.7 + * 87.8 + * This program is free software: you can redistribute it and/or modify 87.9 + * it under the terms of the GNU General Public License as published by 87.10 + * the Free Software Foundation, either version 3 of the License, or 87.11 + * (at your option) any later version. 87.12 + * 87.13 + * This program is distributed in the hope that it will be useful, 87.14 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 87.15 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 87.16 + * GNU General Public License for more details. 87.17 + * 87.18 + * You should have received a copy of the GNU General Public License 87.19 + * along with this program. If not, see <http://www.gnu.org/licenses/>. 87.20 + */ 87.21 + 87.22 +package org.sonews.util.io; 87.23 + 87.24 +import java.io.BufferedInputStream; 87.25 +import java.io.BufferedOutputStream; 87.26 +import java.io.ByteArrayOutputStream; 87.27 +import java.io.IOException; 87.28 +import java.io.InputStream; 87.29 +import java.io.UnsupportedEncodingException; 87.30 +import java.net.Socket; 87.31 +import java.net.UnknownHostException; 87.32 +import org.sonews.util.Log; 87.33 + 87.34 +/** 87.35 + * Reads an news article from a NNTP server. 87.36 + * @author Christian Lins 87.37 + * @since sonews/0.5.0 87.38 + */ 87.39 +public class ArticleReader 87.40 +{ 87.41 + 87.42 + private BufferedOutputStream out; 87.43 + private BufferedInputStream in; 87.44 + private String messageID; 87.45 + 87.46 + public ArticleReader(String host, int port, String messageID) 87.47 + throws IOException, UnknownHostException 87.48 + { 87.49 + this.messageID = messageID; 87.50 + 87.51 + // Connect to NNTP server 87.52 + Socket socket = new Socket(host, port); 87.53 + this.out = new BufferedOutputStream(socket.getOutputStream()); 87.54 + this.in = new BufferedInputStream(socket.getInputStream()); 87.55 + String line = readln(this.in); 87.56 + if(!line.startsWith("200 ")) 87.57 + { 87.58 + throw new IOException("Invalid hello from server: " + line); 87.59 + } 87.60 + } 87.61 + 87.62 + private boolean eofArticle(byte[] buf) 87.63 + { 87.64 + if(buf.length < 4) 87.65 + { 87.66 + return false; 87.67 + } 87.68 + 87.69 + int l = buf.length - 1; 87.70 + return buf[l-3] == 10 // '*\n' 87.71 + && buf[l-2] == '.' // '.' 87.72 + && buf[l-1] == 13 && buf[l] == 10; // '\r\n' 87.73 + } 87.74 + 87.75 + public byte[] getArticleData() 87.76 + throws IOException, UnsupportedEncodingException 87.77 + { 87.78 + try 87.79 + { 87.80 + this.out.write(("ARTICLE " + this.messageID + "\r\n").getBytes("UTF-8")); 87.81 + this.out.flush(); 87.82 + 87.83 + String line = readln(this.in); 87.84 + if(line.startsWith("220 ")) 87.85 + { 87.86 + ByteArrayOutputStream buf = new ByteArrayOutputStream(); 87.87 + 87.88 + while(!eofArticle(buf.toByteArray())) 87.89 + { 87.90 + for(int b = in.read(); b != 10; b = in.read()) 87.91 + { 87.92 + buf.write(b); 87.93 + } 87.94 + 87.95 + buf.write(10); 87.96 + } 87.97 + 87.98 + return buf.toByteArray(); 87.99 + } 87.100 + else 87.101 + { 87.102 + Log.msg("ArticleReader: " + line, false); 87.103 + return null; 87.104 + } 87.105 + } 87.106 + catch(IOException ex) 87.107 + { 87.108 + throw ex; 87.109 + } 87.110 + finally 87.111 + { 87.112 + this.out.write("QUIT\r\n".getBytes("UTF-8")); 87.113 + this.out.flush(); 87.114 + this.out.close(); 87.115 + } 87.116 + } 87.117 + 87.118 + private String readln(InputStream in) 87.119 + throws IOException 87.120 + { 87.121 + ByteArrayOutputStream buf = new ByteArrayOutputStream(); 87.122 + for(int b = in.read(); b != 10 /* \n */; b = in.read()) 87.123 + { 87.124 + buf.write(b); 87.125 + } 87.126 + 87.127 + return new String(buf.toByteArray()); 87.128 + } 87.129 + 87.130 +}
88.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 88.2 +++ b/org/sonews/util/io/ArticleWriter.java Fri Jun 26 16:48:50 2009 +0200 88.3 @@ -0,0 +1,133 @@ 88.4 +/* 88.5 + * SONEWS News Server 88.6 + * see AUTHORS for the list of contributors 88.7 + * 88.8 + * This program is free software: you can redistribute it and/or modify 88.9 + * it under the terms of the GNU General Public License as published by 88.10 + * the Free Software Foundation, either version 3 of the License, or 88.11 + * (at your option) any later version. 88.12 + * 88.13 + * This program is distributed in the hope that it will be useful, 88.14 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 88.15 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 88.16 + * GNU General Public License for more details. 88.17 + * 88.18 + * You should have received a copy of the GNU General Public License 88.19 + * along with this program. If not, see <http://www.gnu.org/licenses/>. 88.20 + */ 88.21 + 88.22 +package org.sonews.util.io; 88.23 + 88.24 +import java.io.BufferedOutputStream; 88.25 +import java.io.BufferedReader; 88.26 +import java.io.IOException; 88.27 +import java.io.InputStreamReader; 88.28 +import java.io.UnsupportedEncodingException; 88.29 +import java.net.Socket; 88.30 +import java.net.UnknownHostException; 88.31 +import org.sonews.daemon.storage.Article; 88.32 + 88.33 +/** 88.34 + * Posts an Article to a NNTP server using the POST command. 88.35 + * @author Christian Lins 88.36 + * @since sonews/0.5.0 88.37 + */ 88.38 +public class ArticleWriter 88.39 +{ 88.40 + 88.41 + private BufferedOutputStream out; 88.42 + private BufferedReader inr; 88.43 + 88.44 + public ArticleWriter(String host, int port) 88.45 + throws IOException, UnknownHostException 88.46 + { 88.47 + // Connect to NNTP server 88.48 + Socket socket = new Socket(host, port); 88.49 + this.out = new BufferedOutputStream(socket.getOutputStream()); 88.50 + this.inr = new BufferedReader(new InputStreamReader(socket.getInputStream())); 88.51 + String line = inr.readLine(); 88.52 + if(line == null || !line.startsWith("200 ")) 88.53 + { 88.54 + throw new IOException("Invalid hello from server: " + line); 88.55 + } 88.56 + } 88.57 + 88.58 + public void close() 88.59 + throws IOException, UnsupportedEncodingException 88.60 + { 88.61 + this.out.write("QUIT\r\n".getBytes("UTF-8")); 88.62 + this.out.flush(); 88.63 + } 88.64 + 88.65 + protected void finishPOST() 88.66 + throws IOException 88.67 + { 88.68 + this.out.write("\r\n.\r\n".getBytes()); 88.69 + this.out.flush(); 88.70 + String line = inr.readLine(); 88.71 + if(line == null || !line.startsWith("240 ")) 88.72 + { 88.73 + throw new IOException(line); 88.74 + } 88.75 + } 88.76 + 88.77 + protected void preparePOST() 88.78 + throws IOException 88.79 + { 88.80 + this.out.write("POST\r\n".getBytes("UTF-8")); 88.81 + this.out.flush(); 88.82 + 88.83 + String line = this.inr.readLine(); 88.84 + if(line == null || !line.startsWith("340 ")) 88.85 + { 88.86 + throw new IOException(line); 88.87 + } 88.88 + } 88.89 + 88.90 + public void writeArticle(Article article) 88.91 + throws IOException, UnsupportedEncodingException 88.92 + { 88.93 + byte[] buf = new byte[512]; 88.94 + ArticleInputStream in = new ArticleInputStream(article); 88.95 + 88.96 + preparePOST(); 88.97 + 88.98 + int len = in.read(buf); 88.99 + while(len != -1) 88.100 + { 88.101 + writeLine(buf, len); 88.102 + len = in.read(buf); 88.103 + } 88.104 + 88.105 + finishPOST(); 88.106 + } 88.107 + 88.108 + /** 88.109 + * Writes the raw content of an article to the remote server. This method 88.110 + * does no charset conversion/handling of any kind so its the preferred 88.111 + * method for sending an article to remote peers. 88.112 + * @param rawArticle 88.113 + * @throws IOException 88.114 + */ 88.115 + public void writeArticle(byte[] rawArticle) 88.116 + throws IOException 88.117 + { 88.118 + preparePOST(); 88.119 + writeLine(rawArticle, rawArticle.length); 88.120 + finishPOST(); 88.121 + } 88.122 + 88.123 + /** 88.124 + * Writes the given buffer to the connect remote server. 88.125 + * @param buffer 88.126 + * @param len 88.127 + * @throws IOException 88.128 + */ 88.129 + protected void writeLine(byte[] buffer, int len) 88.130 + throws IOException 88.131 + { 88.132 + this.out.write(buffer, 0, len); 88.133 + this.out.flush(); 88.134 + } 88.135 + 88.136 +}
89.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 89.2 +++ b/org/sonews/util/io/Resource.java Fri Jun 26 16:48:50 2009 +0200 89.3 @@ -0,0 +1,132 @@ 89.4 +/* 89.5 + * SONEWS News Server 89.6 + * see AUTHORS for the list of contributors 89.7 + * 89.8 + * This program is free software: you can redistribute it and/or modify 89.9 + * it under the terms of the GNU General Public License as published by 89.10 + * the Free Software Foundation, either version 3 of the License, or 89.11 + * (at your option) any later version. 89.12 + * 89.13 + * This program is distributed in the hope that it will be useful, 89.14 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 89.15 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 89.16 + * GNU General Public License for more details. 89.17 + * 89.18 + * You should have received a copy of the GNU General Public License 89.19 + * along with this program. If not, see <http://www.gnu.org/licenses/>. 89.20 + */ 89.21 + 89.22 +package org.sonews.util.io; 89.23 + 89.24 +import java.io.BufferedReader; 89.25 +import java.io.IOException; 89.26 +import java.io.InputStream; 89.27 +import java.io.InputStreamReader; 89.28 +import java.net.URL; 89.29 +import java.nio.charset.Charset; 89.30 + 89.31 +/** 89.32 + * Provides method for loading of resources. 89.33 + * @author Christian Lins 89.34 + * @since sonews/0.5.0 89.35 + */ 89.36 +public final class Resource 89.37 +{ 89.38 + 89.39 + /** 89.40 + * Loads a resource and returns it as URL reference. 89.41 + * The Resource's classloader is used to load the resource, not 89.42 + * the System's ClassLoader so it may be safe to use this method 89.43 + * in a sandboxed environment. 89.44 + * @return 89.45 + */ 89.46 + public static URL getAsURL(final String name) 89.47 + { 89.48 + if(name == null) 89.49 + { 89.50 + return null; 89.51 + } 89.52 + 89.53 + return Resource.class.getClassLoader().getResource(name); 89.54 + } 89.55 + 89.56 + /** 89.57 + * Loads a resource and returns an InputStream to it. 89.58 + * @param name 89.59 + * @return 89.60 + */ 89.61 + public static InputStream getAsStream(String name) 89.62 + { 89.63 + try 89.64 + { 89.65 + URL url = getAsURL(name); 89.66 + if(url == null) 89.67 + { 89.68 + return null; 89.69 + } 89.70 + else 89.71 + { 89.72 + return url.openStream(); 89.73 + } 89.74 + } 89.75 + catch(IOException e) 89.76 + { 89.77 + e.printStackTrace(); 89.78 + return null; 89.79 + } 89.80 + } 89.81 + 89.82 + /** 89.83 + * Loads a plain text resource. 89.84 + * @param withNewline If false all newlines are removed from the 89.85 + * return String 89.86 + */ 89.87 + public static String getAsString(String name, boolean withNewline) 89.88 + { 89.89 + if(name == null) 89.90 + return null; 89.91 + 89.92 + BufferedReader in = null; 89.93 + try 89.94 + { 89.95 + InputStream ins = getAsStream(name); 89.96 + if(ins == null) 89.97 + return null; 89.98 + 89.99 + in = new BufferedReader( 89.100 + new InputStreamReader(ins, Charset.forName("UTF-8"))); 89.101 + StringBuffer buf = new StringBuffer(); 89.102 + 89.103 + for(;;) 89.104 + { 89.105 + String line = in.readLine(); 89.106 + if(line == null) 89.107 + break; 89.108 + 89.109 + buf.append(line); 89.110 + if(withNewline) 89.111 + buf.append('\n'); 89.112 + } 89.113 + 89.114 + return buf.toString(); 89.115 + } 89.116 + catch(Exception e) 89.117 + { 89.118 + e.printStackTrace(); 89.119 + return null; 89.120 + } 89.121 + finally 89.122 + { 89.123 + try 89.124 + { 89.125 + if(in != null) 89.126 + in.close(); 89.127 + } 89.128 + catch(IOException ex) 89.129 + { 89.130 + ex.printStackTrace(); 89.131 + } 89.132 + } 89.133 + } 89.134 + 89.135 +}
90.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 90.2 +++ b/org/sonews/util/io/VarCharsetReader.java Fri Jun 26 16:48:50 2009 +0200 90.3 @@ -0,0 +1,90 @@ 90.4 +/* 90.5 + * SONEWS News Server 90.6 + * see AUTHORS for the list of contributors 90.7 + * 90.8 + * This program is free software: you can redistribute it and/or modify 90.9 + * it under the terms of the GNU General Public License as published by 90.10 + * the Free Software Foundation, either version 3 of the License, or 90.11 + * (at your option) any later version. 90.12 + * 90.13 + * This program is distributed in the hope that it will be useful, 90.14 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 90.15 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 90.16 + * GNU General Public License for more details. 90.17 + * 90.18 + * You should have received a copy of the GNU General Public License 90.19 + * along with this program. If not, see <http://www.gnu.org/licenses/>. 90.20 + */ 90.21 + 90.22 +package org.sonews.util.io; 90.23 + 90.24 +import java.io.IOException; 90.25 +import java.io.InputStream; 90.26 +import java.nio.ByteBuffer; 90.27 +import java.nio.charset.Charset; 90.28 + 90.29 +/** 90.30 + * InputStream that can change its decoding charset while reading from the 90.31 + * underlying byte based stream. 90.32 + * @author Christian Lins 90.33 + * @since sonews/0.5.0 90.34 + */ 90.35 +public class VarCharsetReader 90.36 +{ 90.37 + 90.38 + private final ByteBuffer buf = ByteBuffer.allocate(4096); 90.39 + private InputStream in; 90.40 + 90.41 + public VarCharsetReader(final InputStream in) 90.42 + { 90.43 + if(in == null) 90.44 + { 90.45 + throw new IllegalArgumentException("null InputStream"); 90.46 + } 90.47 + this.in = in; 90.48 + } 90.49 + 90.50 + /** 90.51 + * Reads up to the next newline character and returns the line as String. 90.52 + * The String is decoded using the given charset. 90.53 + */ 90.54 + public String readLine(Charset charset) 90.55 + throws IOException 90.56 + { 90.57 + byte[] byteBuf = new byte[1]; 90.58 + String bufStr; 90.59 + 90.60 + for(;;) 90.61 + { 90.62 + int read = this.in.read(byteBuf); 90.63 + if(read == 0) 90.64 + { 90.65 + continue; 90.66 + } 90.67 + else if(read == -1) 90.68 + { 90.69 + this.in = null; 90.70 + bufStr = new String(this.buf.array(), 0, this.buf.position(), charset); 90.71 + break; 90.72 + } 90.73 + else if(byteBuf[0] == 10) // Is this safe? \n 90.74 + { 90.75 + bufStr = new String(this.buf.array(), 0, this.buf.position(), charset); 90.76 + break; 90.77 + } 90.78 + else if(byteBuf[0] == 13) // \r 90.79 + { // Skip 90.80 + continue; 90.81 + } 90.82 + else 90.83 + { 90.84 + this.buf.put(byteBuf[0]); 90.85 + } 90.86 + } 90.87 + 90.88 + this.buf.clear(); 90.89 + 90.90 + return bufStr; 90.91 + } 90.92 + 90.93 +}
91.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 91.2 +++ b/org/sonews/util/io/package.html Fri Jun 26 16:48:50 2009 +0200 91.3 @@ -0,0 +1,1 @@ 91.4 +Contains I/O utilitiy classes. 91.5 \ No newline at end of file
92.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 92.2 +++ b/org/sonews/util/package.html Fri Jun 26 16:48:50 2009 +0200 92.3 @@ -0,0 +1,1 @@ 92.4 +Contains various utility classes. 92.5 \ No newline at end of file
93.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 93.2 +++ b/org/sonews/web/AbstractSonewsServlet.java Fri Jun 26 16:48:50 2009 +0200 93.3 @@ -0,0 +1,113 @@ 93.4 +/* 93.5 + * SONEWS News Server 93.6 + * see AUTHORS for the list of contributors 93.7 + * 93.8 + * This program is free software: you can redistribute it and/or modify 93.9 + * it under the terms of the GNU General Public License as published by 93.10 + * the Free Software Foundation, either version 3 of the License, or 93.11 + * (at your option) any later version. 93.12 + * 93.13 + * This program is distributed in the hope that it will be useful, 93.14 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 93.15 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 93.16 + * GNU General Public License for more details. 93.17 + * 93.18 + * You should have received a copy of the GNU General Public License 93.19 + * along with this program. If not, see <http://www.gnu.org/licenses/>. 93.20 + */ 93.21 + 93.22 +package org.sonews.web; 93.23 + 93.24 +import java.io.BufferedReader; 93.25 +import java.io.IOException; 93.26 +import java.io.InputStreamReader; 93.27 +import java.io.PrintWriter; 93.28 +import java.net.Socket; 93.29 +import javax.servlet.http.HttpServlet; 93.30 +import org.sonews.util.StringTemplate; 93.31 +import org.sonews.util.io.Resource; 93.32 + 93.33 +/** 93.34 + * Base class for all sonews servlets. 93.35 + * @author Christian Lins 93.36 + * @since sonews/0.5.0 93.37 + */ 93.38 +public class AbstractSonewsServlet extends HttpServlet 93.39 +{ 93.40 + 93.41 + public static final String TemplateRoot = "org/sonews/web/tmpl/"; 93.42 + 93.43 + protected String hello = null; 93.44 + 93.45 + private BufferedReader in = null; 93.46 + private PrintWriter out = null; 93.47 + private Socket socket = null; 93.48 + 93.49 + protected void connectToNewsserver() 93.50 + throws IOException 93.51 + { 93.52 + // Get sonews port from properties 93.53 + String port = System.getProperty("sonews.port", "9119"); 93.54 + String host = System.getProperty("sonews.host", "localhost"); 93.55 + 93.56 + try 93.57 + { 93.58 + this.socket = new Socket(host, Integer.parseInt(port)); 93.59 + 93.60 + this.in = new BufferedReader( 93.61 + new InputStreamReader(socket.getInputStream())); 93.62 + this.out = new PrintWriter(socket.getOutputStream()); 93.63 + 93.64 + hello = in.readLine(); // Read hello message 93.65 + } 93.66 + catch(IOException ex) 93.67 + { 93.68 + System.out.println("sonews.host=" + host); 93.69 + System.out.println("sonews.port=" + port); 93.70 + System.out.flush(); 93.71 + throw ex; 93.72 + } 93.73 + } 93.74 + 93.75 + protected void disconnectFromNewsserver() 93.76 + { 93.77 + try 93.78 + { 93.79 + printlnToNewsserver("QUIT"); 93.80 + out.close(); 93.81 + readlnFromNewsserver(); // Wait for bye message 93.82 + in.close(); 93.83 + socket.close(); 93.84 + } 93.85 + catch(IOException ex) 93.86 + { 93.87 + ex.printStackTrace(); 93.88 + } 93.89 + } 93.90 + 93.91 + protected StringTemplate getTemplate(String res) 93.92 + { 93.93 + StringTemplate tmpl = new StringTemplate( 93.94 + Resource.getAsString(TemplateRoot + "AbstractSonewsServlet.tmpl", true)); 93.95 + String content = Resource.getAsString(TemplateRoot + res, true); 93.96 + String stylesheet = System.getProperty("sonews.web.stylesheet", "style.css"); 93.97 + 93.98 + tmpl.set("CONTENT", content); 93.99 + tmpl.set("STYLESHEET", stylesheet); 93.100 + 93.101 + return new StringTemplate(tmpl.toString()); 93.102 + } 93.103 + 93.104 + protected void printlnToNewsserver(final String line) 93.105 + { 93.106 + this.out.println(line); 93.107 + this.out.flush(); 93.108 + } 93.109 + 93.110 + protected String readlnFromNewsserver() 93.111 + throws IOException 93.112 + { 93.113 + return this.in.readLine(); 93.114 + } 93.115 + 93.116 +}
94.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 94.2 +++ b/org/sonews/web/MemoryBitmapChart.java Fri Jun 26 16:48:50 2009 +0200 94.3 @@ -0,0 +1,61 @@ 94.4 +/* 94.5 + * SONEWS News Server 94.6 + * see AUTHORS for the list of contributors 94.7 + * 94.8 + * This program is free software: you can redistribute it and/or modify 94.9 + * it under the terms of the GNU General Public License as published by 94.10 + * the Free Software Foundation, either version 3 of the License, or 94.11 + * (at your option) any later version. 94.12 + * 94.13 + * This program is distributed in the hope that it will be useful, 94.14 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 94.15 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 94.16 + * GNU General Public License for more details. 94.17 + * 94.18 + * You should have received a copy of the GNU General Public License 94.19 + * along with this program. If not, see <http://www.gnu.org/licenses/>. 94.20 + */ 94.21 + 94.22 +package org.sonews.web; 94.23 + 94.24 +import info.monitorenter.gui.chart.Chart2D; 94.25 +import info.monitorenter.gui.chart.IAxis.AxisTitle; 94.26 +import java.awt.Color; 94.27 +import java.awt.image.BufferedImage; 94.28 +import java.io.ByteArrayOutputStream; 94.29 +import java.io.IOException; 94.30 +import javax.imageio.ImageIO; 94.31 + 94.32 +/** 94.33 + * A chart rendered to a memory bitmap. 94.34 + * @author Christian Lins 94.35 + * @since sonews/0.5.0 94.36 + */ 94.37 +class MemoryBitmapChart extends Chart2D 94.38 +{ 94.39 + 94.40 + public MemoryBitmapChart() 94.41 + { 94.42 + setGridColor(Color.LIGHT_GRAY); 94.43 + getAxisX().setPaintGrid(true); 94.44 + getAxisY().setPaintGrid(true); 94.45 + getAxisX().setAxisTitle(new AxisTitle("time of day")); 94.46 + getAxisY().setAxisTitle(new AxisTitle("processed news")); 94.47 + } 94.48 + 94.49 + public String getContentType() 94.50 + { 94.51 + return "image/png"; 94.52 + } 94.53 + 94.54 + public byte[] getRawData(final int width, final int height) 94.55 + throws IOException 94.56 + { 94.57 + setSize(width, height); 94.58 + BufferedImage img = snapShot(width, height); 94.59 + ByteArrayOutputStream out = new ByteArrayOutputStream(); 94.60 + ImageIO.write(img, "png", out); 94.61 + return out.toByteArray(); 94.62 + } 94.63 + 94.64 +}
95.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 95.2 +++ b/org/sonews/web/SonewsChartServlet.java Fri Jun 26 16:48:50 2009 +0200 95.3 @@ -0,0 +1,114 @@ 95.4 +/* 95.5 + * SONEWS News Server 95.6 + * see AUTHORS for the list of contributors 95.7 + * 95.8 + * This program is free software: you can redistribute it and/or modify 95.9 + * it under the terms of the GNU General Public License as published by 95.10 + * the Free Software Foundation, either version 3 of the License, or 95.11 + * (at your option) any later version. 95.12 + * 95.13 + * This program is distributed in the hope that it will be useful, 95.14 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 95.15 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 95.16 + * GNU General Public License for more details. 95.17 + * 95.18 + * You should have received a copy of the GNU General Public License 95.19 + * along with this program. If not, see <http://www.gnu.org/licenses/>. 95.20 + */ 95.21 + 95.22 +package org.sonews.web; 95.23 + 95.24 +import info.monitorenter.gui.chart.ITrace2D; 95.25 +import info.monitorenter.gui.chart.traces.Trace2DSimple; 95.26 +import java.io.IOException; 95.27 +import javax.servlet.http.HttpServletRequest; 95.28 +import javax.servlet.http.HttpServletResponse; 95.29 + 95.30 +/** 95.31 + * Servlet that creates chart images and returns them as raw PNG images. 95.32 + * @author Christian Lins 95.33 + * @since sonews/0.5.0 95.34 + */ 95.35 +public class SonewsChartServlet extends AbstractSonewsServlet 95.36 +{ 95.37 + 95.38 + private ITrace2D createProcessMails24(String title, String cmd) 95.39 + throws IOException 95.40 + { 95.41 + int[] data = read24Values(cmd); 95.42 + ITrace2D trace = new Trace2DSimple(title); 95.43 + trace.addPoint(0.0, 0.0); // Start 95.44 + 95.45 + for(int n = 0; n < 24; n++) 95.46 + { 95.47 + trace.addPoint(n, data[n]); 95.48 + } 95.49 + 95.50 + return trace; 95.51 + } 95.52 + 95.53 + @Override 95.54 + public void doGet(HttpServletRequest req, HttpServletResponse resp) 95.55 + throws IOException 95.56 + { 95.57 + synchronized(this) 95.58 + { 95.59 + MemoryBitmapChart chart = new MemoryBitmapChart(); 95.60 + 95.61 + String name = req.getParameter("name"); 95.62 + String group = req.getParameter("group"); 95.63 + ITrace2D trace; 95.64 + String cmd = "XDAEMON LOG"; 95.65 + 95.66 + if(name.equals("feedednewsyesterday")) 95.67 + { 95.68 + cmd = cmd + " TRANSMITTED_NEWS"; 95.69 + cmd = group != null ? cmd + " " + group : cmd; 95.70 + trace = createProcessMails24( 95.71 + "To peers transmitted mails yesterday", cmd); 95.72 + } 95.73 + else if(name.equals("gatewayednewsyesterday")) 95.74 + { 95.75 + cmd = cmd + " GATEWAYED_NEWS"; 95.76 + cmd = group != null ? cmd + " " + group : cmd; 95.77 + trace = createProcessMails24( 95.78 + "Gatewayed mails yesterday", cmd); 95.79 + } 95.80 + else 95.81 + { 95.82 + cmd = cmd + " POSTED_NEWS"; 95.83 + cmd = group != null ? cmd + " " + group : cmd; 95.84 + trace = createProcessMails24( 95.85 + "Posted mails yesterday", cmd); 95.86 + } 95.87 + chart.addTrace(trace); 95.88 + 95.89 + resp.getOutputStream().write(chart.getRawData(500, 400)); 95.90 + resp.setContentType(chart.getContentType()); 95.91 + resp.setStatus(HttpServletResponse.SC_OK); 95.92 + } 95.93 + } 95.94 + 95.95 + private int[] read24Values(String command) 95.96 + throws IOException 95.97 + { 95.98 + int[] values = new int[24]; 95.99 + connectToNewsserver(); 95.100 + printlnToNewsserver(command); 95.101 + String line = readlnFromNewsserver(); 95.102 + if(!line.startsWith("200 ")) 95.103 + throw new IOException(command + " not supported!"); 95.104 + 95.105 + for(int n = 0; n < 24; n++) 95.106 + { 95.107 + line = readlnFromNewsserver(); 95.108 + values[n] = Integer.parseInt(line.split(" ")[1]); 95.109 + } 95.110 + 95.111 + line = readlnFromNewsserver(); // "." 95.112 + 95.113 + disconnectFromNewsserver(); 95.114 + return values; 95.115 + } 95.116 + 95.117 +}
96.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 96.2 +++ b/org/sonews/web/SonewsConfigServlet.java Fri Jun 26 16:48:50 2009 +0200 96.3 @@ -0,0 +1,239 @@ 96.4 +/* 96.5 + * SONEWS News Server 96.6 + * see AUTHORS for the list of contributors 96.7 + * 96.8 + * This program is free software: you can redistribute it and/or modify 96.9 + * it under the terms of the GNU General Public License as published by 96.10 + * the Free Software Foundation, either version 3 of the License, or 96.11 + * (at your option) any later version. 96.12 + * 96.13 + * This program is distributed in the hope that it will be useful, 96.14 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 96.15 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 96.16 + * GNU General Public License for more details. 96.17 + * 96.18 + * You should have received a copy of the GNU General Public License 96.19 + * along with this program. If not, see <http://www.gnu.org/licenses/>. 96.20 + */ 96.21 + 96.22 +package org.sonews.web; 96.23 + 96.24 +import java.io.IOException; 96.25 +import java.util.ArrayList; 96.26 +import java.util.List; 96.27 +import java.util.Set; 96.28 +import javax.servlet.http.HttpServletRequest; 96.29 +import javax.servlet.http.HttpServletResponse; 96.30 +import org.sonews.util.StringTemplate; 96.31 +import org.sonews.util.io.Resource; 96.32 + 96.33 +/** 96.34 + * Servlet providing a configuration web interface. 96.35 + * @author Christian Lins 96.36 + * @since sonews/0.5.0 96.37 + */ 96.38 +public class SonewsConfigServlet extends AbstractSonewsServlet 96.39 +{ 96.40 + 96.41 + private static final long serialVersionUID = 2432543253L; 96.42 + 96.43 + @Override 96.44 + public void doGet(HttpServletRequest req, HttpServletResponse resp) 96.45 + throws IOException 96.46 + { 96.47 + synchronized(this) 96.48 + { 96.49 + connectToNewsserver(); 96.50 + String which = req.getParameter("which"); 96.51 + 96.52 + if(which != null && which.equals("config")) 96.53 + { 96.54 + whichConfig(req, resp); 96.55 + } 96.56 + else if(which != null && which.equals("groupadd")) 96.57 + { 96.58 + whichGroupAdd(req, resp); 96.59 + } 96.60 + else if(which != null && which.equals("groupdelete")) 96.61 + { 96.62 + whichGroupDelete(req, resp); 96.63 + } 96.64 + else 96.65 + { 96.66 + whichNone(req, resp); 96.67 + } 96.68 + 96.69 + disconnectFromNewsserver(); 96.70 + } 96.71 + } 96.72 + 96.73 + private void whichConfig(HttpServletRequest req, HttpServletResponse resp) 96.74 + throws IOException 96.75 + { 96.76 + StringBuilder keys = new StringBuilder(); 96.77 + 96.78 + Set pnames = req.getParameterMap().keySet(); 96.79 + for(Object obj : pnames) 96.80 + { 96.81 + String pname = (String)obj; 96.82 + if(pname.startsWith("configkey:")) 96.83 + { 96.84 + String value = req.getParameter(pname); 96.85 + String key = pname.split(":")[1]; 96.86 + if(!value.equals("<not set>")) 96.87 + { 96.88 + printlnToNewsserver("XDAEMON SET " + key + " " + value); 96.89 + readlnFromNewsserver(); 96.90 + 96.91 + keys.append(key); 96.92 + keys.append("<br/>"); 96.93 + } 96.94 + } 96.95 + } 96.96 + 96.97 + StringTemplate tmpl = getTemplate("ConfigUpdated.tmpl"); 96.98 + 96.99 + tmpl.set("UPDATED_KEYS", keys.toString()); 96.100 + 96.101 + resp.setStatus(HttpServletResponse.SC_OK); 96.102 + resp.getWriter().println(tmpl.toString()); 96.103 + resp.getWriter().flush(); 96.104 + } 96.105 + 96.106 + private void whichGroupAdd(HttpServletRequest req, HttpServletResponse resp) 96.107 + throws IOException 96.108 + { 96.109 + String[] groupnames = req.getParameter("groups").split("\n"); 96.110 + 96.111 + for(String groupname : groupnames) 96.112 + { 96.113 + groupname = groupname.trim(); 96.114 + if(groupname.equals("")) 96.115 + { 96.116 + continue; 96.117 + } 96.118 + 96.119 + printlnToNewsserver("XDAEMON GROUPADD " + groupname + " 0"); 96.120 + String line = readlnFromNewsserver(); 96.121 + if(!line.startsWith("200 ")) 96.122 + { 96.123 + System.out.println("Warning " + groupname + " probably not created!"); 96.124 + } 96.125 + } 96.126 + 96.127 + StringTemplate tmpl = getTemplate("GroupAdded.tmpl"); 96.128 + 96.129 + tmpl.set("GROUP", req.getParameter("groups")); 96.130 + 96.131 + resp.setStatus(HttpServletResponse.SC_OK); 96.132 + resp.getWriter().println(tmpl.toString()); 96.133 + resp.getWriter().flush(); 96.134 + } 96.135 + 96.136 + private void whichGroupDelete(HttpServletRequest req, HttpServletResponse resp) 96.137 + throws IOException 96.138 + { 96.139 + String groupname = req.getParameter("group"); 96.140 + printlnToNewsserver("XDAEMON GROUPDEL " + groupname); 96.141 + String line = readlnFromNewsserver(); 96.142 + if(!line.startsWith("200 ")) 96.143 + throw new IOException(line); 96.144 + 96.145 + StringTemplate tmpl = getTemplate("GroupDeleted.tmpl"); 96.146 + 96.147 + tmpl.set("GROUP", groupname); 96.148 + 96.149 + resp.setStatus(HttpServletResponse.SC_OK); 96.150 + resp.getWriter().println(tmpl.toString()); 96.151 + resp.getWriter().flush(); 96.152 + } 96.153 + 96.154 + private void whichNone(HttpServletRequest req, HttpServletResponse resp) 96.155 + throws IOException 96.156 + { 96.157 + StringTemplate tmpl = getTemplate("SonewsConfigServlet.tmpl"); 96.158 + 96.159 + // Retrieve config keys from server 96.160 + List<String> configKeys = new ArrayList<String>(); 96.161 + printlnToNewsserver("XDAEMON LIST CONFIGKEYS"); 96.162 + String line = readlnFromNewsserver(); 96.163 + if(!line.startsWith("200 ")) 96.164 + throw new IOException("XDAEMON command not supported!"); 96.165 + for(;;) 96.166 + { 96.167 + line = readlnFromNewsserver(); 96.168 + if(line.equals(".")) 96.169 + break; 96.170 + else 96.171 + configKeys.add(line); 96.172 + } 96.173 + 96.174 + // Construct config table 96.175 + StringBuilder strb = new StringBuilder(); 96.176 + for(String key : configKeys) 96.177 + { 96.178 + strb.append("<tr><td><code>"); 96.179 + strb.append(key); 96.180 + strb.append("</code></td><td>"); 96.181 + 96.182 + // Retrieve config value from server 96.183 + String value = "<not set>"; 96.184 + printlnToNewsserver("XDAEMON GET " + key); 96.185 + line = readlnFromNewsserver(); 96.186 + if(line.startsWith("200 ")) 96.187 + { 96.188 + value = readlnFromNewsserver(); 96.189 + readlnFromNewsserver(); // Read the "." 96.190 + } 96.191 + 96.192 + strb.append("<input type=text name=\"configkey:"); 96.193 + strb.append(key); 96.194 + strb.append("\" value=\""); 96.195 + strb.append(value); 96.196 + strb.append("\"/></td></tr>"); 96.197 + } 96.198 + tmpl.set("CONFIG", strb.toString()); 96.199 + 96.200 + // Retrieve served newsgroup names from server 96.201 + List<String> groups = new ArrayList<String>(); 96.202 + printlnToNewsserver("LIST"); 96.203 + line = readlnFromNewsserver(); 96.204 + if(line.startsWith("215 ")) 96.205 + { 96.206 + for(;;) 96.207 + { 96.208 + line = readlnFromNewsserver(); 96.209 + if(line.equals(".")) 96.210 + { 96.211 + break; 96.212 + } 96.213 + else 96.214 + { 96.215 + groups.add(line.split(" ")[0]); 96.216 + } 96.217 + } 96.218 + } 96.219 + else 96.220 + throw new IOException("Error issuing LIST command!"); 96.221 + 96.222 + // Construct groups list 96.223 + StringTemplate tmplGroupList = new StringTemplate( 96.224 + Resource.getAsString("org/sonews/web/tmpl/GroupList.tmpl", true)); 96.225 + strb = new StringBuilder(); 96.226 + for(String group : groups) 96.227 + { 96.228 + tmplGroupList.set("GROUPNAME", group); 96.229 + strb.append(tmplGroupList.toString()); 96.230 + } 96.231 + tmpl.set("GROUP", strb.toString()); 96.232 + 96.233 + // Set server name 96.234 + tmpl.set("SERVERNAME", hello.split(" ")[2]); 96.235 + tmpl.set("TITLE", "Configuration"); 96.236 + 96.237 + resp.getWriter().println(tmpl.toString()); 96.238 + resp.getWriter().flush(); 96.239 + resp.setStatus(HttpServletResponse.SC_OK); 96.240 + } 96.241 + 96.242 +}
97.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 97.2 +++ b/org/sonews/web/SonewsGroupServlet.java Fri Jun 26 16:48:50 2009 +0200 97.3 @@ -0,0 +1,66 @@ 97.4 +/* 97.5 + * SONEWS News Server 97.6 + * see AUTHORS for the list of contributors 97.7 + * 97.8 + * This program is free software: you can redistribute it and/or modify 97.9 + * it under the terms of the GNU General Public License as published by 97.10 + * the Free Software Foundation, either version 3 of the License, or 97.11 + * (at your option) any later version. 97.12 + * 97.13 + * This program is distributed in the hope that it will be useful, 97.14 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 97.15 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 97.16 + * GNU General Public License for more details. 97.17 + * 97.18 + * You should have received a copy of the GNU General Public License 97.19 + * along with this program. If not, see <http://www.gnu.org/licenses/>. 97.20 + */ 97.21 + 97.22 +package org.sonews.web; 97.23 + 97.24 +import java.io.IOException; 97.25 +import javax.servlet.http.HttpServletRequest; 97.26 +import javax.servlet.http.HttpServletResponse; 97.27 +import org.sonews.util.StringTemplate; 97.28 + 97.29 +/** 97.30 + * Views the group settings and allows editing. 97.31 + * @author Christian Lins 97.32 + * @since sonews/0.5.0 97.33 + */ 97.34 +public class SonewsGroupServlet extends AbstractSonewsServlet 97.35 +{ 97.36 + 97.37 + @Override 97.38 + public void doGet(HttpServletRequest req, HttpServletResponse resp) 97.39 + throws IOException 97.40 + { 97.41 + synchronized(this) 97.42 + { 97.43 + connectToNewsserver(); 97.44 + String name = req.getParameter("name"); 97.45 + String action = req.getParameter("action"); 97.46 + 97.47 + if("set_flags".equals(action)) 97.48 + { 97.49 + 97.50 + } 97.51 + else if("set_mladdress".equals(action)) 97.52 + { 97.53 + 97.54 + } 97.55 + 97.56 + StringTemplate tmpl = getTemplate("SonewsGroupServlet.tmpl"); 97.57 + tmpl.set("SERVERNAME", hello.split(" ")[2]); 97.58 + tmpl.set("TITLE", "Group " + name); 97.59 + tmpl.set("GROUPNAME", name); 97.60 + 97.61 + resp.getWriter().println(tmpl.toString()); 97.62 + resp.getWriter().flush(); 97.63 + resp.setStatus(HttpServletResponse.SC_OK); 97.64 + 97.65 + disconnectFromNewsserver(); 97.66 + } 97.67 + } 97.68 + 97.69 +}
98.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 98.2 +++ b/org/sonews/web/SonewsPeerServlet.java Fri Jun 26 16:48:50 2009 +0200 98.3 @@ -0,0 +1,95 @@ 98.4 +/* 98.5 + * SONEWS News Server 98.6 + * see AUTHORS for the list of contributors 98.7 + * 98.8 + * This program is free software: you can redistribute it and/or modify 98.9 + * it under the terms of the GNU General Public License as published by 98.10 + * the Free Software Foundation, either version 3 of the License, or 98.11 + * (at your option) any later version. 98.12 + * 98.13 + * This program is distributed in the hope that it will be useful, 98.14 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 98.15 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 98.16 + * GNU General Public License for more details. 98.17 + * 98.18 + * You should have received a copy of the GNU General Public License 98.19 + * along with this program. If not, see <http://www.gnu.org/licenses/>. 98.20 + */ 98.21 + 98.22 +package org.sonews.web; 98.23 + 98.24 +import java.io.IOException; 98.25 +import java.util.HashSet; 98.26 +import javax.servlet.http.HttpServletRequest; 98.27 +import javax.servlet.http.HttpServletResponse; 98.28 +import org.sonews.util.StringTemplate; 98.29 + 98.30 +/** 98.31 + * Servlet that shows the Peers and the Peering Rules. 98.32 + * @author Christian Lins 98.33 + * @since sonews/0.5.0 98.34 + */ 98.35 +public class SonewsPeerServlet extends AbstractSonewsServlet 98.36 +{ 98.37 + 98.38 + private static final long serialVersionUID = 245345346356L; 98.39 + 98.40 + @Override 98.41 + public void doGet(HttpServletRequest req, HttpServletResponse resp) 98.42 + throws IOException 98.43 + { 98.44 + synchronized(this) 98.45 + { 98.46 + connectToNewsserver(); 98.47 + StringTemplate tmpl = getTemplate("SonewsPeerServlet.tmpl"); 98.48 + 98.49 + // Read peering rules from newsserver 98.50 + printlnToNewsserver("XDAEMON LIST PEERINGRULES"); 98.51 + String line = readlnFromNewsserver(); 98.52 + if(!line.startsWith("200 ")) 98.53 + { 98.54 + throw new IOException("Unexpected reply: " + line); 98.55 + } 98.56 + 98.57 + // Create FEED_RULES String 98.58 + HashSet<String> peers = new HashSet<String>(); 98.59 + StringBuilder feedRulesStr = new StringBuilder(); 98.60 + for(;;) 98.61 + { 98.62 + line = readlnFromNewsserver(); 98.63 + if(line.equals(".")) 98.64 + { 98.65 + break; 98.66 + } 98.67 + else 98.68 + { 98.69 + feedRulesStr.append(line); 98.70 + feedRulesStr.append("<br/>"); 98.71 + 98.72 + String[] lineChunks = line.split(" "); 98.73 + peers.add(lineChunks[1]); 98.74 + } 98.75 + } 98.76 + 98.77 + // Create PEERS string 98.78 + StringBuilder peersStr = new StringBuilder(); 98.79 + for(String peer : peers) 98.80 + { 98.81 + peersStr.append(peer); 98.82 + peersStr.append("<br/>"); 98.83 + } 98.84 + 98.85 + // Set server name 98.86 + tmpl.set("PEERS", peersStr.toString()); 98.87 + tmpl.set("PEERING_RULES", feedRulesStr.toString()); 98.88 + tmpl.set("SERVERNAME", hello.split(" ")[2]); 98.89 + tmpl.set("TITLE", "Peers"); 98.90 + 98.91 + resp.getWriter().println(tmpl.toString()); 98.92 + resp.getWriter().flush(); 98.93 + resp.setStatus(HttpServletResponse.SC_OK); 98.94 + disconnectFromNewsserver(); 98.95 + } 98.96 + } 98.97 + 98.98 +}
99.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 99.2 +++ b/org/sonews/web/SonewsServlet.java Fri Jun 26 16:48:50 2009 +0200 99.3 @@ -0,0 +1,127 @@ 99.4 +/* 99.5 + * SONEWS News Server 99.6 + * see AUTHORS for the list of contributors 99.7 + * 99.8 + * This program is free software: you can redistribute it and/or modify 99.9 + * it under the terms of the GNU General Public License as published by 99.10 + * the Free Software Foundation, either version 3 of the License, or 99.11 + * (at your option) any later version. 99.12 + * 99.13 + * This program is distributed in the hope that it will be useful, 99.14 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 99.15 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 99.16 + * GNU General Public License for more details. 99.17 + * 99.18 + * You should have received a copy of the GNU General Public License 99.19 + * along with this program. If not, see <http://www.gnu.org/licenses/>. 99.20 + */ 99.21 + 99.22 +package org.sonews.web; 99.23 + 99.24 +import java.io.IOException; 99.25 +import javax.servlet.http.HttpServletRequest; 99.26 +import javax.servlet.http.HttpServletResponse; 99.27 +import org.sonews.daemon.Main; 99.28 +import org.sonews.util.StringTemplate; 99.29 + 99.30 +/** 99.31 + * Main sonews webpage servlet. 99.32 + * @author Christian Lins 99.33 + * @since sonews/0.5.0 99.34 + */ 99.35 +public class SonewsServlet extends AbstractSonewsServlet 99.36 +{ 99.37 + 99.38 + private static final long serialVersionUID = 2392837459834L; 99.39 + 99.40 + @Override 99.41 + public void doGet(HttpServletRequest res, HttpServletResponse resp) 99.42 + throws IOException 99.43 + { 99.44 + synchronized(this) 99.45 + { 99.46 + connectToNewsserver(); 99.47 + 99.48 + String line; 99.49 + int connectedClients = 0; 99.50 + int hostedGroups = 0; 99.51 + int hostedNews = 0; 99.52 + 99.53 + printlnToNewsserver("XDAEMON LOG CONNECTED_CLIENTS"); 99.54 + 99.55 + line = readlnFromNewsserver(); 99.56 + if(!line.startsWith("200 ")) 99.57 + { 99.58 + throw new IOException("XDAEMON command not allowed by server"); 99.59 + } 99.60 + line = readlnFromNewsserver(); 99.61 + connectedClients = Integer.parseInt(line); 99.62 + line = readlnFromNewsserver(); // Read the "." 99.63 + 99.64 + printlnToNewsserver("XDAEMON LOG HOSTED_NEWS"); 99.65 + line = readlnFromNewsserver(); 99.66 + if(!line.startsWith("200 ")) 99.67 + { 99.68 + throw new IOException("XDAEMON command not allowed by server"); 99.69 + } 99.70 + line = readlnFromNewsserver(); 99.71 + hostedNews = Integer.parseInt(line); 99.72 + line = readlnFromNewsserver(); // read the "." 99.73 + 99.74 + printlnToNewsserver("XDAEMON LOG HOSTED_GROUPS"); 99.75 + line = readlnFromNewsserver(); 99.76 + if(!line.startsWith("200 ")) 99.77 + { 99.78 + throw new IOException("XDAEMON command not allowed by server"); 99.79 + } 99.80 + line = readlnFromNewsserver(); 99.81 + hostedGroups = Integer.parseInt(line); 99.82 + line = readlnFromNewsserver(); // read the "." 99.83 + 99.84 + printlnToNewsserver("XDAEMON LOG POSTED_NEWS_PER_HOUR"); 99.85 + line = readlnFromNewsserver(); 99.86 + if(!line.startsWith("200 ")) 99.87 + { 99.88 + throw new IOException("XDAEMON command not allowed by server"); 99.89 + } 99.90 + String postedNewsPerHour = readlnFromNewsserver(); 99.91 + readlnFromNewsserver(); 99.92 + 99.93 + printlnToNewsserver("XDAEMON LOG GATEWAYED_NEWS_PER_HOUR"); 99.94 + line = readlnFromNewsserver(); 99.95 + if(!line.startsWith("200 ")) 99.96 + { 99.97 + throw new IOException("XDAEMON command not allowed by server"); 99.98 + } 99.99 + String gatewayedNewsPerHour = readlnFromNewsserver(); 99.100 + line = readlnFromNewsserver(); 99.101 + 99.102 + printlnToNewsserver("XDAEMON LOG FEEDED_NEWS_PER_HOUR"); 99.103 + line = readlnFromNewsserver(); 99.104 + if(!line.startsWith("200 ")) 99.105 + { 99.106 + throw new IOException("XDAEMON command not allowed by server"); 99.107 + } 99.108 + String feededNewsPerHour = readlnFromNewsserver(); 99.109 + line = readlnFromNewsserver(); 99.110 + 99.111 + StringTemplate tmpl = getTemplate("SonewsServlet.tmpl"); 99.112 + tmpl.set("SERVERNAME", hello.split(" ")[2]); 99.113 + tmpl.set("STARTDATE", Main.STARTDATE); 99.114 + tmpl.set("ACTIVE_CONNECTIONS", connectedClients); 99.115 + tmpl.set("STORED_NEWS", hostedNews); 99.116 + tmpl.set("SERVED_NEWSGROUPS", hostedGroups); 99.117 + tmpl.set("POSTED_NEWS", postedNewsPerHour); 99.118 + tmpl.set("GATEWAYED_NEWS", gatewayedNewsPerHour); 99.119 + tmpl.set("FEEDED_NEWS", feededNewsPerHour); 99.120 + tmpl.set("TITLE", "Overview"); 99.121 + 99.122 + resp.getWriter().println(tmpl.toString()); 99.123 + resp.getWriter().flush(); 99.124 + resp.setStatus(HttpServletResponse.SC_OK); 99.125 + 99.126 + disconnectFromNewsserver(); 99.127 + } 99.128 + } 99.129 + 99.130 +}
100.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 100.2 +++ b/org/sonews/web/package.html Fri Jun 26 16:48:50 2009 +0200 100.3 @@ -0,0 +1,3 @@ 100.4 +Contains classes of the sonews web interface. These classes are not needed by 100.5 +the running sonews daemon but by the Servlet container 100.6 +<a href="http://kitten.sonews.org/">Kitten</a>. 100.7 \ No newline at end of file
101.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 101.2 +++ b/org/sonews/web/tmpl/AbstractSonewsServlet.tmpl Fri Jun 26 16:48:50 2009 +0200 101.3 @@ -0,0 +1,14 @@ 101.4 +<html> 101.5 +<head> 101.6 + <title>%SERVERNAME - %TITLE</title> 101.7 + <link rel="stylesheet" type="text/css" href="%STYLESHEET" /> 101.8 +</head> 101.9 + 101.10 +<body> 101.11 +<div class="pagetitle">sonews - %TITLE</div> 101.12 + 101.13 +<div class="content"> 101.14 +%CONTENT 101.15 +</div> 101.16 +</body> 101.17 +</html> 101.18 \ No newline at end of file
102.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 102.2 +++ b/org/sonews/web/tmpl/ConfigUpdated.tmpl Fri Jun 26 16:48:50 2009 +0200 102.3 @@ -0,0 +1,7 @@ 102.4 + <p> 102.5 + The following config keys were updated: <br/> 102.6 + %UPDATED_KEYS 102.7 + </p> 102.8 + <p> 102.9 + <a href="/sonews/config">Back to Config</a> 102.10 + </p> 102.11 \ No newline at end of file
103.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 103.2 +++ b/org/sonews/web/tmpl/GroupAdded.tmpl Fri Jun 26 16:48:50 2009 +0200 103.3 @@ -0,0 +1,6 @@ 103.4 + <p> 103.5 + The Newsgroup %GROUP has been created! 103.6 + </p> 103.7 + <p> 103.8 + <a href="/sonews/config">Back to Config</a> 103.9 + </p> 103.10 \ No newline at end of file
104.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 104.2 +++ b/org/sonews/web/tmpl/GroupDeleted.tmpl Fri Jun 26 16:48:50 2009 +0200 104.3 @@ -0,0 +1,6 @@ 104.4 + <p> 104.5 + The Newsgroup %GROUP and all associated articles have been deleted! 104.6 + </p> 104.7 + <p> 104.8 + <a href="/sonews/config">Back to Config</a> 104.9 + </p> 104.10 \ No newline at end of file
105.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 105.2 +++ b/org/sonews/web/tmpl/GroupList.tmpl Fri Jun 26 16:48:50 2009 +0200 105.3 @@ -0,0 +1,8 @@ 105.4 +<tr> 105.5 + <td> 105.6 + <a href="/sonews/group?name=%GROUPNAME">%GROUPNAME</a> 105.7 + </td> 105.8 + <td> 105.9 + <a href="?which=groupdelete&group=%GROUPNAME">delete</a> 105.10 + </td> 105.11 +</tr> 105.12 \ No newline at end of file
106.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 106.2 +++ b/org/sonews/web/tmpl/SonewsConfigServlet.tmpl Fri Jun 26 16:48:50 2009 +0200 106.3 @@ -0,0 +1,30 @@ 106.4 +<p> 106.5 +<a href="/sonews">Back to Main Page</a> 106.6 +</p> 106.7 + 106.8 +<h2>Configuration values</h2> 106.9 +<form action="/sonews/config" method="GET"> 106.10 +<input type="hidden" name="which" value="config"/> 106.11 +<table> 106.12 +%CONFIG 106.13 +</table> 106.14 +<input type="submit" value="Apply changes"/> 106.15 +</form> 106.16 + 106.17 +<h2>Groups served by this sonews instance</h2> 106.18 +<table> 106.19 +%GROUP 106.20 +</table> 106.21 + 106.22 +<p> 106.23 +<h2>Add new group to be served</h2> 106.24 +<form action="/sonews/config" method="GET"> 106.25 + <input type="hidden" name="which" value="groupadd"/> 106.26 +<table> 106.27 + <tr><td>Names (separated by newlines):</td> 106.28 + <td><textarea cols="50" rows="15" name="groups"></textarea></td></tr> 106.29 + </tr> 106.30 +</table> 106.31 +<input type="submit" value="Add groups"/> 106.32 +</form> 106.33 +</p> 106.34 \ No newline at end of file
107.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 107.2 +++ b/org/sonews/web/tmpl/SonewsGroupServlet.tmpl Fri Jun 26 16:48:50 2009 +0200 107.3 @@ -0,0 +1,36 @@ 107.4 +<p> 107.5 +<a href="/sonews">Back to Main Page</a> 107.6 +</p> 107.7 + 107.8 +<h1>Group %GROUPNAME</h1> 107.9 + 107.10 +<h2>Configuration</h2> 107.11 +<h3>General</h3> 107.12 +<form action="" method="GET"> 107.13 + <input type="hidden" name="name" value="%GROUPNAME" /> 107.14 + <input type="hidden" name="action" value="set_flags"/> 107.15 + Is mirrored Mailinglist?: 107.16 + <input type="checkbox" name="flag0" value="true" /> 107.17 + <br/> 107.18 + <input type="submit" value="Update" /> 107.19 +</form> 107.20 + 107.21 +<h3>Mailinglist</h3> 107.22 +<form action="" method="GET"> 107.23 + <input type="hidden" name="name" value="%GROUPNAME" /> 107.24 + <input type="hidden" name="action" value="set_mladdress"/> 107.25 + Mailinglist address: 107.26 + <input type="text" name="mladdress" /> 107.27 + <br/> 107.28 + <input type="submit" value="Update" /> 107.29 +</form> 107.30 + 107.31 +<h2>Statistics</h2> 107.32 +<h3>Posted mails yesterday</h3> 107.33 +<img src="/sonews/chart?name=postednewsyesterday&group=%GROUPNAME" /> 107.34 + 107.35 +<h3>Gatewayed mails yesterday</h3> 107.36 +<img src="/sonews/chart?name=gatewayednewsyesterday&group=%GROUPNAME" /> 107.37 + 107.38 +<h3>Feeded news</h3> 107.39 +<img src="/sonews/chart?name=feedednewsyesterday&group=%GROUPNAME" /> 107.40 \ No newline at end of file
108.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 108.2 +++ b/org/sonews/web/tmpl/SonewsPeerServlet.tmpl Fri Jun 26 16:48:50 2009 +0200 108.3 @@ -0,0 +1,52 @@ 108.4 +<p> 108.5 +<a href="/sonews">Back to Main Page</a> 108.6 +</p> 108.7 + 108.8 +On this page you can configure to which peer hosts new messages are 108.9 +posted or from which peer hosts we should receive messages. 108.10 + 108.11 +<h2>Peers</h2> 108.12 +%PEERS 108.13 + 108.14 +<h3>Add new peer</h3> 108.15 +<form action="" method="GET"> 108.16 +<table style="border: 0px"> 108.17 + <tr> 108.18 + <td>Hostname:</td> 108.19 + <td><input type="text" name="host" value="news.someremotehost.org" /></td> 108.20 + </tr> 108.21 + <tr> 108.22 + <td>Port:</td> 108.23 + <td><input type="text" name="port" value="119" /></td> 108.24 + </tr> 108.25 +</table> 108.26 +<input type="submit" value="Add peer" /> 108.27 +</form> 108.28 + 108.29 +<h2>Rules</h2> 108.30 +<h3>Current</h3> 108.31 +%PEERING_RULES 108.32 + 108.33 +<h3>Add peering rule</h3> 108.34 +<form action="" method="GET"> 108.35 +<table style="border: 0px"> 108.36 + <tr> 108.37 + <td>Peer:</td> 108.38 + <td>%OPTION_PEERS</td> 108.39 + </tr> 108.40 + <tr> 108.41 + <td>Group:</td> 108.42 + <td>%OPTION_GROUP</td> 108.43 + </tr> 108.44 + <tr> 108.45 + <td>Peering type:</td> 108.46 + <td> 108.47 + <select name="peertype"> 108.48 + <option value="0">Pull peering</option> 108.49 + <option value="1">Push peering</option> 108.50 + </select> 108.51 + </td> 108.52 + </tr> 108.53 +</table> 108.54 +<input type="submit" value="Add peering rule" /> 108.55 +</form> 108.56 \ No newline at end of file
109.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 109.2 +++ b/org/sonews/web/tmpl/SonewsServlet.tmpl Fri Jun 26 16:48:50 2009 +0200 109.3 @@ -0,0 +1,54 @@ 109.4 +This server is running since %STARTDATE. 109.5 + 109.6 +<h2>Configuration</h2> 109.7 +Here you can edit most of the configuration values for %SERVERNAME. 109.8 +Please note that some of these values require a server restart, 109.9 +some do not and are valid immediately. 109.10 +<ul> 109.11 + <li><a href="/sonews/config">View/Edit configuration values</a></li> 109.12 + <li><a href="/sonews/peer">View/Edit peer settings</a></li> 109.13 +</ul> 109.14 + 109.15 +<h2>Statistics & Logs</h2> 109.16 +Here is a short overview of useful statistics of %SERVERNAME. Click on a 109.17 +stat key to get more details. 109.18 +<table style="border: 1px dotted black"> 109.19 + <tr> 109.20 + <td><i>Stat key</i></td> 109.21 + <td><i>Value</i></td> 109.22 + </tr> 109.23 + 109.24 + <tr> 109.25 + <td>Active connections:</td> 109.26 + <td>%ACTIVE_CONNECTIONS</td> 109.27 + </tr> 109.28 + 109.29 + <tr> 109.30 + <td>Served newsgroups:</td> 109.31 + <td>%SERVED_NEWSGROUPS</td> 109.32 + </tr> 109.33 + 109.34 + <tr> 109.35 + <td>Stored news messages:</td> 109.36 + <td>%STORED_NEWS</td> 109.37 + </tr> 109.38 + 109.39 + <tr> 109.40 + <td><a href="/sonews/chart?name=postednewsyesterday">Posted news</a>:</td> 109.41 + <td>%POSTED_NEWS per hour</td> 109.42 + </tr> 109.43 + 109.44 + <tr> 109.45 + <td><a href="/sonews/chart?name=gatewayednewsyesterday">Gatewayed news</a>:</td> 109.46 + <td>%GATEWAYED_NEWS per hour</td> 109.47 + </tr> 109.48 + 109.49 + <tr> 109.50 + <td><a href="/sonews/chart?name=feedednewsyesterday">Feeded news</a>:</td> 109.51 + <td>%FEEDED_NEWS per hour</td> 109.52 + </tr> 109.53 +</table> 109.54 + 109.55 +<h2>Documentation</h2> 109.56 +You'll find the most recent 109.57 +<a href="http://www.sonews.org/">documentation of %SERVERNAME here</a>. 109.58 \ No newline at end of file
110.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 110.2 +++ b/test/AbstractTest.java Fri Jun 26 16:48:50 2009 +0200 110.3 @@ -0,0 +1,93 @@ 110.4 +/* 110.5 + * StarOffice News Server 110.6 + * see AUTHORS for the list of contributors 110.7 + * 110.8 + * This program is free software: you can redistribute it and/or modify 110.9 + * it under the terms of the GNU General Public License as published by 110.10 + * the Free Software Foundation, either version 3 of the License, or 110.11 + * (at your option) any later version. 110.12 + * 110.13 + * This program is distributed in the hope that it will be useful, 110.14 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 110.15 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 110.16 + * GNU General Public License for more details. 110.17 + * 110.18 + * You should have received a copy of the GNU General Public License 110.19 + * along with this program. If not, see <http://www.gnu.org/licenses/>. 110.20 + */ 110.21 + 110.22 +package test; 110.23 + 110.24 +import java.io.BufferedReader; 110.25 +import java.io.File; 110.26 +import java.io.IOException; 110.27 +import java.io.InputStreamReader; 110.28 +import java.io.PrintWriter; 110.29 +import java.net.Socket; 110.30 +import java.net.UnknownHostException; 110.31 + 110.32 +/** 110.33 + * Base class for every test performed by the TestBench. 110.34 + * Connects to a NNTP Server and provides basic methods for sending and 110.35 + * receiving data. 110.36 + * @author Christian Lins 110.37 + * @since sonews/0.5.0 110.38 + */ 110.39 +public abstract class AbstractTest 110.40 +{ 110.41 + 110.42 + protected static PrintWriter log; 110.43 + 110.44 + static 110.45 + { 110.46 + try 110.47 + { 110.48 + log = new PrintWriter(new File("test.log")); 110.49 + } 110.50 + catch(Exception ex) 110.51 + { 110.52 + ex.printStackTrace(); 110.53 + } 110.54 + } 110.55 + 110.56 + protected BufferedReader in; 110.57 + protected PrintWriter out; 110.58 + protected Socket socket; 110.59 + 110.60 + /** 110.61 + * Connects to NNTP Server using for 110.62 + * @param host 110.63 + * @param port 110.64 + * @throws java.io.IOException 110.65 + * @throws java.net.UnknownHostException 110.66 + */ 110.67 + public void connect(String host, int port) 110.68 + throws IOException, UnknownHostException 110.69 + { 110.70 + socket = new Socket(host, port); 110.71 + socket.setSoTimeout(10000); 110.72 + this.in = new BufferedReader(new InputStreamReader(socket.getInputStream())); 110.73 + this.out = new PrintWriter(socket.getOutputStream()); 110.74 + } 110.75 + 110.76 + protected void println(String line) 110.77 + { 110.78 + this.out.println(line); 110.79 + this.out.flush(); 110.80 + 110.81 + log.println(">> " + line); 110.82 + log.flush(); 110.83 + } 110.84 + 110.85 + protected String readln() 110.86 + throws IOException 110.87 + { 110.88 + String line = this.in.readLine(); 110.89 + log.println("<< " + line); 110.90 + log.flush(); 110.91 + return line; 110.92 + } 110.93 + 110.94 + public abstract int runTest() throws Exception; 110.95 + 110.96 +}
111.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 111.2 +++ b/test/CollectionsSpeedTest.java Fri Jun 26 16:48:50 2009 +0200 111.3 @@ -0,0 +1,72 @@ 111.4 +/* 111.5 + * StarOffice News Server 111.6 + * see AUTHORS for the list of contributors 111.7 + * 111.8 + * This program is free software: you can redistribute it and/or modify 111.9 + * it under the terms of the GNU General Public License as published by 111.10 + * the Free Software Foundation, either version 3 of the License, or 111.11 + * (at your option) any later version. 111.12 + * 111.13 + * This program is distributed in the hope that it will be useful, 111.14 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 111.15 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 111.16 + * GNU General Public License for more details. 111.17 + * 111.18 + * You should have received a copy of the GNU General Public License 111.19 + * along with this program. If not, see <http://www.gnu.org/licenses/>. 111.20 + */ 111.21 + 111.22 +package test; 111.23 + 111.24 +import java.util.ArrayList; 111.25 +import java.util.LinkedList; 111.26 +import java.util.List; 111.27 +import java.util.ListIterator; 111.28 + 111.29 +/** 111.30 + * Tests the speed of LinkedList and ArrayList. 111.31 + * @author Christian Lins 111.32 + * @since sonews/0.5.0 111.33 + */ 111.34 +public class CollectionsSpeedTest 111.35 +{ 111.36 + 111.37 + public static void main(String[] args) 111.38 + { 111.39 + List arrayList = new ArrayList(); 111.40 + List linkedList = new LinkedList(); 111.41 + 111.42 + int numElements = 100000; 111.43 + 111.44 + System.out.println("ArrayList.add(): " + add(arrayList, numElements) + "ms"); 111.45 + System.out.println("LinkenList.add(): " + add(linkedList, numElements) + "ms"); 111.46 + System.out.println("ArrayList.iterate: " + iterate(arrayList) + "ms"); 111.47 + System.out.println("LinkedList.iterate: " + iterate(linkedList) + "ms"); 111.48 + } 111.49 + 111.50 + private static long add(List list, int numElements) 111.51 + { 111.52 + long start = System.currentTimeMillis(); 111.53 + 111.54 + for(int n = 0; n < numElements; n++) 111.55 + { 111.56 + list.add(new Object()); 111.57 + } 111.58 + 111.59 + return System.currentTimeMillis() - start; 111.60 + } 111.61 + 111.62 + private static long iterate(List list) 111.63 + { 111.64 + long start = System.currentTimeMillis(); 111.65 + 111.66 + ListIterator iter = list.listIterator(); 111.67 + while(iter.hasNext()) 111.68 + { 111.69 + iter.next(); 111.70 + } 111.71 + 111.72 + return System.currentTimeMillis() - start; 111.73 + } 111.74 + 111.75 +}
112.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 112.2 +++ b/test/PerfTest.java Fri Jun 26 16:48:50 2009 +0200 112.3 @@ -0,0 +1,44 @@ 112.4 +/* 112.5 + * StarOffice News Server 112.6 + * see AUTHORS for the list of contributors 112.7 + * 112.8 + * This program is free software: you can redistribute it and/or modify 112.9 + * it under the terms of the GNU General Public License as published by 112.10 + * the Free Software Foundation, either version 3 of the License, or 112.11 + * (at your option) any later version. 112.12 + * 112.13 + * This program is distributed in the hope that it will be useful, 112.14 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 112.15 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 112.16 + * GNU General Public License for more details. 112.17 + * 112.18 + * You should have received a copy of the GNU General Public License 112.19 + * along with this program. If not, see <http://www.gnu.org/licenses/>. 112.20 + */ 112.21 + 112.22 +package test; 112.23 + 112.24 +/** 112.25 + * Opens a connection, waits for Hello and exits while leaving the connection 112.26 + * open until SoTimeout. 112.27 + * @author Christian Lins 112.28 + * @since sonews/0.5.0 112.29 + */ 112.30 +public class PerfTest extends AbstractTest 112.31 +{ 112.32 + 112.33 + @Override 112.34 + public int runTest() throws Exception 112.35 + { 112.36 + String line = readln(); 112.37 + if(!line.startsWith("200 ")) 112.38 + { 112.39 + return 1; 112.40 + } 112.41 + 112.42 + socket.setSoTimeout(0); 112.43 + 112.44 + return 0; 112.45 + } 112.46 + 112.47 +}
113.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 113.2 +++ b/test/PerfTestBench.java Fri Jun 26 16:48:50 2009 +0200 113.3 @@ -0,0 +1,63 @@ 113.4 +/* 113.5 + * StarOffice News Server 113.6 + * see AUTHORS for the list of contributors 113.7 + * 113.8 + * This program is free software: you can redistribute it and/or modify 113.9 + * it under the terms of the GNU General Public License as published by 113.10 + * the Free Software Foundation, either version 3 of the License, or 113.11 + * (at your option) any later version. 113.12 + * 113.13 + * This program is distributed in the hope that it will be useful, 113.14 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 113.15 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 113.16 + * GNU General Public License for more details. 113.17 + * 113.18 + * You should have received a copy of the GNU General Public License 113.19 + * along with this program. If not, see <http://www.gnu.org/licenses/>. 113.20 + */ 113.21 + 113.22 +package test; 113.23 + 113.24 +/** 113.25 + * TestBench that performs a - yes - performance test. The test runs until 113.26 + * the opened sockets reach the systems maximum. The test has now valid end 113.27 + * as it will throw IOErrors at the end. 113.28 + * @author Christian Lins 113.29 + * @since sonews/0.5.0 113.30 + */ 113.31 +public class PerfTestBench 113.32 +{ 113.33 + 113.34 + public static void main(String[] args) 113.35 + throws Exception 113.36 + { 113.37 + System.out.println("Performance TestBench for NNTP (RFC3799) based servers "); 113.38 + if(args.length < 1) 113.39 + { 113.40 + System.out.println("Usage: TestBench <host>[:port]"); 113.41 + return; 113.42 + } 113.43 + 113.44 + String[] hostport = args[0].split(":"); 113.45 + String host = hostport[0]; 113.46 + int port = 119; 113.47 + if(hostport.length == 2) 113.48 + { 113.49 + port = Integer.parseInt(hostport[1]); 113.50 + } 113.51 + 113.52 + for(int n = 0; true; n++) 113.53 + { 113.54 + PerfTest pf = new PerfTest(); 113.55 + pf.connect(host, port); 113.56 + pf.runTest(); 113.57 + 113.58 + if(n % 100 == 0) 113.59 + { 113.60 + System.out.println("Test #" + n); 113.61 + System.out.flush(); 113.62 + } 113.63 + } 113.64 + } 113.65 + 113.66 +}
114.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 114.2 +++ b/test/StringTemplateTest.java Fri Jun 26 16:48:50 2009 +0200 114.3 @@ -0,0 +1,43 @@ 114.4 +/* 114.5 + * StarOffice News Server 114.6 + * see AUTHORS for the list of contributors 114.7 + * 114.8 + * This program is free software: you can redistribute it and/or modify 114.9 + * it under the terms of the GNU General Public License as published by 114.10 + * the Free Software Foundation, either version 3 of the License, or 114.11 + * (at your option) any later version. 114.12 + * 114.13 + * This program is distributed in the hope that it will be useful, 114.14 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 114.15 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 114.16 + * GNU General Public License for more details. 114.17 + * 114.18 + * You should have received a copy of the GNU General Public License 114.19 + * along with this program. If not, see <http://www.gnu.org/licenses/>. 114.20 + */ 114.21 + 114.22 +package test; 114.23 + 114.24 +import org.sonews.util.StringTemplate; 114.25 + 114.26 +/** 114.27 + * Tests the StringTemplate class. 114.28 + * @author Christian Lins 114.29 + * @since sonews/0.5.0 114.30 + * @see org.sonews.util.StringTemplate 114.31 + */ 114.32 +public class StringTemplateTest 114.33 +{ 114.34 + 114.35 + public static void main(String[] args) 114.36 + { 114.37 + StringTemplate templ 114.38 + = new StringTemplate("SELECT %row FROM %table WHERE %row = ich"); 114.39 + 114.40 + templ.set("row", "name"); 114.41 + templ.set("table", "UserTable"); 114.42 + 114.43 + System.out.println(templ.toString()); 114.44 + } 114.45 + 114.46 +}
115.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 115.2 +++ b/test/TestBench.java Fri Jun 26 16:48:50 2009 +0200 115.3 @@ -0,0 +1,98 @@ 115.4 +/* 115.5 + * StarOffice News Server 115.6 + * see AUTHORS for the list of contributors 115.7 + * 115.8 + * This program is free software: you can redistribute it and/or modify 115.9 + * it under the terms of the GNU General Public License as published by 115.10 + * the Free Software Foundation, either version 3 of the License, or 115.11 + * (at your option) any later version. 115.12 + * 115.13 + * This program is distributed in the hope that it will be useful, 115.14 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 115.15 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 115.16 + * GNU General Public License for more details. 115.17 + * 115.18 + * You should have received a copy of the GNU General Public License 115.19 + * along with this program. If not, see <http://www.gnu.org/licenses/>. 115.20 + */ 115.21 + 115.22 +package test; 115.23 + 115.24 +import test.command.HelloQuitTest; 115.25 +import test.command.ArticleTest; 115.26 +import java.util.LinkedList; 115.27 +import java.util.List; 115.28 +import test.command.CapabilitiesTest; 115.29 +import test.command.GroupTest; 115.30 +import test.command.ListGroupTests; 115.31 +import test.command.ListTest; 115.32 +import test.command.NewGroupsTest; 115.33 +import test.command.NextTest; 115.34 +import test.command.OverTest; 115.35 +import test.command.PostTest; 115.36 + 115.37 +/** 115.38 + * Run this class to perform a full test. 115.39 + * @author Christian Lins 115.40 + * @since sonews/0.5.0 115.41 + */ 115.42 +public final class TestBench 115.43 +{ 115.44 + 115.45 + public static void main(String[] args) 115.46 + { 115.47 + System.out.println("TestBench for NNTP (RFC3799) based servers "); 115.48 + if(args.length < 1) 115.49 + { 115.50 + System.out.println("Usage: TestBench <host>[:port]"); 115.51 + return; 115.52 + } 115.53 + 115.54 + String[] hostport = args[0].split(":"); 115.55 + String host = hostport[0]; 115.56 + int port = 119; 115.57 + if(hostport.length == 2) 115.58 + { 115.59 + port = Integer.parseInt(hostport[1]); 115.60 + } 115.61 + 115.62 + List<AbstractTest> tests = new LinkedList<AbstractTest>(); 115.63 + 115.64 + // Add tests to perform 115.65 + tests.add(new HelloQuitTest()); 115.66 + tests.add(new PostTest()); // Post before Article 115.67 + tests.add(new ArticleTest()); 115.68 + tests.add(new CapabilitiesTest()); 115.69 + tests.add(new GroupTest()); 115.70 + tests.add(new ListGroupTests()); 115.71 + tests.add(new ListTest()); 115.72 + tests.add(new NewGroupsTest()); 115.73 + tests.add(new NextTest()); 115.74 + tests.add(new OverTest()); 115.75 + 115.76 + // Perform all tests 115.77 + for(AbstractTest test : tests) 115.78 + { 115.79 + try 115.80 + { 115.81 + test.connect(host, port); 115.82 + int result = test.runTest(); 115.83 + System.out.print(test.getClass().getName() + " finished with exit code " + result + "\t => "); 115.84 + if(result == 0) 115.85 + { 115.86 + System.out.println("SUCCESS"); 115.87 + } 115.88 + else 115.89 + { 115.90 + System.out.println("FAILURE"); 115.91 + } 115.92 + } 115.93 + catch(Exception ex) 115.94 + { 115.95 + System.out.println("Test " + test.getClass().getName() + " failed: " + ex.getLocalizedMessage()); 115.96 + ex.printStackTrace(); 115.97 + } 115.98 + } 115.99 + } 115.100 + 115.101 +}
116.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 116.2 +++ b/test/command/ArticleTest.java Fri Jun 26 16:48:50 2009 +0200 116.3 @@ -0,0 +1,90 @@ 116.4 +/* 116.5 + * StarOffice News Server 116.6 + * see AUTHORS for the list of contributors 116.7 + * 116.8 + * This program is free software: you can redistribute it and/or modify 116.9 + * it under the terms of the GNU General Public License as published by 116.10 + * the Free Software Foundation, either version 3 of the License, or 116.11 + * (at your option) any later version. 116.12 + * 116.13 + * This program is distributed in the hope that it will be useful, 116.14 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 116.15 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 116.16 + * GNU General Public License for more details. 116.17 + * 116.18 + * You should have received a copy of the GNU General Public License 116.19 + * along with this program. If not, see <http://www.gnu.org/licenses/>. 116.20 + */ 116.21 + 116.22 +package test.command; 116.23 + 116.24 +import test.AbstractTest; 116.25 + 116.26 +/** 116.27 + * Tests the ARTICLE command. 116.28 + * @author Christian Lins 116.29 + * @since sonews/0.5.0 116.30 + */ 116.31 +public class ArticleTest extends AbstractTest 116.32 +{ 116.33 + 116.34 + @Override 116.35 + public int runTest() 116.36 + throws Exception 116.37 + { 116.38 + String line = readln(); 116.39 + if(!line.startsWith("200 ")) 116.40 + { 116.41 + return 1; 116.42 + } 116.43 + 116.44 + // Select a group (we assume that local.test is existing) 116.45 + println("GROUP local.test"); 116.46 + line = readln(); 116.47 + if(!line.startsWith("211 ")) 116.48 + { 116.49 + println("GROUP test"); 116.50 + line = readln(); 116.51 + if(!line.startsWith("211 ")) 116.52 + { 116.53 + return 3; 116.54 + } 116.55 + } 116.56 + 116.57 + // Retrieve the first article 116.58 + println("ARTICLE " + line.split(" ")[2]); 116.59 + line = readln(); 116.60 + if(!line.startsWith("220 ")) 116.61 + { 116.62 + return 4; 116.63 + } 116.64 + 116.65 + while(!line.equals(".")) 116.66 + { 116.67 + line = readln(); 116.68 + } 116.69 + 116.70 + // Retrieve currently selected article (without a parameter number!) 116.71 + println("ARTICLE"); 116.72 + line = readln(); 116.73 + if(!line.startsWith("220 ")) 116.74 + { 116.75 + return 5; 116.76 + } 116.77 + 116.78 + while(!line.equals(".")) 116.79 + { 116.80 + line = readln(); 116.81 + } 116.82 + 116.83 + println("QUIT"); 116.84 + line = readln(); 116.85 + if(!line.startsWith("205 ")) 116.86 + { 116.87 + return 2; 116.88 + } 116.89 + 116.90 + return 0; 116.91 + } 116.92 + 116.93 +}
117.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 117.2 +++ b/test/command/CapabilitiesTest.java Fri Jun 26 16:48:50 2009 +0200 117.3 @@ -0,0 +1,63 @@ 117.4 +/* 117.5 + * StarOffice News Server 117.6 + * see AUTHORS for the list of contributors 117.7 + * 117.8 + * This program is free software: you can redistribute it and/or modify 117.9 + * it under the terms of the GNU General Public License as published by 117.10 + * the Free Software Foundation, either version 3 of the License, or 117.11 + * (at your option) any later version. 117.12 + * 117.13 + * This program is distributed in the hope that it will be useful, 117.14 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 117.15 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 117.16 + * GNU General Public License for more details. 117.17 + * 117.18 + * You should have received a copy of the GNU General Public License 117.19 + * along with this program. If not, see <http://www.gnu.org/licenses/>. 117.20 + */ 117.21 + 117.22 +package test.command; 117.23 + 117.24 +import test.AbstractTest; 117.25 + 117.26 +/** 117.27 + * Tests the CAPABILITIES command. 117.28 + * @author Christian Lins 117.29 + * @since sonews/0.5.0 117.30 + */ 117.31 +public class CapabilitiesTest extends AbstractTest 117.32 +{ 117.33 + 117.34 + @Override 117.35 + public int runTest() 117.36 + throws Exception 117.37 + { 117.38 + String line = readln(); 117.39 + if(!line.startsWith("200 ")) 117.40 + { 117.41 + return 1; 117.42 + } 117.43 + 117.44 + println("CAPABILITIES"); 117.45 + line = readln(); 117.46 + if(!line.startsWith("101")) 117.47 + { 117.48 + return 3; 117.49 + } 117.50 + 117.51 + while(!line.equals(".")) 117.52 + { 117.53 + line = readln(); 117.54 + } 117.55 + 117.56 + println("QUIT"); 117.57 + line = readln(); 117.58 + if(!line.startsWith("205 ")) 117.59 + { 117.60 + return 2; 117.61 + } 117.62 + 117.63 + return 0; 117.64 + } 117.65 + 117.66 +}
118.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 118.2 +++ b/test/command/GroupTest.java Fri Jun 26 16:48:50 2009 +0200 118.3 @@ -0,0 +1,49 @@ 118.4 +/* 118.5 + * StarOffice News Server 118.6 + * see AUTHORS for the list of contributors 118.7 + * 118.8 + * This program is free software: you can redistribute it and/or modify 118.9 + * it under the terms of the GNU General Public License as published by 118.10 + * the Free Software Foundation, either version 3 of the License, or 118.11 + * (at your option) any later version. 118.12 + * 118.13 + * This program is distributed in the hope that it will be useful, 118.14 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 118.15 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 118.16 + * GNU General Public License for more details. 118.17 + * 118.18 + * You should have received a copy of the GNU General Public License 118.19 + * along with this program. If not, see <http://www.gnu.org/licenses/>. 118.20 + */ 118.21 + 118.22 +package test.command; 118.23 + 118.24 +import test.AbstractTest; 118.25 + 118.26 +/** 118.27 + * Tests the GROUP command. 118.28 + * @author Christian Lins 118.29 + * @since sonews/0.5.0 118.30 + */ 118.31 +public class GroupTest extends AbstractTest 118.32 +{ 118.33 + 118.34 + @Override 118.35 + public int runTest() 118.36 + throws Exception 118.37 + { 118.38 + String line = readln(); 118.39 + 118.40 + println("GROUP misc.test"); 118.41 + line = readln(); 118.42 + if(line.startsWith("211 ")) 118.43 + { 118.44 + return 0; 118.45 + } 118.46 + else 118.47 + { 118.48 + return 1; 118.49 + } 118.50 + } 118.51 + 118.52 +}
119.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 119.2 +++ b/test/command/HelloQuitTest.java Fri Jun 26 16:48:50 2009 +0200 119.3 @@ -0,0 +1,47 @@ 119.4 +/* 119.5 + * StarOffice News Server 119.6 + * see AUTHORS for the list of contributors 119.7 + * 119.8 + * This program is free software: you can redistribute it and/or modify 119.9 + * it under the terms of the GNU General Public License as published by 119.10 + * the Free Software Foundation, either version 3 of the License, or 119.11 + * (at your option) any later version. 119.12 + * 119.13 + * This program is distributed in the hope that it will be useful, 119.14 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 119.15 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 119.16 + * GNU General Public License for more details. 119.17 + * 119.18 + * You should have received a copy of the GNU General Public License 119.19 + * along with this program. If not, see <http://www.gnu.org/licenses/>. 119.20 + */ 119.21 + 119.22 +package test.command; 119.23 + 119.24 +import test.AbstractTest; 119.25 + 119.26 +/** 119.27 + * Test: connects to server, waits for initial hello and quits. 119.28 + * @author Christian Lins 119.29 + * @since sonews/0.5.0 119.30 + */ 119.31 +public class HelloQuitTest extends AbstractTest 119.32 +{ 119.33 + 119.34 + @Override 119.35 + public int runTest() 119.36 + throws Exception 119.37 + { 119.38 + String line = readln(); 119.39 + if(!line.startsWith("200 ")) 119.40 + return 1; 119.41 + 119.42 + println("QUIT"); 119.43 + line = readln(); 119.44 + if(!line.startsWith("205 ")) 119.45 + return 2; 119.46 + 119.47 + return 0; 119.48 + } 119.49 + 119.50 +}
120.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 120.2 +++ b/test/command/ListGroupTests.java Fri Jun 26 16:48:50 2009 +0200 120.3 @@ -0,0 +1,38 @@ 120.4 +/* 120.5 + * StarOffice News Server 120.6 + * see AUTHORS for the list of contributors 120.7 + * 120.8 + * This program is free software: you can redistribute it and/or modify 120.9 + * it under the terms of the GNU General Public License as published by 120.10 + * the Free Software Foundation, either version 3 of the License, or 120.11 + * (at your option) any later version. 120.12 + * 120.13 + * This program is distributed in the hope that it will be useful, 120.14 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 120.15 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 120.16 + * GNU General Public License for more details. 120.17 + * 120.18 + * You should have received a copy of the GNU General Public License 120.19 + * along with this program. If not, see <http://www.gnu.org/licenses/>. 120.20 + */ 120.21 + 120.22 +package test.command; 120.23 + 120.24 +import test.AbstractTest; 120.25 + 120.26 +/** 120.27 + * Tests the LISTGROUP command. 120.28 + * @author Christian Lins 120.29 + * @since sonews/0.5.0 120.30 + */ 120.31 +public class ListGroupTests extends AbstractTest 120.32 +{ 120.33 + 120.34 + @Override 120.35 + public int runTest() 120.36 + throws Exception 120.37 + { 120.38 + return 1; 120.39 + } 120.40 + 120.41 +}
121.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 121.2 +++ b/test/command/ListTest.java Fri Jun 26 16:48:50 2009 +0200 121.3 @@ -0,0 +1,49 @@ 121.4 +/* 121.5 + * StarOffice News Server 121.6 + * see AUTHORS for the list of contributors 121.7 + * 121.8 + * This program is free software: you can redistribute it and/or modify 121.9 + * it under the terms of the GNU General Public License as published by 121.10 + * the Free Software Foundation, either version 3 of the License, or 121.11 + * (at your option) any later version. 121.12 + * 121.13 + * This program is distributed in the hope that it will be useful, 121.14 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 121.15 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 121.16 + * GNU General Public License for more details. 121.17 + * 121.18 + * You should have received a copy of the GNU General Public License 121.19 + * along with this program. If not, see <http://www.gnu.org/licenses/>. 121.20 + */ 121.21 + 121.22 +package test.command; 121.23 + 121.24 +import test.AbstractTest; 121.25 + 121.26 +/** 121.27 + * Blackbox Test testing the LIST command 121.28 + * @author Christian Lins 121.29 + * @since sonews/0.5.0 121.30 + */ 121.31 +public class ListTest extends AbstractTest 121.32 +{ 121.33 + 121.34 + @Override 121.35 + public int runTest() 121.36 + throws Exception 121.37 + { 121.38 + println("LIST OVERVIEW.FMT"); 121.39 + String line = readln(); 121.40 + if(line.startsWith("215 ")) 121.41 + { 121.42 + while(!line.equals(".")) 121.43 + { 121.44 + line = readln(); 121.45 + } 121.46 + return 0; 121.47 + } 121.48 + else 121.49 + return 1; 121.50 + } 121.51 + 121.52 +}
122.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 122.2 +++ b/test/command/NewGroupsTest.java Fri Jun 26 16:48:50 2009 +0200 122.3 @@ -0,0 +1,37 @@ 122.4 +/* 122.5 + * StarOffice News Server 122.6 + * see AUTHORS for the list of contributors 122.7 + * 122.8 + * This program is free software: you can redistribute it and/or modify 122.9 + * it under the terms of the GNU General Public License as published by 122.10 + * the Free Software Foundation, either version 3 of the License, or 122.11 + * (at your option) any later version. 122.12 + * 122.13 + * This program is distributed in the hope that it will be useful, 122.14 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 122.15 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 122.16 + * GNU General Public License for more details. 122.17 + * 122.18 + * You should have received a copy of the GNU General Public License 122.19 + * along with this program. If not, see <http://www.gnu.org/licenses/>. 122.20 + */ 122.21 +package test.command; 122.22 + 122.23 +import test.AbstractTest; 122.24 + 122.25 +/** 122.26 + * Tests the NEWGROUPS command. 122.27 + * @author Christian Lins 122.28 + * @since sonews/0.5.0 122.29 + */ 122.30 +public class NewGroupsTest extends AbstractTest 122.31 +{ 122.32 + 122.33 + @Override 122.34 + public int runTest() 122.35 + throws Exception 122.36 + { 122.37 + return 1; 122.38 + } 122.39 + 122.40 +}
123.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 123.2 +++ b/test/command/NextTest.java Fri Jun 26 16:48:50 2009 +0200 123.3 @@ -0,0 +1,38 @@ 123.4 +/* 123.5 + * StarOffice News Server 123.6 + * see AUTHORS for the list of contributors 123.7 + * 123.8 + * This program is free software: you can redistribute it and/or modify 123.9 + * it under the terms of the GNU General Public License as published by 123.10 + * the Free Software Foundation, either version 3 of the License, or 123.11 + * (at your option) any later version. 123.12 + * 123.13 + * This program is distributed in the hope that it will be useful, 123.14 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 123.15 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 123.16 + * GNU General Public License for more details. 123.17 + * 123.18 + * You should have received a copy of the GNU General Public License 123.19 + * along with this program. If not, see <http://www.gnu.org/licenses/>. 123.20 + */ 123.21 + 123.22 +package test.command; 123.23 + 123.24 +import test.AbstractTest; 123.25 + 123.26 +/** 123.27 + * Tests the NEXT command. 123.28 + * @author Christian Lins 123.29 + * @since sonews/0.5.0 123.30 + */ 123.31 +public class NextTest extends AbstractTest 123.32 +{ 123.33 + 123.34 + @Override 123.35 + public int runTest() 123.36 + throws Exception 123.37 + { 123.38 + return 1; 123.39 + } 123.40 + 123.41 +}
124.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 124.2 +++ b/test/command/OverTest.java Fri Jun 26 16:48:50 2009 +0200 124.3 @@ -0,0 +1,135 @@ 124.4 +/* 124.5 + * StarOffice News Server 124.6 + * see AUTHORS for the list of contributors 124.7 + * 124.8 + * This program is free software: you can redistribute it and/or modify 124.9 + * it under the terms of the GNU General Public License as published by 124.10 + * the Free Software Foundation, either version 3 of the License, or 124.11 + * (at your option) any later version. 124.12 + * 124.13 + * This program is distributed in the hope that it will be useful, 124.14 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 124.15 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 124.16 + * GNU General Public License for more details. 124.17 + * 124.18 + * You should have received a copy of the GNU General Public License 124.19 + * along with this program. If not, see <http://www.gnu.org/licenses/>. 124.20 + */ 124.21 + 124.22 +package test.command; 124.23 + 124.24 +import java.text.SimpleDateFormat; 124.25 +import java.util.ArrayList; 124.26 +import java.util.List; 124.27 +import test.AbstractTest; 124.28 + 124.29 +/** 124.30 + * Tests the OVER/XOVER command. 124.31 + * @author Christian Lins 124.32 + * @since sonews/0.5.0 124.33 + */ 124.34 +public class OverTest extends AbstractTest 124.35 +{ 124.36 + 124.37 + @Override 124.38 + public int runTest() 124.39 + throws Exception 124.40 + { 124.41 + // Send HELLO to server 124.42 + String line = readln(); 124.43 + if(!line.startsWith("200 ")) 124.44 + { 124.45 + return 1; 124.46 + } 124.47 + 124.48 + // Determine available groups 124.49 + println("LIST"); 124.50 + line = readln(); 124.51 + if(!line.startsWith("215 ")) 124.52 + { 124.53 + return 2; 124.54 + } 124.55 + 124.56 + List<String> groups = new ArrayList<String>(); 124.57 + line = readln(); 124.58 + for(;;) 124.59 + { 124.60 + if(line.equals(".")) 124.61 + { 124.62 + break; 124.63 + } 124.64 + else 124.65 + { 124.66 + groups.add(line); 124.67 + line = readln(); 124.68 + } 124.69 + } 124.70 + 124.71 + if(groups.size() <= 0) 124.72 + { 124.73 + return 3; 124.74 + } 124.75 + 124.76 + // Test OVER command on every group 124.77 + for(String group : groups) 124.78 + { 124.79 + String groupName = group.split(" ")[0]; 124.80 + println("GROUP " + groupName); 124.81 + line = readln(); 124.82 + if(!line.startsWith("211 ")) 124.83 + { 124.84 + return 4; 124.85 + } 124.86 + 124.87 + String[] lineToks = line.split(" "); 124.88 + println("XOVER " + lineToks[2] + "-" + lineToks[3]); 124.89 + line = readln(); 124.90 + if(line.startsWith("423")) 124.91 + { 124.92 + continue; 124.93 + } 124.94 + else if(!line.startsWith("224 ")) 124.95 + { 124.96 + return 5; 124.97 + } 124.98 + 124.99 + line = readln(); 124.100 + for(;;) 124.101 + { 124.102 + if(line == null) 124.103 + { 124.104 + return 7; 124.105 + } 124.106 + else if(line.equals(".")) 124.107 + { 124.108 + break; 124.109 + } 124.110 + 124.111 + // Validate the line 124.112 + lineToks = line.split("\t"); 124.113 + if(lineToks.length < 6) 124.114 + { 124.115 + return 6; 124.116 + } 124.117 + else 124.118 + { 124.119 + Integer.parseInt(lineToks[0]); 124.120 + 124.121 + //SimpleDateFormat sdf = new SimpleDateFormat(group) 124.122 + 124.123 + if(!lineToks[4].startsWith("<") && !lineToks[4].endsWith(">")) 124.124 + { 124.125 + log.println("Invalid Message-ID: " + lineToks[1]); 124.126 + log.flush(); 124.127 + return 8; 124.128 + } 124.129 + } 124.130 + 124.131 + line = readln(); 124.132 + } 124.133 + } 124.134 + 124.135 + return 0; 124.136 + } 124.137 + 124.138 +}
125.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 125.2 +++ b/test/command/PostTest.java Fri Jun 26 16:48:50 2009 +0200 125.3 @@ -0,0 +1,82 @@ 125.4 +/* 125.5 + * StarOffice News Server 125.6 + * see AUTHORS for the list of contributors 125.7 + * 125.8 + * This program is free software: you can redistribute it and/or modify 125.9 + * it under the terms of the GNU General Public License as published by 125.10 + * the Free Software Foundation, either version 3 of the License, or 125.11 + * (at your option) any later version. 125.12 + * 125.13 + * This program is distributed in the hope that it will be useful, 125.14 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 125.15 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 125.16 + * GNU General Public License for more details. 125.17 + * 125.18 + * You should have received a copy of the GNU General Public License 125.19 + * along with this program. If not, see <http://www.gnu.org/licenses/>. 125.20 + */ 125.21 + 125.22 +package test.command; 125.23 + 125.24 +import test.AbstractTest; 125.25 + 125.26 +/** 125.27 + * Tests the POST command. 125.28 + * @author Christian Lins 125.29 + * @since sonews/0.5.0 125.30 + */ 125.31 +public class PostTest extends AbstractTest 125.32 +{ 125.33 + 125.34 + @Override 125.35 + public int runTest() 125.36 + throws Exception 125.37 + { 125.38 + String line = readln(); 125.39 + if(!line.startsWith("200 ")) 125.40 + { 125.41 + return 1; 125.42 + } 125.43 + 125.44 + println("POST"); 125.45 + line = readln(); 125.46 + if(!line.startsWith("340 ")) 125.47 + { 125.48 + return 1; 125.49 + } 125.50 + 125.51 + // Post a sample article 125.52 + postArticle("local.test"); 125.53 + line = readln(); 125.54 + if(line.startsWith("441 ")) 125.55 + { 125.56 + println("POST"); 125.57 + line = readln(); 125.58 + if(!line.startsWith("340 ")) 125.59 + { 125.60 + return 2; 125.61 + } 125.62 + 125.63 + postArticle("test"); 125.64 + line = readln(); 125.65 + } 125.66 + 125.67 + if(!line.startsWith("240 ")) 125.68 + { 125.69 + return 3; 125.70 + } 125.71 + 125.72 + return 0; 125.73 + } 125.74 + 125.75 + private void postArticle(String toGroup) 125.76 + { 125.77 + println("Subject: A simple test mail"); 125.78 + println("From: NNTP TestBench <testbench@sonews.org>"); 125.79 + println("Newsgroups: " + toGroup); 125.80 + println(""); 125.81 + println("Hello World!"); 125.82 + println("."); 125.83 + } 125.84 + 125.85 +}
126.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 126.2 +++ b/test/command/package.html Fri Jun 26 16:48:50 2009 +0200 126.3 @@ -0,0 +1,1 @@ 126.4 +Contains conformance tests for various NNTP commands. 126.5 \ No newline at end of file
127.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 127.2 +++ b/test/package.html Fri Jun 26 16:48:50 2009 +0200 127.3 @@ -0,0 +1,1 @@ 127.4 +Root package for test classes. 127.5 \ No newline at end of file
128.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 128.2 +++ b/test/unit/DaemonTests.java Fri Jun 26 16:48:50 2009 +0200 128.3 @@ -0,0 +1,38 @@ 128.4 +/* 128.5 + * SONEWS News Server 128.6 + * see AUTHORS for the list of contributors 128.7 + * 128.8 + * This program is free software: you can redistribute it and/or modify 128.9 + * it under the terms of the GNU General Public License as published by 128.10 + * the Free Software Foundation, either version 3 of the License, or 128.11 + * (at your option) any later version. 128.12 + * 128.13 + * This program is distributed in the hope that it will be useful, 128.14 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 128.15 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 128.16 + * GNU General Public License for more details. 128.17 + * 128.18 + * You should have received a copy of the GNU General Public License 128.19 + * along with this program. If not, see <http://www.gnu.org/licenses/>. 128.20 + */ 128.21 + 128.22 +package test.unit; 128.23 + 128.24 +import junit.textui.TestRunner; 128.25 +import test.unit.daemon.NNTPConnectionTest; 128.26 + 128.27 +/** 128.28 + * Tests the org.sonews.daemon package classes. 128.29 + * @author Christian Lins 128.30 + * @since sonews/0.5.0 128.31 + */ 128.32 +public class DaemonTests 128.33 +{ 128.34 + 128.35 + public static void main(String[] args) 128.36 + { 128.37 + System.out.println("NNTPConnectionTest"); 128.38 + TestRunner.run(NNTPConnectionTest.class); 128.39 + } 128.40 + 128.41 +}
129.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 129.2 +++ b/test/unit/UtilTests.java Fri Jun 26 16:48:50 2009 +0200 129.3 @@ -0,0 +1,47 @@ 129.4 +/* 129.5 + * StarOffice News Server 129.6 + * see AUTHORS for the list of contributors 129.7 + * 129.8 + * This program is free software: you can redistribute it and/or modify 129.9 + * it under the terms of the GNU General Public License as published by 129.10 + * the Free Software Foundation, either version 3 of the License, or 129.11 + * (at your option) any later version. 129.12 + * 129.13 + * This program is distributed in the hope that it will be useful, 129.14 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 129.15 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 129.16 + * GNU General Public License for more details. 129.17 + * 129.18 + * You should have received a copy of the GNU General Public License 129.19 + * along with this program. If not, see <http://www.gnu.org/licenses/>. 129.20 + */ 129.21 + 129.22 +package test.unit; 129.23 + 129.24 +import junit.textui.TestRunner; 129.25 +import test.unit.util.ResourceTest; 129.26 +import test.unit.util.StringTemplateTest; 129.27 +import test.unit.util.TimeoutMapTest; 129.28 + 129.29 + 129.30 +/** 129.31 + * Tests classes of package org.sonews.util. 129.32 + * @author Christian Lins 129.33 + * @since sonews/0.5.0 129.34 + */ 129.35 +public class UtilTests 129.36 +{ 129.37 + 129.38 + public static void main(String[] args) 129.39 + { 129.40 + System.out.println("StringTemplateTest"); 129.41 + TestRunner.run(StringTemplateTest.class); 129.42 + 129.43 + System.out.println("TimeoutMapTest"); 129.44 + TestRunner.run(TimeoutMapTest.class); 129.45 + 129.46 + System.out.println("ResourceTest"); 129.47 + TestRunner.run(ResourceTest.class); 129.48 + } 129.49 + 129.50 +}
130.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 130.2 +++ b/test/unit/daemon/NNTPConnectionTest.java Fri Jun 26 16:48:50 2009 +0200 130.3 @@ -0,0 +1,122 @@ 130.4 +/* 130.5 + * SONEWS News Server 130.6 + * see AUTHORS for the list of contributors 130.7 + * 130.8 + * This program is free software: you can redistribute it and/or modify 130.9 + * it under the terms of the GNU General Public License as published by 130.10 + * the Free Software Foundation, either version 3 of the License, or 130.11 + * (at your option) any later version. 130.12 + * 130.13 + * This program is distributed in the hope that it will be useful, 130.14 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 130.15 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 130.16 + * GNU General Public License for more details. 130.17 + * 130.18 + * You should have received a copy of the GNU General Public License 130.19 + * along with this program. If not, see <http://www.gnu.org/licenses/>. 130.20 + */ 130.21 + 130.22 +package test.unit.daemon; 130.23 + 130.24 +import java.io.IOException; 130.25 +import java.lang.reflect.InvocationTargetException; 130.26 +import java.lang.reflect.Method; 130.27 +import java.nio.channels.SocketChannel; 130.28 +import junit.framework.TestCase; 130.29 +import org.sonews.daemon.NNTPConnection; 130.30 +import org.sonews.daemon.command.ArticleCommand; 130.31 +import org.sonews.daemon.command.CapabilitiesCommand; 130.32 +import org.sonews.daemon.command.GroupCommand; 130.33 +import org.sonews.daemon.command.UnsupportedCommand; 130.34 + 130.35 +/** 130.36 + * Unit test for class NNTPConnection. 130.37 + * @author Christian Lins 130.38 + * @since sonews/0.5.0 130.39 + */ 130.40 +public class NNTPConnectionTest extends TestCase 130.41 +{ 130.42 + 130.43 + public void testLineReceived() 130.44 + throws NoSuchMethodException, IllegalAccessException, InvocationTargetException 130.45 + { 130.46 + NNTPConnection conn = null; 130.47 + 130.48 + try 130.49 + { 130.50 + try 130.51 + { 130.52 + conn = new NNTPConnection(null); 130.53 + fail("Should have raised an IllegalArgumentException"); 130.54 + } 130.55 + catch(IOException ex) {ex.printStackTrace();} 130.56 + } 130.57 + catch(IllegalArgumentException ex){} 130.58 + 130.59 + try 130.60 + { 130.61 + conn = new NNTPConnection(SocketChannel.open()); 130.62 + } 130.63 + catch(IOException ex) 130.64 + { 130.65 + ex.printStackTrace(); 130.66 + } 130.67 + 130.68 + assertNotNull(conn); 130.69 + 130.70 + // Make interesting methods accessible 130.71 + Class clazz = conn.getClass(); 130.72 + Method methTryReadLock = clazz.getDeclaredMethod("tryReadLock", null); 130.73 + methTryReadLock.setAccessible(true); 130.74 + Method methLineReceived = clazz.getDeclaredMethod("lineReceived", new byte[0].getClass()); 130.75 + methLineReceived.setAccessible(true); 130.76 + 130.77 + try 130.78 + { 130.79 + // conn.lineReceived(null); 130.80 + methLineReceived.invoke(conn, null); 130.81 + fail("Should have raised an IllegalArgumentException"); 130.82 + } 130.83 + catch(IllegalArgumentException ex){} 130.84 + 130.85 + try 130.86 + { 130.87 + // conn.lineReceived(new byte[0]); 130.88 + methLineReceived.invoke(conn, new byte[0]); 130.89 + fail("Should have raised IllegalStateException"); 130.90 + } 130.91 + catch(InvocationTargetException ex){} 130.92 + 130.93 + boolean tryReadLock = (Boolean)methTryReadLock.invoke(conn, null); 130.94 + assertTrue(tryReadLock); 130.95 + 130.96 + // conn.lineReceived("MODE READER".getBytes()); 130.97 + methLineReceived.invoke(conn, "MODE READER".getBytes()); 130.98 + 130.99 + // conn.lineReceived("sdkfsdjnfksjfdng ksdf gksjdfngk nskfng ksndfg ".getBytes()); 130.100 + methLineReceived.invoke(conn, "sdkfsdjnfksjfdng ksdf ksndfg ".getBytes()); 130.101 + 130.102 + // conn.lineReceived(new byte[1024]); // Too long 130.103 + methLineReceived.invoke(conn, new byte[1024]); 130.104 + 130.105 + Method mpcmdl = conn.getClass().getDeclaredMethod("parseCommandLine", String.class); 130.106 + mpcmdl.setAccessible(true); 130.107 + 130.108 + Object result = mpcmdl.invoke(conn, ""); 130.109 + assertNotNull(result); 130.110 + assertTrue(result instanceof UnsupportedCommand); 130.111 + 130.112 + result = mpcmdl.invoke(conn, "aRtiCle"); 130.113 + assertNotNull(result); 130.114 + assertTrue(result instanceof ArticleCommand); 130.115 + 130.116 + result = mpcmdl.invoke(conn, "capAbilItIEs"); 130.117 + assertNotNull(result); 130.118 + assertTrue(result instanceof CapabilitiesCommand); 130.119 + 130.120 + result = mpcmdl.invoke(conn, "grOUp"); 130.121 + assertNotNull(result); 130.122 + assertTrue(result instanceof GroupCommand); 130.123 + } 130.124 + 130.125 +}
131.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 131.2 +++ b/test/unit/daemon/package.html Fri Jun 26 16:48:50 2009 +0200 131.3 @@ -0,0 +1,1 @@ 131.4 +Contains Unittests for the org.sonews.daemon package. 131.5 \ No newline at end of file
132.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 132.2 +++ b/test/unit/package.html Fri Jun 26 16:48:50 2009 +0200 132.3 @@ -0,0 +1,1 @@ 132.4 +Root package for Unittest classes. 132.5 \ No newline at end of file
133.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 133.2 +++ b/test/unit/util/ResourceTest.java Fri Jun 26 16:48:50 2009 +0200 133.3 @@ -0,0 +1,80 @@ 133.4 +/* 133.5 + * SONEWS News Server 133.6 + * see AUTHORS for the list of contributors 133.7 + * 133.8 + * This program is free software: you can redistribute it and/or modify 133.9 + * it under the terms of the GNU General Public License as published by 133.10 + * the Free Software Foundation, either version 3 of the License, or 133.11 + * (at your option) any later version. 133.12 + * 133.13 + * This program is distributed in the hope that it will be useful, 133.14 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 133.15 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 133.16 + * GNU General Public License for more details. 133.17 + * 133.18 + * You should have received a copy of the GNU General Public License 133.19 + * along with this program. If not, see <http://www.gnu.org/licenses/>. 133.20 + */ 133.21 + 133.22 +package test.unit.util; 133.23 + 133.24 +import junit.framework.TestCase; 133.25 +import org.sonews.util.io.Resource; 133.26 + 133.27 +/** 133.28 + * Unit test for class org.sonews.util.io.Resource. 133.29 + * @author Christian Lins 133.30 + * @see org.sonews.util.io.Resource 133.31 + * @since sonews/0.5.0 133.32 + */ 133.33 +public class ResourceTest extends TestCase 133.34 +{ 133.35 + 133.36 + public void testGetAsURL() 133.37 + { 133.38 + Object url; 133.39 + 133.40 + url = Resource.getAsURL(null); 133.41 + assertNull(url); 133.42 + 133.43 + url = Resource.getAsURL("this is absolutely bullshit"); 133.44 + assertNull(url); 133.45 + 133.46 + // This file should exist 133.47 + url = Resource.getAsURL("org/sonews/daemon/Main.class"); 133.48 + assertNotNull(url); 133.49 + } 133.50 + 133.51 + public void testGetAsStream() 133.52 + { 133.53 + Object stream; 133.54 + 133.55 + stream = Resource.getAsStream(null); 133.56 + assertNull(stream); 133.57 + 133.58 + stream = Resource.getAsStream("this is bullshit"); 133.59 + assertNull(stream); 133.60 + 133.61 + stream = Resource.getAsStream("org/sonews/daemon/Main.class"); 133.62 + assertNotNull(stream); 133.63 + } 133.64 + 133.65 + public void testGetAsString() 133.66 + { 133.67 + String str; 133.68 + 133.69 + str = Resource.getAsString(null, true); 133.70 + assertNull(str); 133.71 + 133.72 + str = Resource.getAsString("this is bullshit", true); 133.73 + assertNull(str); 133.74 + 133.75 + str = Resource.getAsString("org/sonews/daemon/Main.class", true); 133.76 + assertNotNull(str); 133.77 + 133.78 + str = Resource.getAsString("org/sonews/daemon/Main.class", false); 133.79 + assertNotNull(str); 133.80 + assertEquals(str.indexOf("\n"), -1); 133.81 + } 133.82 + 133.83 +}
134.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 134.2 +++ b/test/unit/util/StringTemplateTest.java Fri Jun 26 16:48:50 2009 +0200 134.3 @@ -0,0 +1,91 @@ 134.4 +/* 134.5 + * SONEWS News Server 134.6 + * see AUTHORS for the list of contributors 134.7 + * 134.8 + * This program is free software: you can redistribute it and/or modify 134.9 + * it under the terms of the GNU General Public License as published by 134.10 + * the Free Software Foundation, either version 3 of the License, or 134.11 + * (at your option) any later version. 134.12 + * 134.13 + * This program is distributed in the hope that it will be useful, 134.14 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 134.15 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 134.16 + * GNU General Public License for more details. 134.17 + * 134.18 + * You should have received a copy of the GNU General Public License 134.19 + * along with this program. If not, see <http://www.gnu.org/licenses/>. 134.20 + */ 134.21 + 134.22 +package test.unit.util; 134.23 + 134.24 +import junit.framework.TestCase; 134.25 +import org.sonews.util.StringTemplate; 134.26 + 134.27 +/** 134.28 + * Unit test for class org.sonews.util.StringTemplate. 134.29 + * @author Christian Lins 134.30 + * @see org.sonews.util.StringTemplate 134.31 + * @since sonews/0.5.0 134.32 + */ 134.33 +public class StringTemplateTest extends TestCase 134.34 +{ 134.35 + 134.36 + private static final String template = "Hello %WORLD and others!"; 134.37 + 134.38 + public StringTemplateTest() 134.39 + { 134.40 + super("StringTemplateTest"); 134.41 + } 134.42 + 134.43 + public void testCtor() 134.44 + { 134.45 + StringTemplate st; 134.46 + 134.47 + try 134.48 + { 134.49 + st = new StringTemplate(null); 134.50 + fail("Should have raised an IllegalArgumentException"); 134.51 + } 134.52 + catch(IllegalArgumentException ex) {} 134.53 + 134.54 + st = new StringTemplate(template); 134.55 + assertNotNull(st); 134.56 + 134.57 + try 134.58 + { 134.59 + st = new StringTemplate(template, null); 134.60 + fail("Should have raised an IllegalArgumentException"); 134.61 + } 134.62 + catch(IllegalArgumentException ex) {} 134.63 + 134.64 + st = new StringTemplate(template, "?"); 134.65 + assertNotNull(st); 134.66 + 134.67 + st = new StringTemplate(template, "%"); 134.68 + assertNotNull(st); 134.69 + } 134.70 + 134.71 + public void testSetter() 134.72 + { 134.73 + StringTemplate st = new StringTemplate(template); 134.74 + 134.75 + try 134.76 + { 134.77 + st.set("WORLD", null); 134.78 + fail("Should have raised an IllegalArgumentException"); 134.79 + } 134.80 + catch(IllegalArgumentException ex){} 134.81 + 134.82 + st.set("WORLD", "Universe"); 134.83 + } 134.84 + 134.85 + public void testToString() 134.86 + { 134.87 + StringTemplate st = new StringTemplate(template); 134.88 + st.set("WORLD", "Universe"); 134.89 + 134.90 + String result = st.toString(); 134.91 + assertNotNull(result); 134.92 + } 134.93 + 134.94 +}
135.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 135.2 +++ b/test/unit/util/TimeoutMapTest.java Fri Jun 26 16:48:50 2009 +0200 135.3 @@ -0,0 +1,70 @@ 135.4 +/* 135.5 + * SONEWS News Server 135.6 + * see AUTHORS for the list of contributors 135.7 + * 135.8 + * This program is free software: you can redistribute it and/or modify 135.9 + * it under the terms of the GNU General Public License as published by 135.10 + * the Free Software Foundation, either version 3 of the License, or 135.11 + * (at your option) any later version. 135.12 + * 135.13 + * This program is distributed in the hope that it will be useful, 135.14 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 135.15 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 135.16 + * GNU General Public License for more details. 135.17 + * 135.18 + * You should have received a copy of the GNU General Public License 135.19 + * along with this program. If not, see <http://www.gnu.org/licenses/>. 135.20 + */ 135.21 + 135.22 +package test.unit.util; 135.23 + 135.24 +import junit.framework.TestCase; 135.25 +import org.sonews.util.TimeoutMap; 135.26 + 135.27 +/** 135.28 + * Unit test for class org.sonews.util.TimeoutMap. 135.29 + * @author Christian Lins 135.30 + * @since sonews/0.5.0 135.31 + * @see org.sonews.util.TimeoutMap 135.32 + */ 135.33 +public class TimeoutMapTest extends TestCase 135.34 +{ 135.35 + 135.36 + public TimeoutMapTest() 135.37 + { 135.38 + super("TimeoutMapTest"); 135.39 + } 135.40 + 135.41 + public void testTimeoutBehaviour() 135.42 + { 135.43 + TimeoutMap<String, Object> tm = new TimeoutMap<String, Object>(1000); 135.44 + Object testobj = new Object(); 135.45 + 135.46 + tm.put("testkey", testobj); 135.47 + 135.48 + assertNotNull(tm.get("testkey")); 135.49 + assertTrue(tm.containsKey("testkey")); 135.50 + assertTrue(tm.contains(testobj)); 135.51 + 135.52 + try 135.53 + { 135.54 + Thread.sleep(800); 135.55 + } 135.56 + catch(InterruptedException ex) { ex.printStackTrace(); } 135.57 + 135.58 + assertNotNull(tm.get("testkey")); 135.59 + assertTrue(tm.containsKey("testkey")); 135.60 + assertTrue(tm.contains(testobj)); 135.61 + 135.62 + try 135.63 + { 135.64 + Thread.sleep(200); 135.65 + } 135.66 + catch(InterruptedException ex) { ex.printStackTrace(); } 135.67 + 135.68 + assertNull(tm.get("testkey")); 135.69 + assertFalse(tm.containsKey("testkey")); 135.70 + assertFalse(tm.contains(testobj)); 135.71 + } 135.72 + 135.73 +}
136.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 136.2 +++ b/test/unit/util/package.html Fri Jun 26 16:48:50 2009 +0200 136.3 @@ -0,0 +1,1 @@ 136.4 +Contains Unittests for the package org.sonews.util. 136.5 \ No newline at end of file
137.1 --- a/trunk/AUTHORS Tue Jan 20 10:21:03 2009 +0100 137.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 137.3 @@ -1,26 +0,0 @@ 137.4 -AUTHORS & CREDITS 137.5 -================= 137.6 - 137.7 -As most software applications "StarOffice News Server" is based on the work 137.8 -of individuals or projects. These fine people contributing to the OpenSource 137.9 -community are mentioned here: 137.10 - 137.11 -StarOffice News Server 137.12 ----------------------- 137.13 -(c)Copyright 2009 by 137.14 - * Sun Microsystems, Inc. 137.15 - * Christian Lins <christian.lins@sun.com> 137.16 - 137.17 -based partly upon 137.18 - 137.19 -Neat NNTP Daemon (n3tpd) 137.20 ------------------------- 137.21 -(c)Copyright 2007, 2008 by Christian Lins <christian.lins@web.de> 137.22 - 137.23 -based partly upon 137.24 - 137.25 -tnntpd 137.26 ------- 137.27 -(c)Copyright 2003 by Dennis Schwerdel 137.28 - 137.29 -If you find someone missing here, please contact the project leader! 137.30 \ No newline at end of file
138.1 --- a/trunk/COPYING Tue Jan 20 10:21:03 2009 +0100 138.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 138.3 @@ -1,674 +0,0 @@ 138.4 - GNU GENERAL PUBLIC LICENSE 138.5 - Version 3, 29 June 2007 138.6 - 138.7 - Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/> 138.8 - Everyone is permitted to copy and distribute verbatim copies 138.9 - of this license document, but changing it is not allowed. 138.10 - 138.11 - Preamble 138.12 - 138.13 - The GNU General Public License is a free, copyleft license for 138.14 -software and other kinds of works. 138.15 - 138.16 - The licenses for most software and other practical works are designed 138.17 -to take away your freedom to share and change the works. By contrast, 138.18 -the GNU General Public License is intended to guarantee your freedom to 138.19 -share and change all versions of a program--to make sure it remains free 138.20 -software for all its users. We, the Free Software Foundation, use the 138.21 -GNU General Public License for most of our software; it applies also to 138.22 -any other work released this way by its authors. You can apply it to 138.23 -your programs, too. 138.24 - 138.25 - When we speak of free software, we are referring to freedom, not 138.26 -price. Our General Public Licenses are designed to make sure that you 138.27 -have the freedom to distribute copies of free software (and charge for 138.28 -them if you wish), that you receive source code or can get it if you 138.29 -want it, that you can change the software or use pieces of it in new 138.30 -free programs, and that you know you can do these things. 138.31 - 138.32 - To protect your rights, we need to prevent others from denying you 138.33 -these rights or asking you to surrender the rights. Therefore, you have 138.34 -certain responsibilities if you distribute copies of the software, or if 138.35 -you modify it: responsibilities to respect the freedom of others. 138.36 - 138.37 - For example, if you distribute copies of such a program, whether 138.38 -gratis or for a fee, you must pass on to the recipients the same 138.39 -freedoms that you received. You must make sure that they, too, receive 138.40 -or can get the source code. And you must show them these terms so they 138.41 -know their rights. 138.42 - 138.43 - Developers that use the GNU GPL protect your rights with two steps: 138.44 -(1) assert copyright on the software, and (2) offer you this License 138.45 -giving you legal permission to copy, distribute and/or modify it. 138.46 - 138.47 - For the developers' and authors' protection, the GPL clearly explains 138.48 -that there is no warranty for this free software. For both users' and 138.49 -authors' sake, the GPL requires that modified versions be marked as 138.50 -changed, so that their problems will not be attributed erroneously to 138.51 -authors of previous versions. 138.52 - 138.53 - Some devices are designed to deny users access to install or run 138.54 -modified versions of the software inside them, although the manufacturer 138.55 -can do so. This is fundamentally incompatible with the aim of 138.56 -protecting users' freedom to change the software. The systematic 138.57 -pattern of such abuse occurs in the area of products for individuals to 138.58 -use, which is precisely where it is most unacceptable. Therefore, we 138.59 -have designed this version of the GPL to prohibit the practice for those 138.60 -products. If such problems arise substantially in other domains, we 138.61 -stand ready to extend this provision to those domains in future versions 138.62 -of the GPL, as needed to protect the freedom of users. 138.63 - 138.64 - Finally, every program is threatened constantly by software patents. 138.65 -States should not allow patents to restrict development and use of 138.66 -software on general-purpose computers, but in those that do, we wish to 138.67 -avoid the special danger that patents applied to a free program could 138.68 -make it effectively proprietary. To prevent this, the GPL assures that 138.69 -patents cannot be used to render the program non-free. 138.70 - 138.71 - The precise terms and conditions for copying, distribution and 138.72 -modification follow. 138.73 - 138.74 - TERMS AND CONDITIONS 138.75 - 138.76 - 0. Definitions. 138.77 - 138.78 - "This License" refers to version 3 of the GNU General Public License. 138.79 - 138.80 - "Copyright" also means copyright-like laws that apply to other kinds of 138.81 -works, such as semiconductor masks. 138.82 - 138.83 - "The Program" refers to any copyrightable work licensed under this 138.84 -License. Each licensee is addressed as "you". "Licensees" and 138.85 -"recipients" may be individuals or organizations. 138.86 - 138.87 - To "modify" a work means to copy from or adapt all or part of the work 138.88 -in a fashion requiring copyright permission, other than the making of an 138.89 -exact copy. The resulting work is called a "modified version" of the 138.90 -earlier work or a work "based on" the earlier work. 138.91 - 138.92 - A "covered work" means either the unmodified Program or a work based 138.93 -on the Program. 138.94 - 138.95 - To "propagate" a work means to do anything with it that, without 138.96 -permission, would make you directly or secondarily liable for 138.97 -infringement under applicable copyright law, except executing it on a 138.98 -computer or modifying a private copy. Propagation includes copying, 138.99 -distribution (with or without modification), making available to the 138.100 -public, and in some countries other activities as well. 138.101 - 138.102 - To "convey" a work means any kind of propagation that enables other 138.103 -parties to make or receive copies. Mere interaction with a user through 138.104 -a computer network, with no transfer of a copy, is not conveying. 138.105 - 138.106 - An interactive user interface displays "Appropriate Legal Notices" 138.107 -to the extent that it includes a convenient and prominently visible 138.108 -feature that (1) displays an appropriate copyright notice, and (2) 138.109 -tells the user that there is no warranty for the work (except to the 138.110 -extent that warranties are provided), that licensees may convey the 138.111 -work under this License, and how to view a copy of this License. If 138.112 -the interface presents a list of user commands or options, such as a 138.113 -menu, a prominent item in the list meets this criterion. 138.114 - 138.115 - 1. Source Code. 138.116 - 138.117 - The "source code" for a work means the preferred form of the work 138.118 -for making modifications to it. "Object code" means any non-source 138.119 -form of a work. 138.120 - 138.121 - A "Standard Interface" means an interface that either is an official 138.122 -standard defined by a recognized standards body, or, in the case of 138.123 -interfaces specified for a particular programming language, one that 138.124 -is widely used among developers working in that language. 138.125 - 138.126 - The "System Libraries" of an executable work include anything, other 138.127 -than the work as a whole, that (a) is included in the normal form of 138.128 -packaging a Major Component, but which is not part of that Major 138.129 -Component, and (b) serves only to enable use of the work with that 138.130 -Major Component, or to implement a Standard Interface for which an 138.131 -implementation is available to the public in source code form. A 138.132 -"Major Component", in this context, means a major essential component 138.133 -(kernel, window system, and so on) of the specific operating system 138.134 -(if any) on which the executable work runs, or a compiler used to 138.135 -produce the work, or an object code interpreter used to run it. 138.136 - 138.137 - The "Corresponding Source" for a work in object code form means all 138.138 -the source code needed to generate, install, and (for an executable 138.139 -work) run the object code and to modify the work, including scripts to 138.140 -control those activities. However, it does not include the work's 138.141 -System Libraries, or general-purpose tools or generally available free 138.142 -programs which are used unmodified in performing those activities but 138.143 -which are not part of the work. For example, Corresponding Source 138.144 -includes interface definition files associated with source files for 138.145 -the work, and the source code for shared libraries and dynamically 138.146 -linked subprograms that the work is specifically designed to require, 138.147 -such as by intimate data communication or control flow between those 138.148 -subprograms and other parts of the work. 138.149 - 138.150 - The Corresponding Source need not include anything that users 138.151 -can regenerate automatically from other parts of the Corresponding 138.152 -Source. 138.153 - 138.154 - The Corresponding Source for a work in source code form is that 138.155 -same work. 138.156 - 138.157 - 2. Basic Permissions. 138.158 - 138.159 - All rights granted under this License are granted for the term of 138.160 -copyright on the Program, and are irrevocable provided the stated 138.161 -conditions are met. This License explicitly affirms your unlimited 138.162 -permission to run the unmodified Program. The output from running a 138.163 -covered work is covered by this License only if the output, given its 138.164 -content, constitutes a covered work. This License acknowledges your 138.165 -rights of fair use or other equivalent, as provided by copyright law. 138.166 - 138.167 - You may make, run and propagate covered works that you do not 138.168 -convey, without conditions so long as your license otherwise remains 138.169 -in force. You may convey covered works to others for the sole purpose 138.170 -of having them make modifications exclusively for you, or provide you 138.171 -with facilities for running those works, provided that you comply with 138.172 -the terms of this License in conveying all material for which you do 138.173 -not control copyright. Those thus making or running the covered works 138.174 -for you must do so exclusively on your behalf, under your direction 138.175 -and control, on terms that prohibit them from making any copies of 138.176 -your copyrighted material outside their relationship with you. 138.177 - 138.178 - Conveying under any other circumstances is permitted solely under 138.179 -the conditions stated below. Sublicensing is not allowed; section 10 138.180 -makes it unnecessary. 138.181 - 138.182 - 3. Protecting Users' Legal Rights From Anti-Circumvention Law. 138.183 - 138.184 - No covered work shall be deemed part of an effective technological 138.185 -measure under any applicable law fulfilling obligations under article 138.186 -11 of the WIPO copyright treaty adopted on 20 December 1996, or 138.187 -similar laws prohibiting or restricting circumvention of such 138.188 -measures. 138.189 - 138.190 - When you convey a covered work, you waive any legal power to forbid 138.191 -circumvention of technological measures to the extent such circumvention 138.192 -is effected by exercising rights under this License with respect to 138.193 -the covered work, and you disclaim any intention to limit operation or 138.194 -modification of the work as a means of enforcing, against the work's 138.195 -users, your or third parties' legal rights to forbid circumvention of 138.196 -technological measures. 138.197 - 138.198 - 4. Conveying Verbatim Copies. 138.199 - 138.200 - You may convey verbatim copies of the Program's source code as you 138.201 -receive it, in any medium, provided that you conspicuously and 138.202 -appropriately publish on each copy an appropriate copyright notice; 138.203 -keep intact all notices stating that this License and any 138.204 -non-permissive terms added in accord with section 7 apply to the code; 138.205 -keep intact all notices of the absence of any warranty; and give all 138.206 -recipients a copy of this License along with the Program. 138.207 - 138.208 - You may charge any price or no price for each copy that you convey, 138.209 -and you may offer support or warranty protection for a fee. 138.210 - 138.211 - 5. Conveying Modified Source Versions. 138.212 - 138.213 - You may convey a work based on the Program, or the modifications to 138.214 -produce it from the Program, in the form of source code under the 138.215 -terms of section 4, provided that you also meet all of these conditions: 138.216 - 138.217 - a) The work must carry prominent notices stating that you modified 138.218 - it, and giving a relevant date. 138.219 - 138.220 - b) The work must carry prominent notices stating that it is 138.221 - released under this License and any conditions added under section 138.222 - 7. This requirement modifies the requirement in section 4 to 138.223 - "keep intact all notices". 138.224 - 138.225 - c) You must license the entire work, as a whole, under this 138.226 - License to anyone who comes into possession of a copy. This 138.227 - License will therefore apply, along with any applicable section 7 138.228 - additional terms, to the whole of the work, and all its parts, 138.229 - regardless of how they are packaged. This License gives no 138.230 - permission to license the work in any other way, but it does not 138.231 - invalidate such permission if you have separately received it. 138.232 - 138.233 - d) If the work has interactive user interfaces, each must display 138.234 - Appropriate Legal Notices; however, if the Program has interactive 138.235 - interfaces that do not display Appropriate Legal Notices, your 138.236 - work need not make them do so. 138.237 - 138.238 - A compilation of a covered work with other separate and independent 138.239 -works, which are not by their nature extensions of the covered work, 138.240 -and which are not combined with it such as to form a larger program, 138.241 -in or on a volume of a storage or distribution medium, is called an 138.242 -"aggregate" if the compilation and its resulting copyright are not 138.243 -used to limit the access or legal rights of the compilation's users 138.244 -beyond what the individual works permit. Inclusion of a covered work 138.245 -in an aggregate does not cause this License to apply to the other 138.246 -parts of the aggregate. 138.247 - 138.248 - 6. Conveying Non-Source Forms. 138.249 - 138.250 - You may convey a covered work in object code form under the terms 138.251 -of sections 4 and 5, provided that you also convey the 138.252 -machine-readable Corresponding Source under the terms of this License, 138.253 -in one of these ways: 138.254 - 138.255 - a) Convey the object code in, or embodied in, a physical product 138.256 - (including a physical distribution medium), accompanied by the 138.257 - Corresponding Source fixed on a durable physical medium 138.258 - customarily used for software interchange. 138.259 - 138.260 - b) Convey the object code in, or embodied in, a physical product 138.261 - (including a physical distribution medium), accompanied by a 138.262 - written offer, valid for at least three years and valid for as 138.263 - long as you offer spare parts or customer support for that product 138.264 - model, to give anyone who possesses the object code either (1) a 138.265 - copy of the Corresponding Source for all the software in the 138.266 - product that is covered by this License, on a durable physical 138.267 - medium customarily used for software interchange, for a price no 138.268 - more than your reasonable cost of physically performing this 138.269 - conveying of source, or (2) access to copy the 138.270 - Corresponding Source from a network server at no charge. 138.271 - 138.272 - c) Convey individual copies of the object code with a copy of the 138.273 - written offer to provide the Corresponding Source. This 138.274 - alternative is allowed only occasionally and noncommercially, and 138.275 - only if you received the object code with such an offer, in accord 138.276 - with subsection 6b. 138.277 - 138.278 - d) Convey the object code by offering access from a designated 138.279 - place (gratis or for a charge), and offer equivalent access to the 138.280 - Corresponding Source in the same way through the same place at no 138.281 - further charge. You need not require recipients to copy the 138.282 - Corresponding Source along with the object code. If the place to 138.283 - copy the object code is a network server, the Corresponding Source 138.284 - may be on a different server (operated by you or a third party) 138.285 - that supports equivalent copying facilities, provided you maintain 138.286 - clear directions next to the object code saying where to find the 138.287 - Corresponding Source. Regardless of what server hosts the 138.288 - Corresponding Source, you remain obligated to ensure that it is 138.289 - available for as long as needed to satisfy these requirements. 138.290 - 138.291 - e) Convey the object code using peer-to-peer transmission, provided 138.292 - you inform other peers where the object code and Corresponding 138.293 - Source of the work are being offered to the general public at no 138.294 - charge under subsection 6d. 138.295 - 138.296 - A separable portion of the object code, whose source code is excluded 138.297 -from the Corresponding Source as a System Library, need not be 138.298 -included in conveying the object code work. 138.299 - 138.300 - A "User Product" is either (1) a "consumer product", which means any 138.301 -tangible personal property which is normally used for personal, family, 138.302 -or household purposes, or (2) anything designed or sold for incorporation 138.303 -into a dwelling. In determining whether a product is a consumer product, 138.304 -doubtful cases shall be resolved in favor of coverage. For a particular 138.305 -product received by a particular user, "normally used" refers to a 138.306 -typical or common use of that class of product, regardless of the status 138.307 -of the particular user or of the way in which the particular user 138.308 -actually uses, or expects or is expected to use, the product. A product 138.309 -is a consumer product regardless of whether the product has substantial 138.310 -commercial, industrial or non-consumer uses, unless such uses represent 138.311 -the only significant mode of use of the product. 138.312 - 138.313 - "Installation Information" for a User Product means any methods, 138.314 -procedures, authorization keys, or other information required to install 138.315 -and execute modified versions of a covered work in that User Product from 138.316 -a modified version of its Corresponding Source. The information must 138.317 -suffice to ensure that the continued functioning of the modified object 138.318 -code is in no case prevented or interfered with solely because 138.319 -modification has been made. 138.320 - 138.321 - If you convey an object code work under this section in, or with, or 138.322 -specifically for use in, a User Product, and the conveying occurs as 138.323 -part of a transaction in which the right of possession and use of the 138.324 -User Product is transferred to the recipient in perpetuity or for a 138.325 -fixed term (regardless of how the transaction is characterized), the 138.326 -Corresponding Source conveyed under this section must be accompanied 138.327 -by the Installation Information. But this requirement does not apply 138.328 -if neither you nor any third party retains the ability to install 138.329 -modified object code on the User Product (for example, the work has 138.330 -been installed in ROM). 138.331 - 138.332 - The requirement to provide Installation Information does not include a 138.333 -requirement to continue to provide support service, warranty, or updates 138.334 -for a work that has been modified or installed by the recipient, or for 138.335 -the User Product in which it has been modified or installed. Access to a 138.336 -network may be denied when the modification itself materially and 138.337 -adversely affects the operation of the network or violates the rules and 138.338 -protocols for communication across the network. 138.339 - 138.340 - Corresponding Source conveyed, and Installation Information provided, 138.341 -in accord with this section must be in a format that is publicly 138.342 -documented (and with an implementation available to the public in 138.343 -source code form), and must require no special password or key for 138.344 -unpacking, reading or copying. 138.345 - 138.346 - 7. Additional Terms. 138.347 - 138.348 - "Additional permissions" are terms that supplement the terms of this 138.349 -License by making exceptions from one or more of its conditions. 138.350 -Additional permissions that are applicable to the entire Program shall 138.351 -be treated as though they were included in this License, to the extent 138.352 -that they are valid under applicable law. If additional permissions 138.353 -apply only to part of the Program, that part may be used separately 138.354 -under those permissions, but the entire Program remains governed by 138.355 -this License without regard to the additional permissions. 138.356 - 138.357 - When you convey a copy of a covered work, you may at your option 138.358 -remove any additional permissions from that copy, or from any part of 138.359 -it. (Additional permissions may be written to require their own 138.360 -removal in certain cases when you modify the work.) You may place 138.361 -additional permissions on material, added by you to a covered work, 138.362 -for which you have or can give appropriate copyright permission. 138.363 - 138.364 - Notwithstanding any other provision of this License, for material you 138.365 -add to a covered work, you may (if authorized by the copyright holders of 138.366 -that material) supplement the terms of this License with terms: 138.367 - 138.368 - a) Disclaiming warranty or limiting liability differently from the 138.369 - terms of sections 15 and 16 of this License; or 138.370 - 138.371 - b) Requiring preservation of specified reasonable legal notices or 138.372 - author attributions in that material or in the Appropriate Legal 138.373 - Notices displayed by works containing it; or 138.374 - 138.375 - c) Prohibiting misrepresentation of the origin of that material, or 138.376 - requiring that modified versions of such material be marked in 138.377 - reasonable ways as different from the original version; or 138.378 - 138.379 - d) Limiting the use for publicity purposes of names of licensors or 138.380 - authors of the material; or 138.381 - 138.382 - e) Declining to grant rights under trademark law for use of some 138.383 - trade names, trademarks, or service marks; or 138.384 - 138.385 - f) Requiring indemnification of licensors and authors of that 138.386 - material by anyone who conveys the material (or modified versions of 138.387 - it) with contractual assumptions of liability to the recipient, for 138.388 - any liability that these contractual assumptions directly impose on 138.389 - those licensors and authors. 138.390 - 138.391 - All other non-permissive additional terms are considered "further 138.392 -restrictions" within the meaning of section 10. If the Program as you 138.393 -received it, or any part of it, contains a notice stating that it is 138.394 -governed by this License along with a term that is a further 138.395 -restriction, you may remove that term. If a license document contains 138.396 -a further restriction but permits relicensing or conveying under this 138.397 -License, you may add to a covered work material governed by the terms 138.398 -of that license document, provided that the further restriction does 138.399 -not survive such relicensing or conveying. 138.400 - 138.401 - If you add terms to a covered work in accord with this section, you 138.402 -must place, in the relevant source files, a statement of the 138.403 -additional terms that apply to those files, or a notice indicating 138.404 -where to find the applicable terms. 138.405 - 138.406 - Additional terms, permissive or non-permissive, may be stated in the 138.407 -form of a separately written license, or stated as exceptions; 138.408 -the above requirements apply either way. 138.409 - 138.410 - 8. Termination. 138.411 - 138.412 - You may not propagate or modify a covered work except as expressly 138.413 -provided under this License. Any attempt otherwise to propagate or 138.414 -modify it is void, and will automatically terminate your rights under 138.415 -this License (including any patent licenses granted under the third 138.416 -paragraph of section 11). 138.417 - 138.418 - However, if you cease all violation of this License, then your 138.419 -license from a particular copyright holder is reinstated (a) 138.420 -provisionally, unless and until the copyright holder explicitly and 138.421 -finally terminates your license, and (b) permanently, if the copyright 138.422 -holder fails to notify you of the violation by some reasonable means 138.423 -prior to 60 days after the cessation. 138.424 - 138.425 - Moreover, your license from a particular copyright holder is 138.426 -reinstated permanently if the copyright holder notifies you of the 138.427 -violation by some reasonable means, this is the first time you have 138.428 -received notice of violation of this License (for any work) from that 138.429 -copyright holder, and you cure the violation prior to 30 days after 138.430 -your receipt of the notice. 138.431 - 138.432 - Termination of your rights under this section does not terminate the 138.433 -licenses of parties who have received copies or rights from you under 138.434 -this License. If your rights have been terminated and not permanently 138.435 -reinstated, you do not qualify to receive new licenses for the same 138.436 -material under section 10. 138.437 - 138.438 - 9. Acceptance Not Required for Having Copies. 138.439 - 138.440 - You are not required to accept this License in order to receive or 138.441 -run a copy of the Program. Ancillary propagation of a covered work 138.442 -occurring solely as a consequence of using peer-to-peer transmission 138.443 -to receive a copy likewise does not require acceptance. However, 138.444 -nothing other than this License grants you permission to propagate or 138.445 -modify any covered work. These actions infringe copyright if you do 138.446 -not accept this License. Therefore, by modifying or propagating a 138.447 -covered work, you indicate your acceptance of this License to do so. 138.448 - 138.449 - 10. Automatic Licensing of Downstream Recipients. 138.450 - 138.451 - Each time you convey a covered work, the recipient automatically 138.452 -receives a license from the original licensors, to run, modify and 138.453 -propagate that work, subject to this License. You are not responsible 138.454 -for enforcing compliance by third parties with this License. 138.455 - 138.456 - An "entity transaction" is a transaction transferring control of an 138.457 -organization, or substantially all assets of one, or subdividing an 138.458 -organization, or merging organizations. If propagation of a covered 138.459 -work results from an entity transaction, each party to that 138.460 -transaction who receives a copy of the work also receives whatever 138.461 -licenses to the work the party's predecessor in interest had or could 138.462 -give under the previous paragraph, plus a right to possession of the 138.463 -Corresponding Source of the work from the predecessor in interest, if 138.464 -the predecessor has it or can get it with reasonable efforts. 138.465 - 138.466 - You may not impose any further restrictions on the exercise of the 138.467 -rights granted or affirmed under this License. For example, you may 138.468 -not impose a license fee, royalty, or other charge for exercise of 138.469 -rights granted under this License, and you may not initiate litigation 138.470 -(including a cross-claim or counterclaim in a lawsuit) alleging that 138.471 -any patent claim is infringed by making, using, selling, offering for 138.472 -sale, or importing the Program or any portion of it. 138.473 - 138.474 - 11. Patents. 138.475 - 138.476 - A "contributor" is a copyright holder who authorizes use under this 138.477 -License of the Program or a work on which the Program is based. The 138.478 -work thus licensed is called the contributor's "contributor version". 138.479 - 138.480 - A contributor's "essential patent claims" are all patent claims 138.481 -owned or controlled by the contributor, whether already acquired or 138.482 -hereafter acquired, that would be infringed by some manner, permitted 138.483 -by this License, of making, using, or selling its contributor version, 138.484 -but do not include claims that would be infringed only as a 138.485 -consequence of further modification of the contributor version. For 138.486 -purposes of this definition, "control" includes the right to grant 138.487 -patent sublicenses in a manner consistent with the requirements of 138.488 -this License. 138.489 - 138.490 - Each contributor grants you a non-exclusive, worldwide, royalty-free 138.491 -patent license under the contributor's essential patent claims, to 138.492 -make, use, sell, offer for sale, import and otherwise run, modify and 138.493 -propagate the contents of its contributor version. 138.494 - 138.495 - In the following three paragraphs, a "patent license" is any express 138.496 -agreement or commitment, however denominated, not to enforce a patent 138.497 -(such as an express permission to practice a patent or covenant not to 138.498 -sue for patent infringement). To "grant" such a patent license to a 138.499 -party means to make such an agreement or commitment not to enforce a 138.500 -patent against the party. 138.501 - 138.502 - If you convey a covered work, knowingly relying on a patent license, 138.503 -and the Corresponding Source of the work is not available for anyone 138.504 -to copy, free of charge and under the terms of this License, through a 138.505 -publicly available network server or other readily accessible means, 138.506 -then you must either (1) cause the Corresponding Source to be so 138.507 -available, or (2) arrange to deprive yourself of the benefit of the 138.508 -patent license for this particular work, or (3) arrange, in a manner 138.509 -consistent with the requirements of this License, to extend the patent 138.510 -license to downstream recipients. "Knowingly relying" means you have 138.511 -actual knowledge that, but for the patent license, your conveying the 138.512 -covered work in a country, or your recipient's use of the covered work 138.513 -in a country, would infringe one or more identifiable patents in that 138.514 -country that you have reason to believe are valid. 138.515 - 138.516 - If, pursuant to or in connection with a single transaction or 138.517 -arrangement, you convey, or propagate by procuring conveyance of, a 138.518 -covered work, and grant a patent license to some of the parties 138.519 -receiving the covered work authorizing them to use, propagate, modify 138.520 -or convey a specific copy of the covered work, then the patent license 138.521 -you grant is automatically extended to all recipients of the covered 138.522 -work and works based on it. 138.523 - 138.524 - A patent license is "discriminatory" if it does not include within 138.525 -the scope of its coverage, prohibits the exercise of, or is 138.526 -conditioned on the non-exercise of one or more of the rights that are 138.527 -specifically granted under this License. You may not convey a covered 138.528 -work if you are a party to an arrangement with a third party that is 138.529 -in the business of distributing software, under which you make payment 138.530 -to the third party based on the extent of your activity of conveying 138.531 -the work, and under which the third party grants, to any of the 138.532 -parties who would receive the covered work from you, a discriminatory 138.533 -patent license (a) in connection with copies of the covered work 138.534 -conveyed by you (or copies made from those copies), or (b) primarily 138.535 -for and in connection with specific products or compilations that 138.536 -contain the covered work, unless you entered into that arrangement, 138.537 -or that patent license was granted, prior to 28 March 2007. 138.538 - 138.539 - Nothing in this License shall be construed as excluding or limiting 138.540 -any implied license or other defenses to infringement that may 138.541 -otherwise be available to you under applicable patent law. 138.542 - 138.543 - 12. No Surrender of Others' Freedom. 138.544 - 138.545 - If conditions are imposed on you (whether by court order, agreement or 138.546 -otherwise) that contradict the conditions of this License, they do not 138.547 -excuse you from the conditions of this License. If you cannot convey a 138.548 -covered work so as to satisfy simultaneously your obligations under this 138.549 -License and any other pertinent obligations, then as a consequence you may 138.550 -not convey it at all. For example, if you agree to terms that obligate you 138.551 -to collect a royalty for further conveying from those to whom you convey 138.552 -the Program, the only way you could satisfy both those terms and this 138.553 -License would be to refrain entirely from conveying the Program. 138.554 - 138.555 - 13. Use with the GNU Affero General Public License. 138.556 - 138.557 - Notwithstanding any other provision of this License, you have 138.558 -permission to link or combine any covered work with a work licensed 138.559 -under version 3 of the GNU Affero General Public License into a single 138.560 -combined work, and to convey the resulting work. The terms of this 138.561 -License will continue to apply to the part which is the covered work, 138.562 -but the special requirements of the GNU Affero General Public License, 138.563 -section 13, concerning interaction through a network will apply to the 138.564 -combination as such. 138.565 - 138.566 - 14. Revised Versions of this License. 138.567 - 138.568 - The Free Software Foundation may publish revised and/or new versions of 138.569 -the GNU General Public License from time to time. Such new versions will 138.570 -be similar in spirit to the present version, but may differ in detail to 138.571 -address new problems or concerns. 138.572 - 138.573 - Each version is given a distinguishing version number. If the 138.574 -Program specifies that a certain numbered version of the GNU General 138.575 -Public License "or any later version" applies to it, you have the 138.576 -option of following the terms and conditions either of that numbered 138.577 -version or of any later version published by the Free Software 138.578 -Foundation. If the Program does not specify a version number of the 138.579 -GNU General Public License, you may choose any version ever published 138.580 -by the Free Software Foundation. 138.581 - 138.582 - If the Program specifies that a proxy can decide which future 138.583 -versions of the GNU General Public License can be used, that proxy's 138.584 -public statement of acceptance of a version permanently authorizes you 138.585 -to choose that version for the Program. 138.586 - 138.587 - Later license versions may give you additional or different 138.588 -permissions. However, no additional obligations are imposed on any 138.589 -author or copyright holder as a result of your choosing to follow a 138.590 -later version. 138.591 - 138.592 - 15. Disclaimer of Warranty. 138.593 - 138.594 - THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY 138.595 -APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT 138.596 -HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY 138.597 -OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, 138.598 -THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 138.599 -PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM 138.600 -IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF 138.601 -ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 138.602 - 138.603 - 16. Limitation of Liability. 138.604 - 138.605 - IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING 138.606 -WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS 138.607 -THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY 138.608 -GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE 138.609 -USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF 138.610 -DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD 138.611 -PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), 138.612 -EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF 138.613 -SUCH DAMAGES. 138.614 - 138.615 - 17. Interpretation of Sections 15 and 16. 138.616 - 138.617 - If the disclaimer of warranty and limitation of liability provided 138.618 -above cannot be given local legal effect according to their terms, 138.619 -reviewing courts shall apply local law that most closely approximates 138.620 -an absolute waiver of all civil liability in connection with the 138.621 -Program, unless a warranty or assumption of liability accompanies a 138.622 -copy of the Program in return for a fee. 138.623 - 138.624 - END OF TERMS AND CONDITIONS 138.625 - 138.626 - How to Apply These Terms to Your New Programs 138.627 - 138.628 - If you develop a new program, and you want it to be of the greatest 138.629 -possible use to the public, the best way to achieve this is to make it 138.630 -free software which everyone can redistribute and change under these terms. 138.631 - 138.632 - To do so, attach the following notices to the program. It is safest 138.633 -to attach them to the start of each source file to most effectively 138.634 -state the exclusion of warranty; and each file should have at least 138.635 -the "copyright" line and a pointer to where the full notice is found. 138.636 - 138.637 - <one line to give the program's name and a brief idea of what it does.> 138.638 - Copyright (C) <year> <name of author> 138.639 - 138.640 - This program is free software: you can redistribute it and/or modify 138.641 - it under the terms of the GNU General Public License as published by 138.642 - the Free Software Foundation, either version 3 of the License, or 138.643 - (at your option) any later version. 138.644 - 138.645 - This program is distributed in the hope that it will be useful, 138.646 - but WITHOUT ANY WARRANTY; without even the implied warranty of 138.647 - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 138.648 - GNU General Public License for more details. 138.649 - 138.650 - You should have received a copy of the GNU General Public License 138.651 - along with this program. If not, see <http://www.gnu.org/licenses/>. 138.652 - 138.653 -Also add information on how to contact you by electronic and paper mail. 138.654 - 138.655 - If the program does terminal interaction, make it output a short 138.656 -notice like this when it starts in an interactive mode: 138.657 - 138.658 - <program> Copyright (C) <year> <name of author> 138.659 - This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. 138.660 - This is free software, and you are welcome to redistribute it 138.661 - under certain conditions; type `show c' for details. 138.662 - 138.663 -The hypothetical commands `show w' and `show c' should show the appropriate 138.664 -parts of the General Public License. Of course, your program's commands 138.665 -might be different; for a GUI interface, you would use an "about box". 138.666 - 138.667 - You should also get your employer (if you work as a programmer) or school, 138.668 -if any, to sign a "copyright disclaimer" for the program, if necessary. 138.669 -For more information on this, and how to apply and follow the GNU GPL, see 138.670 -<http://www.gnu.org/licenses/>. 138.671 - 138.672 - The GNU General Public License does not permit incorporating your program 138.673 -into proprietary programs. If your program is a subroutine library, you 138.674 -may consider it more useful to permit linking proprietary applications with 138.675 -the library. If this is what you want to do, use the GNU Lesser General 138.676 -Public License instead of this License. But first, please read 138.677 -<http://www.gnu.org/philosophy/why-not-lgpl.html>. 138.678 \ No newline at end of file
139.1 --- a/trunk/README Tue Jan 20 10:21:03 2009 +0100 139.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 139.3 @@ -1,24 +0,0 @@ 139.4 -n3tpd README 139.5 -============ 139.6 - 139.7 -Prerequisites: 139.8 --------------- 139.9 - 139.10 -* Java Runtime, Version 1.5 139.11 -* MySQL, Version 5 or higher 139.12 -* Java-MySQL-Connector (JDBC driver) 139.13 - 139.14 - 139.15 -Installation: 139.16 -------------- 139.17 - 139.18 -* Create a database in your DBMS, e.g. named like 'n3tpd_data' 139.19 -* Create the necessary table structure using the helpers/table.sql file 139.20 -* Customize the settings within the n3tpd.conf file 139.21 -* Invoke 'java -jar n3tpd.jar' to start the daemon 139.22 - 139.23 -Bugs and other Issues: 139.24 ----------------------- 139.25 - 139.26 -Please mail them to christian.lins@web.de or, better, issue them 139.27 -into our bugtracker at http://bugs.netvader.net/ . 139.28 \ No newline at end of file
140.1 --- a/trunk/TODO Tue Jan 20 10:21:03 2009 +0100 140.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 140.3 @@ -1,10 +0,0 @@ 140.4 -TODO 140.5 -==== 140.6 - 140.7 -* Implement new SQL table structure 140.8 -* Implement a --init-tables command that creates the necessary database/tables 140.9 - 140.10 -ROADMAP 140.11 -======= 140.12 - 140.13 -Version 1.0 must be fully RFC3977 compliant. 140.14 \ No newline at end of file
141.1 --- a/trunk/com/so/news/Config.java Tue Jan 20 10:21:03 2009 +0100 141.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 141.3 @@ -1,198 +0,0 @@ 141.4 -/* 141.5 - * StarOffice News Server 141.6 - * see AUTHORS for the list of contributors 141.7 - * 141.8 - * This program is free software: you can redistribute it and/or modify 141.9 - * it under the terms of the GNU General Public License as published by 141.10 - * the Free Software Foundation, either version 3 of the License, or 141.11 - * (at your option) any later version. 141.12 - * 141.13 - * This program is distributed in the hope that it will be useful, 141.14 - * but WITHOUT ANY WARRANTY; without even the implied warranty of 141.15 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 141.16 - * GNU General Public License for more details. 141.17 - * 141.18 - * You should have received a copy of the GNU General Public License 141.19 - * along with this program. If not, see <http://www.gnu.org/licenses/>. 141.20 - */ 141.21 - 141.22 -package com.so.news; 141.23 - 141.24 -import java.io.FileInputStream; 141.25 -import java.io.FileNotFoundException; 141.26 -import java.io.FileOutputStream; 141.27 -import java.io.IOException; 141.28 -import java.util.Properties; 141.29 - 141.30 -/** 141.31 - * Manages the n3tpd configuration. 141.32 - * @author Christian Lins 141.33 - */ 141.34 -public class Config 141.35 -{ 141.36 - /** The filename of the logfile */ 141.37 - public static final String CONFIG_N3TPD_LOGFILE = "n3tpd.logfile"; 141.38 - 141.39 - /** The filename of the config file that is loaded on startup */ 141.40 - public static final String FILE = "n3tpd.conf"; 141.41 - 141.42 - private static final Properties defaultConfig = new Properties(); 141.43 - 141.44 - private static Config instance = null; 141.45 - 141.46 - static 141.47 - { 141.48 - // Set some default values 141.49 - defaultConfig.setProperty("n3tpd.article.lifetime", "300"); // 300 days 141.50 - defaultConfig.setProperty("n3tpd.article.maxsize", "100"); // 100 kbyte 141.51 - defaultConfig.setProperty("n3tpd.port", "119"); 141.52 - defaultConfig.setProperty("n3tpd.auxport", "8080"); 141.53 - defaultConfig.setProperty("n3tpd.server.backlog", "10"); 141.54 - defaultConfig.setProperty("n3tpd.hostname", "localhost"); 141.55 - defaultConfig.setProperty("n3tpd.storage.database", "jdbc:mysql://localhost/n3tpd_data"); 141.56 - defaultConfig.setProperty("n3tpd.storage.dbmsdriver", "com.mysql.jdbc.Driver"); 141.57 - defaultConfig.setProperty("n3tpd.storage.user", "n3tpd_user"); 141.58 - defaultConfig.setProperty("n3tpd.storage.password", "mysecret"); 141.59 - 141.60 - instance = new Config(); 141.61 - } 141.62 - 141.63 - /** 141.64 - * @return A Config instance 141.65 - */ 141.66 - public static Config getInstance() 141.67 - { 141.68 - return instance; 141.69 - } 141.70 - 141.71 - // Every config instance is initialized with the default values. 141.72 - private Properties settings = (Properties)defaultConfig.clone(); 141.73 - 141.74 - /** 141.75 - * Config is a singelton class with only one instance at time. 141.76 - * So the constructor is private to prevent the creation of more 141.77 - * then one Config instance. 141.78 - * @see Config.getInstance() to retrieve an instance of Config 141.79 - */ 141.80 - private Config() 141.81 - { 141.82 - try 141.83 - { 141.84 - // Load settings from file 141.85 - load(); 141.86 - } 141.87 - catch(IOException e) 141.88 - { 141.89 - e.printStackTrace(); 141.90 - } 141.91 - } 141.92 - 141.93 - /** 141.94 - * Loads the configuration from the config file. By default this is done 141.95 - * by the (private) constructor but it can be useful to reload the config 141.96 - * by invoking this method. 141.97 - * @throws IOException 141.98 - */ 141.99 - public void load() throws IOException 141.100 - { 141.101 - try 141.102 - { 141.103 - settings.load(new FileInputStream(FILE)); 141.104 - } 141.105 - catch (FileNotFoundException e) 141.106 - { 141.107 - save(); 141.108 - } 141.109 - } 141.110 - 141.111 - /** 141.112 - * Saves this Config to the config file. By default this is done 141.113 - * at program end. 141.114 - * @throws FileNotFoundException 141.115 - * @throws IOException 141.116 - */ 141.117 - public void save() throws FileNotFoundException, IOException 141.118 - { 141.119 - settings.store(new FileOutputStream(FILE), "N3TPD Config File"); 141.120 - } 141.121 - 141.122 - /** 141.123 - * Returns the value that is stored within this config 141.124 - * identified by the given key. If the key cannot be found 141.125 - * the default value is returned. 141.126 - * @param key Key to identify the value. 141.127 - * @param def The default value that is returned if the key 141.128 - * is not found in this Config. 141.129 - * @return 141.130 - */ 141.131 - public String get(String key, String def) 141.132 - { 141.133 - return settings.getProperty(key, def); 141.134 - } 141.135 - 141.136 - /** 141.137 - * Returns the value that is stored within this config 141.138 - * identified by the given key. If the key cannot be found 141.139 - * the default value is returned. 141.140 - * @param key Key to identify the value. 141.141 - * @param def The default value that is returned if the key 141.142 - * is not found in this Config. 141.143 - * @return 141.144 - */ 141.145 - public int get(String key, int def) 141.146 - { 141.147 - try 141.148 - { 141.149 - String val = get(key); 141.150 - return Integer.parseInt(val); 141.151 - } 141.152 - catch(Exception e) 141.153 - { 141.154 - return def; 141.155 - } 141.156 - } 141.157 - 141.158 - /** 141.159 - * Returns the value that is stored within this config 141.160 - * identified by the given key. If the key cannot be found 141.161 - * the default value is returned. 141.162 - * @param key Key to identify the value. 141.163 - * @param def The default value that is returned if the key 141.164 - * is not found in this Config. 141.165 - * @return 141.166 - */ 141.167 - public long get(String key, long def) 141.168 - { 141.169 - try 141.170 - { 141.171 - String val = get(key); 141.172 - return Long.parseLong(val); 141.173 - } 141.174 - catch(Exception e) 141.175 - { 141.176 - return def; 141.177 - } 141.178 - } 141.179 - 141.180 - /** 141.181 - * Returns the value for the given key or null if the 141.182 - * key is not found in this Config. 141.183 - * @param key 141.184 - * @return 141.185 - */ 141.186 - private String get(String key) 141.187 - { 141.188 - return settings.getProperty(key); 141.189 - } 141.190 - 141.191 - /** 141.192 - * Sets the value for a given key. 141.193 - * @param key 141.194 - * @param value 141.195 - */ 141.196 - public void set(String key, String value) 141.197 - { 141.198 - settings.setProperty(key, value); 141.199 - } 141.200 - 141.201 -}
142.1 --- a/trunk/com/so/news/Debug.java Tue Jan 20 10:21:03 2009 +0100 142.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 142.3 @@ -1,95 +0,0 @@ 142.4 -/* 142.5 - * StarOffice News Server 142.6 - * see AUTHORS for the list of contributors 142.7 - * 142.8 - * This program is free software: you can redistribute it and/or modify 142.9 - * it under the terms of the GNU General Public License as published by 142.10 - * the Free Software Foundation, either version 3 of the License, or 142.11 - * (at your option) any later version. 142.12 - * 142.13 - * This program is distributed in the hope that it will be useful, 142.14 - * but WITHOUT ANY WARRANTY; without even the implied warranty of 142.15 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 142.16 - * GNU General Public License for more details. 142.17 - * 142.18 - * You should have received a copy of the GNU General Public License 142.19 - * along with this program. If not, see <http://www.gnu.org/licenses/>. 142.20 - */ 142.21 - 142.22 -package com.so.news; 142.23 - 142.24 -import java.io.FileOutputStream; 142.25 -import java.io.IOException; 142.26 -import java.io.PrintStream; 142.27 -import java.util.Date; 142.28 - 142.29 -/** 142.30 - * Provides logging and debugging methods. 142.31 - * @author Christian Lins 142.32 - */ 142.33 -public class Debug 142.34 -{ 142.35 - private static Debug instance = null; 142.36 - 142.37 - /** 142.38 - * Returns the singelton instance of this class. 142.39 - */ 142.40 - public static Debug getInstance() 142.41 - { 142.42 - if(instance == null) 142.43 - instance = new Debug(); 142.44 - 142.45 - return instance; 142.46 - } 142.47 - 142.48 - private PrintStream out = System.err; 142.49 - 142.50 - /** 142.51 - * This class is a singelton class. The constructor is private to prevent 142.52 - * the creation of more than one instance. 142.53 - */ 142.54 - private Debug() 142.55 - { 142.56 - try 142.57 - { 142.58 - String filename = Config.getInstance().get(Config.CONFIG_N3TPD_LOGFILE, "n3tpd.log"); 142.59 - 142.60 - this.out = new PrintStream(new FileOutputStream(filename)); 142.61 - } 142.62 - catch(IOException e) 142.63 - { 142.64 - e.printStackTrace(); 142.65 - } 142.66 - } 142.67 - 142.68 - /** 142.69 - * Returns the debug output PrintStream. By default this is System.err. 142.70 - */ 142.71 - public PrintStream getStream() 142.72 - { 142.73 - return out; 142.74 - } 142.75 - 142.76 - /** 142.77 - * Writes the given message to the debug output. 142.78 - * @param msg A String message or an object. 142.79 - */ 142.80 - public void log(Object msg) 142.81 - { 142.82 - log(out, msg); 142.83 - log(System.out, msg); 142.84 - } 142.85 - 142.86 - /** 142.87 - * Writes the given debug message to the given PrintStream. 142.88 - * @param out 142.89 - * @param msg 142.90 - */ 142.91 - public void log(PrintStream out, Object msg) 142.92 - { 142.93 - out.print(new Date().toString()); 142.94 - out.print(": "); 142.95 - out.println(msg.toString()); 142.96 - out.flush(); 142.97 - } 142.98 -}
143.1 --- a/trunk/com/so/news/Main.java Tue Jan 20 10:21:03 2009 +0100 143.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 143.3 @@ -1,96 +0,0 @@ 143.4 -/* 143.5 - * StarOffice News Server 143.6 - * see AUTHORS for the list of contributors 143.7 - * 143.8 - * This program is free software: you can redistribute it and/or modify 143.9 - * it under the terms of the GNU General Public License as published by 143.10 - * the Free Software Foundation, either version 3 of the License, or 143.11 - * (at your option) any later version. 143.12 - * 143.13 - * This program is distributed in the hope that it will be useful, 143.14 - * but WITHOUT ANY WARRANTY; without even the implied warranty of 143.15 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 143.16 - * GNU General Public License for more details. 143.17 - * 143.18 - * You should have received a copy of the GNU General Public License 143.19 - * along with this program. If not, see <http://www.gnu.org/licenses/>. 143.20 - */ 143.21 - 143.22 -package com.so.news; 143.23 - 143.24 -import java.net.BindException; 143.25 - 143.26 -import java.sql.Driver; 143.27 -import java.sql.DriverManager; 143.28 -import java.util.Enumeration; 143.29 - 143.30 -import com.so.news.storage.Database; 143.31 -import com.so.news.storage.Purger; 143.32 - 143.33 -/** 143.34 - * Startup class of the daemon. 143.35 - * @author Christian Lins 143.36 - */ 143.37 -public class Main 143.38 -{ 143.39 - /** Version information of the StarOffice News daemon */ 143.40 - public static final String VERSION = "StarOffice News Server 0.5alpha1"; 143.41 - 143.42 - /** 143.43 - * The main entrypoint. 143.44 - * @param args 143.45 - * @throws Exception 143.46 - */ 143.47 - public static void main(String args[]) throws Exception 143.48 - { 143.49 - System.out.println(VERSION); 143.50 - 143.51 - // Command line arguments 143.52 - boolean auxPort = false; 143.53 - 143.54 - for(int n = 0; n < args.length; n++) 143.55 - { 143.56 - if(args[n].equals("--dumpjdbcdriver")) 143.57 - { 143.58 - System.out.println("Available JDBC drivers:"); 143.59 - Enumeration<Driver> drvs = DriverManager.getDrivers(); 143.60 - while(drvs.hasMoreElements()) 143.61 - System.out.println(drvs.nextElement()); 143.62 - return; 143.63 - } 143.64 - else if(args[n].equals("--useaux")) 143.65 - auxPort = true; 143.66 - } 143.67 - 143.68 - // Try to load the Database 143.69 - try 143.70 - { 143.71 - Database.arise(); 143.72 - } 143.73 - catch(Exception ex) 143.74 - { 143.75 - ex.printStackTrace(Debug.getInstance().getStream()); 143.76 - System.err.println("Database initialization failed with " + ex.toString()); 143.77 - 143.78 - return; 143.79 - } 143.80 - 143.81 - // Start the n3tpd garbage collector 143.82 - new Purger().start(); 143.83 - 143.84 - // Start the listening daemon 143.85 - try 143.86 - { 143.87 - new NNTPDaemon(false).start(); 143.88 - } 143.89 - catch(BindException ex) 143.90 - { 143.91 - ex.printStackTrace(Debug.getInstance().getStream()); 143.92 - System.err.println("Could not bind to interface. Perhaps you need superuser rights?"); 143.93 - } 143.94 - 143.95 - // Start auxilary listening port... 143.96 - if(auxPort) 143.97 - new NNTPDaemon(true).start(); 143.98 - } 143.99 -}
144.1 --- a/trunk/com/so/news/NNTPConnection.java Tue Jan 20 10:21:03 2009 +0100 144.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 144.3 @@ -1,395 +0,0 @@ 144.4 -/* 144.5 - * StarOffice News Server 144.6 - * see AUTHORS for the list of contributors 144.7 - * 144.8 - * This program is free software: you can redistribute it and/or modify 144.9 - * it under the terms of the GNU General Public License as published by 144.10 - * the Free Software Foundation, either version 3 of the License, or 144.11 - * (at your option) any later version. 144.12 - * 144.13 - * This program is distributed in the hope that it will be useful, 144.14 - * but WITHOUT ANY WARRANTY; without even the implied warranty of 144.15 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 144.16 - * GNU General Public License for more details. 144.17 - * 144.18 - * You should have received a copy of the GNU General Public License 144.19 - * along with this program. If not, see <http://www.gnu.org/licenses/>. 144.20 - */ 144.21 - 144.22 -package com.so.news; 144.23 - 144.24 -import java.io.BufferedReader; 144.25 -import java.io.BufferedWriter; 144.26 -import java.io.File; 144.27 -import java.io.InputStreamReader; 144.28 -import java.io.IOException; 144.29 -import java.io.OutputStreamWriter; 144.30 -import java.net.Socket; 144.31 -import java.net.SocketException; 144.32 -import java.text.SimpleDateFormat; 144.33 -import java.util.Date; 144.34 -import java.util.LinkedList; 144.35 -import java.util.List; 144.36 -import com.so.news.command.ArticleCommand; 144.37 -import com.so.news.command.GroupCommand; 144.38 -import com.so.news.command.ListCommand; 144.39 -import com.so.news.command.PostCommand; 144.40 -import com.so.news.command.OverCommand; 144.41 -import com.so.news.storage.Article; 144.42 -import com.so.news.storage.Group; 144.43 - 144.44 -/** 144.45 - * Represents the connection between the server and one client. 144.46 - * @author Christian Lins (christian.lins@web.de) 144.47 - */ 144.48 -public class NNTPConnection extends Thread 144.49 -{ 144.50 - public static final String NEWLINE = "\r\n"; 144.51 - public static final String MESSAGE_ID_PATTERN = "<[^>]+>"; 144.52 - 144.53 - private boolean debug 144.54 - = Boolean.parseBoolean(Config.getInstance().get("n3tpd.debug", "false")); 144.55 - private Socket socket; 144.56 - private boolean exit = false; 144.57 - private BufferedWriter out; 144.58 - private BufferedReader in; 144.59 - private Article currentArticle = null; 144.60 - private Group currentGroup = null; 144.61 - 144.62 - /** 144.63 - * Creates a new NNTPConnection instance using the given connected Socket. 144.64 - * @param socket 144.65 - * @throws java.io.IOException 144.66 - */ 144.67 - public NNTPConnection(Socket socket) 144.68 - throws IOException 144.69 - { 144.70 - this.socket = socket; 144.71 - this.in = new BufferedReader(new InputStreamReader(socket.getInputStream())); 144.72 - this.out = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream())); 144.73 - // TODO: The output stream should be of type PrintStream so that many 144.74 - // of the printX() methods of this class can go to trash 144.75 - 144.76 - setDaemon(true); // Exits if the main thread is killed 144.77 - } 144.78 - 144.79 - /** 144.80 - * Closes the associated socket end exits the Thread. 144.81 - */ 144.82 - public void exit() 144.83 - { 144.84 - try 144.85 - { 144.86 - exit = true; 144.87 - socket.close(); 144.88 - } 144.89 - catch (Exception e) 144.90 - { 144.91 - e.printStackTrace(); 144.92 - } 144.93 - } 144.94 - 144.95 - /** 144.96 - * Prints a CharSequence to the sockets output stream. 144.97 - */ 144.98 - public void print(CharSequence s) throws IOException 144.99 - { 144.100 - out.append(s); 144.101 - } 144.102 - 144.103 - public void println(CharSequence s) throws IOException 144.104 - { 144.105 - print(s); 144.106 - print(NEWLINE); 144.107 - if (debug) 144.108 - System.out.println("<<< " + s); 144.109 - } 144.110 - 144.111 - public void printStatus(int code, String description) throws IOException 144.112 - { 144.113 - println("" + code + " " + description); 144.114 - flush(); 144.115 - } 144.116 - 144.117 - public void printTextLine(CharSequence line) throws IOException 144.118 - { 144.119 - if (line.length() > 0 && line.charAt(0) == '.') 144.120 - print(".."); 144.121 - println(line); 144.122 - } 144.123 - 144.124 - public void printTextPart(CharSequence text) throws IOException 144.125 - { 144.126 - String[] lines = text.toString().split(NEWLINE); 144.127 - for (String line : lines) 144.128 - printTextLine(line); 144.129 - } 144.130 - 144.131 - public void printText(CharSequence text) throws IOException 144.132 - { 144.133 - printTextPart(text); 144.134 - println("."); 144.135 - flush(); 144.136 - } 144.137 - 144.138 - public void flush() throws IOException 144.139 - { 144.140 - out.flush(); 144.141 - } 144.142 - 144.143 - public String readln() throws IOException 144.144 - { 144.145 - String s = in.readLine(); 144.146 - if (s == null) 144.147 - throw new IOException("Socket closed"); 144.148 - if (debug) 144.149 - System.out.println(">>> " + s); 144.150 - return s; 144.151 - } 144.152 - 144.153 - public String[] readCommand() throws IOException 144.154 - { 144.155 - return readln().split("[ ]+"); 144.156 - } 144.157 - 144.158 - public List<String> readText() throws IOException 144.159 - { 144.160 - List<String> l = new LinkedList<String>(); 144.161 - String s; 144.162 - do 144.163 - { 144.164 - s = readln(); 144.165 - if (!s.equals(".")) 144.166 - { 144.167 - if (s.startsWith("..")) 144.168 - s = s.substring(1); 144.169 - l.add(s); 144.170 - } 144.171 - } 144.172 - while (!s.equals(".")); 144.173 - return l; 144.174 - } 144.175 - 144.176 - public String readTextLine() throws IOException 144.177 - { 144.178 - String s = null; 144.179 - do 144.180 - { 144.181 - s = readln(); 144.182 - } 144.183 - while (s == null); 144.184 - if (s.equals(".")) 144.185 - return null; 144.186 - if (s.startsWith("..")) 144.187 - s = s.substring(1); 144.188 - return s; 144.189 - } 144.190 - 144.191 - public void setCurrentArticle(Article current) 144.192 - { 144.193 - currentArticle = current; 144.194 - } 144.195 - 144.196 - public Article getCurrentArticle() 144.197 - { 144.198 - return currentArticle; 144.199 - } 144.200 - 144.201 - public void setCurrentGroup(Group current) 144.202 - { 144.203 - currentGroup = current; 144.204 - } 144.205 - 144.206 - public Group getCurrentGroup() 144.207 - { 144.208 - return currentGroup; 144.209 - } 144.210 - 144.211 - private void processCommand(String[] command) 144.212 - throws Exception 144.213 - { 144.214 - if (command.length == 0) 144.215 - return; // TODO Error 144.216 - 144.217 - String commandName = command[0]; 144.218 - 144.219 - // RFC977 144.220 - // TODO HELP command 144.221 - // TODO NEWGROUPS command 144.222 - // TODO NEWNEWS command 144.223 - 144.224 - // RFC2980 144.225 - // TODO LIST ACTIVE command 144.226 - // TODO LIST ACTIVE.TIMES command 144.227 - // TODO LIST DISTRIBUTIONS command 144.228 - // TODO LIST DISTRIB.PATS command 144.229 - // TODO XGTITLE command 144.230 - // TODO XHDR command 144.231 - // TODO XPAT command 144.232 - // TODO XPATH command 144.233 - // TODO XROVER command 144.234 - // TODO XTHREAD command 144.235 - // TODO AUTHINFO command 144.236 - 144.237 - // STANDARD COMMANDS 144.238 - if (commandName.equalsIgnoreCase("ARTICLE") 144.239 - || commandName.equalsIgnoreCase("STAT") 144.240 - || commandName.equalsIgnoreCase("HEAD") 144.241 - || commandName.equalsIgnoreCase("BODY")) 144.242 - { 144.243 - ArticleCommand cmd = new ArticleCommand(this); 144.244 - cmd.process(command); 144.245 - } 144.246 - 144.247 - else if (commandName.equalsIgnoreCase("LIST")) 144.248 - { 144.249 - ListCommand cmd = new ListCommand(this); 144.250 - cmd.process(command); 144.251 - } 144.252 - 144.253 - else if (commandName.equalsIgnoreCase("GROUP")) 144.254 - { 144.255 - GroupCommand cmd = new GroupCommand(this); 144.256 - cmd.process(command); 144.257 - } 144.258 - 144.259 - else if(commandName.equalsIgnoreCase("POST")) 144.260 - { 144.261 - PostCommand cmd = new PostCommand(this); 144.262 - cmd.process(command); 144.263 - } 144.264 - 144.265 - else if (commandName.equalsIgnoreCase("CHECK") 144.266 - || commandName.equalsIgnoreCase("TAKETHIS")) 144.267 - { 144.268 - // untested, RFC2980 compliant 144.269 - printStatus(400, "not accepting articles"); 144.270 - return; 144.271 - } 144.272 - 144.273 - else if (commandName.equalsIgnoreCase("IHAVE") 144.274 - || commandName.equalsIgnoreCase("XREPLIC")) 144.275 - { 144.276 - // untested, RFC977 compliant 144.277 - printStatus(435, "article not wanted - do not send it"); 144.278 - return; 144.279 - } 144.280 - 144.281 - else if (commandName.equalsIgnoreCase("XCREATEGROUP")) 144.282 - { 144.283 - return; 144.284 - } 144.285 - 144.286 - else if (commandName.equalsIgnoreCase("SLAVE")) 144.287 - { 144.288 - // untested, RFC977 compliant 144.289 - printStatus(202, "slave status noted"); 144.290 - return; 144.291 - } 144.292 - 144.293 - else if (commandName.equalsIgnoreCase("XINDEX")) 144.294 - { 144.295 - // untested, RFC2980 compliant 144.296 - printStatus(418, "no tin-style index is available for this news group"); 144.297 - return; 144.298 - } 144.299 - 144.300 - else if (commandName.equalsIgnoreCase("DATE")) 144.301 - { 144.302 - printStatus(111, new SimpleDateFormat("yyyyMMddHHmmss") 144.303 - .format(new Date())); 144.304 - return; 144.305 - } 144.306 - 144.307 - else if (commandName.equalsIgnoreCase("MODE")) 144.308 - { 144.309 - if (command[1].equalsIgnoreCase("READER")) 144.310 - { 144.311 - // untested, RFC2980 compliant 144.312 - printStatus(200, "Hello, you can post"); 144.313 - } 144.314 - else if (command[1].equalsIgnoreCase("STREAM")) 144.315 - { 144.316 - printStatus(203, "Streaming is OK"); 144.317 - } 144.318 - else 144.319 - printStatus(501, "Command not supported"); 144.320 - } 144.321 - 144.322 - else if (commandName.equalsIgnoreCase("QUIT")) 144.323 - { 144.324 - // untested, RFC977 compliant 144.325 - printStatus(205, "closing connection - goodbye!"); 144.326 - exit(); 144.327 - return; 144.328 - } 144.329 - 144.330 - else if (commandName.equalsIgnoreCase("XSHUTDOWN")) 144.331 - { 144.332 - printStatus(205, "closing connection - goodbye!"); 144.333 - exit(); 144.334 - return; 144.335 - } 144.336 - 144.337 - // X COMMANDS 144.338 - else if(commandName.equalsIgnoreCase("XOVER") 144.339 - || commandName.equalsIgnoreCase("OVER")) 144.340 - { 144.341 - OverCommand cmd = new OverCommand(this); 144.342 - cmd.process(command); 144.343 - } 144.344 - 144.345 - else 144.346 - printStatus(501, "Command not supported"); 144.347 - } 144.348 - 144.349 - /** 144.350 - * Runloop of this Thread. 144.351 - * @throws RuntimeException if this method is called directly. 144.352 - */ 144.353 - @Override 144.354 - public void run() 144.355 - { 144.356 - assert !this.equals(Thread.currentThread()); 144.357 - 144.358 - try 144.359 - { 144.360 - printStatus(200, Config.getInstance().get("n3tpd.hostname", "localhost") 144.361 - + " " + Main.VERSION + " news server ready - (posting ok)."); 144.362 - } 144.363 - catch (IOException e1) 144.364 - { 144.365 - exit(); 144.366 - } 144.367 - 144.368 - while (!exit) 144.369 - { 144.370 - try 144.371 - { 144.372 - processCommand(readCommand()); 144.373 - } 144.374 - catch (SocketException e) 144.375 - { 144.376 - if (exit) 144.377 - return; 144.378 - exit(); 144.379 - e.printStackTrace(); 144.380 - } 144.381 - catch (IOException e) 144.382 - { 144.383 - if (exit) 144.384 - return; 144.385 - exit(); 144.386 - e.printStackTrace(); 144.387 - } 144.388 - catch (Throwable e) 144.389 - { 144.390 - if (exit) 144.391 - return; 144.392 - e.printStackTrace(); 144.393 - // silently ignore 144.394 - } 144.395 - } 144.396 - } 144.397 - 144.398 -}
145.1 --- a/trunk/com/so/news/NNTPDaemon.java Tue Jan 20 10:21:03 2009 +0100 145.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 145.3 @@ -1,64 +0,0 @@ 145.4 -/* 145.5 - * StarOffice News Server 145.6 - * see AUTHORS for the list of contributors 145.7 - * 145.8 - * This program is free software: you can redistribute it and/or modify 145.9 - * it under the terms of the GNU General Public License as published by 145.10 - * the Free Software Foundation, either version 3 of the License, or 145.11 - * (at your option) any later version. 145.12 - * 145.13 - * This program is distributed in the hope that it will be useful, 145.14 - * but WITHOUT ANY WARRANTY; without even the implied warranty of 145.15 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 145.16 - * GNU General Public License for more details. 145.17 - * 145.18 - * You should have received a copy of the GNU General Public License 145.19 - * along with this program. If not, see <http://www.gnu.org/licenses/>. 145.20 - */ 145.21 - 145.22 -package com.so.news; 145.23 - 145.24 -import java.io.IOException; 145.25 -import java.net.ServerSocket; 145.26 - 145.27 -/** 145.28 - * Server component of the n3tpd. 145.29 - * @author Christian Lins 145.30 - * @author Dennis Schwerdel 145.31 - */ 145.32 -public class NNTPDaemon extends Thread 145.33 -{ 145.34 - private ServerSocket socket; 145.35 - 145.36 - public NNTPDaemon(boolean aux) throws IOException 145.37 - { 145.38 - int port; 145.39 - if(!aux) 145.40 - port = Config.getInstance().get("n3tpd.port", 119); 145.41 - else 145.42 - port = Config.getInstance().get("n3tpd.auxport", 8080); 145.43 - 145.44 - int backlog = Config.getInstance().get("n3tpd.server.backlog", 10); 145.45 - 145.46 - // Create and bind the socket 145.47 - socket = new ServerSocket(port, backlog); 145.48 - } 145.49 - 145.50 - @Override 145.51 - public void run() 145.52 - { 145.53 - System.out.println("Daemon listening on port " + socket.getLocalPort() + " ..."); 145.54 - 145.55 - while(isAlive() && !isInterrupted()) 145.56 - { 145.57 - try 145.58 - { 145.59 - new NNTPConnection(socket.accept()).start(); 145.60 - } 145.61 - catch (Exception e) 145.62 - { 145.63 - e.printStackTrace(); 145.64 - } 145.65 - } 145.66 - } 145.67 -}
146.1 --- a/trunk/com/so/news/command/ArticleCommand.java Tue Jan 20 10:21:03 2009 +0100 146.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 146.3 @@ -1,124 +0,0 @@ 146.4 -/* 146.5 - * StarOffice News Server 146.6 - * see AUTHORS for the list of contributors 146.7 - * 146.8 - * This program is free software: you can redistribute it and/or modify 146.9 - * it under the terms of the GNU General Public License as published by 146.10 - * the Free Software Foundation, either version 3 of the License, or 146.11 - * (at your option) any later version. 146.12 - * 146.13 - * This program is distributed in the hope that it will be useful, 146.14 - * but WITHOUT ANY WARRANTY; without even the implied warranty of 146.15 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 146.16 - * GNU General Public License for more details. 146.17 - * 146.18 - * You should have received a copy of the GNU General Public License 146.19 - * along with this program. If not, see <http://www.gnu.org/licenses/>. 146.20 - */ 146.21 - 146.22 -package com.so.news.command; 146.23 - 146.24 -import java.io.IOException; 146.25 -import java.text.SimpleDateFormat; 146.26 -import java.util.Locale; 146.27 -import java.util.Map; 146.28 -import com.so.news.Debug; 146.29 -import com.so.news.NNTPConnection; 146.30 -import com.so.news.storage.Article; 146.31 - 146.32 -/** 146.33 - * Class handling the ARTICLE command. 146.34 - * @author Christian Lins 146.35 - * @author Dennis Schwerdel 146.36 - */ 146.37 -public class ArticleCommand extends Command 146.38 -{ 146.39 - public ArticleCommand(NNTPConnection connection) 146.40 - { 146.41 - super(connection); 146.42 - } 146.43 - 146.44 - public boolean process(String[] command) throws IOException 146.45 - { 146.46 - String commandName = command[0]; 146.47 - 146.48 - // untested, RFC977 compliant 146.49 - Article article = null; 146.50 - if (command.length <= 1) 146.51 - { 146.52 - article = getCurrentArticle(); 146.53 - if (article == null) 146.54 - { 146.55 - printStatus(420, "no current article has been selected"); 146.56 - return true; 146.57 - } 146.58 - } 146.59 - else if (command[1].matches(NNTPConnection.MESSAGE_ID_PATTERN)) 146.60 - { 146.61 - // Message-ID 146.62 - article = Article.getByMessageID(command[1]); 146.63 - if (article == null) 146.64 - { 146.65 - printStatus(430, "no such article found"); 146.66 - return true; 146.67 - } 146.68 - } 146.69 - else 146.70 - { 146.71 - // Message Number 146.72 - try 146.73 - { 146.74 - int num = Integer.parseInt(command[1]); 146.75 - article = Article.getByNumberInGroup(connection.getCurrentGroup(), num); 146.76 - } 146.77 - catch (Exception ex) 146.78 - { 146.79 - ex.printStackTrace(Debug.getInstance().getStream()); 146.80 - System.err.println(ex.getLocalizedMessage()); 146.81 - } 146.82 - if (article == null) 146.83 - { 146.84 - printStatus(423, "no such article number in this group"); 146.85 - return true; 146.86 - } 146.87 - setCurrentArticle(article); 146.88 - } 146.89 - 146.90 - if (commandName.equalsIgnoreCase("ARTICLE")) 146.91 - { 146.92 - printStatus(220, article.getNumberInGroup() + " " + article.getMessageID() 146.93 - + " article retrieved - head and body follow"); 146.94 - Map<String, String> header = article.getHeader(); 146.95 - for(Map.Entry<String, String> entry : header.entrySet()) 146.96 - { 146.97 - if(entry.getKey().equals("Date")) 146.98 - { 146.99 - SimpleDateFormat sdf = new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss Z", Locale.US); 146.100 - printTextPart("Date: " + sdf.format(article.getDate())); 146.101 - } 146.102 - else 146.103 - printTextPart(entry.getKey() + ": " + entry.getValue()); 146.104 - } 146.105 - println(""); 146.106 - printText(article.getBody()); 146.107 - } 146.108 - else if (commandName.equalsIgnoreCase("HEAD")) 146.109 - { 146.110 - printStatus(500, "No longer supported! Use XOVER instead."); 146.111 - return false; 146.112 - } 146.113 - else if (commandName.equalsIgnoreCase("BODY")) 146.114 - { 146.115 - printStatus(222, article.getNumberInGroup() + " " + article.getMessageID() 146.116 - + " body"); 146.117 - printText(article.getBody()); 146.118 - } 146.119 - else if (commandName.equalsIgnoreCase("STAT")) 146.120 - { 146.121 - printStatus(223, article.getNumberInGroup() + " " + article.getMessageID() 146.122 - + " article retrieved - request text separately"); 146.123 - } 146.124 - return true; 146.125 - } 146.126 - 146.127 -}
147.1 --- a/trunk/com/so/news/command/CapabilitiesCommand.java Tue Jan 20 10:21:03 2009 +0100 147.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 147.3 @@ -1,50 +0,0 @@ 147.4 -/* 147.5 - * StarOffice News Server 147.6 - * see AUTHORS for the list of contributors 147.7 - * 147.8 - * This program is free software: you can redistribute it and/or modify 147.9 - * it under the terms of the GNU General Public License as published by 147.10 - * the Free Software Foundation, either version 3 of the License, or 147.11 - * (at your option) any later version. 147.12 - * 147.13 - * This program is distributed in the hope that it will be useful, 147.14 - * but WITHOUT ANY WARRANTY; without even the implied warranty of 147.15 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 147.16 - * GNU General Public License for more details. 147.17 - * 147.18 - * You should have received a copy of the GNU General Public License 147.19 - * along with this program. If not, see <http://www.gnu.org/licenses/>. 147.20 - */ 147.21 - 147.22 -package com.so.news.command; 147.23 - 147.24 -import com.so.news.NNTPConnection; 147.25 - 147.26 -/** 147.27 - * The CAPABILITIES command allows a client to determine the 147.28 - capabilities of the server at any given time. 147.29 - 147.30 - This command MAY be issued at any time; the server MUST NOT require 147.31 - it to be issued in order to make use of any capability. The response 147.32 - generated by this command MAY change during a session because of 147.33 - other state information (which, in turn, may be changed by the 147.34 - effects of other commands or by external events). An NNTP client is 147.35 - only able to get the current and correct information concerning 147.36 - available capabilities at any point during a session by issuing a 147.37 - CAPABILITIES command at that point of that session and processing the 147.38 - response. 147.39 - * @author chris 147.40 - */ 147.41 -public class CapabilitiesCommand extends Command 147.42 -{ 147.43 - public CapabilitiesCommand(NNTPConnection connection) 147.44 - { 147.45 - super(connection); 147.46 - } 147.47 - 147.48 - public boolean process(String[] command) 147.49 - throws Exception 147.50 - { 147.51 - return false; 147.52 - } 147.53 -}
148.1 --- a/trunk/com/so/news/command/Command.java Tue Jan 20 10:21:03 2009 +0100 148.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 148.3 @@ -1,106 +0,0 @@ 148.4 -/* 148.5 - * StarOffice News Server 148.6 - * see AUTHORS for the list of contributors 148.7 - * 148.8 - * This program is free software: you can redistribute it and/or modify 148.9 - * it under the terms of the GNU General Public License as published by 148.10 - * the Free Software Foundation, either version 3 of the License, or 148.11 - * (at your option) any later version. 148.12 - * 148.13 - * This program is distributed in the hope that it will be useful, 148.14 - * but WITHOUT ANY WARRANTY; without even the implied warranty of 148.15 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 148.16 - * GNU General Public License for more details. 148.17 - * 148.18 - * You should have received a copy of the GNU General Public License 148.19 - * along with this program. If not, see <http://www.gnu.org/licenses/>. 148.20 - */ 148.21 - 148.22 -package com.so.news.command; 148.23 - 148.24 -import java.io.IOException; 148.25 -import java.util.List; 148.26 -import com.so.news.NNTPConnection; 148.27 -import com.so.news.storage.Article; 148.28 -import com.so.news.storage.Group; 148.29 - 148.30 -/** 148.31 - * Base class for all command handling classes. 148.32 - * @author Christian Lins 148.33 - * @author Dennis Schwerdel 148.34 - */ 148.35 -public abstract class Command 148.36 -{ 148.37 - protected NNTPConnection connection; 148.38 - 148.39 - public Command(NNTPConnection connection) 148.40 - { 148.41 - this.connection = connection; 148.42 - } 148.43 - 148.44 - protected static String NEWLINE = NNTPConnection.NEWLINE; 148.45 - 148.46 - protected List<String> readText() 148.47 - throws IOException 148.48 - { 148.49 - return connection.readText(); 148.50 - } 148.51 - 148.52 - protected String readTextLine() throws IOException 148.53 - { 148.54 - return connection.readTextLine(); 148.55 - } 148.56 - 148.57 - protected void printStatus(int status, String text) throws IOException 148.58 - { 148.59 - connection.printStatus(status, text); 148.60 - } 148.61 - 148.62 - protected void printTextLine(CharSequence text) throws IOException 148.63 - { 148.64 - connection.printTextLine(text); 148.65 - } 148.66 - 148.67 - protected void printTextPart(CharSequence text) throws IOException 148.68 - { 148.69 - connection.printTextPart(text); 148.70 - } 148.71 - 148.72 - protected void printText(CharSequence text) throws IOException 148.73 - { 148.74 - connection.printText(text); 148.75 - } 148.76 - 148.77 - protected void println(CharSequence text) throws IOException 148.78 - { 148.79 - connection.println(text); 148.80 - } 148.81 - 148.82 - protected void flush() throws IOException 148.83 - { 148.84 - connection.flush(); 148.85 - } 148.86 - 148.87 - protected Article getCurrentArticle() 148.88 - { 148.89 - return connection.getCurrentArticle(); 148.90 - } 148.91 - 148.92 - protected Group getCurrentGroup() 148.93 - { 148.94 - return connection.getCurrentGroup(); 148.95 - } 148.96 - 148.97 - protected void setCurrentArticle(Article current) 148.98 - { 148.99 - connection.setCurrentArticle(current); 148.100 - } 148.101 - 148.102 - protected void setCurrentGroup(Group current) 148.103 - { 148.104 - connection.setCurrentGroup(current); 148.105 - } 148.106 - 148.107 - public abstract boolean process(String[] command) 148.108 - throws Exception; 148.109 -}
149.1 --- a/trunk/com/so/news/command/GroupCommand.java Tue Jan 20 10:21:03 2009 +0100 149.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 149.3 @@ -1,60 +0,0 @@ 149.4 -/* 149.5 - * StarOffice News Server 149.6 - * see AUTHORS for the list of contributors 149.7 - * 149.8 - * This program is free software: you can redistribute it and/or modify 149.9 - * it under the terms of the GNU General Public License as published by 149.10 - * the Free Software Foundation, either version 3 of the License, or 149.11 - * (at your option) any later version. 149.12 - * 149.13 - * This program is distributed in the hope that it will be useful, 149.14 - * but WITHOUT ANY WARRANTY; without even the implied warranty of 149.15 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 149.16 - * GNU General Public License for more details. 149.17 - * 149.18 - * You should have received a copy of the GNU General Public License 149.19 - * along with this program. If not, see <http://www.gnu.org/licenses/>. 149.20 - */ 149.21 - 149.22 -package com.so.news.command; 149.23 - 149.24 -import com.so.news.NNTPConnection; 149.25 -import com.so.news.storage.Group; 149.26 - 149.27 -/** 149.28 - * Class handling the GROUP command. 149.29 - * @author Christian Lins 149.30 - * @author Dennis Schwerdel 149.31 - */ 149.32 -public class GroupCommand extends Command 149.33 -{ 149.34 - public GroupCommand(NNTPConnection conn) 149.35 - { 149.36 - super(conn); 149.37 - } 149.38 - 149.39 - public boolean process(String[] command) 149.40 - throws Exception 149.41 - { 149.42 - // untested, RFC977 compliant 149.43 - Group g = null; 149.44 - if (command.length >= 2) 149.45 - { 149.46 - g = Group.getByName(command[1]); 149.47 - } 149.48 - if (g == null) 149.49 - { 149.50 - printStatus(411, "no such news group"); 149.51 - return true; 149.52 - } 149.53 - else 149.54 - { 149.55 - setCurrentGroup(g); 149.56 - 149.57 - printStatus(211, g.getEstimatedArticleCount() + " " + g.getFirstArticle() 149.58 - + " " + g.getLastArticle() + " " + g.getName() + " group selected"); 149.59 - return true; 149.60 - } 149.61 - } 149.62 - 149.63 -}
150.1 --- a/trunk/com/so/news/command/ListCommand.java Tue Jan 20 10:21:03 2009 +0100 150.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 150.3 @@ -1,92 +0,0 @@ 150.4 -/* 150.5 - * StarOffice News Server 150.6 - * see AUTHORS for the list of contributors 150.7 - * 150.8 - * This program is free software: you can redistribute it and/or modify 150.9 - * it under the terms of the GNU General Public License as published by 150.10 - * the Free Software Foundation, either version 3 of the License, or 150.11 - * (at your option) any later version. 150.12 - * 150.13 - * This program is distributed in the hope that it will be useful, 150.14 - * but WITHOUT ANY WARRANTY; without even the implied warranty of 150.15 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 150.16 - * GNU General Public License for more details. 150.17 - * 150.18 - * You should have received a copy of the GNU General Public License 150.19 - * along with this program. If not, see <http://www.gnu.org/licenses/>. 150.20 - */ 150.21 - 150.22 -package com.so.news.command; 150.23 - 150.24 -import java.io.IOException; 150.25 -import java.util.ArrayList; 150.26 -import com.so.news.NNTPConnection; 150.27 -import com.so.news.storage.Group; 150.28 - 150.29 -/** 150.30 - * Class handling the LIST command. 150.31 - * @author Christian Lins 150.32 - * @author Dennis Schwerdel 150.33 - */ 150.34 -public class ListCommand extends Command 150.35 -{ 150.36 - public ListCommand(NNTPConnection conn) 150.37 - { 150.38 - super(conn); 150.39 - } 150.40 - 150.41 - public boolean process(String[] command) 150.42 - throws Exception 150.43 - { 150.44 - if (command.length >= 2) 150.45 - { 150.46 - if (command[1].equalsIgnoreCase("OVERVIEW.FMT")) 150.47 - { 150.48 - printStatus(215, "information follows"); 150.49 - printText("Subject:\nFrom:\nDate:\nMessage-ID:\nReferences:\nBytes:\nLines:"); 150.50 - return true; 150.51 - } 150.52 - if (command[1].equalsIgnoreCase("NEWSGROUPS")) 150.53 - { 150.54 - printStatus(215, "information follows"); 150.55 - ArrayList<Group> list = Group.getAll(); 150.56 - for (Group g : list) 150.57 - { 150.58 - printTextLine(g.getName() + "\t" + "-"); 150.59 - } 150.60 - println("."); 150.61 - flush(); 150.62 - return true; 150.63 - } 150.64 - if (command[1].equalsIgnoreCase("SUBSCRIPTIONS")) 150.65 - { 150.66 - printStatus(215, "information follows"); 150.67 - println("."); 150.68 - flush(); 150.69 - return true; 150.70 - } 150.71 - if (command[1].equalsIgnoreCase("EXTENSIONS")) 150.72 - { 150.73 - printStatus(202, "Supported NNTP extensions."); 150.74 - printTextLine("LISTGROUP"); 150.75 - println("."); 150.76 - flush(); 150.77 - return true; 150.78 - } 150.79 - return false; 150.80 - } 150.81 - printStatus(215, "list of newsgroups follows"); 150.82 - for (Group g : Group.getAll()) 150.83 - { 150.84 - //if(g.getEstimatedArticleCount() <= 0) 150.85 - // continue; 150.86 - 150.87 - printTextLine(g.getName() + " " + g.getLastArticle() + " " 150.88 - + g.getFirstArticle() + " y"); 150.89 - } 150.90 - println("."); 150.91 - flush(); 150.92 - return true; 150.93 - } 150.94 - 150.95 -}
151.1 --- a/trunk/com/so/news/command/ListGroupCommand.java Tue Jan 20 10:21:03 2009 +0100 151.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 151.3 @@ -1,71 +0,0 @@ 151.4 -/* 151.5 - * StarOffice News Server 151.6 - * see AUTHORS for the list of contributors 151.7 - * 151.8 - * This program is free software: you can redistribute it and/or modify 151.9 - * it under the terms of the GNU General Public License as published by 151.10 - * the Free Software Foundation, either version 3 of the License, or 151.11 - * (at your option) any later version. 151.12 - * 151.13 - * This program is distributed in the hope that it will be useful, 151.14 - * but WITHOUT ANY WARRANTY; without even the implied warranty of 151.15 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 151.16 - * GNU General Public License for more details. 151.17 - * 151.18 - * You should have received a copy of the GNU General Public License 151.19 - * along with this program. If not, see <http://www.gnu.org/licenses/>. 151.20 - */ 151.21 - 151.22 -package com.so.news.command; 151.23 - 151.24 -import java.util.List; 151.25 -import com.so.news.NNTPConnection; 151.26 -import com.so.news.storage.Article; 151.27 -import com.so.news.storage.Group; 151.28 - 151.29 -/** 151.30 - * Class handling the LISTGROUP command. 151.31 - * @author Christian Lins 151.32 - * @author Dennis Schwerdel 151.33 - */ 151.34 -public class ListGroupCommand extends Command 151.35 -{ 151.36 - public ListGroupCommand(NNTPConnection conn) 151.37 - { 151.38 - super(conn); 151.39 - } 151.40 - 151.41 - public boolean process(String[] command) 151.42 - throws Exception 151.43 - { 151.44 - String commandName = command[0]; 151.45 - if (!commandName.equalsIgnoreCase("LISTGROUP")) 151.46 - return false; 151.47 - // untested, RFC977 complient 151.48 - Group group = null; 151.49 - if (command.length >= 2) 151.50 - { 151.51 - group = Group.getByName(command[1]); 151.52 - } 151.53 - else 151.54 - { 151.55 - group = getCurrentGroup(); 151.56 - } 151.57 - if (group == null) 151.58 - { 151.59 - printStatus(412, "Not currently in newsgroup"); 151.60 - return true; 151.61 - } 151.62 - List<Article> list = group.getAllArticles(); 151.63 - printStatus(211, "list of article numbers follow"); // argh, bad english in 151.64 - // RFC 151.65 - for (Article a : list) 151.66 - { 151.67 - printTextLine("" + a.getNumberInGroup()); 151.68 - } 151.69 - println("."); 151.70 - flush(); 151.71 - return true; 151.72 - } 151.73 - 151.74 -}
152.1 --- a/trunk/com/so/news/command/NewGroupsCommand.java Tue Jan 20 10:21:03 2009 +0100 152.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 152.3 @@ -1,68 +0,0 @@ 152.4 -/* 152.5 - * StarOffice News Server 152.6 - * see AUTHORS for the list of contributors 152.7 - * 152.8 - * This program is free software: you can redistribute it and/or modify 152.9 - * it under the terms of the GNU General Public License as published by 152.10 - * the Free Software Foundation, either version 3 of the License, or 152.11 - * (at your option) any later version. 152.12 - * 152.13 - * This program is distributed in the hope that it will be useful, 152.14 - * but WITHOUT ANY WARRANTY; without even the implied warranty of 152.15 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 152.16 - * GNU General Public License for more details. 152.17 - * 152.18 - * You should have received a copy of the GNU General Public License 152.19 - * along with this program. If not, see <http://www.gnu.org/licenses/>. 152.20 - */ 152.21 - 152.22 -package com.so.news.command; 152.23 - 152.24 -import java.io.IOException; 152.25 -import java.util.ArrayList; 152.26 -import com.so.news.NNTPConnection; 152.27 -import com.so.news.storage.Group; 152.28 - 152.29 -/** 152.30 - * Class handling the NEWGROUPS command. 152.31 - * @author Christian Lins 152.32 - * @author Dennis Schwerdel 152.33 - */ 152.34 -public class NewGroupsCommand extends Command 152.35 -{ 152.36 - public NewGroupsCommand(NNTPConnection conn) 152.37 - { 152.38 - super(conn); 152.39 - } 152.40 - 152.41 - public boolean process(String[] command) throws IOException 152.42 - { 152.43 - String commandName = command[0]; 152.44 - if (!commandName.equalsIgnoreCase("NEWGROUPS")) 152.45 - return false; 152.46 - if (command.length != 3) 152.47 - return false; 152.48 - // untested, not RFC977 complient 152.49 - try 152.50 - { 152.51 - // Timestamp date = new Timestamp ( new SimpleDateFormat ("yyMMdd 152.52 - // HHmmss").parse(command[1] + " " + command[2] ).getTime()) ; 152.53 - printStatus(231, "list of new newsgroups follows"); 152.54 - ArrayList<Group> list = Group.getAll();// (date) ; 152.55 - for (Group g : list) 152.56 - { 152.57 - printTextLine(g.getName() + " " + g.getLastArticle() + " " 152.58 - + g.getFirstArticle() + " y"); 152.59 - } 152.60 - println("."); 152.61 - flush(); 152.62 - return true; 152.63 - } 152.64 - catch (Exception e) 152.65 - { 152.66 - printStatus(511, "listing failed - invalid date format"); 152.67 - return true; 152.68 - } 152.69 - } 152.70 - 152.71 -}
153.1 --- a/trunk/com/so/news/command/NextCommand.java Tue Jan 20 10:21:03 2009 +0100 153.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 153.3 @@ -1,82 +0,0 @@ 153.4 -/* 153.5 - * StarOffice News Server 153.6 - * see AUTHORS for the list of contributors 153.7 - * 153.8 - * This program is free software: you can redistribute it and/or modify 153.9 - * it under the terms of the GNU General Public License as published by 153.10 - * the Free Software Foundation, either version 3 of the License, or 153.11 - * (at your option) any later version. 153.12 - * 153.13 - * This program is distributed in the hope that it will be useful, 153.14 - * but WITHOUT ANY WARRANTY; without even the implied warranty of 153.15 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 153.16 - * GNU General Public License for more details. 153.17 - * 153.18 - * You should have received a copy of the GNU General Public License 153.19 - * along with this program. If not, see <http://www.gnu.org/licenses/>. 153.20 - */ 153.21 - 153.22 -package com.so.news.command; 153.23 - 153.24 -import java.io.IOException; 153.25 -import com.so.news.NNTPConnection; 153.26 -import com.so.news.storage.Article; 153.27 -import com.so.news.storage.Group; 153.28 - 153.29 -/** 153.30 - * Class handling the NEXT and LAST command. 153.31 - * @author Christian Lins 153.32 - * @author Dennis Schwerdel 153.33 - */ 153.34 -public class NextCommand extends Command 153.35 -{ 153.36 - public NextCommand(NNTPConnection conn) 153.37 - { 153.38 - super(conn); 153.39 - } 153.40 - 153.41 - public boolean process(String[] command) throws IOException 153.42 - { 153.43 - String commandName = command[0]; 153.44 - if (!(commandName.equalsIgnoreCase("NEXT") || commandName 153.45 - .equalsIgnoreCase("LAST"))) 153.46 - return false; 153.47 - // untested, RFC977 complient 153.48 - Article currA = getCurrentArticle(); 153.49 - Group currG = getCurrentGroup(); 153.50 - if (currA == null) 153.51 - { 153.52 - printStatus(420, "no current article has been selected"); 153.53 - return true; 153.54 - } 153.55 - if (currG == null) 153.56 - { 153.57 - printStatus(412, "no newsgroup selected"); 153.58 - return true; 153.59 - } 153.60 - Article article; 153.61 - if (commandName.equalsIgnoreCase("NEXT")) 153.62 - { 153.63 - article = currA.nextArticleInGroup(); 153.64 - if (article == null) 153.65 - { 153.66 - printStatus(421, "no next article in this group"); 153.67 - return true; 153.68 - } 153.69 - } 153.70 - else 153.71 - { 153.72 - article = currA.prevArticleInGroup(); 153.73 - if (article == null) 153.74 - { 153.75 - printStatus(422, "no previous article in this group"); 153.76 - return true; 153.77 - } 153.78 - } 153.79 - setCurrentArticle(article); 153.80 - printStatus(223, article.getNumberInGroup() + " " + article.getMessageID() 153.81 - + " article retrieved - request text separately"); 153.82 - return true; 153.83 - } 153.84 - 153.85 -}
154.1 --- a/trunk/com/so/news/command/OverCommand.java Tue Jan 20 10:21:03 2009 +0100 154.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 154.3 @@ -1,183 +0,0 @@ 154.4 -/* 154.5 - * StarOffice News Server 154.6 - * see AUTHORS for the list of contributors 154.7 - * 154.8 - * This program is free software: you can redistribute it and/or modify 154.9 - * it under the terms of the GNU General Public License as published by 154.10 - * the Free Software Foundation, either version 3 of the License, or 154.11 - * (at your option) any later version. 154.12 - * 154.13 - * This program is distributed in the hope that it will be useful, 154.14 - * but WITHOUT ANY WARRANTY; without even the implied warranty of 154.15 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 154.16 - * GNU General Public License for more details. 154.17 - * 154.18 - * You should have received a copy of the GNU General Public License 154.19 - * along with this program. If not, see <http://www.gnu.org/licenses/>. 154.20 - */ 154.21 - 154.22 -package com.so.news.command; 154.23 - 154.24 -import java.text.SimpleDateFormat; 154.25 -import java.util.Locale; 154.26 - 154.27 -import com.so.news.Debug; 154.28 -import com.so.news.NNTPConnection; 154.29 -import com.so.news.storage.Article; 154.30 - 154.31 -/** 154.32 - * Class handling the OVER/XOVER command. 154.33 - * 154.34 - * Description of the XOVER command: 154.35 - * 154.36 - * XOVER [range] 154.37 - * 154.38 - * The XOVER command returns information from the overview 154.39 - * database for the article(s) specified. 154.40 - * 154.41 - * The optional range argument may be any of the following: 154.42 - * an article number 154.43 - * an article number followed by a dash to indicate 154.44 - * all following 154.45 - * an article number followed by a dash followed by 154.46 - * another article number 154.47 - * 154.48 - * If no argument is specified, then information from the 154.49 - * current article is displayed. Successful responses start 154.50 - * with a 224 response followed by the overview information 154.51 - * for all matched messages. Once the output is complete, a 154.52 - * period is sent on a line by itself. If no argument is 154.53 - * specified, the information for the current article is 154.54 - * returned. A news group must have been selected earlier, 154.55 - * else a 412 error response is returned. If no articles are 154.56 - * in the range specified, a 420 error response is returned 154.57 - * by the server. A 502 response will be returned if the 154.58 - * client only has permission to transfer articles. 154.59 - * 154.60 - * Each line of output will be formatted with the article number, 154.61 - * followed by each of the headers in the overview database or the 154.62 - * article itself (when the data is not available in the overview 154.63 - * database) for that article separated by a tab character. The 154.64 - * sequence of fields must be in this order: subject, author, 154.65 - * date, message-id, references, byte count, and line count. Other 154.66 - * optional fields may follow line count. Other optional fields may 154.67 - * follow line count. These fields are specified by examining the 154.68 - * response to the LIST OVERVIEW.FMT command. Where no data exists, 154.69 - * a null field must be provided (i.e. the output will have two tab 154.70 - * characters adjacent to each other). Servers should not output 154.71 - * fields for articles that have been removed since the XOVER database 154.72 - * was created. 154.73 - * 154.74 - * The LIST OVERVIEW.FMT command should be implemented if XOVER 154.75 - * is implemented. A client can use LIST OVERVIEW.FMT to determine 154.76 - * what optional fields and in which order all fields will be 154.77 - * supplied by the XOVER command. 154.78 - * 154.79 - * Note that any tab and end-of-line characters in any header 154.80 - * data that is returned will be converted to a space character. 154.81 - * 154.82 - * Responses: 154.83 - * 154.84 - * 224 Overview information follows 154.85 - * 412 No news group current selected 154.86 - * 420 No article(s) selected 154.87 - * 502 no permission 154.88 - * 154.89 - * @author Christian Lins 154.90 - */ 154.91 -public class OverCommand extends Command 154.92 -{ 154.93 - public OverCommand(NNTPConnection conn) 154.94 - { 154.95 - super(conn); 154.96 - } 154.97 - 154.98 - public boolean process(String[] command) 154.99 - throws Exception 154.100 - { 154.101 - if(getCurrentGroup() == null) 154.102 - { 154.103 - printStatus(412, "No news group current selected"); 154.104 - return false; 154.105 - } 154.106 - 154.107 - // If no parameter was specified, show information about 154.108 - // the currently selected article(s) 154.109 - if(command.length == 1) 154.110 - { 154.111 - Article art = getCurrentArticle(); 154.112 - if(art == null) 154.113 - { 154.114 - printStatus(420, "No article(s) selected"); 154.115 - return false; 154.116 - } 154.117 - 154.118 - String o = buildOverview(art, -1); 154.119 - printText(o); 154.120 - } 154.121 - // otherwise print information about the specified range 154.122 - else 154.123 - { 154.124 - int artStart = -1; 154.125 - int artEnd = -1; 154.126 - String[] nums = command[1].split("-"); 154.127 - if(nums.length > 1) 154.128 - { 154.129 - try 154.130 - { 154.131 - artStart = Integer.parseInt(nums[0]); 154.132 - } 154.133 - catch(Exception e) 154.134 - { 154.135 - artStart = Integer.parseInt(command[1]); 154.136 - } 154.137 - try 154.138 - { 154.139 - artEnd = Integer.parseInt(nums[1]); 154.140 - } 154.141 - catch(Exception e) {} 154.142 - } 154.143 - 154.144 - printStatus(224, "Overview information follows"); 154.145 - for(int n = artStart; n <= artEnd; n++) 154.146 - { 154.147 - Article art = Article.getByNumberInGroup(getCurrentGroup(), n); 154.148 - if(art == null) 154.149 - { 154.150 - Debug.getInstance().log("Article (gid=" + getCurrentGroup() + ", art=" + n + " is null!"); 154.151 - } 154.152 - else 154.153 - { 154.154 - printTextPart(buildOverview(art, n) + NEWLINE); 154.155 - } 154.156 - } 154.157 - println("."); 154.158 - flush(); 154.159 - } 154.160 - 154.161 - return true; 154.162 - } 154.163 - 154.164 - private String buildOverview(Article art, int nr) 154.165 - { 154.166 - SimpleDateFormat sdf = new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss Z", Locale.US); 154.167 - StringBuilder overview = new StringBuilder(); 154.168 - overview.append(nr); 154.169 - overview.append('\t'); 154.170 - overview.append(art.getHeader().get("Subject")); 154.171 - overview.append('\t'); 154.172 - overview.append(art.getHeader().get("From")); 154.173 - overview.append('\t'); 154.174 - overview.append(sdf.format(art.getDate())); 154.175 - overview.append('\t'); 154.176 - overview.append(art.getHeader().get("Message-ID")); 154.177 - overview.append('\t'); 154.178 - overview.append(art.getHeader().get("References")); 154.179 - overview.append('\t'); 154.180 - overview.append(art.getHeader().get("Bytes")); 154.181 - overview.append('\t'); 154.182 - overview.append(art.getHeader().get("Lines")); 154.183 - 154.184 - return overview.toString(); 154.185 - } 154.186 -}
155.1 --- a/trunk/com/so/news/command/PostCommand.java Tue Jan 20 10:21:03 2009 +0100 155.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 155.3 @@ -1,166 +0,0 @@ 155.4 -/* 155.5 - * StarOffice News Server 155.6 - * see AUTHORS for the list of contributors 155.7 - * 155.8 - * This program is free software: you can redistribute it and/or modify 155.9 - * it under the terms of the GNU General Public License as published by 155.10 - * the Free Software Foundation, either version 3 of the License, or 155.11 - * (at your option) any later version. 155.12 - * 155.13 - * This program is distributed in the hope that it will be useful, 155.14 - * but WITHOUT ANY WARRANTY; without even the implied warranty of 155.15 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 155.16 - * GNU General Public License for more details. 155.17 - * 155.18 - * You should have received a copy of the GNU General Public License 155.19 - * along with this program. If not, see <http://www.gnu.org/licenses/>. 155.20 - */ 155.21 - 155.22 -package com.so.news.command; 155.23 - 155.24 -import java.io.IOException; 155.25 -import java.sql.SQLException; 155.26 -import java.util.Date; 155.27 -import java.text.SimpleDateFormat; 155.28 -import java.util.HashMap; 155.29 -import java.util.Locale; 155.30 - 155.31 -import com.so.news.Config; 155.32 -import com.so.news.Debug; 155.33 -import com.so.news.NNTPConnection; 155.34 -import com.so.news.storage.Article; 155.35 -import com.so.news.storage.Database; 155.36 - 155.37 -/** 155.38 - * Contains the code for the POST command. 155.39 - * @author Christian Lins 155.40 - * @author Dennis Schwerdel 155.41 - */ 155.42 -public class PostCommand extends Command 155.43 -{ 155.44 - public PostCommand(NNTPConnection conn) 155.45 - { 155.46 - super(conn); 155.47 - } 155.48 - 155.49 - public boolean process(String[] command) throws IOException 155.50 - { 155.51 - printStatus(340, "send article to be posted. End with <CR-LF>.<CR-LF>"); 155.52 - 155.53 - // some initialization 155.54 - Article article = new Article(); 155.55 - int lineCount = 0; 155.56 - long bodySize = 0; 155.57 - long maxBodySize = Config.getInstance().get("n3tpd.article.maxsize", 1024) * 1024; // Size in bytes 155.58 - 155.59 - // begin with a stringbuilder body 155.60 - StringBuilder body = new StringBuilder(); 155.61 - HashMap<String, String> header = new HashMap<String, String>(); 155.62 - 155.63 - boolean isHeader = true; // are we in the header part 155.64 - 155.65 - String line = readTextLine(); 155.66 - while(line != null) 155.67 - { 155.68 - bodySize += line.length(); 155.69 - if(bodySize > maxBodySize) 155.70 - { 155.71 - printStatus(500, "article is too long"); 155.72 - return false; 155.73 - } 155.74 - 155.75 - if(!isHeader) 155.76 - { // body 155.77 - if(line.trim().equals(".")) 155.78 - break; 155.79 - 155.80 - bodySize += line.length() + 1; 155.81 - lineCount++; 155.82 - body.append(line + NEWLINE); 155.83 - } 155.84 - 155.85 - if(line.equals("")) 155.86 - { 155.87 - isHeader = false; // we finally met the blank line 155.88 - // separating headers from body 155.89 - } 155.90 - 155.91 - if(isHeader) 155.92 - { // header 155.93 - // split name and value and add the header to the map 155.94 - int colon = line.indexOf(':'); 155.95 - String fieldName = line.substring(0, colon).trim(); 155.96 - String fieldValue = line.substring(colon + 1).trim(); 155.97 - header.put(fieldName, fieldValue); 155.98 - } 155.99 - line = readTextLine(); // read a new line 155.100 - } // end of input reading 155.101 - 155.102 - article.setBody(body.toString()); // set the article body 155.103 - article.setHeader(header); // add the header entries for the article 155.104 - 155.105 - // Read the date header and fall back to the current date if it is not set 155.106 - try 155.107 - { 155.108 - SimpleDateFormat sdf = new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss Z", Locale.US); 155.109 - String date = header.get("DATE"); 155.110 - if(date == null) 155.111 - article.setDate(new Date()); 155.112 - else 155.113 - article.setDate(new Date(sdf.parse(date).getTime())) ; 155.114 - } 155.115 - catch (Exception e) 155.116 - { 155.117 - e.printStackTrace(Debug.getInstance().getStream()); 155.118 - printStatus(541, "posting failed - invalid date format"); 155.119 - return true; 155.120 - } 155.121 - 155.122 - // check for a cancel command 155.123 - if ( header.containsKey("Control") ) 155.124 - { 155.125 - String[] control = header.get("Control").split(" ") ; 155.126 - if ( control.length >= 2 && control[0].equalsIgnoreCase("cancel") ) 155.127 - { 155.128 - // this article is a cancel-article, try to delete the old article 155.129 - try 155.130 - { 155.131 - Article.getByMessageID(control[1]).delete(); 155.132 - printStatus(240, "article posted ok - original article canceled"); // quite 155.133 - return true; // quit, do not actually post this article since it 155.134 - } 155.135 - catch (Exception e) 155.136 - { 155.137 - e.printStackTrace(); 155.138 - printStatus(441, "posting failed - original posting not found"); 155.139 - return true; 155.140 - } 155.141 - } 155.142 - } 155.143 - 155.144 - // set some headers 155.145 - header.put("Message-ID", article.getMessageID()); 155.146 - header.put("Lines", "" + lineCount); 155.147 - header.put("Bytes", "" + bodySize); 155.148 - 155.149 - // if needed, set an empty references header, that means this is 155.150 - // a initial posting 155.151 - if (!header.containsKey("References")) 155.152 - header.put("References", ""); 155.153 - 155.154 - // try to create the article in the database 155.155 - try 155.156 - { 155.157 - Database.getInstance().addArticle(article); 155.158 - printStatus(240, "article posted ok"); 155.159 - } 155.160 - catch(SQLException ex) 155.161 - { 155.162 - System.err.println(ex.getLocalizedMessage()); 155.163 - ex.printStackTrace(Debug.getInstance().getStream()); 155.164 - printStatus(500, "internal server error"); 155.165 - } 155.166 - 155.167 - return true; 155.168 - } 155.169 -}
156.1 --- a/trunk/com/so/news/io/Resource.java Tue Jan 20 10:21:03 2009 +0100 156.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 156.3 @@ -1,123 +0,0 @@ 156.4 -/* 156.5 - * StarOffice News Server 156.6 - * see AUTHORS for the list of contributors 156.7 - * 156.8 - * This program is free software: you can redistribute it and/or modify 156.9 - * it under the terms of the GNU General Public License as published by 156.10 - * the Free Software Foundation, either version 3 of the License, or 156.11 - * (at your option) any later version. 156.12 - * 156.13 - * This program is distributed in the hope that it will be useful, 156.14 - * but WITHOUT ANY WARRANTY; without even the implied warranty of 156.15 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 156.16 - * GNU General Public License for more details. 156.17 - * 156.18 - * You should have received a copy of the GNU General Public License 156.19 - * along with this program. If not, see <http://www.gnu.org/licenses/>. 156.20 - */ 156.21 - 156.22 -package com.so.news.io; 156.23 - 156.24 -import java.io.BufferedReader; 156.25 -import java.io.File; 156.26 -import java.io.FileInputStream; 156.27 -import java.io.IOException; 156.28 -import java.io.InputStream; 156.29 -import java.io.InputStreamReader; 156.30 -import java.net.URL; 156.31 -import java.nio.charset.Charset; 156.32 - 156.33 -/** 156.34 - * Provides method for loading of resources. 156.35 - * @author Christian Lins 156.36 - */ 156.37 -public class Resource 156.38 -{ 156.39 - /** 156.40 - * Loads a file as array of byte. As the file is completely loaded into 156.41 - * memory this method should only be used with small files. 156.42 - * @param file 156.43 - * @return 156.44 - */ 156.45 - public static byte[] getBytes(File file) 156.46 - { 156.47 - try 156.48 - { 156.49 - FileInputStream in = new FileInputStream(file); 156.50 - byte[] buffer = new byte[(int)file.length()]; 156.51 - 156.52 - in.read(buffer); 156.53 - 156.54 - return buffer; 156.55 - } 156.56 - catch(IOException ex) 156.57 - { 156.58 - System.err.println(ex.getLocalizedMessage()); 156.59 - return null; 156.60 - } 156.61 - } 156.62 - 156.63 - /** 156.64 - * Loads a resource and returns it as URL reference. 156.65 - * The Resource's classloader is used to load the resource, not 156.66 - * the System's ClassLoader so it may be safe to use this method 156.67 - * in a sandboxed environment. 156.68 - * @return 156.69 - */ 156.70 - public static URL getAsURL(String name) 156.71 - { 156.72 - return Resource.class.getClassLoader().getResource(name); 156.73 - } 156.74 - 156.75 - /** 156.76 - * Loads a resource and returns an InputStream to it. 156.77 - * @param name 156.78 - * @return 156.79 - */ 156.80 - public static InputStream getAsStream(String name) 156.81 - { 156.82 - try 156.83 - { 156.84 - URL url = getAsURL(name); 156.85 - return url.openStream(); 156.86 - } 156.87 - catch(IOException e) 156.88 - { 156.89 - e.printStackTrace(); 156.90 - return null; 156.91 - } 156.92 - } 156.93 - 156.94 - /** 156.95 - * Loads a plain text resource. 156.96 - * @param withNewline If false all newlines are removed from the 156.97 - * return String 156.98 - */ 156.99 - public static String getAsString(String name, boolean withNewline) 156.100 - { 156.101 - try 156.102 - { 156.103 - BufferedReader in = new BufferedReader( 156.104 - new InputStreamReader(getAsStream(name), Charset.forName("UTF-8"))); 156.105 - StringBuffer buf = new StringBuffer(); 156.106 - 156.107 - for(;;) 156.108 - { 156.109 - String line = in.readLine(); 156.110 - if(line == null) 156.111 - break; 156.112 - 156.113 - buf.append(line); 156.114 - if(withNewline) 156.115 - buf.append('\n'); 156.116 - } 156.117 - 156.118 - return buf.toString(); 156.119 - } 156.120 - catch(Exception e) 156.121 - { 156.122 - e.printStackTrace(); 156.123 - return null; 156.124 - } 156.125 - } 156.126 -}
157.1 --- a/trunk/com/so/news/storage/Article.java Tue Jan 20 10:21:03 2009 +0100 157.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 157.3 @@ -1,307 +0,0 @@ 157.4 -/* 157.5 - * StarOffice News Server 157.6 - * see AUTHORS for the list of contributors 157.7 - * 157.8 - * This program is free software: you can redistribute it and/or modify 157.9 - * it under the terms of the GNU General Public License as published by 157.10 - * the Free Software Foundation, either version 3 of the License, or 157.11 - * (at your option) any later version. 157.12 - * 157.13 - * This program is distributed in the hope that it will be useful, 157.14 - * but WITHOUT ANY WARRANTY; without even the implied warranty of 157.15 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 157.16 - * GNU General Public License for more details. 157.17 - * 157.18 - * You should have received a copy of the GNU General Public License 157.19 - * along with this program. If not, see <http://www.gnu.org/licenses/>. 157.20 - */ 157.21 - 157.22 -package com.so.news.storage; 157.23 - 157.24 -import java.sql.ResultSet; 157.25 -import java.sql.SQLException; 157.26 -import java.util.Date; 157.27 -import java.util.HashMap; 157.28 -import java.util.Map; 157.29 -import java.util.Map.Entry; 157.30 -import java.util.UUID; 157.31 - 157.32 -import com.so.news.Config; 157.33 -import com.so.news.Debug; 157.34 - 157.35 -/** 157.36 - * Represents a newsgroup article. 157.37 - * @author Christian Lins 157.38 - * @author Denis Schwerdel 157.39 - */ 157.40 -public class Article 157.41 -{ 157.42 - /** 157.43 - * Loads the Article identified by the given ID from the Database. 157.44 - * @param messageID 157.45 - * @return null if Article is not found or if an error occurred. 157.46 - */ 157.47 - public static Article getByMessageID(String messageID) 157.48 - { 157.49 - try 157.50 - { 157.51 - return Database.getInstance().getArticle(messageID); 157.52 - } 157.53 - catch(SQLException ex) 157.54 - { 157.55 - ex.printStackTrace(Debug.getInstance().getStream()); 157.56 - return null; 157.57 - } 157.58 - } 157.59 - 157.60 - public static Article getByNumberInGroup(Group group, int number) 157.61 - throws SQLException 157.62 - { 157.63 - long gid = group.getID(); 157.64 - return Database.getInstance().getArticle(gid, number); // Is number her correct? 157.65 - } 157.66 - 157.67 - private String body = ""; 157.68 - private long groupID = -1; 157.69 - private Map<String, String> header = new HashMap<String, String>(); 157.70 - private int numberInGroup = -1; 157.71 - private String msgID = null; 157.72 - 157.73 - /** 157.74 - * Default constructor. 157.75 - */ 157.76 - public Article() 157.77 - { 157.78 - } 157.79 - 157.80 - /** 157.81 - * Creates a new Article object using the date from the given 157.82 - * ResultSet. It is expected that ResultSet.next() was already 157.83 - * called by the Database class. 157.84 - * This construction has only package visibility. 157.85 - * @param rs 157.86 - */ 157.87 - Article(ResultSet rs) 157.88 - throws SQLException 157.89 - { 157.90 - this.body = rs.getString("body"); 157.91 - this.msgID = rs.getString("message_id"); 157.92 - 157.93 - // Parse the header 157.94 - parseHeader(rs.getString("header")); 157.95 - } 157.96 - 157.97 - /** 157.98 - * Parses the header fields and puts them into a map for faster access. 157.99 - * TODO: There could be fields that go over more than one line, some 157.100 - * bad clients do create them. 157.101 - * @param hsrc 157.102 - */ 157.103 - private void parseHeader(String hsrc) 157.104 - { 157.105 - String[] lines = hsrc.split("\n"); 157.106 - 157.107 - for(String line : lines) 157.108 - { 157.109 - String[] kv = line.split(":"); 157.110 - if(kv.length < 2) 157.111 - { 157.112 - Debug.getInstance().log("Invalid header field: " + line); 157.113 - continue; 157.114 - } 157.115 - else 157.116 - { 157.117 - // Set value in the header hash map 157.118 - String value = kv[1]; 157.119 - for(int n = 2; n < kv.length; n++) 157.120 - value += ":" + kv[n]; 157.121 - this.header.put(kv[0], value); 157.122 - } 157.123 - } 157.124 - } 157.125 - 157.126 - /** 157.127 - * Returnes the next Article in the group of this Article. 157.128 - * @return 157.129 - */ 157.130 - public Article nextArticleInGroup() 157.131 - { 157.132 - return null; 157.133 - } 157.134 - 157.135 - /** 157.136 - * Returns the previous Article in the group of this Article. 157.137 - * @return 157.138 - */ 157.139 - public Article prevArticleInGroup() 157.140 - { 157.141 - return null; 157.142 - } 157.143 - 157.144 - /** 157.145 - * Generates a message id for this article and sets it into 157.146 - * the header HashMap. 157.147 - */ 157.148 - private String generateMessageID() 157.149 - { 157.150 - this.msgID = "<" + UUID.randomUUID() + "@" 157.151 - + Config.getInstance().get("n3tpd.hostname", "localhost") + ">"; 157.152 - 157.153 - this.header.put("Message-ID", msgID); 157.154 - 157.155 - return msgID; 157.156 - } 157.157 - 157.158 - /** 157.159 - * Tries to delete this article. 157.160 - * @return false if the article could not be deleted, otherwise true 157.161 - */ 157.162 - public boolean delete() 157.163 - { 157.164 - return false; 157.165 - } 157.166 - 157.167 - /** 157.168 - * Checks if all necessary header fields are within this header. 157.169 - */ 157.170 - private void validateHeader() 157.171 - { 157.172 - // Forces a MessageID creation if not existing 157.173 - getMessageID(); 157.174 - 157.175 - // Check if the references are correct... 157.176 - String rep = header.get("In-Reply-To"); 157.177 - if(rep == null) // Some clients use only references instead of In-Reply-To 157.178 - return; //rep = header.get("References"); 157.179 - 157.180 - String ref = getMessageID(); 157.181 - 157.182 - if(rep != null && !rep.equals("")) 157.183 - { 157.184 - Article art = null; //TODO // getByMessageID(rep, articleDir); 157.185 - if(art != null) 157.186 - { 157.187 - ref = art.header.get("References") + " " + rep; 157.188 - } 157.189 - } 157.190 - header.put("References", ref); 157.191 - } 157.192 - 157.193 - /** 157.194 - * Returns the body string. 157.195 - */ 157.196 - public String getBody() 157.197 - { 157.198 - return body; 157.199 - } 157.200 - 157.201 - /** 157.202 - * @return Numerical ID of the associated Group. 157.203 - */ 157.204 - long getGroupID() 157.205 - { 157.206 - if(groupID == -1) // If the GroupID was not determined yet 157.207 - { 157.208 - // Determining GroupID 157.209 - String newsgroups = this.header.get("Newsgroups"); 157.210 - if(newsgroups != null) 157.211 - { 157.212 - String[] newsgroup = newsgroups.split(","); 157.213 - // Crossposting is not supported 157.214 - try 157.215 - { 157.216 - Group group; 157.217 - if(newsgroup.length > 0) 157.218 - group = Database.getInstance().getGroup(newsgroup[0].trim()); 157.219 - else 157.220 - group = Database.getInstance().getGroup(newsgroups.trim()); 157.221 - // TODO: What to do if Group does not exist? 157.222 - this.groupID = group.getID(); 157.223 - } 157.224 - catch(SQLException ex) 157.225 - { 157.226 - ex.printStackTrace(Debug.getInstance().getStream()); 157.227 - System.err.println(ex.getLocalizedMessage()); 157.228 - } 157.229 - } 157.230 - else 157.231 - System.err.println("Should never happen: Article::getGroupID"); 157.232 - } 157.233 - return this.groupID; 157.234 - } 157.235 - 157.236 - public void setBody(String body) 157.237 - { 157.238 - this.body = body; 157.239 - } 157.240 - 157.241 - public int getNumberInGroup() 157.242 - { 157.243 - return this.numberInGroup; 157.244 - } 157.245 - 157.246 - public void setHeader(HashMap<String, String> header) 157.247 - { 157.248 - this.header = header; 157.249 - } 157.250 - 157.251 - public void setNumberInGroup(int id) 157.252 - { 157.253 - this.numberInGroup = id; 157.254 - } 157.255 - 157.256 - public String getMessageID() 157.257 - { 157.258 - if(msgID == null) 157.259 - msgID = generateMessageID(); 157.260 - return msgID; 157.261 - } 157.262 - 157.263 - /** 157.264 - * @return Header source code of this Article. 157.265 - */ 157.266 - public String getHeaderSource() 157.267 - { 157.268 - StringBuffer buf = new StringBuffer(); 157.269 - 157.270 - for(Entry<String, String> entry : this.header.entrySet()) 157.271 - { 157.272 - buf.append(entry.getKey()); 157.273 - buf.append(":"); 157.274 - buf.append(entry.getValue()); 157.275 - buf.append("\n"); 157.276 - } 157.277 - 157.278 - return buf.toString(); 157.279 - } 157.280 - 157.281 - public Map<String, String> getHeader() 157.282 - { 157.283 - return this.header; 157.284 - } 157.285 - 157.286 - public Date getDate() 157.287 - { 157.288 - try 157.289 - { 157.290 - String date = this.header.get("Date"); 157.291 - return new Date(Date.parse(date)); 157.292 - } 157.293 - catch(Exception e) 157.294 - { 157.295 - e.printStackTrace(Debug.getInstance().getStream()); 157.296 - return null; 157.297 - } 157.298 - } 157.299 - 157.300 - public void setDate(Date date) 157.301 - { 157.302 - this.header.put("Date", date.toString()); 157.303 - } 157.304 - 157.305 - @Override 157.306 - public String toString() 157.307 - { 157.308 - return getMessageID(); 157.309 - } 157.310 -}
158.1 --- a/trunk/com/so/news/storage/Database.java Tue Jan 20 10:21:03 2009 +0100 158.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 158.3 @@ -1,327 +0,0 @@ 158.4 -/* 158.5 - * StarOffice News Server 158.6 - * see AUTHORS for the list of contributors 158.7 - * 158.8 - * This program is free software: you can redistribute it and/or modify 158.9 - * it under the terms of the GNU General Public License as published by 158.10 - * the Free Software Foundation, either version 3 of the License, or 158.11 - * (at your option) any later version. 158.12 - * 158.13 - * This program is distributed in the hope that it will be useful, 158.14 - * but WITHOUT ANY WARRANTY; without even the implied warranty of 158.15 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 158.16 - * GNU General Public License for more details. 158.17 - * 158.18 - * You should have received a copy of the GNU General Public License 158.19 - * along with this program. If not, see <http://www.gnu.org/licenses/>. 158.20 - */ 158.21 - 158.22 -package com.so.news.storage; 158.23 - 158.24 -import java.sql.Connection; 158.25 -import java.sql.DriverManager; 158.26 -import java.sql.ResultSet; 158.27 -import java.sql.SQLException; 158.28 -import java.sql.Statement; 158.29 - 158.30 -import java.util.zip.CRC32; 158.31 -import com.so.news.Config; 158.32 -import com.so.news.util.StringTemplate; 158.33 - 158.34 -/** 158.35 - * Database abstraction class. 158.36 - * @author Christian Lins (christian.lins@web.de) 158.37 - */ 158.38 -public class Database 158.39 -{ 158.40 - private static Database instance = null; 158.41 - 158.42 - /** 158.43 - * Initializes the Database subsystem, e.g. loading a JDBC driver and 158.44 - * connection to the Database Managment System. 158.45 - * This method is called when the daemon starts up or at the first 158.46 - * call to Database.getInstance(). 158.47 - * @throws java.lang.Exception 158.48 - */ 158.49 - public static void arise() 158.50 - throws Exception 158.51 - { 158.52 - // Tries to load the Database driver and establish a connection. 158.53 - if(instance == null) 158.54 - instance = new Database(); 158.55 - } 158.56 - 158.57 - /** 158.58 - * @return Instance of the current Database backend. Returns null if an error 158.59 - * has occurred. 158.60 - */ 158.61 - public static Database getInstance() 158.62 - { 158.63 - try 158.64 - { 158.65 - arise(); 158.66 - return instance; 158.67 - } 158.68 - catch(Exception ex) 158.69 - { 158.70 - ex.printStackTrace(); 158.71 - return null; 158.72 - } 158.73 - } 158.74 - 158.75 - private Connection conn = null; 158.76 - 158.77 - /** 158.78 - * Private constructor. 158.79 - * @throws java.lang.Exception 158.80 - */ 158.81 - private Database() 158.82 - throws Exception 158.83 - { 158.84 - Class.forName( 158.85 - Config.getInstance().get("n3tpd.storage.dbmsdriver", "")); 158.86 - this.conn = DriverManager.getConnection( 158.87 - Config.getInstance().get("n3tpd.storage.database", ""), 158.88 - Config.getInstance().get("n3tpd.storage.user", "n3tpd_user"), 158.89 - Config.getInstance().get("n3tpd.storage.password", "")); 158.90 - this.conn.setAutoCommit(false); 158.91 - } 158.92 - 158.93 - /** 158.94 - * Adds an article to the database. 158.95 - * @param article 158.96 - * @return 158.97 - * @throws java.sql.SQLException 158.98 - */ 158.99 - public boolean addArticle(Article article) 158.100 - throws SQLException 158.101 - { 158.102 - Statement stmt = this.conn.createStatement(); 158.103 - 158.104 - String sql0 = "START TRANSACTION"; 158.105 - String sql1 = "INSERT INTO articles (message_id,header,body)" + 158.106 - "VALUES('%mid', '%header', '%body')"; 158.107 - StringTemplate tmpl = new StringTemplate(sql1); 158.108 - tmpl.set("body", article.getBody()); 158.109 - tmpl.set("mid", article.getMessageID()); 158.110 - tmpl.set("header", article.getHeaderSource()); 158.111 - sql1 = tmpl.toString(); 158.112 - 158.113 - String sql2 = "COMMIT"; 158.114 - 158.115 - // Add statements as batch 158.116 - stmt.addBatch(sql0); 158.117 - stmt.addBatch(sql1); 158.118 - 158.119 - // TODO: For each newsgroup add a reference 158.120 - String sql = "INSERT INTO postings (group_id, article_id, article_index)" + 158.121 - "VALUES (%gid, (SELECT article_id FROM articles WHERE message_id = '%mid')," + 158.122 - " %idx)"; 158.123 - 158.124 - tmpl = new StringTemplate(sql); 158.125 - tmpl.set("gid", article.getGroupID()); 158.126 - tmpl.set("mid", article.getMessageID()); 158.127 - tmpl.set("idx", getMaxArticleIndex() + 1); 158.128 - stmt.addBatch(tmpl.toString()); 158.129 - 158.130 - // Commit 158.131 - stmt.addBatch(sql2); 158.132 - 158.133 - // And execute the batch 158.134 - stmt.executeBatch(); 158.135 - 158.136 - return true; 158.137 - } 158.138 - 158.139 - /** 158.140 - * Adds a group to the Database. 158.141 - * @param name 158.142 - * @throws java.sql.SQLException 158.143 - */ 158.144 - public boolean addGroup(String name) 158.145 - throws SQLException 158.146 - { 158.147 - CRC32 crc = new CRC32(); 158.148 - crc.update(name.getBytes()); 158.149 - 158.150 - long id = crc.getValue(); 158.151 - 158.152 - Statement stmt = conn.createStatement(); 158.153 - return 1 == stmt.executeUpdate("INSERT INTO Groups (ID, Name) VALUES (" + id + ", '" + name + "')"); 158.154 - } 158.155 - 158.156 - public void delete(Article article) 158.157 - { 158.158 - 158.159 - } 158.160 - 158.161 - public void delete(Group group) 158.162 - { 158.163 - 158.164 - } 158.165 - 158.166 - public Article getArticle(String messageID) 158.167 - throws SQLException 158.168 - { 158.169 - Statement stmt = this.conn.createStatement(); 158.170 - ResultSet rs = 158.171 - stmt.executeQuery("SELECT * FROM articles WHERE message_id = '" + messageID + "'"); 158.172 - 158.173 - return new Article(rs); 158.174 - } 158.175 - 158.176 - public Article getArticle(long gid, long article_id) 158.177 - throws SQLException 158.178 - { 158.179 - Statement stmt = this.conn.createStatement(); 158.180 - String sql = "SELECT * FROM articles WHERE article_id = " + 158.181 - "(SELECT article_id FROM postings WHERE " + 158.182 - "group_id = " + gid + " AND article_id = " + article_id +")"; 158.183 - ResultSet rs = 158.184 - stmt.executeQuery(sql); 158.185 - 158.186 - if(rs.next()) 158.187 - return new Article(rs); 158.188 - else 158.189 - return null; 158.190 - } 158.191 - 158.192 - public ResultSet getArticles() 158.193 - throws SQLException 158.194 - { 158.195 - Statement stmt = conn.createStatement(); 158.196 - return stmt.executeQuery("SELECT * FROM articles"); 158.197 - } 158.198 - 158.199 - /** 158.200 - * Reads all Groups from the Database. 158.201 - * @return 158.202 - * @throws java.sql.SQLException 158.203 - */ 158.204 - public ResultSet getGroups() 158.205 - throws SQLException 158.206 - { 158.207 - Statement stmt = conn.createStatement(); 158.208 - ResultSet rs = stmt.executeQuery("SELECT * FROM groups"); 158.209 - 158.210 - return rs; 158.211 - } 158.212 - 158.213 - /** 158.214 - * Returns the Group that is identified by the name. 158.215 - * @param name 158.216 - * @return 158.217 - * @throws java.sql.SQLException 158.218 - */ 158.219 - public Group getGroup(String name) 158.220 - throws SQLException 158.221 - { 158.222 - Statement stmt = this.conn.createStatement(); 158.223 - String sql = "SELECT group_id FROM groups WHERE Name = '%name'"; 158.224 - StringTemplate tmpl = new StringTemplate(sql); 158.225 - tmpl.set("name", name); 158.226 - 158.227 - ResultSet rs = stmt.executeQuery(tmpl.toString()); 158.228 - 158.229 - if(!rs.next()) 158.230 - return null; 158.231 - else 158.232 - { 158.233 - long id = rs.getLong("group_id"); 158.234 - return new Group(name, id); 158.235 - } 158.236 - } 158.237 - 158.238 - public int getMaxArticleIndex() 158.239 - throws SQLException 158.240 - { 158.241 - Statement stmt = conn.createStatement(); 158.242 - ResultSet rs = stmt.executeQuery( 158.243 - "SELECT Max(article_index) FROM postings"); 158.244 - 158.245 - if(!rs.next()) 158.246 - return 0; 158.247 - else 158.248 - return rs.getInt(1); 158.249 - } 158.250 - 158.251 - public int getLastArticleNumber(Group group) 158.252 - throws SQLException 158.253 - { 158.254 - Statement stmt = conn.createStatement(); 158.255 - ResultSet rs = stmt.executeQuery( 158.256 - "SELECT Max(article_index) FROM postings WHERE group_id = " + group.getID()); 158.257 - 158.258 - if(!rs.next()) 158.259 - return 0; 158.260 - else 158.261 - return rs.getInt(1); 158.262 - } 158.263 - 158.264 - public int getFirstArticleNumber(Group group) 158.265 - throws SQLException 158.266 - { 158.267 - Statement stmt = conn.createStatement(); 158.268 - ResultSet rs = stmt.executeQuery( 158.269 - "SELECT Min(article_index) FROM postings WHERE group_id = " + group.getID()); 158.270 - 158.271 - if(!rs.next()) 158.272 - return 0; 158.273 - else 158.274 - return rs.getInt(1); 158.275 - } 158.276 - 158.277 - /** 158.278 - * Returns a group name identified by the given id. 158.279 - * @param id 158.280 - * @return 158.281 - * @throws java.sql.SQLException 158.282 - */ 158.283 - public String getGroup(int id) 158.284 - throws SQLException 158.285 - { 158.286 - Statement stmt = conn.createStatement(); 158.287 - ResultSet rs = stmt.executeQuery( 158.288 - "SELECT name FROM groups WHERE group_id = '" + id + "'"); 158.289 - 158.290 - if(rs.next()) 158.291 - { 158.292 - return rs.getString(1); 158.293 - } 158.294 - else 158.295 - return null; 158.296 - } 158.297 - 158.298 - public Article getOldestArticle() 158.299 - throws SQLException 158.300 - { 158.301 - Statement stmt = conn.createStatement(); 158.302 - ResultSet rs = 158.303 - stmt.executeQuery("SELECT * FROM Articles WHERE Date = (SELECT Min(Date) FROM Articles)"); 158.304 - 158.305 - if(rs.next()) 158.306 - return new Article(rs); 158.307 - else 158.308 - return null; 158.309 - } 158.310 - 158.311 - /** 158.312 - * Checks if there is a group with the given name in the Database. 158.313 - * @param name 158.314 - * @return 158.315 - * @throws java.sql.SQLException 158.316 - */ 158.317 - public boolean isGroupExisting(String name) 158.318 - throws SQLException 158.319 - { 158.320 - Statement stmt = this.conn.createStatement(); 158.321 - ResultSet rs = stmt.executeQuery("SELECT * FROM Groups WHERE Name = '" + name + "'"); 158.322 - 158.323 - return rs.next(); 158.324 - } 158.325 - 158.326 - public void updateArticle(Article article) 158.327 - { 158.328 - 158.329 - } 158.330 -}
159.1 --- a/trunk/com/so/news/storage/Group.java Tue Jan 20 10:21:03 2009 +0100 159.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 159.3 @@ -1,142 +0,0 @@ 159.4 -/* 159.5 - * StarOffice News Server 159.6 - * see AUTHORS for the list of contributors 159.7 - * 159.8 - * This program is free software: you can redistribute it and/or modify 159.9 - * it under the terms of the GNU General Public License as published by 159.10 - * the Free Software Foundation, either version 3 of the License, or 159.11 - * (at your option) any later version. 159.12 - * 159.13 - * This program is distributed in the hope that it will be useful, 159.14 - * but WITHOUT ANY WARRANTY; without even the implied warranty of 159.15 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 159.16 - * GNU General Public License for more details. 159.17 - * 159.18 - * You should have received a copy of the GNU General Public License 159.19 - * along with this program. If not, see <http://www.gnu.org/licenses/>. 159.20 - */ 159.21 - 159.22 -package com.so.news.storage; 159.23 - 159.24 -import java.sql.ResultSet; 159.25 -import java.sql.SQLException; 159.26 -import java.util.ArrayList; 159.27 -import java.util.List; 159.28 -import com.so.news.Debug; 159.29 - 159.30 -/** 159.31 - * Represents a logical Group within this newsserver. 159.32 - * @author Christian Lins 159.33 - */ 159.34 -public class Group 159.35 -{ 159.36 - private long id; 159.37 - private String name; 159.38 - 159.39 - /** 159.40 - * Private constructor. 159.41 - * @param name 159.42 - * @param id 159.43 - */ 159.44 - Group(String name, long id) 159.45 - { 159.46 - this.id = id; 159.47 - this.name = name; 159.48 - } 159.49 - 159.50 - /** 159.51 - * Returns a Group identified by its full name. 159.52 - * @param name 159.53 - * @return 159.54 - */ 159.55 - public static Group getByName(String name) 159.56 - { 159.57 - try 159.58 - { 159.59 - return Database.getInstance().getGroup(name); 159.60 - } 159.61 - catch(SQLException ex) 159.62 - { 159.63 - System.err.println(ex.getLocalizedMessage()); 159.64 - ex.printStackTrace(Debug.getInstance().getStream()); 159.65 - return null; 159.66 - } 159.67 - } 159.68 - 159.69 - /** 159.70 - * Returns a list of all groups this server handles. 159.71 - * @return 159.72 - */ 159.73 - public static ArrayList<Group> getAll() 159.74 - { 159.75 - ArrayList<Group> buffer = new ArrayList<Group>(); 159.76 - 159.77 - try 159.78 - { 159.79 - ResultSet rs = Database.getInstance().getGroups(); 159.80 - 159.81 - while(rs.next()) 159.82 - { 159.83 - String name = rs.getString("name"); 159.84 - long id = rs.getLong("group_id"); 159.85 - 159.86 - Group group = new Group(name, id); 159.87 - buffer.add(group); 159.88 - } 159.89 - } 159.90 - catch(SQLException ex) 159.91 - { 159.92 - ex.printStackTrace(Debug.getInstance().getStream()); 159.93 - System.err.println(ex.getLocalizedMessage()); 159.94 - } 159.95 - 159.96 - return buffer; 159.97 - } 159.98 - 159.99 - public List<Article> getAllArticles() 159.100 - throws SQLException 159.101 - { 159.102 - return getAllArticles(getFirstArticle(), getLastArticle()); 159.103 - } 159.104 - 159.105 - public List<Article> getAllArticles(int first, int last) 159.106 - { 159.107 - return null; 159.108 - } 159.109 - 159.110 - public int getFirstArticle() 159.111 - throws SQLException 159.112 - { 159.113 - return Database.getInstance().getFirstArticleNumber(this); 159.114 - } 159.115 - 159.116 - public long getID() 159.117 - { 159.118 - return id; 159.119 - } 159.120 - 159.121 - public int getLastArticle() 159.122 - throws SQLException 159.123 - { 159.124 - return Database.getInstance().getLastArticleNumber(this); 159.125 - } 159.126 - 159.127 - public String getName() 159.128 - { 159.129 - return name; 159.130 - } 159.131 - 159.132 - public void setName(String name) 159.133 - { 159.134 - this.name = name; 159.135 - } 159.136 - 159.137 - public int getEstimatedArticleCount() 159.138 - throws SQLException 159.139 - { 159.140 - if (getLastArticle() < getFirstArticle()) 159.141 - return 0; 159.142 - return getLastArticle() - getFirstArticle() + 1; 159.143 - } 159.144 - 159.145 -}
160.1 --- a/trunk/com/so/news/storage/Purger.java Tue Jan 20 10:21:03 2009 +0100 160.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 160.3 @@ -1,96 +0,0 @@ 160.4 -/* 160.5 - * StarOffice News Server 160.6 - * see AUTHORS for the list of contributors 160.7 - * 160.8 - * This program is free software: you can redistribute it and/or modify 160.9 - * it under the terms of the GNU General Public License as published by 160.10 - * the Free Software Foundation, either version 3 of the License, or 160.11 - * (at your option) any later version. 160.12 - * 160.13 - * This program is distributed in the hope that it will be useful, 160.14 - * but WITHOUT ANY WARRANTY; without even the implied warranty of 160.15 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 160.16 - * GNU General Public License for more details. 160.17 - * 160.18 - * You should have received a copy of the GNU General Public License 160.19 - * along with this program. If not, see <http://www.gnu.org/licenses/>. 160.20 - */ 160.21 - 160.22 -package com.so.news.storage; 160.23 - 160.24 -import java.util.Date; 160.25 - 160.26 -import com.so.news.Config; 160.27 -import com.so.news.Debug; 160.28 - 160.29 -/** 160.30 - * The purger is started in configurable intervals to search 160.31 - * for old messages that can be purged. 160.32 - * @author Christian Lins 160.33 - */ 160.34 -public class Purger extends Thread 160.35 -{ 160.36 - private int interval; 160.37 - 160.38 - public Purger() 160.39 - { 160.40 - setDaemon(true); // Daemons run only along with the main thread 160.41 - setPriority(Thread.MIN_PRIORITY); 160.42 - 160.43 - this.interval = Config.getInstance().get("n3tpd.article.lifetime", 30) * 24 * 60 * 60 * 1000; // Milliseconds 160.44 - if(this.interval < 0) 160.45 - this.interval = Integer.MAX_VALUE; 160.46 - } 160.47 - 160.48 - /** 160.49 - * Runloop of this Purger class. 160.50 - */ 160.51 - @Override 160.52 - public void run() 160.53 - { 160.54 - for(;;) 160.55 - { 160.56 - purge(); 160.57 - 160.58 - try 160.59 - { 160.60 - sleep(interval); 160.61 - } 160.62 - catch(InterruptedException e) 160.63 - { 160.64 - e.printStackTrace(Debug.getInstance().getStream()); 160.65 - } 160.66 - } 160.67 - } 160.68 - 160.69 - /** 160.70 - * Loops through all messages and deletes them if their time 160.71 - * has come. 160.72 - */ 160.73 - private void purge() 160.74 - { 160.75 - Debug.getInstance().log("Purging old messages..."); 160.76 - 160.77 - try 160.78 - { 160.79 - for(;;) 160.80 - { 160.81 - Article art = null; //Database.getInstance().getOldestArticle(); 160.82 - if(art == null) // No articles in the database 160.83 - break; 160.84 - 160.85 - if(art.getDate().getTime() < (new Date().getTime() + this.interval)) 160.86 - { 160.87 - Database.getInstance().delete(art); 160.88 - Debug.getInstance().log("Deleted: " + art); 160.89 - } 160.90 - else 160.91 - break; 160.92 - } 160.93 - } 160.94 - catch(Exception ex) 160.95 - { 160.96 - ex.printStackTrace(); 160.97 - } 160.98 - } 160.99 -}
161.1 --- a/trunk/com/so/news/util/StringTemplate.java Tue Jan 20 10:21:03 2009 +0100 161.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 161.3 @@ -1,77 +0,0 @@ 161.4 -/* 161.5 - * StarOffice News Server 161.6 - * see AUTHORS for the list of contributors 161.7 - * 161.8 - * This program is free software: you can redistribute it and/or modify 161.9 - * it under the terms of the GNU General Public License as published by 161.10 - * the Free Software Foundation, either version 3 of the License, or 161.11 - * (at your option) any later version. 161.12 - * 161.13 - * This program is distributed in the hope that it will be useful, 161.14 - * but WITHOUT ANY WARRANTY; without even the implied warranty of 161.15 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 161.16 - * GNU General Public License for more details. 161.17 - * 161.18 - * You should have received a copy of the GNU General Public License 161.19 - * along with this program. If not, see <http://www.gnu.org/licenses/>. 161.20 - */ 161.21 - 161.22 -package com.so.news.util; 161.23 - 161.24 -import java.util.HashMap; 161.25 - 161.26 -/** 161.27 - * Class that allows simple String template handling. 161.28 - * @author Christian Lins (christian.lins@web.de) 161.29 - */ 161.30 -public class StringTemplate 161.31 -{ 161.32 - private String str = null; 161.33 - private String templateDelimiter = "%"; 161.34 - private HashMap<String, String> templateValues = new HashMap<String, String>(); 161.35 - 161.36 - public StringTemplate(String str, String templateDelimiter) 161.37 - { 161.38 - this.str = str; 161.39 - this.templateDelimiter = templateDelimiter; 161.40 - } 161.41 - 161.42 - public StringTemplate(String str) 161.43 - { 161.44 - this(str, "%"); 161.45 - } 161.46 - 161.47 - public void set(String template, String value) 161.48 - { 161.49 - this.templateValues.put(template, value); 161.50 - } 161.51 - 161.52 - public void set(String template, long value) 161.53 - { 161.54 - set(template, Long.toString(value)); 161.55 - } 161.56 - 161.57 - public void set(String template, double value) 161.58 - { 161.59 - set(template, Double.toString(value)); 161.60 - } 161.61 - 161.62 - public void set(String template, Object obj) 161.63 - { 161.64 - set(template, obj.toString()); 161.65 - } 161.66 - 161.67 - @Override 161.68 - public String toString() 161.69 - { 161.70 - String ret = new String(str); 161.71 - 161.72 - for(String key : this.templateValues.keySet()) 161.73 - { 161.74 - String value = this.templateValues.get(key); 161.75 - ret = ret.replace(templateDelimiter + key, value); 161.76 - } 161.77 - 161.78 - return ret; 161.79 - } 161.80 -}
162.1 --- a/trunk/helpers/tbl_mysql6_tmpl.sql Tue Jan 20 10:21:03 2009 +0100 162.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 162.3 @@ -1,39 +0,0 @@ 162.4 -CREATE DATABASE staroffice_news; 162.5 - 162.6 -CREATE TABLE groups 162.7 -( 162.8 - group_id SERIAL, 162.9 - name VARCHAR(80) NOT NULL, 162.10 - flags INTEGER DEFAULT 0 NOT NULL 162.11 -); 162.12 - 162.13 -CREATE UNIQUE INDEX name_id_index ON groups (name); 162.14 - 162.15 -CREATE TABLE articles 162.16 -( 162.17 - article_id SERIAL, 162.18 - message_id TEXT, 162.19 - header TEXT, 162.20 - body TEXT 162.21 -); 162.22 - 162.23 -CREATE UNIQUE INDEX article_message_index ON articles (message_id(255)); 162.24 - 162.25 -CREATE TABLE postings 162.26 -( 162.27 - group_id INTEGER, 162.28 - article_id INTEGER, 162.29 - article_index INTEGER NOT NULL 162.30 -); 162.31 - 162.32 -CREATE UNIQUE INDEX posting_article_index ON postings (article_id); 162.33 - 162.34 -CREATE TABLE subscriptions 162.35 -( 162.36 - group_id INTEGER 162.37 -); 162.38 - 162.39 -CREATE TABLE overview 162.40 -( 162.41 - header TEXT 162.42 -);
163.1 --- a/trunk/rfc3977.txt Tue Jan 20 10:21:03 2009 +0100 163.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 163.3 @@ -1,6998 +0,0 @@ 163.4 - 163.5 -Network Working Group C. Feather 163.6 -Request for Comments: 3977 THUS plc 163.7 -Obsoletes: 977 October 2006 163.8 -Updates: 2980 163.9 -Category: Standards Track 163.10 - 163.11 - 163.12 - Network News Transfer Protocol (NNTP) 163.13 - 163.14 -Status of This Memo 163.15 - 163.16 - This document specifies an Internet standards track protocol for the 163.17 - Internet community, and requests discussion and suggestions for 163.18 - improvements. Please refer to the current edition of the "Internet 163.19 - Official Protocol Standards" (STD 1) for the standardization state 163.20 - and status of this protocol. Distribution of this memo is unlimited. 163.21 - 163.22 -Copyright Notice 163.23 - 163.24 - Copyright (C) The Internet Society (2006). 163.25 - 163.26 -Abstract 163.27 - 163.28 - The Network News Transfer Protocol (NNTP) has been in use in the 163.29 - Internet for a decade, and remains one of the most popular protocols 163.30 - (by volume) in use today. This document is a replacement for 163.31 - RFC 977, and officially updates the protocol specification. It 163.32 - clarifies some vagueness in RFC 977, includes some new base 163.33 - functionality, and provides a specific mechanism to add standardized 163.34 - extensions to NNTP. 163.35 - 163.36 -Table of Contents 163.37 - 163.38 - 1. Introduction . . . . . . . . . . . . . . . . . . . . . . . . 3 163.39 - 1.1. Author's Note . . . . . . . . . . . . . . . . . . . . . . 4 163.40 - 2. Notation . . . . . . . . . . . . . . . . . . . . . . . . . . 5 163.41 - 3. Basic Concepts . . . . . . . . . . . . . . . . . . . . . . . 6 163.42 - 3.1. Commands and Responses . . . . . . . . . . . . . . . . . 6 163.43 - 3.1.1. Multi-line Data Blocks . . . . . . . . . . . . . . . . 8 163.44 - 3.2. Response Codes . . . . . . . . . . . . . . . . . . . . . 9 163.45 - 3.2.1. Generic Response Codes . . . . . . . . . . . . . . . 10 163.46 - 3.2.1.1. Examples . . . . . . . . . . . . . . . . . . . . 12 163.47 - 3.3. Capabilities and Extensions . . . . . . . . . . . . . . . 14 163.48 - 3.3.1. Capability Descriptions . . . . . . . . . . . . . . . 14 163.49 - 3.3.2. Standard Capabilities . . . . . . . . . . . . . . . . 15 163.50 - 3.3.3. Extensions . . . . . . . . . . . . . . . . . . . . . 16 163.51 - 3.3.4. Initial IANA Register . . . . . . . . . . . . . . . . 18 163.52 - 3.4. Mandatory and Optional Commands . . . . . . . . . . . . . 20 163.53 - 163.54 - 163.55 - 163.56 -Feather Standards Track [Page 1] 163.57 - 163.58 -RFC 3977 Network News Transfer Protocol (NNTP) October 2006 163.59 - 163.60 - 163.61 - 3.4.1. Reading and Transit Servers . . . . . . . . . . . . . 21 163.62 - 3.4.2. Mode Switching . . . . . . . . . . . . . . . . . . . 21 163.63 - 3.5. Pipelining . . . . . . . . . . . . . . . . . . . . . . . 22 163.64 - 3.5.1. Examples . . . . . . . . . . . . . . . . . . . . . . 23 163.65 - 3.6. Articles . . . . . . . . . . . . . . . . . . . . . . . . 24 163.66 - 4. The WILDMAT Format . . . . . . . . . . . . . . . . . . . . . 25 163.67 - 4.1. Wildmat Syntax . . . . . . . . . . . . . . . . . . . . . 26 163.68 - 4.2. Wildmat Semantics . . . . . . . . . . . . . . . . . . . . 26 163.69 - 4.3. Extensions . . . . . . . . . . . . . . . . . . . . . . . 27 163.70 - 4.4. Examples . . . . . . . . . . . . . . . . . . . . . . . . 27 163.71 - 5. Session Administration Commands . . . . . . . . . . . . . . . 28 163.72 - 5.1. Initial Connection . . . . . . . . . . . . . . . . . . . 28 163.73 - 5.2. CAPABILITIES . . . . . . . . . . . . . . . . . . . . . . 29 163.74 - 5.3. MODE READER . . . . . . . . . . . . . . . . . . . . . . . 32 163.75 - 5.4. QUIT . . . . . . . . . . . . . . . . . . . . . . . . . . 34 163.76 - 6. Article Posting and Retrieval . . . . . . . . . . . . . . . . 35 163.77 - 6.1. Group and Article Selection . . . . . . . . . . . . . . . 36 163.78 - 6.1.1. GROUP . . . . . . . . . . . . . . . . . . . . . . . . 36 163.79 - 6.1.2. LISTGROUP . . . . . . . . . . . . . . . . . . . . . . 39 163.80 - 6.1.3. LAST . . . . . . . . . . . . . . . . . . . . . . . . 42 163.81 - 6.1.4. NEXT . . . . . . . . . . . . . . . . . . . . . . . . 44 163.82 - 6.2. Retrieval of Articles and Article Sections . . . . . . . 45 163.83 - 6.2.1. ARTICLE . . . . . . . . . . . . . . . . . . . . . . . 46 163.84 - 6.2.2. HEAD . . . . . . . . . . . . . . . . . . . . . . . . 49 163.85 - 6.2.3. BODY . . . . . . . . . . . . . . . . . . . . . . . . 51 163.86 - 6.2.4. STAT . . . . . . . . . . . . . . . . . . . . . . . . 53 163.87 - 6.3. Article Posting . . . . . . . . . . . . . . . . . . . . . 56 163.88 - 6.3.1. POST . . . . . . . . . . . . . . . . . . . . . . . . 56 163.89 - 6.3.2. IHAVE . . . . . . . . . . . . . . . . . . . . . . . . 58 163.90 - 7. Information Commands . . . . . . . . . . . . . . . . . . . . 61 163.91 - 7.1. DATE . . . . . . . . . . . . . . . . . . . . . . . . . . 61 163.92 - 7.2. HELP . . . . . . . . . . . . . . . . . . . . . . . . . . 62 163.93 - 7.3. NEWGROUPS . . . . . . . . . . . . . . . . . . . . . . . . 63 163.94 - 7.4. NEWNEWS . . . . . . . . . . . . . . . . . . . . . . . . . 64 163.95 - 7.5. Time . . . . . . . . . . . . . . . . . . . . . . . . . . 65 163.96 - 7.5.1. Examples . . . . . . . . . . . . . . . . . . . . . . 66 163.97 - 7.6. The LIST Commands . . . . . . . . . . . . . . . . . . . . 66 163.98 - 7.6.1. LIST . . . . . . . . . . . . . . . . . . . . . . . . 67 163.99 - 7.6.2. Standard LIST Keywords . . . . . . . . . . . . . . . 69 163.100 - 7.6.3. LIST ACTIVE . . . . . . . . . . . . . . . . . . . . . 70 163.101 - 7.6.4. LIST ACTIVE.TIMES . . . . . . . . . . . . . . . . . . 71 163.102 - 7.6.5. LIST DISTRIB.PATS . . . . . . . . . . . . . . . . . . 72 163.103 - 7.6.6. LIST NEWSGROUPS . . . . . . . . . . . . . . . . . . . 73 163.104 - 8. Article Field Access Commands . . . . . . . . . . . . . . . . 73 163.105 - 8.1. Article Metadata . . . . . . . . . . . . . . . . . . . . 74 163.106 - 8.1.1. The :bytes Metadata Item . . . . . . . . . . . . . . 74 163.107 - 8.1.2. The :lines Metadata Item . . . . . . . . . . . . . . 75 163.108 - 8.2. Database Consistency . . . . . . . . . . . . . . . . . . 75 163.109 - 163.110 - 163.111 - 163.112 -Feather Standards Track [Page 2] 163.113 - 163.114 -RFC 3977 Network News Transfer Protocol (NNTP) October 2006 163.115 - 163.116 - 163.117 - 8.3. OVER . . . . . . . . . . . . . . . . . . . . . . . . . . 76 163.118 - 8.4. LIST OVERVIEW.FMT . . . . . . . . . . . . . . . . . . . . 81 163.119 - 8.5. HDR . . . . . . . . . . . . . . . . . . . . . . . . . . . 83 163.120 - 8.6. LIST HEADERS . . . . . . . . . . . . . . . . . . . . . . 87 163.121 - 9. Augmented BNF Syntax for NNTP . . . . . . . . . . . . . . . . 90 163.122 - 9.1. Introduction . . . . . . . . . . . . . . . . . . . . . . 90 163.123 - 9.2. Commands . . . . . . . . . . . . . . . . . . . . . . . . 92 163.124 - 9.3. Command Continuation . . . . . . . . . . . . . . . . . . 93 163.125 - 9.4. Responses . . . . . . . . . . . . . . . . . . . . . . . . 93 163.126 - 9.4.1. Generic Responses . . . . . . . . . . . . . . . . . . 93 163.127 - 9.4.2. Initial Response Line Contents . . . . . . . . . . . 94 163.128 - 9.4.3. Multi-line Response Contents . . . . . . . . . . . . 94 163.129 - 9.5. Capability Lines . . . . . . . . . . . . . . . . . . . . 95 163.130 - 9.6. LIST Variants . . . . . . . . . . . . . . . . . . . . . . 96 163.131 - 9.7. Articles . . . . . . . . . . . . . . . . . . . . . . . . 97 163.132 - 9.8. General Non-terminals . . . . . . . . . . . . . . . . . . 97 163.133 - 9.9. Extensions and Validation . . . . . . . . . . . . . . . . 99 163.134 - 10. Internationalisation Considerations . . . . . . . . . . . . .100 163.135 - 10.1. Introduction and Historical Situation . . . . . . . . . .100 163.136 - 10.2. This Specification . . . . . . . . . . . . . . . . . . .101 163.137 - 10.3. Outstanding Issues . . . . . . . . . . . . . . . . . . .102 163.138 - 11. IANA Considerations . . . . . . . . . . . . . . . . . . . . .103 163.139 - 12. Security Considerations . . . . . . . . . . . . . . . . . . .103 163.140 - 12.1. Personal and Proprietary Information . . . . . . . . . .104 163.141 - 12.2. Abuse of Server Log Information . . . . . . . . . . . . .104 163.142 - 12.3. Weak Authentication and Access Control . . . . . . . . .104 163.143 - 12.4. DNS Spoofing . . . . . . . . . . . . . . . . . . . . . .104 163.144 - 12.5. UTF-8 Issues . . . . . . . . . . . . . . . . . . . . . .105 163.145 - 12.6. Caching of Capability Lists . . . . . . . . . . . . . . .106 163.146 - 13. Acknowledgements . . . . . . . . . . . . . . . . . . . . . .107 163.147 - 14. References . . . . . . . . . . . . . . . . . . . . . . . . .110 163.148 - 14.1. Normative References . . . . . . . . . . . . . . . . . .110 163.149 - 14.2. Informative References . . . . . . . . . . . . . . . . .110 163.150 - A. Interaction with Other Specifications . . . . . . . . . . . .112 163.151 - A.1. Header Folding . . . . . . . . . . . . . . . . . . . . .112 163.152 - A.2. Message-IDs . . . . . . . . . . . . . . . . . . . . . . .112 163.153 - A.3. Article Posting . . . . . . . . . . . . . . . . . . . . .114 163.154 - B. Summary of Commands . . . . . . . . . . . . . . . . . . . . .115 163.155 - C. Summary of Response Codes . . . . . . . . . . . . . . . . . .117 163.156 - D. Changes from RFC 977 . . . . . . . . . . . . . . . . . . . .121 163.157 - 163.158 -1. Introduction 163.159 - 163.160 - This document specifies the Network News Transfer Protocol (NNTP), 163.161 - which is used for the distribution, inquiry, retrieval, and posting 163.162 - of Netnews articles using a reliable stream-based mechanism. For 163.163 - news-reading clients, NNTP enables retrieval of news articles that 163.164 - 163.165 - 163.166 - 163.167 - 163.168 -Feather Standards Track [Page 3] 163.169 - 163.170 -RFC 3977 Network News Transfer Protocol (NNTP) October 2006 163.171 - 163.172 - 163.173 - are stored in a central database, giving subscribers the ability to 163.174 - select only those articles they wish to read. 163.175 - 163.176 - The Netnews model provides for indexing, cross-referencing, and 163.177 - expiration of aged messages. NNTP is designed for efficient 163.178 - transmission of Netnews articles over a reliable full duplex 163.179 - communication channel. 163.180 - 163.181 - Although the protocol specification in this document is largely 163.182 - compatible with the version specified in RFC 977 [RFC977], a number 163.183 - of changes are summarised in Appendix D. In particular: 163.184 - 163.185 - o the default character set is changed from US-ASCII [ANSI1986] to 163.186 - UTF-8 [RFC3629] (note that US-ASCII is a subset of UTF-8); 163.187 - 163.188 - o a number of commands that were optional in RFC 977 or that have 163.189 - been taken from RFC 2980 [RFC2980] are now mandatory; and 163.190 - 163.191 - o a CAPABILITIES command has been added to allow clients to 163.192 - determine what functionality is available from a server. 163.193 - 163.194 - The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", 163.195 - "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this 163.196 - document are to be interpreted as described in RFC 2119 [RFC2119]. 163.197 - 163.198 - An implementation is not compliant if it fails to satisfy one or more 163.199 - of the MUST requirements for this protocol. An implementation that 163.200 - satisfies all the MUST and all the SHOULD requirements for its 163.201 - protocols is said to be "unconditionally compliant"; one that 163.202 - satisfies all the MUST requirements but not all the SHOULD 163.203 - requirements for NNTP is said to be "conditionally compliant". 163.204 - 163.205 - For the remainder of this document, the terms "client" and "client 163.206 - host" refer to a host making use of the NNTP service, while the terms 163.207 - "server" and "server host" refer to a host that offers the NNTP 163.208 - service. 163.209 - 163.210 -1.1. Author's Note 163.211 - 163.212 - This document is written in XML using an NNTP-specific DTD. Custom 163.213 - software is used to convert this to RFC 2629 [RFC2629] format, and 163.214 - then the public "xml2rfc" package to further reduce this to text, 163.215 - nroff source, and HTML. 163.216 - 163.217 - No perl was used in producing this document. 163.218 - 163.219 - 163.220 - 163.221 - 163.222 - 163.223 - 163.224 -Feather Standards Track [Page 4] 163.225 - 163.226 -RFC 3977 Network News Transfer Protocol (NNTP) October 2006 163.227 - 163.228 - 163.229 -2. Notation 163.230 - 163.231 - The following notational conventions are used in this document. 163.232 - 163.233 - UPPERCASE indicates literal text to be included in the 163.234 - command. 163.235 - 163.236 - lowercase indicates a token described elsewhere. 163.237 - 163.238 - [brackets] indicate that the enclosed material is optional. 163.239 - 163.240 - elliptical indicates that the argument may be repeated any 163.241 - ... marks number of times (it must occur at least once). 163.242 - 163.243 - vertical|bar indicates a choice of two mutually exclusive 163.244 - arguments (exactly one must be provided). 163.245 - 163.246 - The name "message-id" for a command or response argument indicates 163.247 - that it is the message-id of an article as described in Section 3.6, 163.248 - including the angle brackets. 163.249 - 163.250 - The name "wildmat" for an argument indicates that it is a wildmat as 163.251 - defined in Section 4. If the argument does not meet the requirements 163.252 - of that section (for example, if it does not fit the grammar of 163.253 - Section 4.1), the NNTP server MAY place some interpretation on it 163.254 - (not specified by this document) or otherwise MUST treat it as a 163.255 - syntax error. 163.256 - 163.257 - Responses for each command will be described in tables listing the 163.258 - required format of a response followed by the meaning that should be 163.259 - ascribed to that response. 163.260 - 163.261 - The terms "NUL", "TAB", "LF", "CR, and "space" refer to the octets 163.262 - %x00, %x09, %x0A, %x0D, and %x20, respectively (that is, the octets 163.263 - with those codes in US-ASCII [ANSI1986] and thus in UTF-8 [RFC3629]). 163.264 - The term "CRLF" or "CRLF pair" means the sequence CR immediately 163.265 - followed by LF (that is, %x0D.0A). A "printable US-ASCII character" 163.266 - is an octet in the range %x21-7E. Quoted characters refer to the 163.267 - octets with those codes in US-ASCII (so "." and "<" refer to %x2E and 163.268 - %x3C) and will always be printable US-ASCII characters; similarly, 163.269 - "digit" refers to the octets %x30-39. 163.270 - 163.271 - A "keyword" MUST consist only of US-ASCII letters, digits, and the 163.272 - characters dot (".") and dash ("-") and MUST begin with a letter. 163.273 - Keywords MUST be at least three characters in length. 163.274 - 163.275 - 163.276 - 163.277 - 163.278 - 163.279 - 163.280 -Feather Standards Track [Page 5] 163.281 - 163.282 -RFC 3977 Network News Transfer Protocol (NNTP) October 2006 163.283 - 163.284 - 163.285 - Examples in this document are not normative but serve to illustrate 163.286 - usages, arguments, and responses. In the examples, a "[C]" will be 163.287 - used to represent the client host and an "[S]" will be used to 163.288 - represent the server host. Most of the examples do not rely on a 163.289 - particular server state. In some cases, however, they do assume that 163.290 - the currently selected newsgroup (see the GROUP command, 163.291 - Section 6.1.1) is invalid; when so, this is indicated at the start of 163.292 - the example. Examples may use commands or other keywords not defined 163.293 - in this specification (such as an XENCRYPT command). These will be 163.294 - used to illustrate some point and do not imply that any such command 163.295 - is defined elsewhere or needs to exist in any particular 163.296 - implementation. 163.297 - 163.298 - Terms that might be read as specifying details of a client or server 163.299 - implementation, such as "database", are used simply to ease 163.300 - description. Provided that implementations conform to the protocol 163.301 - and format specifications in this document, no specific technique is 163.302 - mandated. 163.303 - 163.304 -3. Basic Concepts 163.305 - 163.306 -3.1. Commands and Responses 163.307 - 163.308 - NNTP operates over any reliable bi-directional 8-bit-wide data stream 163.309 - channel. When the connection is established, the NNTP server host 163.310 - MUST send a greeting. The client host and server host then exchange 163.311 - commands and responses (respectively) until the connection is closed 163.312 - or aborted. If the connection used is TCP, then the server host 163.313 - starts the NNTP service by listening on a TCP port. When a client 163.314 - host wishes to make use of the service, it MUST establish a TCP 163.315 - connection with the server host by connecting to that host on the 163.316 - same port on which the server is listening. 163.317 - 163.318 - The character set for all NNTP commands is UTF-8 [RFC3629]. Commands 163.319 - in NNTP MUST consist of a keyword, which MAY be followed by one or 163.320 - more arguments. A CRLF pair MUST terminate all commands. Multiple 163.321 - commands MUST NOT be on the same line. Unless otherwise noted 163.322 - elsewhere in this document, arguments SHOULD consist of printable US- 163.323 - ASCII characters. Keywords and arguments MUST each be separated by 163.324 - one or more space or TAB characters. Command lines MUST NOT exceed 163.325 - 512 octets, which includes the terminating CRLF pair. The arguments 163.326 - MUST NOT exceed 497 octets. A server MAY relax these limits for 163.327 - commands defined in an extension. 163.328 - 163.329 - Where this specification permits UTF-8 characters outside the range 163.330 - of U+0000 to U+007F, implementations MUST NOT use the Byte Order Mark 163.331 - (U+FEFF, encoding %xEF.BB.BF) and MUST use the Word Joiner (U+2060, 163.332 - encoding %xE2.91.A0) for the meaning Zero Width No-Break Space in 163.333 - 163.334 - 163.335 - 163.336 -Feather Standards Track [Page 6] 163.337 - 163.338 -RFC 3977 Network News Transfer Protocol (NNTP) October 2006 163.339 - 163.340 - 163.341 - command lines and the initial lines of responses. Implementations 163.342 - SHOULD apply these same principles throughout. 163.343 - 163.344 - The term "character" means a single Unicode code point. 163.345 - Implementations are not required to carry out Unicode normalisation. 163.346 - Thus, U+0084 (A-dieresis) is one character, while U+0041 U+0308 (A 163.347 - composed with dieresis) is two; the two need not be treated as 163.348 - equivalent. 163.349 - 163.350 - Commands may have variants; if so, they use a second keyword 163.351 - immediately after the first to indicate which variant is required. 163.352 - The only such commands in this specification are LIST and MODE. Note 163.353 - that such variants are sometimes referred to as if they were commands 163.354 - in their own right: "the LIST ACTIVE" command should be read as 163.355 - shorthand for "the ACTIVE variant of the LIST command". 163.356 - 163.357 - Keywords are case insensitive; the case of keywords for commands MUST 163.358 - be ignored by the server. Command and response arguments are case or 163.359 - language specific only when stated, either in this document or in 163.360 - other relevant specifications. 163.361 - 163.362 - In some cases, a command involves more data than just a single line. 163.363 - The further data may be sent either immediately after the command 163.364 - line (there are no instances of this in this specification, but there 163.365 - are in extensions such as [NNTP-STREAM]) or following a request from 163.366 - the server (indicated by a 3xx response). 163.367 - 163.368 - Each response MUST start with a three-digit response code that is 163.369 - sufficient to distinguish all responses. Certain valid responses are 163.370 - defined to be multi-line; for all others, the response is contained 163.371 - in a single line. The initial line of the response MUST NOT exceed 163.372 - 512 octets, which includes the response code and the terminating CRLF 163.373 - pair; an extension MAY specify a greater maximum for commands that it 163.374 - defines, but not for any other command. Single-line responses 163.375 - consist of an initial line only. Multi-line responses consist of an 163.376 - initial line followed by a multi-line data block. 163.377 - 163.378 - An NNTP server MAY have an inactivity autologout timer. Such a timer 163.379 - SHOULD be of at least three minutes' duration, with the exception 163.380 - that there MAY be a shorter limit on how long the server is willing 163.381 - to wait for the first command from the client. The receipt of any 163.382 - command from the client during the timer interval SHOULD suffice to 163.383 - reset the autologout timer. Similarly, the receipt of any 163.384 - significant amount of data from a client that is sending a multi-line 163.385 - data block (such as during a POST or IHAVE command) SHOULD suffice to 163.386 - reset the autologout timer. When the timer expires, the server 163.387 - SHOULD close the connection without sending any response to the 163.388 - client. 163.389 - 163.390 - 163.391 - 163.392 -Feather Standards Track [Page 7] 163.393 - 163.394 -RFC 3977 Network News Transfer Protocol (NNTP) October 2006 163.395 - 163.396 - 163.397 -3.1.1. Multi-line Data Blocks 163.398 - 163.399 - A multi-line data block is used in certain commands and responses. 163.400 - It MUST adhere to the following rules: 163.401 - 163.402 - 1. The block consists of a sequence of zero or more "lines", each 163.403 - being a stream of octets ending with a CRLF pair. Apart from 163.404 - those line endings, the stream MUST NOT include the octets NUL, 163.405 - LF, or CR. 163.406 - 163.407 - 2. In a multi-line response, the block immediately follows the CRLF 163.408 - at the end of the initial line of the response. When used in any 163.409 - other context, the specific command will define when the block is 163.410 - sent. 163.411 - 163.412 - 3. If any line of the data block begins with the "termination octet" 163.413 - ("." or %x2E), that line MUST be "dot-stuffed" by prepending an 163.414 - additional termination octet to that line of the block. 163.415 - 163.416 - 4. The lines of the block MUST be followed by a terminating line 163.417 - consisting of a single termination octet followed by a CRLF pair 163.418 - in the normal way. Thus, unless it is empty, a multi-line block 163.419 - is always terminated with the five octets CRLF "." CRLF 163.420 - (%x0D.0A.2E.0D.0A). 163.421 - 163.422 - 5. When a multi-line block is interpreted, the "dot-stuffing" MUST 163.423 - be undone; i.e., the recipient MUST ensure that, in any line 163.424 - beginning with the termination octet followed by octets other 163.425 - than a CRLF pair, that initial termination octet is disregarded. 163.426 - 163.427 - 6. Likewise, the terminating line ("." CRLF or %x2E.0D.0A) MUST NOT 163.428 - be considered part of the multi-line block; i.e., the recipient 163.429 - MUST ensure that any line beginning with the termination octet 163.430 - followed immediately by a CRLF pair is disregarded. (The first 163.431 - CRLF pair of the terminating CRLF "." CRLF of a non-empty block 163.432 - is, of course, part of the last line of the block.) 163.433 - 163.434 - Note that texts using an encoding (such as UTF-16 or UTF-32) that may 163.435 - contain the octets NUL, LF, or CR other than a CRLF pair cannot be 163.436 - reliably conveyed in the above format (that is, they violate the MUST 163.437 - requirement above). However, except when stated otherwise, this 163.438 - specification does not require the content to be UTF-8, and therefore 163.439 - (subject to that same requirement) it MAY include octets above and 163.440 - below 128 mixed arbitrarily. 163.441 - 163.442 - This document does not place any limit on the length of a line in a 163.443 - multi-line block. However, the standards that define the format of 163.444 - articles may do so. 163.445 - 163.446 - 163.447 - 163.448 -Feather Standards Track [Page 8] 163.449 - 163.450 -RFC 3977 Network News Transfer Protocol (NNTP) October 2006 163.451 - 163.452 - 163.453 -3.2. Response Codes 163.454 - 163.455 - Each response MUST begin with a three-digit status indicator. These 163.456 - are status reports from the server and indicate the response to the 163.457 - last command received from the client. 163.458 - 163.459 - The first digit of the response broadly indicates the success, 163.460 - failure, or progress of the previous command: 163.461 - 163.462 - 1xx - Informative message 163.463 - 2xx - Command completed OK 163.464 - 3xx - Command OK so far; send the rest of it 163.465 - 4xx - Command was syntactically correct but failed for some reason 163.466 - 5xx - Command unknown, unsupported, unavailable, or syntax error 163.467 - 163.468 - The next digit in the code indicates the function response category: 163.469 - 163.470 - x0x - Connection, setup, and miscellaneous messages 163.471 - x1x - Newsgroup selection 163.472 - x2x - Article selection 163.473 - x3x - Distribution functions 163.474 - x4x - Posting 163.475 - x8x - Reserved for authentication and privacy extensions 163.476 - x9x - Reserved for private use (non-standard extensions) 163.477 - 163.478 - Certain responses contain arguments such as numbers and names in 163.479 - addition to the status indicator. In those cases, to simplify 163.480 - interpretation by the client, the number and type of such arguments 163.481 - is fixed for each response code, as is whether the code is 163.482 - single-line or multi-line. Any extension MUST follow this principle 163.483 - as well. Note that, for historical reasons, the 211 response code is 163.484 - an exception to this in that the response may be single-line or 163.485 - multi-line depending on the command (GROUP or LISTGROUP) that 163.486 - generated it. In all other cases, the client MUST only use the 163.487 - status indicator itself to determine the nature of the response. The 163.488 - exact response codes that can be returned by any given command are 163.489 - detailed in the description of that command. 163.490 - 163.491 - Arguments MUST be separated from the numeric status indicator and 163.492 - from each other by a single space. All numeric arguments MUST be in 163.493 - base 10 (decimal) format and MAY have leading zeros. String 163.494 - arguments MUST contain at least one character and MUST NOT contain 163.495 - TAB, LF, CR, or space. The server MAY add any text after the 163.496 - response code or last argument, as appropriate, and the client MUST 163.497 - NOT make decisions based on this text. Such text MUST be separated 163.498 - from the numeric status indicator or the last argument by at least 163.499 - one space. 163.500 - 163.501 - 163.502 - 163.503 - 163.504 -Feather Standards Track [Page 9] 163.505 - 163.506 -RFC 3977 Network News Transfer Protocol (NNTP) October 2006 163.507 - 163.508 - 163.509 - The server MUST respond to any command with the appropriate generic 163.510 - response (given in Section 3.2.1) if it represents the situation. 163.511 - Otherwise, each recognized command MUST return one of the response 163.512 - codes specifically listed in its description or in an extension. A 163.513 - server MAY provide extensions to this specification, including new 163.514 - commands, new variants or features of existing commands, and other 163.515 - ways of changing the internal state of the server. However, the 163.516 - server MUST NOT produce any other responses to a client that does not 163.517 - invoke any of the additional features. (Therefore, a client that 163.518 - restricts itself to this specification will only receive the 163.519 - responses that are listed.) 163.520 - 163.521 - If a client receives an unexpected response, it SHOULD use the first 163.522 - digit of the response to determine the result. For example, an 163.523 - unexpected 2xx should be taken as success, and an unexpected 4xx or 163.524 - 5xx as failure. 163.525 - 163.526 - Response codes not specified in this document MAY be used for any 163.527 - installation-specific additional commands also not specified. These 163.528 - SHOULD be chosen to fit the pattern of x9x specified above. 163.529 - 163.530 - Neither this document nor any registered extension (see 163.531 - Section 3.3.3) will specify any response codes of the x9x pattern. 163.532 - (Implementers of extensions are accordingly cautioned not to use such 163.533 - responses for extensions that may subsequently be submitted for 163.534 - registration.) 163.535 - 163.536 -3.2.1. Generic Response Codes 163.537 - 163.538 - The server MUST respond to any command with the appropriate one of 163.539 - the following generic responses if it represents the situation. 163.540 - 163.541 - If the command is not recognized, or if it is an optional command 163.542 - that is not implemented by the server, the response code 500 MUST be 163.543 - returned. 163.544 - 163.545 - If there is a syntax error in the arguments of a recognized command, 163.546 - including the case where more arguments are provided than the command 163.547 - specifies or the command line is longer than the server accepts, the 163.548 - response code 501 MUST be returned. The line MUST NOT be truncated 163.549 - or split and then interpreted. Note that where a command has 163.550 - variants depending on a second keyword (e.g., LIST ACTIVE and LIST 163.551 - NEWSGROUPS), 501 MUST be used when the base command is implemented 163.552 - but the requested variant is not, and 500 MUST be used only when the 163.553 - base command itself is not implemented. 163.554 - 163.555 - If an argument is required to be a base64-encoded string [RFC4648] 163.556 - (there are no such arguments in this specification, but there may be 163.557 - 163.558 - 163.559 - 163.560 -Feather Standards Track [Page 10] 163.561 - 163.562 -RFC 3977 Network News Transfer Protocol (NNTP) October 2006 163.563 - 163.564 - 163.565 - in extensions) and is not validly encoded, the response code 504 MUST 163.566 - be returned. 163.567 - 163.568 - If the server experiences an internal fault or problem that means it 163.569 - is unable to carry out the command (for example, a necessary file is 163.570 - missing or a necessary service could not be contacted), the response 163.571 - code 403 MUST be returned. If the server recognizes the command but 163.572 - does not provide an optional feature (for example, because it does 163.573 - not store the required information), or if it only handles a subset 163.574 - of legitimate cases (see the HDR command, Section 8.5, for an 163.575 - example), the response code 503 MUST be returned. 163.576 - 163.577 - If the client is not authorized to use the specified facility when 163.578 - the server is in its current state, then the appropriate one of the 163.579 - following response codes MUST be used. 163.580 - 163.581 - 502: It is necessary to terminate the connection and to start a new 163.582 - one with the appropriate authority before the command can be used. 163.583 - Historically, some mode-switching servers (see Section 3.4.1) used 163.584 - this response to indicate that this command will become available 163.585 - after the MODE READER command (Section 5.3) is used, but this 163.586 - usage does not conform to this specification and MUST NOT be used. 163.587 - Note that the server MUST NOT close the connection immediately 163.588 - after a 502 response except at the initial connection 163.589 - (Section 5.1) and with the MODE READER command. 163.590 - 163.591 - 480: The client must authenticate itself to the server (that is, it 163.592 - must provide information as to the identity of the client) before 163.593 - the facility can be used on this connection. This will involve 163.594 - the use of an authentication extension such as [NNTP-AUTH]. 163.595 - 163.596 - 483: The client must negotiate appropriate privacy protection on the 163.597 - connection. This will involve the use of a privacy extension such 163.598 - as [NNTP-TLS]. 163.599 - 163.600 - 401: The client must change the state of the connection in some other 163.601 - manner. The first argument of the response MUST be the capability 163.602 - label (see Section 5.2) of the facility that provides the 163.603 - necessary mechanism (usually an extension, which may be a private 163.604 - extension). The server MUST NOT use this response code except as 163.605 - specified by the definition of the capability in question. 163.606 - 163.607 - If the server has to terminate the connection for some reason, it 163.608 - MUST give a 400 response code to the next command and then 163.609 - immediately close the connection. Following a 400 response, clients 163.610 - SHOULD NOT simply reconnect immediately and retry the same actions. 163.611 - Rather, a client SHOULD either use an exponentially increasing delay 163.612 - between retries (e.g., double the waiting time after each 400 163.613 - 163.614 - 163.615 - 163.616 -Feather Standards Track [Page 11] 163.617 - 163.618 -RFC 3977 Network News Transfer Protocol (NNTP) October 2006 163.619 - 163.620 - 163.621 - response) or present any associated text to the user for them to 163.622 - decide whether and when to retry. 163.623 - 163.624 - The client MUST be prepared to receive any of these responses for any 163.625 - command (except, of course, that the server MUST NOT generate a 500 163.626 - response code for mandatory commands). 163.627 - 163.628 -3.2.1.1. Examples 163.629 - 163.630 - Example of an unknown command: 163.631 - 163.632 - [C] MAIL 163.633 - [S] 500 Unknown command 163.634 - 163.635 - Example of an unsupported command: 163.636 - 163.637 - [C] CAPABILITIES 163.638 - [S] 101 Capability list: 163.639 - [S] VERSION 2 163.640 - [S] READER 163.641 - [S] NEWNEWS 163.642 - [S] LIST ACTIVE NEWSGROUPS 163.643 - [S] . 163.644 - [C] OVER 163.645 - [S] 500 Unknown command 163.646 - 163.647 - Example of an unsupported variant: 163.648 - 163.649 - [C] MODE POSTER 163.650 - [S] 501 Unknown MODE option 163.651 - 163.652 - Example of a syntax error: 163.653 - 163.654 - [C] ARTICLE a.message.id@no.angle.brackets 163.655 - [S] 501 Syntax error 163.656 - 163.657 - Example of an overlong command line: 163.658 - 163.659 - [C] HEAD 53 54 55 163.660 - [S] 501 Too many arguments 163.661 - 163.662 - Example of a bad wildmat: 163.663 - 163.664 - [C] LIST ACTIVE u[ks].* 163.665 - [S] 501 Syntax error 163.666 - 163.667 - 163.668 - 163.669 - 163.670 - 163.671 - 163.672 -Feather Standards Track [Page 12] 163.673 - 163.674 -RFC 3977 Network News Transfer Protocol (NNTP) October 2006 163.675 - 163.676 - 163.677 - Example of a base64-encoding error (the second argument is meant to 163.678 - be base64 encoded): 163.679 - 163.680 - [C] XENCRYPT RSA abcd=efg 163.681 - [S] 504 Base64 encoding error 163.682 - 163.683 - Example of an attempt to access a facility not available to this 163.684 - connection: 163.685 - 163.686 - [C] MODE READER 163.687 - [S] 200 Reader mode, posting permitted 163.688 - [C] IHAVE <i.am.an.article.you.will.want@example.com> 163.689 - [S] 500 Permission denied 163.690 - 163.691 - Example of an attempt to access a facility requiring authentication: 163.692 - 163.693 - [C] GROUP secret.group 163.694 - [S] 480 Permission denied 163.695 - 163.696 - Example of a successful attempt following such authentication: 163.697 - 163.698 - [C] XSECRET fred flintstone 163.699 - [S] 290 Password for fred accepted 163.700 - [C] GROUP secret.group 163.701 - [S] 211 5 1 20 secret.group selected 163.702 - 163.703 - Example of an attempt to access a facility requiring privacy: 163.704 - 163.705 - [C] GROUP secret.group 163.706 - [S] 483 Secure connection required 163.707 - [C] XENCRYPT 163.708 - [Client and server negotiate encryption on the link] 163.709 - [S] 283 Encrypted link established 163.710 - [C] GROUP secret.group 163.711 - [S] 211 5 1 20 secret.group selected 163.712 - 163.713 - Example of a need to change mode before a facility is used: 163.714 - 163.715 - [C] GROUP binary.group 163.716 - [S] 401 XHOST Not on this virtual host 163.717 - [C] XHOST binary.news.example.org 163.718 - [S] 290 binary.news.example.org virtual host selected 163.719 - [C] GROUP binary.group 163.720 - [S] 211 5 1 77 binary.group selected 163.721 - 163.722 - 163.723 - 163.724 - 163.725 - 163.726 - 163.727 - 163.728 -Feather Standards Track [Page 13] 163.729 - 163.730 -RFC 3977 Network News Transfer Protocol (NNTP) October 2006 163.731 - 163.732 - 163.733 - Example of a temporary failure: 163.734 - 163.735 - [C] GROUP archive.local 163.736 - [S] 403 Archive server temporarily offline 163.737 - 163.738 - Example of the server needing to close down immediately: 163.739 - 163.740 - [C] ARTICLE 123 163.741 - [S] 400 Power supply failed, running on UPS 163.742 - [Server closes connection.] 163.743 - 163.744 -3.3. Capabilities and Extensions 163.745 - 163.746 - Not all NNTP servers provide exactly the same facilities, both 163.747 - because this specification allows variation and because servers may 163.748 - provide extensions. A set of facilities that are related are called 163.749 - a "capability". This specification provides a way to determine what 163.750 - capabilities are available, includes a list of standard capabilities, 163.751 - and includes a mechanism (the extension mechanism) for defining new 163.752 - capabilities. 163.753 - 163.754 -3.3.1. Capability Descriptions 163.755 - 163.756 - A client can determine the available capabilities of the server by 163.757 - using the CAPABILITIES command (Section 5.2). This returns a 163.758 - capability list, which is a list of capability lines. Each line 163.759 - describes one available capability. 163.760 - 163.761 - Each capability line consists of one or more tokens, which MUST be 163.762 - separated by one or more space or TAB characters. A token is a 163.763 - string of 1 or more printable UTF-8 characters (that is, either 163.764 - printable US-ASCII characters or any UTF-8 sequence outside the US- 163.765 - ASCII range, but not space or TAB). Unless stated otherwise, tokens 163.766 - are case insensitive. Each capability line consists of the 163.767 - following: 163.768 - 163.769 - o The capability label, which is a keyword indicating the 163.770 - capability. A capability label may be defined by this 163.771 - specification or a successor, or by an extension. 163.772 - 163.773 - o The label is then followed by zero or more tokens, which are 163.774 - arguments of the capability. The form and meaning of these tokens 163.775 - is specific to each capability. 163.776 - 163.777 - The server MUST ensure that the capability list accurately reflects 163.778 - the capabilities (including extensions) currently available. If a 163.779 - capability is only available with the server in a certain state (for 163.780 - example, only after authentication), the list MUST only include the 163.781 - 163.782 - 163.783 - 163.784 -Feather Standards Track [Page 14] 163.785 - 163.786 -RFC 3977 Network News Transfer Protocol (NNTP) October 2006 163.787 - 163.788 - 163.789 - capability label when the server is in that state. Similarly, if 163.790 - only some of the commands in an extension will be available, or if 163.791 - the behaviour of the extension will change in some other manner, 163.792 - according to the state of the server, this MUST be indicated by 163.793 - different arguments in the capability line. 163.794 - 163.795 - Note that a capability line can only begin with a letter. Lines 163.796 - beginning with other characters are reserved for future versions of 163.797 - this specification. In order to interoperate with such versions, 163.798 - clients MUST be prepared to receive lines beginning with other 163.799 - characters and MUST ignore any they do not understand. 163.800 - 163.801 -3.3.2. Standard Capabilities 163.802 - 163.803 - The following capabilities are defined by this specification. 163.804 - 163.805 - VERSION 163.806 - This capability MUST be advertised by all servers and MUST be the 163.807 - first capability in the capability list; it indicates the 163.808 - version(s) of NNTP that the server supports. There must be at 163.809 - least one argument; each argument is a decimal number and MUST NOT 163.810 - have a leading zero. Version numbers are assigned only in RFCs 163.811 - that update or replace this specification; servers MUST NOT create 163.812 - their own version numbers. 163.813 - 163.814 - The version number of this specification is 2. 163.815 - 163.816 - READER 163.817 - This capability indicates that the server implements the various 163.818 - commands useful for reading clients. 163.819 - 163.820 - IHAVE 163.821 - This capability indicates that the server implements the IHAVE 163.822 - command. 163.823 - 163.824 - POST 163.825 - This capability indicates that the server implements the POST 163.826 - command. 163.827 - 163.828 - NEWNEWS 163.829 - This capability indicates that the server implements the NEWNEWS 163.830 - command. 163.831 - 163.832 - HDR 163.833 - This capability indicates that the server implements the header 163.834 - access commands (HDR and LIST HEADERS). 163.835 - 163.836 - 163.837 - 163.838 - 163.839 - 163.840 -Feather Standards Track [Page 15] 163.841 - 163.842 -RFC 3977 Network News Transfer Protocol (NNTP) October 2006 163.843 - 163.844 - 163.845 - OVER 163.846 - This capability indicates that the server implements the overview 163.847 - access commands (OVER and LIST OVERVIEW.FMT). If and only if the 163.848 - server supports the message-id form of the OVER command, there 163.849 - must be a single argument MSGID. 163.850 - 163.851 - LIST 163.852 - This capability indicates that the server implements at least one 163.853 - variant of the LIST command. There MUST be one argument for each 163.854 - variant of the LIST command supported by the server, giving the 163.855 - keyword for that variant. 163.856 - 163.857 - IMPLEMENTATION 163.858 - This capability MAY be provided by a server. If so, the arguments 163.859 - SHOULD be used to provide information such as the server software 163.860 - name and version number. The client MUST NOT use this line to 163.861 - determine capabilities of the server. (While servers often 163.862 - provide this information in the initial greeting, clients need to 163.863 - guess whether this is the case; this capability makes it clear 163.864 - what the information is.) 163.865 - 163.866 - MODE-READER 163.867 - This capability indicates that the server is mode-switching 163.868 - (Section 3.4.2) and that the MODE READER command needs to be used 163.869 - to enable the READER capability. 163.870 - 163.871 -3.3.3. Extensions 163.872 - 163.873 - Although NNTP is widely and robustly deployed, some parts of the 163.874 - Internet community might wish to extend the NNTP service. It must be 163.875 - emphasized that any extension to NNTP should not be considered 163.876 - lightly. NNTP's strength comes primarily from its simplicity. 163.877 - Experience with many protocols has shown that: 163.878 - 163.879 - Protocols with few options tend towards ubiquity, whilst protocols 163.880 - with many options tend towards obscurity. 163.881 - 163.882 - This means that each and every extension, regardless of its benefits, 163.883 - must be carefully scrutinized with respect to its implementation, 163.884 - deployment, and interoperability costs. In many cases, the cost of 163.885 - extending the NNTP service will likely outweigh the benefit. 163.886 - 163.887 - An extension is a package of associated facilities, often but not 163.888 - always including one or more new commands. Each extension MUST 163.889 - define at least one new capability label (this will often, but need 163.890 - not, be the name of one of these new commands). While any additional 163.891 - capability information can normally be specified using arguments to 163.892 - 163.893 - 163.894 - 163.895 - 163.896 -Feather Standards Track [Page 16] 163.897 - 163.898 -RFC 3977 Network News Transfer Protocol (NNTP) October 2006 163.899 - 163.900 - 163.901 - that label, an extension MAY define more than one capability label. 163.902 - However, this SHOULD be limited to exceptional circumstances. 163.903 - 163.904 - An extension is either a private extension, or its capabilities are 163.905 - included in the IANA registry of capabilities (see Section 3.3.4) and 163.906 - it is defined in an RFC (in which case it is a "registered 163.907 - extension"). Such RFCs either must be on the standards track or must 163.908 - define an IESG-approved experimental protocol. 163.909 - 163.910 - The definition of an extension must include the following: 163.911 - 163.912 - o a descriptive name for the extension. 163.913 - 163.914 - o the capability label or labels defined by the extension (the 163.915 - capability label of a registered extension MUST NOT begin with 163.916 - "X"). 163.917 - 163.918 - o The syntax, values, and meanings of any arguments for each 163.919 - capability label defined by the extension. 163.920 - 163.921 - o Any new NNTP commands associated with the extension (the names of 163.922 - commands associated with registered extensions MUST NOT begin with 163.923 - "X"). 163.924 - 163.925 - o The syntax and possible values of arguments associated with the 163.926 - new NNTP commands. 163.927 - 163.928 - o The response codes and possible values of arguments for the 163.929 - responses of the new NNTP commands. 163.930 - 163.931 - o Any new arguments the extension associates with any other 163.932 - pre-existing NNTP commands. 163.933 - 163.934 - o Any increase in the maximum length of commands and initial 163.935 - response lines over the value specified in this document. 163.936 - 163.937 - o A specific statement about the effect on pipelining that this 163.938 - extension may have (if any). 163.939 - 163.940 - o A specific statement about the circumstances when use of this 163.941 - extension can alter the contents of the capabilities list (other 163.942 - than the new capability labels it defines). 163.943 - 163.944 - o A specific statement about the circumstances under which the 163.945 - extension can cause any pre-existing command to produce a 401, 163.946 - 480, or 483 response. 163.947 - 163.948 - 163.949 - 163.950 - 163.951 - 163.952 -Feather Standards Track [Page 17] 163.953 - 163.954 -RFC 3977 Network News Transfer Protocol (NNTP) October 2006 163.955 - 163.956 - 163.957 - o A description of how the use of MODE READER on a mode-switching 163.958 - server interacts with the extension. 163.959 - 163.960 - o A description of how support for the extension affects the 163.961 - behaviour of a server and NNTP client in any other manner not 163.962 - outlined above. 163.963 - 163.964 - o Formal syntax as described in Section 9.9. 163.965 - 163.966 - A private extension MAY or MAY NOT be included in the capabilities 163.967 - list. If it is, the capability label MUST begin with "X". A server 163.968 - MAY provide additional keywords (for new commands and also for new 163.969 - variants of existing commands) as part of a private extension. To 163.970 - avoid the risk of a clash with a future registered extension, these 163.971 - keywords SHOULD begin with "X". 163.972 - 163.973 - If the server advertises a capability defined by a registered 163.974 - extension, it MUST implement the extension so as to fully conform 163.975 - with the specification (for example, it MUST implement all the 163.976 - commands that the extension describes as mandatory). If it does not 163.977 - implement the extension as specified, it MUST NOT list the extension 163.978 - in the capabilities list under its registered name. In that case, it 163.979 - MAY, but SHOULD NOT, provide a private extension (not listed, or 163.980 - listed with a different name) that implements part of the extension 163.981 - or implements the commands of the extension with a different meaning. 163.982 - 163.983 - A server MUST NOT send different response codes to basic NNTP 163.984 - commands documented here or to commands documented in registered 163.985 - extensions in response to the availability or use of a private 163.986 - extension. 163.987 - 163.988 -3.3.4. Initial IANA Register 163.989 - 163.990 - IANA will maintain a registry of NNTP capability labels. All 163.991 - capability labels in the registry MUST be keywords and MUST NOT begin 163.992 - with X. 163.993 - 163.994 - 163.995 - 163.996 - 163.997 - 163.998 - 163.999 - 163.1000 - 163.1001 - 163.1002 - 163.1003 - 163.1004 - 163.1005 - 163.1006 - 163.1007 - 163.1008 -Feather Standards Track [Page 18] 163.1009 - 163.1010 -RFC 3977 Network News Transfer Protocol (NNTP) October 2006 163.1011 - 163.1012 - 163.1013 - The initial content of the registry consists of these entries: 163.1014 - 163.1015 - +-------------------+--------------------------+--------------------+ 163.1016 - | Label | Meaning | Definition | 163.1017 - +-------------------+--------------------------+--------------------+ 163.1018 - | AUTHINFO | Authentication | [NNTP-AUTH] | 163.1019 - | | | | 163.1020 - | HDR | Batched header retrieval | Section 3.3.2, | 163.1021 - | | | Section 8.5, and | 163.1022 - | | | Section 8.6 | 163.1023 - | | | | 163.1024 - | IHAVE | IHAVE command available | Section 3.3.2 and | 163.1025 - | | | Section 6.3.2 | 163.1026 - | | | | 163.1027 - | IMPLEMENTATION | Server | Section 3.3.2 | 163.1028 - | | implementation-specific | | 163.1029 - | | information | | 163.1030 - | | | | 163.1031 - | LIST | LIST command variants | Section 3.3.2 and | 163.1032 - | | | Section 7.6.1 | 163.1033 - | | | | 163.1034 - | MODE-READER | Mode-switching server | Section 3.4.2 | 163.1035 - | | and MODE READER command | | 163.1036 - | | available | | 163.1037 - | | | | 163.1038 - | NEWNEWS | NEWNEWS command | Section 3.3.2 and | 163.1039 - | | available | Section 7.4 | 163.1040 - | | | | 163.1041 - | OVER | Overview support | Section 3.3.2, | 163.1042 - | | | Section 8.3, and | 163.1043 - | | | Section 8.4 | 163.1044 - | | | | 163.1045 - | POST | POST command available | Section 3.3.2 and | 163.1046 - | | | Section 6.3.1 | 163.1047 - | | | | 163.1048 - | READER | Reader commands | Section 3.3.2 | 163.1049 - | | available | | 163.1050 - | | | | 163.1051 - | SASL | Supported SASL | [NNTP-AUTH] | 163.1052 - | | mechanisms | | 163.1053 - | | | | 163.1054 - | STARTTLS | Transport layer security | [NNTP-TLS] | 163.1055 - | | | | 163.1056 - | STREAMING | Streaming feeds | [NNTP-STREAM] | 163.1057 - | | | | 163.1058 - | VERSION | Supported NNTP versions | Section 3.3.2 | 163.1059 - +-------------------+--------------------------+--------------------+ 163.1060 - 163.1061 - 163.1062 - 163.1063 - 163.1064 -Feather Standards Track [Page 19] 163.1065 - 163.1066 -RFC 3977 Network News Transfer Protocol (NNTP) October 2006 163.1067 - 163.1068 - 163.1069 -3.4. Mandatory and Optional Commands 163.1070 - 163.1071 - For a number of reasons, not all the commands in this specification 163.1072 - are mandatory. However, it is equally undesirable for every command 163.1073 - to be optional, since this means that a client will have no idea what 163.1074 - facilities are available. Therefore, as a compromise, some of the 163.1075 - commands in this specification are mandatory (they must be supported 163.1076 - by all servers) while the remainder are not. The latter are then 163.1077 - subdivided into bundles, each indicated by a single capability label. 163.1078 - 163.1079 - o If the label is included in the capability list returned by the 163.1080 - server, the server MUST support all commands in that bundle. 163.1081 - 163.1082 - o If the label is not included, the server MAY support none or some 163.1083 - of the commands but SHOULD NOT support all of them. In general, 163.1084 - there will be no way for a client to determine which commands are 163.1085 - supported without trying them. 163.1086 - 163.1087 - The bundles have been chosen to provide useful functionality, and 163.1088 - therefore server authors are discouraged from implementing only part 163.1089 - of a bundle. 163.1090 - 163.1091 - The description of each command will either indicate that it is 163.1092 - mandatory, or will give, using the term "indicating capability", the 163.1093 - capability label indicating whether the bundle including this command 163.1094 - is available. 163.1095 - 163.1096 - Where a server does not implement a command, it MUST always generate 163.1097 - a 500 generic response code (or a 501 generic response code in the 163.1098 - case of a variant of a command depending on a second keyword where 163.1099 - the base command is recognised). Otherwise, the command MUST be 163.1100 - fully implemented as specified; a server MUST NOT only partially 163.1101 - implement any of the commands in this specification. (Client authors 163.1102 - should note that some servers not conforming to this specification 163.1103 - will return a 502 generic response code to some commands that are not 163.1104 - implemented.) 163.1105 - 163.1106 - Note: some commands have cases that require other commands to be used 163.1107 - first. If the former command is implemented but the latter is not, 163.1108 - the former MUST still generate the relevant specific response code. 163.1109 - For example, if ARTICLE (Section 6.2.1) is implemented but GROUP 163.1110 - (Section 6.1.1) is not, the correct response to "ARTICLE 1234" 163.1111 - remains 412. 163.1112 - 163.1113 - 163.1114 - 163.1115 - 163.1116 - 163.1117 - 163.1118 - 163.1119 - 163.1120 -Feather Standards Track [Page 20] 163.1121 - 163.1122 -RFC 3977 Network News Transfer Protocol (NNTP) October 2006 163.1123 - 163.1124 - 163.1125 -3.4.1. Reading and Transit Servers 163.1126 - 163.1127 - NNTP is traditionally used in two different ways. The first use is 163.1128 - "reading", where the client fetches articles from a large store 163.1129 - maintained by the server for immediate or later presentation to a 163.1130 - user and sends articles created by that user back to the server (an 163.1131 - action called "posting") to be stored and distributed to other stores 163.1132 - and users. The second use is for the bulk transfer of articles from 163.1133 - one store to another. Since the hosts making this transfer tend to 163.1134 - be peers in a network that transmit articles among one another, and 163.1135 - not end-user systems, this process is called "peering" or "transit". 163.1136 - (Even so, one host is still the client and the other is the server). 163.1137 - 163.1138 - In practice, these two uses are so different that some server 163.1139 - implementations are optimised for reading or for transit and, as a 163.1140 - result, do not offer the other facility or only offer limited 163.1141 - features. Other implementations are more general and offer both. 163.1142 - This specification allows for this by bundling the relevant commands 163.1143 - accordingly: the IHAVE command is designed for transit, while the 163.1144 - commands indicated by the READER capability are designed for reading 163.1145 - clients. 163.1146 - 163.1147 - Except as an effect of the MODE READER command (Section 5.3) on a 163.1148 - mode-switching server, once a server advertises either or both of the 163.1149 - IHAVE or READER capabilities, it MUST continue to advertise them for 163.1150 - the entire session. 163.1151 - 163.1152 - A server MAY provide different modes of behaviour (transit, reader, 163.1153 - or a combination) to different client connections and MAY use 163.1154 - external information, such as the IP address of the client, to 163.1155 - determine which mode to provide to any given connection. 163.1156 - 163.1157 - The official TCP port for the NNTP service is 119. However, if a 163.1158 - host wishes to offer separate servers for transit and reading 163.1159 - clients, port 433 SHOULD be used for the transit server and 119 for 163.1160 - the reading server. 163.1161 - 163.1162 -3.4.2. Mode Switching 163.1163 - 163.1164 - An implementation MAY, but SHOULD NOT, provide both transit and 163.1165 - reader facilities on the same server but require the client to select 163.1166 - which it wishes to use. Such an arrangement is called a 163.1167 - "mode-switching" server. 163.1168 - 163.1169 - 163.1170 - 163.1171 - 163.1172 - 163.1173 - 163.1174 - 163.1175 - 163.1176 -Feather Standards Track [Page 21] 163.1177 - 163.1178 -RFC 3977 Network News Transfer Protocol (NNTP) October 2006 163.1179 - 163.1180 - 163.1181 - A mode-switching server has two modes: 163.1182 - 163.1183 - o Transit mode, which applies after the initial connection. 163.1184 - 163.1185 - * It MUST advertise the MODE-READER capability. 163.1186 - 163.1187 - * It MUST NOT advertise the READER capability. 163.1188 - 163.1189 - However, the server MAY cease to advertise the MODE-READER 163.1190 - capability after the client uses any command except CAPABILITIES. 163.1191 - 163.1192 - o Reading mode, after a successful MODE READER command (see Section 163.1193 - 5.3). 163.1194 - 163.1195 - * It MUST NOT advertise the MODE-READER capability. 163.1196 - 163.1197 - * It MUST advertise the READER capability. 163.1198 - 163.1199 - * It MAY NOT advertise the IHAVE capability, even if it was 163.1200 - advertising it in transit mode. 163.1201 - 163.1202 - A client SHOULD only issue a MODE READER command to a server if it is 163.1203 - advertising the MODE-READER capability. If the server does not 163.1204 - support CAPABILITIES (and therefore does not conform to this 163.1205 - specification), the client MAY use the following heuristic: 163.1206 - 163.1207 - o If the client wishes to use any "reader" commands, it SHOULD use 163.1208 - the MODE READER command immediately after the initial connection. 163.1209 - 163.1210 - o Otherwise, it SHOULD NOT use the MODE READER command. 163.1211 - 163.1212 - In each case, it should be prepared for some commands to be 163.1213 - unavailable that would have been available if it had made the other 163.1214 - choice. 163.1215 - 163.1216 -3.5. Pipelining 163.1217 - 163.1218 - NNTP is designed to operate over a reliable bi-directional 163.1219 - connection, such as TCP. Therefore, if a command does not depend on 163.1220 - the response to the previous one, it should not matter if it is sent 163.1221 - before that response is received. Doing this is called "pipelining". 163.1222 - However, certain server implementations throw away all text received 163.1223 - from the client following certain commands before sending their 163.1224 - response. If this happens, pipelining will be affected because one 163.1225 - or more commands will have been ignored or misinterpreted, and the 163.1226 - client will be matching the wrong responses to each command. Since 163.1227 - there are significant benefits to pipelining, but also circumstances 163.1228 - where it is reasonable or common for servers to behave in the above 163.1229 - 163.1230 - 163.1231 - 163.1232 -Feather Standards Track [Page 22] 163.1233 - 163.1234 -RFC 3977 Network News Transfer Protocol (NNTP) October 2006 163.1235 - 163.1236 - 163.1237 - manner, this document puts certain requirements on both clients and 163.1238 - servers. 163.1239 - 163.1240 - Except where stated otherwise, a client MAY use pipelining. That is, 163.1241 - it may send a command before receiving the response for the previous 163.1242 - command. The server MUST allow pipelining and MUST NOT throw away 163.1243 - any text received after a command. Irrespective of whether 163.1244 - pipelining is used, the server MUST process commands in the order 163.1245 - they are sent. 163.1246 - 163.1247 - If the specific description of a command says it "MUST NOT be 163.1248 - pipelined", that command MUST end any pipeline of commands. That is, 163.1249 - the client MUST NOT send any following command until it receives the 163.1250 - CRLF at the end of the response from the command. The server MAY 163.1251 - ignore any data received after the command and before the CRLF at the 163.1252 - end of the response is sent to the client. 163.1253 - 163.1254 - The initial connection must not be part of a pipeline; that is, the 163.1255 - client MUST NOT send any command until it receives the CRLF at the 163.1256 - end of the greeting. 163.1257 - 163.1258 - If the client uses blocking system calls to send commands, it MUST 163.1259 - ensure that the amount of text sent in pipelining does not cause a 163.1260 - deadlock between transmission and reception. The amount of text 163.1261 - involved will depend on window sizes in the transmission layer; 163.1262 - typically, it is 4k octets for TCP. (Since the server only sends 163.1263 - data in response to commands from the client, the converse problem 163.1264 - does not occur.) 163.1265 - 163.1266 -3.5.1. Examples 163.1267 - 163.1268 - Example of correct use of pipelining: 163.1269 - 163.1270 - [C] GROUP misc.test 163.1271 - [C] STAT 163.1272 - [C] NEXT 163.1273 - [S] 211 1234 3000234 3002322 misc.test 163.1274 - [S] 223 3000234 <45223423@example.com> retrieved 163.1275 - [S] 223 3000237 <668929@example.org> retrieved 163.1276 - 163.1277 - Example of incorrect use of pipelining (the MODE READER command may 163.1278 - not be pipelined): 163.1279 - 163.1280 - [C] MODE READER 163.1281 - [C] DATE 163.1282 - [C] NEXT 163.1283 - [S] 200 Server ready, posting allowed 163.1284 - [S] 223 3000237 <668929@example.org> retrieved 163.1285 - 163.1286 - 163.1287 - 163.1288 -Feather Standards Track [Page 23] 163.1289 - 163.1290 -RFC 3977 Network News Transfer Protocol (NNTP) October 2006 163.1291 - 163.1292 - 163.1293 - The DATE command has been thrown away by the server, so there is no 163.1294 - 111 response to match it. 163.1295 - 163.1296 -3.6. Articles 163.1297 - 163.1298 - NNTP is intended to transfer articles between clients and servers. 163.1299 - For the purposes of this specification, articles are required to 163.1300 - conform to the rules in this section, and clients and servers MUST 163.1301 - correctly process any article received from the other that does so. 163.1302 - Note that this requirement applies only to the contents of 163.1303 - communications over NNTP; it does not prevent the client or server 163.1304 - from subsequently rejecting an article for reasons of local policy. 163.1305 - Also see Appendix A for further restrictions on the format of 163.1306 - articles in some uses of NNTP. 163.1307 - 163.1308 - An article consists of two parts: the headers and the body. They are 163.1309 - separated by a single empty line, or in other words by two 163.1310 - consecutive CRLF pairs (if there is more than one empty line, the 163.1311 - second and subsequent ones are part of the body). In order to meet 163.1312 - the general requirements of NNTP, an article MUST NOT include the 163.1313 - octet NUL, MUST NOT contain the octets LF and CR other than as part 163.1314 - of a CRLF pair, and MUST end with a CRLF pair. This specification 163.1315 - puts no further restrictions on the body; in particular, it MAY be 163.1316 - empty. 163.1317 - 163.1318 - The headers of an article consist of one or more header lines. Each 163.1319 - header line consists of a header name, a colon, a space, the header 163.1320 - content, and a CRLF, in that order. The name consists of one or more 163.1321 - printable US-ASCII characters other than colon and, for the purposes 163.1322 - of this specification, is not case sensitive. There MAY be more than 163.1323 - one header line with the same name. The content MUST NOT contain 163.1324 - CRLF; it MAY be empty. A header may be "folded"; that is, a CRLF 163.1325 - pair may be placed before any TAB or space in the line. There MUST 163.1326 - still be some other octet between any two CRLF pairs in a header 163.1327 - line. (Note that folding means that the header line occupies more 163.1328 - than one line when displayed or transmitted; nevertheless, it is 163.1329 - still referred to as "a" header line.) The presence or absence of 163.1330 - folding does not affect the meaning of the header line; that is, the 163.1331 - CRLF pairs introduced by folding are not considered part of the 163.1332 - header content. Header lines SHOULD NOT be folded before the space 163.1333 - after the colon that follows the header name and SHOULD include at 163.1334 - least one octet other than %x09 or %x20 between CRLF pairs. However, 163.1335 - if an article that fails to satisfy this requirement has been 163.1336 - received from elsewhere, clients and servers MAY transfer it to each 163.1337 - other without re-folding it. 163.1338 - 163.1339 - 163.1340 - 163.1341 - 163.1342 - 163.1343 - 163.1344 -Feather Standards Track [Page 24] 163.1345 - 163.1346 -RFC 3977 Network News Transfer Protocol (NNTP) October 2006 163.1347 - 163.1348 - 163.1349 - The content of a header SHOULD be in UTF-8. However, if an 163.1350 - implementation receives an article from elsewhere that uses octets in 163.1351 - the range 128 to 255 in some other manner, it MAY pass it to a client 163.1352 - or server without modification. Therefore, implementations MUST be 163.1353 - prepared to receive such headers, and data derived from them (e.g., 163.1354 - in the responses from the OVER command, Section 8.3), and MUST NOT 163.1355 - assume that they are always UTF-8. Any external processing of those 163.1356 - headers, including identifying the encoding used, is outside the 163.1357 - scope of this document. 163.1358 - 163.1359 - Each article MUST have a unique message-id; two articles offered by 163.1360 - an NNTP server MUST NOT have the same message-id. For the purposes 163.1361 - of this specification, message-ids are opaque strings that MUST meet 163.1362 - the following requirements: 163.1363 - 163.1364 - o A message-id MUST begin with "<", end with ">", and MUST NOT 163.1365 - contain the latter except at the end. 163.1366 - 163.1367 - o A message-id MUST be between 3 and 250 octets in length. 163.1368 - 163.1369 - o A message-id MUST NOT contain octets other than printable US-ASCII 163.1370 - characters. 163.1371 - 163.1372 - Two message-ids are the same if and only if they consist of the same 163.1373 - sequence of octets. 163.1374 - 163.1375 - This specification does not describe how the message-id of an article 163.1376 - is determined. If the server does not have any way to determine a 163.1377 - message-id from the article itself, it MUST synthesize one (this 163.1378 - specification does not require that the article be changed as a 163.1379 - result). See also Appendix A.2. 163.1380 - 163.1381 -4. The WILDMAT Format 163.1382 - 163.1383 - The WILDMAT format described here is based on the version first 163.1384 - developed by Rich Salz [SALZ1992], which was in turn derived from the 163.1385 - format used in the UNIX "find" command to articulate file names. It 163.1386 - was developed to provide a uniform mechanism for matching patterns in 163.1387 - the same manner that the UNIX shell matches filenames. 163.1388 - 163.1389 - 163.1390 - 163.1391 - 163.1392 - 163.1393 - 163.1394 - 163.1395 - 163.1396 - 163.1397 - 163.1398 - 163.1399 - 163.1400 -Feather Standards Track [Page 25] 163.1401 - 163.1402 -RFC 3977 Network News Transfer Protocol (NNTP) October 2006 163.1403 - 163.1404 - 163.1405 -4.1. Wildmat Syntax 163.1406 - 163.1407 - A wildmat is described by the following ABNF [RFC4234] syntax, which 163.1408 - is an extract of that in Section 9.8. 163.1409 - 163.1410 - wildmat = wildmat-pattern *("," ["!"] wildmat-pattern) 163.1411 - wildmat-pattern = 1*wildmat-item 163.1412 - wildmat-item = wildmat-exact / wildmat-wild 163.1413 - wildmat-exact = %x22-29 / %x2B / %x2D-3E / %x40-5A / %x5E-7E / 163.1414 - UTF8-non-ascii ; exclude ! * , ? [ \ ] 163.1415 - wildmat-wild = "*" / "?" 163.1416 - 163.1417 - Note: the characters ",", "\", "[", and "]" are not allowed in 163.1418 - wildmats, while * and ? are always wildcards. This should not be a 163.1419 - problem, since these characters cannot occur in newsgroup names, 163.1420 - which is the only current use of wildmats. Backslash is commonly 163.1421 - used to suppress the special meaning of characters, whereas brackets 163.1422 - are used to introduce sets. However, these usages are not universal, 163.1423 - and interpretation of these characters in the context of UTF-8 163.1424 - strings is potentially complex and differs from existing practice, so 163.1425 - they were omitted from this specification. A future extension to 163.1426 - this specification may provide semantics for these characters. 163.1427 - 163.1428 -4.2. Wildmat Semantics 163.1429 - 163.1430 - A wildmat is tested against a string and either matches or does not 163.1431 - match. To do this, each constituent <wildmat-pattern> is matched 163.1432 - against the string, and the rightmost pattern that matches is 163.1433 - identified. If that <wildmat-pattern> is not preceded with "!", the 163.1434 - whole wildmat matches. If it is preceded by "!", or if no <wildmat- 163.1435 - pattern> matches, the whole wildmat does not match. 163.1436 - 163.1437 - For example, consider the wildmat "a*,!*b,*c*": 163.1438 - 163.1439 - o The string "aaa" matches because the rightmost match is with "a*". 163.1440 - 163.1441 - o The string "abb" does not match because the rightmost match is 163.1442 - with "*b". 163.1443 - 163.1444 - o The string "ccb" matches because the rightmost match is with 163.1445 - "*c*". 163.1446 - 163.1447 - o The string "xxx" does not match because no <wildmat-pattern> 163.1448 - matches. 163.1449 - 163.1450 - A <wildmat-pattern> matches a string if the string can be broken into 163.1451 - components, each of which matches the corresponding <wildmat-item> in 163.1452 - the pattern. The matches must be in the same order, and the whole 163.1453 - 163.1454 - 163.1455 - 163.1456 -Feather Standards Track [Page 26] 163.1457 - 163.1458 -RFC 3977 Network News Transfer Protocol (NNTP) October 2006 163.1459 - 163.1460 - 163.1461 - string must be used in the match. The pattern is "anchored"; that 163.1462 - is, the first and last characters in the string must match the first 163.1463 - and last item, respectively (unless that item is an asterisk matching 163.1464 - zero characters). 163.1465 - 163.1466 - A <wildmat-exact> matches the same character (which may be more than 163.1467 - one octet in UTF-8). 163.1468 - 163.1469 - "?" matches exactly one character (which may be more than one octet). 163.1470 - 163.1471 - "*" matches zero or more characters. It can match an empty string, 163.1472 - but it cannot match a subsequence of a UTF-8 sequence that is not 163.1473 - aligned to the character boundaries. 163.1474 - 163.1475 -4.3. Extensions 163.1476 - 163.1477 - An NNTP server or extension MAY extend the syntax or semantics of 163.1478 - wildmats provided that all wildmats that meet the requirements of 163.1479 - Section 4.1 have the meaning ascribed to them by Section 4.2. Future 163.1480 - editions of this document may also extend wildmats. 163.1481 - 163.1482 -4.4. Examples 163.1483 - 163.1484 - In these examples, $ and @ are used to represent the two octets %xC2 163.1485 - and %xA3, respectively; $@ is thus the UTF-8 encoding for the pound 163.1486 - sterling symbol, shown as # in the descriptions. 163.1487 - 163.1488 - Wildmat Description of strings that match 163.1489 - abc The one string "abc" 163.1490 - abc,def The two strings "abc" and "def" 163.1491 - $@ The one character string "#" 163.1492 - a* Any string that begins with "a" 163.1493 - a*b Any string that begins with "a" and ends with "b" 163.1494 - a*,*b Any string that begins with "a" or ends with "b" 163.1495 - a*,!*b Any string that begins with "a" and does not end with 163.1496 - "b" 163.1497 - a*,!*b,c* Any string that begins with "a" and does not end with 163.1498 - "b", and any string that begins with "c" no matter 163.1499 - what it ends with 163.1500 - a*,c*,!*b Any string that begins with "a" or "c" and does not 163.1501 - end with "b" 163.1502 - ?a* Any string with "a" as its second character 163.1503 - ??a* Any string with "a" as its third character 163.1504 - *a? Any string with "a" as its penultimate character 163.1505 - *a?? Any string with "a" as its antepenultimate character 163.1506 - 163.1507 - 163.1508 - 163.1509 - 163.1510 - 163.1511 - 163.1512 -Feather Standards Track [Page 27] 163.1513 - 163.1514 -RFC 3977 Network News Transfer Protocol (NNTP) October 2006 163.1515 - 163.1516 - 163.1517 -5. Session Administration Commands 163.1518 - 163.1519 -5.1. Initial Connection 163.1520 - 163.1521 -5.1.1. Usage 163.1522 - 163.1523 - This command MUST NOT be pipelined. 163.1524 - 163.1525 - Responses [1] 163.1526 - 200 Service available, posting allowed 163.1527 - 201 Service available, posting prohibited 163.1528 - 400 Service temporarily unavailable [2] 163.1529 - 502 Service permanently unavailable [2] 163.1530 - 163.1531 - [1] These are the only valid response codes for the initial greeting; 163.1532 - the server MUST not return any other generic response code. 163.1533 - 163.1534 - [2] Following a 400 or 502 response, the server MUST immediately 163.1535 - close the connection. 163.1536 - 163.1537 -5.1.2. Description 163.1538 - 163.1539 - There is no command presented by the client upon initial connection 163.1540 - to the server. The server MUST present an appropriate response code 163.1541 - as a greeting to the client. This response informs the client 163.1542 - whether service is available and whether the client is permitted to 163.1543 - post. 163.1544 - 163.1545 - If the server will accept further commands from the client including 163.1546 - POST, the server MUST present a 200 greeting code. If the server 163.1547 - will accept further commands from the client, but the client is not 163.1548 - authorized to post articles using the POST command, the server MUST 163.1549 - present a 201 greeting code. 163.1550 - 163.1551 - Otherwise, the server MUST present a 400 or 502 greeting code and 163.1552 - then immediately close the connection. 400 SHOULD be used if the 163.1553 - issue is only temporary (for example, because of load) and the client 163.1554 - can expect to be able to connect successfully at some point in the 163.1555 - future without making any changes. 502 MUST be used if the client is 163.1556 - not permitted under any circumstances to interact with the server, 163.1557 - and MAY be used if the server has insufficient information to 163.1558 - determine whether the issue is temporary or permanent. 163.1559 - 163.1560 - Note: the distinction between the 200 and 201 response codes has 163.1561 - turned out in practice to be insufficient; for example, some servers 163.1562 - do not allow posting until the client has authenticated, while other 163.1563 - clients assume that a 201 response means that posting will never be 163.1564 - possible even after authentication. Therefore, clients SHOULD use 163.1565 - 163.1566 - 163.1567 - 163.1568 -Feather Standards Track [Page 28] 163.1569 - 163.1570 -RFC 3977 Network News Transfer Protocol (NNTP) October 2006 163.1571 - 163.1572 - 163.1573 - the CAPABILITIES command (Section 5.2) rather than rely on this 163.1574 - response. 163.1575 - 163.1576 -5.1.3. Examples 163.1577 - 163.1578 - Example of a normal connection from an authorized client that then 163.1579 - terminates the session (see Section 5.4): 163.1580 - 163.1581 - [Initial connection set-up completed.] 163.1582 - [S] 200 NNTP Service Ready, posting permitted 163.1583 - [C] QUIT 163.1584 - [S] 205 NNTP Service exits normally 163.1585 - [Server closes connection.] 163.1586 - 163.1587 - Example of a normal connection from an authorized client that is not 163.1588 - permitted to post, which also immediately terminates the session: 163.1589 - 163.1590 - [Initial connection set-up completed.] 163.1591 - [S] 201 NNTP Service Ready, posting prohibited 163.1592 - [C] QUIT 163.1593 - [S] 205 NNTP Service exits normally 163.1594 - [Server closes connection.] 163.1595 - 163.1596 - Example of a normal connection from an unauthorized client: 163.1597 - 163.1598 - [Initial connection set-up completed.] 163.1599 - [S] 502 NNTP Service permanently unavailable 163.1600 - [Server closes connection.] 163.1601 - 163.1602 - Example of a connection from a client if the server is unable to 163.1603 - provide service: 163.1604 - 163.1605 - [Initial connection set-up completed.] 163.1606 - [S] 400 NNTP Service temporarily unavailable 163.1607 - [Server closes connection.] 163.1608 - 163.1609 -5.2. CAPABILITIES 163.1610 - 163.1611 -5.2.1. Usage 163.1612 - 163.1613 - This command is mandatory. 163.1614 - 163.1615 - Syntax 163.1616 - CAPABILITIES [keyword] 163.1617 - 163.1618 - Responses 163.1619 - 101 Capability list follows (multi-line) 163.1620 - 163.1621 - 163.1622 - 163.1623 - 163.1624 -Feather Standards Track [Page 29] 163.1625 - 163.1626 -RFC 3977 Network News Transfer Protocol (NNTP) October 2006 163.1627 - 163.1628 - 163.1629 - Parameters 163.1630 - keyword additional feature, see description 163.1631 - 163.1632 -5.2.2. Description 163.1633 - 163.1634 - The CAPABILITIES command allows a client to determine the 163.1635 - capabilities of the server at any given time. 163.1636 - 163.1637 - This command MAY be issued at any time; the server MUST NOT require 163.1638 - it to be issued in order to make use of any capability. The response 163.1639 - generated by this command MAY change during a session because of 163.1640 - other state information (which, in turn, may be changed by the 163.1641 - effects of other commands or by external events). An NNTP client is 163.1642 - only able to get the current and correct information concerning 163.1643 - available capabilities at any point during a session by issuing a 163.1644 - CAPABILITIES command at that point of that session and processing the 163.1645 - response. 163.1646 - 163.1647 - The capability list is returned as a multi-line data block following 163.1648 - the 101 response code. Each capability is described by a separate 163.1649 - capability line. The server MUST NOT list the same capability twice 163.1650 - in the response, even with different arguments. Except that the 163.1651 - VERSION capability MUST be the first line, the order in which the 163.1652 - capability lines appears is not significant; the server need not even 163.1653 - consistently return the same order. 163.1654 - 163.1655 - While some capabilities are likely to be always available or never 163.1656 - available, others (notably extensions) will appear and disappear 163.1657 - depending on server state changes within the session or on external 163.1658 - events between sessions. An NNTP client MAY cache the results of 163.1659 - this command, but MUST NOT rely on the correctness of any cached 163.1660 - results, whether from earlier in this session or from a previous 163.1661 - session, MUST cope gracefully with the cached status being out of 163.1662 - date, and SHOULD (if caching results) provide a way to force the 163.1663 - cached information to be refreshed. Furthermore, a client MUST NOT 163.1664 - use cached results in relation to security, privacy, and 163.1665 - authentication extensions. See Section 12.6 for further discussion 163.1666 - of this topic. 163.1667 - 163.1668 - The keyword argument is not used by this specification. It is 163.1669 - provided so that extensions or revisions to this specification can 163.1670 - include extra features for this command without requiring the 163.1671 - CAPABILITIES command to be used twice (once to determine if the extra 163.1672 - features are available, and a second time to make use of them). If 163.1673 - the server does not recognise the argument (and it is a keyword), it 163.1674 - MUST respond with the 101 response code as if the argument had been 163.1675 - omitted. If an argument is provided that the server does recognise, 163.1676 - it MAY use the 101 response code or MAY use some other response code 163.1677 - 163.1678 - 163.1679 - 163.1680 -Feather Standards Track [Page 30] 163.1681 - 163.1682 -RFC 3977 Network News Transfer Protocol (NNTP) October 2006 163.1683 - 163.1684 - 163.1685 - (which will be defined in the specification of that feature). If the 163.1686 - argument is not a keyword, the 501 generic response code MUST be 163.1687 - returned. The server MUST NOT generate any other response code to 163.1688 - the CAPABILITIES command. 163.1689 - 163.1690 -5.2.3. Examples 163.1691 - 163.1692 - Example of a minimal response (a read-only server): 163.1693 - 163.1694 - [C] CAPABILITIES 163.1695 - [S] 101 Capability list: 163.1696 - [S] VERSION 2 163.1697 - [S] READER 163.1698 - [S] LIST ACTIVE NEWSGROUPS 163.1699 - [S] . 163.1700 - 163.1701 - Example of a response from a server that has a range of facilities 163.1702 - and that also describes itself: 163.1703 - 163.1704 - [C] CAPABILITIES 163.1705 - [S] 101 Capability list: 163.1706 - [S] VERSION 2 163.1707 - [S] READER 163.1708 - [S] IHAVE 163.1709 - [S] POST 163.1710 - [S] NEWNEWS 163.1711 - [S] LIST ACTIVE NEWSGROUPS ACTIVE.TIMES OVERVIEW.FMT 163.1712 - [S] IMPLEMENTATION INN 4.2 2004-12-25 163.1713 - [S] OVER MSGID 163.1714 - [S] STREAMING 163.1715 - [S] XSECRET 163.1716 - [S] . 163.1717 - 163.1718 - Example of a server that supports more than one version of NNTP: 163.1719 - 163.1720 - [C] CAPABILITIES 163.1721 - [S] 101 Capability list: 163.1722 - [S] VERSION 2 3 163.1723 - [S] READER 163.1724 - [S] LIST ACTIVE NEWSGROUPS 163.1725 - [S] . 163.1726 - 163.1727 - 163.1728 - 163.1729 - 163.1730 - 163.1731 - 163.1732 - 163.1733 - 163.1734 - 163.1735 - 163.1736 -Feather Standards Track [Page 31] 163.1737 - 163.1738 -RFC 3977 Network News Transfer Protocol (NNTP) October 2006 163.1739 - 163.1740 - 163.1741 - Example of a client attempting to use a feature of the CAPABILITIES 163.1742 - command that the server does not support: 163.1743 - 163.1744 - [C] CAPABILITIES AUTOUPDATE 163.1745 - [S] 101 Capability list: 163.1746 - [S] VERSION 2 163.1747 - [S] READER 163.1748 - [S] IHAVE 163.1749 - [S] LIST ACTIVE NEWSGROUPS OVERVIEW.FMT HEADERS 163.1750 - [S] OVER MSGID 163.1751 - [S] HDR 163.1752 - [S] NEWNEWS 163.1753 - [S] . 163.1754 - 163.1755 -5.3. MODE READER 163.1756 - 163.1757 -5.3.1. Usage 163.1758 - 163.1759 - Indicating capability: MODE-READER 163.1760 - 163.1761 - This command MUST NOT be pipelined. 163.1762 - 163.1763 - Syntax 163.1764 - MODE READER 163.1765 - 163.1766 - Responses 163.1767 - 200 Posting allowed 163.1768 - 201 Posting prohibited 163.1769 - 502 Reading service permanently unavailable [1] 163.1770 - 163.1771 - [1] Following a 502 response the server MUST immediately close the 163.1772 - connection. 163.1773 - 163.1774 -5.3.2. Description 163.1775 - 163.1776 - The MODE READER command instructs a mode-switching server to switch 163.1777 - modes, as described in Section 3.4.2. 163.1778 - 163.1779 - If the server is mode-switching, it switches from its transit mode to 163.1780 - its reader mode, indicating this by changing the capability list 163.1781 - accordingly. It MUST then return a 200 or 201 response with the same 163.1782 - meaning as for the initial greeting (as described in Section 5.1.1). 163.1783 - Note that the response need not be the same as that presented during 163.1784 - the initial greeting. The client MUST NOT issue MODE READER more 163.1785 - than once in a session or after any security or privacy commands are 163.1786 - issued. When the MODE READER command is issued, the server MAY reset 163.1787 - its state to that immediately after the initial connection before 163.1788 - switching mode. 163.1789 - 163.1790 - 163.1791 - 163.1792 -Feather Standards Track [Page 32] 163.1793 - 163.1794 -RFC 3977 Network News Transfer Protocol (NNTP) October 2006 163.1795 - 163.1796 - 163.1797 - If the server is not mode-switching, then the following apply: 163.1798 - 163.1799 - o If it advertises the READER capability, it MUST return a 200 or 163.1800 - 201 response with the same meaning as for the initial greeting; in 163.1801 - this case, the command MUST NOT affect the server state in any 163.1802 - way. 163.1803 - 163.1804 - o If it does not advertise the READER capability, it MUST return a 163.1805 - 502 response and then immediately close the connection. 163.1806 - 163.1807 -5.3.3. Examples 163.1808 - 163.1809 - Example of use of the MODE READER command on a transit-only server 163.1810 - (which therefore does not providing reading facilities): 163.1811 - 163.1812 - [C] CAPABILITIES 163.1813 - [S] 101 Capability list: 163.1814 - [S] VERSION 2 163.1815 - [S] IHAVE 163.1816 - [S] . 163.1817 - [C] MODE READER 163.1818 - [S] 502 Transit service only 163.1819 - [Server closes connection.] 163.1820 - 163.1821 - Example of use of the MODE READER command on a server that provides 163.1822 - reading facilities: 163.1823 - 163.1824 - [C] CAPABILITIES 163.1825 - [S] 101 Capability list: 163.1826 - [S] VERSION 2 163.1827 - [S] READER 163.1828 - [S] LIST ACTIVE NEWSGROUPS 163.1829 - [S] . 163.1830 - [C] MODE READER 163.1831 - [S] 200 Reader mode, posting permitted 163.1832 - [C] IHAVE <i.am.an.article.you.have@example.com> 163.1833 - [S] 500 Permission denied 163.1834 - [C] GROUP misc.test 163.1835 - [S] 211 1234 3000234 3002322 misc.test 163.1836 - 163.1837 - Note that in both of these situations, the client SHOULD NOT use MODE 163.1838 - READER. 163.1839 - 163.1840 - 163.1841 - 163.1842 - 163.1843 - 163.1844 - 163.1845 - 163.1846 - 163.1847 - 163.1848 -Feather Standards Track [Page 33] 163.1849 - 163.1850 -RFC 3977 Network News Transfer Protocol (NNTP) October 2006 163.1851 - 163.1852 - 163.1853 - Example of use of the MODE READER command on a mode-switching server: 163.1854 - 163.1855 - [C] CAPABILITIES 163.1856 - [S] 101 Capability list: 163.1857 - [S] VERSION 2 163.1858 - [S] IHAVE 163.1859 - [S] MODE-READER 163.1860 - [S] . 163.1861 - [C] MODE READER 163.1862 - [S] 200 Reader mode, posting permitted 163.1863 - [C] CAPABILITIES 163.1864 - [S] 101 Capability list: 163.1865 - [S] VERSION 2 163.1866 - [S] READER 163.1867 - [S] NEWNEWS 163.1868 - [S] LIST ACTIVE NEWSGROUPS 163.1869 - [S] STARTTLS 163.1870 - [S] . 163.1871 - 163.1872 - In this case, the server offers (but does not require) TLS privacy in 163.1873 - its reading mode but not in its transit mode. 163.1874 - 163.1875 - Example of use of the MODE READER command where the client is not 163.1876 - permitted to post: 163.1877 - 163.1878 - [C] MODE READER 163.1879 - [S] 201 NNTP Service Ready, posting prohibited 163.1880 - 163.1881 -5.4. QUIT 163.1882 - 163.1883 -5.4.1. Usage 163.1884 - 163.1885 - This command is mandatory. 163.1886 - 163.1887 - Syntax 163.1888 - QUIT 163.1889 - 163.1890 - Responses 163.1891 - 205 Connection closing 163.1892 - 163.1893 -5.4.2. Description 163.1894 - 163.1895 - The client uses the QUIT command to terminate the session. The 163.1896 - server MUST acknowledge the QUIT command and then close the 163.1897 - connection to the client. This is the preferred method for a client 163.1898 - to indicate that it has finished all of its transactions with the 163.1899 - NNTP server. 163.1900 - 163.1901 - 163.1902 - 163.1903 - 163.1904 -Feather Standards Track [Page 34] 163.1905 - 163.1906 -RFC 3977 Network News Transfer Protocol (NNTP) October 2006 163.1907 - 163.1908 - 163.1909 - If a client simply disconnects (or if the connection times out or 163.1910 - some other fault occurs), the server MUST gracefully cease its 163.1911 - attempts to service the client, disconnecting from its end if 163.1912 - necessary. 163.1913 - 163.1914 - The server MUST NOT generate any response code to the QUIT command 163.1915 - other than 205 or, if any arguments are provided, 501. 163.1916 - 163.1917 -5.4.3. Examples 163.1918 - 163.1919 - [C] QUIT 163.1920 - [S] 205 closing connection 163.1921 - [Server closes connection.] 163.1922 - 163.1923 -6. Article Posting and Retrieval 163.1924 - 163.1925 - News-reading clients have available a variety of mechanisms to 163.1926 - retrieve articles via NNTP. The news articles are stored and indexed 163.1927 - using three types of keys. The first type of key is the message-id 163.1928 - of an article and is globally unique. The second type of key is 163.1929 - composed of a newsgroup name and an article number within that 163.1930 - newsgroup. On a particular server, there MUST only be one article 163.1931 - with a given number within any newsgroup, and an article MUST NOT 163.1932 - have two different numbers in the same newsgroup. An article can be 163.1933 - cross-posted to multiple newsgroups, so there may be multiple keys 163.1934 - that point to the same article on the same server; these MAY have 163.1935 - different numbers in each newsgroup. However, this type of key is 163.1936 - not required to be globally unique, so the same key MAY refer to 163.1937 - different articles on different servers. (Note that the terms 163.1938 - "group" and "newsgroup" are equivalent.) 163.1939 - 163.1940 - The final type of key is the arrival timestamp, giving the time that 163.1941 - the article arrived at the server. The server MUST ensure that 163.1942 - article numbers are issued in order of arrival timestamp; that is, 163.1943 - articles arriving later MUST have higher numbers than those that 163.1944 - arrive earlier. The server SHOULD allocate the next sequential 163.1945 - unused number to each new article. 163.1946 - 163.1947 - Article numbers MUST lie between 1 and 2,147,483,647, inclusive. The 163.1948 - client and server MAY use leading zeroes in specifying article 163.1949 - numbers but MUST NOT use more than 16 digits. In some situations, 163.1950 - the value zero replaces an article number to show some special 163.1951 - situation. 163.1952 - 163.1953 - Note that it is likely that the article number limit of 2,147,483,647 163.1954 - will be increased by a future revision or extension to this 163.1955 - specification. While servers MUST NOT send article numbers greater 163.1956 - than this current limit, client and server developers are advised to 163.1957 - 163.1958 - 163.1959 - 163.1960 -Feather Standards Track [Page 35] 163.1961 - 163.1962 -RFC 3977 Network News Transfer Protocol (NNTP) October 2006 163.1963 - 163.1964 - 163.1965 - use internal structures and datatypes capable of handling larger 163.1966 - values in anticipation of such a change. 163.1967 - 163.1968 -6.1. Group and Article Selection 163.1969 - 163.1970 - The following commands are used to set the "currently selected 163.1971 - newsgroup" and the "current article number", which are used by 163.1972 - various commands. At the start of an NNTP session, both of these 163.1973 - values are set to the special value "invalid". 163.1974 - 163.1975 -6.1.1. GROUP 163.1976 - 163.1977 -6.1.1.1. Usage 163.1978 - 163.1979 - Indicating capability: READER 163.1980 - 163.1981 - Syntax 163.1982 - GROUP group 163.1983 - 163.1984 - Responses 163.1985 - 211 number low high group Group successfully selected 163.1986 - 411 No such newsgroup 163.1987 - 163.1988 - Parameters 163.1989 - group Name of newsgroup 163.1990 - number Estimated number of articles in the group 163.1991 - low Reported low water mark 163.1992 - high Reported high water mark 163.1993 - 163.1994 -6.1.1.2. Description 163.1995 - 163.1996 - The GROUP command selects a newsgroup as the currently selected 163.1997 - newsgroup and returns summary information about it. 163.1998 - 163.1999 - The required argument is the name of the newsgroup to be selected 163.2000 - (e.g., "news.software.nntp"). A list of valid newsgroups may be 163.2001 - obtained by using the LIST ACTIVE command (see Section 7.6.3). 163.2002 - 163.2003 - The successful selection response will return the article numbers of 163.2004 - the first and last articles in the group at the moment of selection 163.2005 - (these numbers are referred to as the "reported low water mark" and 163.2006 - the "reported high water mark") and an estimate of the number of 163.2007 - articles in the group currently available. 163.2008 - 163.2009 - If the group is not empty, the estimate MUST be at least the actual 163.2010 - number of articles available and MUST be no greater than one more 163.2011 - than the difference between the reported low and high water marks. 163.2012 - (Some implementations will actually count the number of articles 163.2013 - 163.2014 - 163.2015 - 163.2016 -Feather Standards Track [Page 36] 163.2017 - 163.2018 -RFC 3977 Network News Transfer Protocol (NNTP) October 2006 163.2019 - 163.2020 - 163.2021 - currently stored. Others will just subtract the low water mark from 163.2022 - the high water mark and add one to get an estimate.) 163.2023 - 163.2024 - If the group is empty, one of the following three situations will 163.2025 - occur. Clients MUST accept all three cases; servers MUST NOT 163.2026 - represent an empty group in any other way. 163.2027 - 163.2028 - o The high water mark will be one less than the low water mark, and 163.2029 - the estimated article count will be zero. Servers SHOULD use this 163.2030 - method to show an empty group. This is the only time that the 163.2031 - high water mark can be less than the low water mark. 163.2032 - 163.2033 - o All three numbers will be zero. 163.2034 - 163.2035 - o The high water mark is greater than or equal to the low water 163.2036 - mark. The estimated article count might be zero or non-zero; if 163.2037 - it is non-zero, the same requirements apply as for a non-empty 163.2038 - group. 163.2039 - 163.2040 - The set of articles in a group may change after the GROUP command is 163.2041 - carried out: 163.2042 - 163.2043 - o Articles may be removed from the group. 163.2044 - 163.2045 - o Articles may be reinstated in the group with the same article 163.2046 - number, but those articles MUST have numbers no less than the 163.2047 - reported low water mark (note that this is a reinstatement of the 163.2048 - previous article, not a new article reusing the number). 163.2049 - 163.2050 - o New articles may be added with article numbers greater than the 163.2051 - reported high water mark. (If an article that was the one with 163.2052 - the highest number has been removed and the high water mark has 163.2053 - been adjusted accordingly, the next new article will not have the 163.2054 - number one greater than the reported high water mark.) 163.2055 - 163.2056 - Except when the group is empty and all three numbers are zero, 163.2057 - whenever a subsequent GROUP command for the same newsgroup is issued, 163.2058 - either by the same client or a different client, the reported low 163.2059 - water mark in the response MUST be no less than that in any previous 163.2060 - response for that newsgroup in this session, and it SHOULD be no less 163.2061 - than that in any previous response for that newsgroup ever sent to 163.2062 - any client. Any failure to meet the latter condition SHOULD be 163.2063 - transient only. The client may make use of the low water mark to 163.2064 - remove all remembered information about articles with lower numbers, 163.2065 - as these will never recur. This includes the situation when the high 163.2066 - water mark is one less than the low water mark. No similar 163.2067 - assumption can be made about the high water mark, as this can 163.2068 - 163.2069 - 163.2070 - 163.2071 - 163.2072 -Feather Standards Track [Page 37] 163.2073 - 163.2074 -RFC 3977 Network News Transfer Protocol (NNTP) October 2006 163.2075 - 163.2076 - 163.2077 - decrease if an article is removed and then increase again if it is 163.2078 - reinstated or if new articles arrive. 163.2079 - 163.2080 - When a valid group is selected by means of this command, the 163.2081 - currently selected newsgroup MUST be set to that group, and the 163.2082 - current article number MUST be set to the first article in the group 163.2083 - (this applies even if the group is already the currently selected 163.2084 - newsgroup). If an empty newsgroup is selected, the current article 163.2085 - number is made invalid. If an invalid group is specified, the 163.2086 - currently selected newsgroup and current article number MUST NOT be 163.2087 - changed. 163.2088 - 163.2089 - The GROUP or LISTGROUP command (see Section 6.1.2) MUST be used by a 163.2090 - client, and a successful response received, before any other command 163.2091 - is used that depends on the value of the currently selected newsgroup 163.2092 - or current article number. 163.2093 - 163.2094 - If the group specified is not available on the server, a 411 response 163.2095 - MUST be returned. 163.2096 - 163.2097 -6.1.1.3. Examples 163.2098 - 163.2099 - Example for a group known to the server: 163.2100 - 163.2101 - [C] GROUP misc.test 163.2102 - [S] 211 1234 3000234 3002322 misc.test 163.2103 - 163.2104 - Example for a group unknown to the server: 163.2105 - 163.2106 - [C] GROUP example.is.sob.bradner.or.barber 163.2107 - [S] 411 example.is.sob.bradner.or.barber is unknown 163.2108 - 163.2109 - Example of an empty group using the preferred response: 163.2110 - 163.2111 - [C] GROUP example.currently.empty.newsgroup 163.2112 - [S] 211 0 4000 3999 example.currently.empty.newsgroup 163.2113 - 163.2114 - Example of an empty group using an alternative response: 163.2115 - 163.2116 - [C] GROUP example.currently.empty.newsgroup 163.2117 - [S] 211 0 0 0 example.currently.empty.newsgroup 163.2118 - 163.2119 - Example of an empty group using a different alternative response: 163.2120 - 163.2121 - [C] GROUP example.currently.empty.newsgroup 163.2122 - [S] 211 0 4000 4321 example.currently.empty.newsgroup 163.2123 - 163.2124 - 163.2125 - 163.2126 - 163.2127 - 163.2128 -Feather Standards Track [Page 38] 163.2129 - 163.2130 -RFC 3977 Network News Transfer Protocol (NNTP) October 2006 163.2131 - 163.2132 - 163.2133 - Example reselecting the currently selected newsgroup: 163.2134 - 163.2135 - [C] GROUP misc.test 163.2136 - [S] 211 1234 234 567 misc.test 163.2137 - [C] STAT 444 163.2138 - [S] 223 444 <123456@example.net> retrieved 163.2139 - [C] GROUP misc.test 163.2140 - [S] 211 1234 234 567 misc.test 163.2141 - [C] STAT 163.2142 - [S] 223 234 <different@example.net> retrieved 163.2143 - 163.2144 -6.1.2. LISTGROUP 163.2145 - 163.2146 -6.1.2.1. Usage 163.2147 - 163.2148 - Indicating capability: READER 163.2149 - 163.2150 - Syntax 163.2151 - LISTGROUP [group [range]] 163.2152 - 163.2153 - Responses 163.2154 - 211 number low high group Article numbers follow (multi-line) 163.2155 - 411 No such newsgroup 163.2156 - 412 No newsgroup selected [1] 163.2157 - 163.2158 - Parameters 163.2159 - group Name of newsgroup 163.2160 - range Range of articles to report 163.2161 - number Estimated number of articles in the group 163.2162 - low Reported low water mark 163.2163 - high Reported high water mark 163.2164 - 163.2165 - [1] The 412 response can only occur if no group has been specified. 163.2166 - 163.2167 -6.1.2.2. Description 163.2168 - 163.2169 - The LISTGROUP command selects a newsgroup in the same manner as the 163.2170 - GROUP command (see Section 6.1.1) but also provides a list of article 163.2171 - numbers in the newsgroup. If no group is specified, the currently 163.2172 - selected newsgroup is used. 163.2173 - 163.2174 - On success, a list of article numbers is returned as a multi-line 163.2175 - data block following the 211 response code (the arguments on the 163.2176 - initial response line are the same as for the GROUP command). The 163.2177 - list contains one number per line and is in numerical order. It 163.2178 - lists precisely those articles that exist in the group at the moment 163.2179 - of selection (therefore, an empty group produces an empty list). If 163.2180 - the optional range argument is specified, only articles within the 163.2181 - 163.2182 - 163.2183 - 163.2184 -Feather Standards Track [Page 39] 163.2185 - 163.2186 -RFC 3977 Network News Transfer Protocol (NNTP) October 2006 163.2187 - 163.2188 - 163.2189 - range are included in the list (therefore, the list MAY be empty even 163.2190 - if the group is not). 163.2191 - 163.2192 - The range argument may be any of the following: 163.2193 - 163.2194 - o An article number. 163.2195 - 163.2196 - o An article number followed by a dash to indicate all following. 163.2197 - 163.2198 - o An article number followed by a dash followed by another article 163.2199 - number. 163.2200 - 163.2201 - In the last case, if the second number is less than the first number, 163.2202 - then the range contains no articles. Omitting the range is 163.2203 - equivalent to the range 1- being specified. 163.2204 - 163.2205 - If the group specified is not available on the server, a 411 response 163.2206 - MUST be returned. If no group is specified and the currently 163.2207 - selected newsgroup is invalid, a 412 response MUST be returned. 163.2208 - 163.2209 - Except that the group argument is optional, that a range argument can 163.2210 - be specified, and that a multi-line data block follows the 211 163.2211 - response code, the LISTGROUP command is identical to the GROUP 163.2212 - command. In particular, when successful, the command sets the 163.2213 - current article number to the first article in the group, if any, 163.2214 - even if this is not within the range specified by the second 163.2215 - argument. 163.2216 - 163.2217 - Note that the range argument is a new feature in this specification 163.2218 - and servers that do not support CAPABILITIES (and therefore do not 163.2219 - conform to this specification) are unlikely to support it. 163.2220 - 163.2221 -6.1.2.3. Examples 163.2222 - 163.2223 - Example of LISTGROUP being used to select a group: 163.2224 - 163.2225 - [C] LISTGROUP misc.test 163.2226 - [S] 211 2000 3000234 3002322 misc.test list follows 163.2227 - [S] 3000234 163.2228 - [S] 3000237 163.2229 - [S] 3000238 163.2230 - [S] 3000239 163.2231 - [S] 3002322 163.2232 - [S] . 163.2233 - 163.2234 - 163.2235 - 163.2236 - 163.2237 - 163.2238 - 163.2239 - 163.2240 -Feather Standards Track [Page 40] 163.2241 - 163.2242 -RFC 3977 Network News Transfer Protocol (NNTP) October 2006 163.2243 - 163.2244 - 163.2245 - Example of LISTGROUP on an empty group: 163.2246 - 163.2247 - [C] LISTGROUP example.empty.newsgroup 163.2248 - [S] 211 0 0 0 example.empty.newsgroup list follows 163.2249 - [S] . 163.2250 - 163.2251 - Example of LISTGROUP on a valid, currently selected newsgroup: 163.2252 - 163.2253 - [C] GROUP misc.test 163.2254 - [S] 211 2000 3000234 3002322 misc.test 163.2255 - [C] LISTGROUP 163.2256 - [S] 211 2000 3000234 3002322 misc.test list follows 163.2257 - [S] 3000234 163.2258 - [S] 3000237 163.2259 - [S] 3000238 163.2260 - [S] 3000239 163.2261 - [S] 3002322 163.2262 - [S] . 163.2263 - 163.2264 - Example of LISTGROUP with a range: 163.2265 - 163.2266 - [C] LISTGROUP misc.test 3000238-3000248 163.2267 - [S] 211 2000 3000234 3002322 misc.test list follows 163.2268 - [S] 3000238 163.2269 - [S] 3000239 163.2270 - [S] . 163.2271 - 163.2272 - Example of LISTGROUP with an empty range: 163.2273 - 163.2274 - [C] LISTGROUP misc.test 12345678- 163.2275 - [S] 211 2000 3000234 3002322 misc.test list follows 163.2276 - [S] . 163.2277 - 163.2278 - Example of LISTGROUP with an invalid range: 163.2279 - 163.2280 - [C] LISTGROUP misc.test 9999-111 163.2281 - [S] 211 2000 3000234 3002322 misc.test list follows 163.2282 - [S] . 163.2283 - 163.2284 - 163.2285 - 163.2286 - 163.2287 - 163.2288 - 163.2289 - 163.2290 - 163.2291 - 163.2292 - 163.2293 - 163.2294 - 163.2295 - 163.2296 -Feather Standards Track [Page 41] 163.2297 - 163.2298 -RFC 3977 Network News Transfer Protocol (NNTP) October 2006 163.2299 - 163.2300 - 163.2301 -6.1.3. LAST 163.2302 - 163.2303 -6.1.3.1. Usage 163.2304 - 163.2305 - Indicating capability: READER 163.2306 - 163.2307 - Syntax 163.2308 - LAST 163.2309 - 163.2310 - Responses 163.2311 - 223 n message-id Article found 163.2312 - 412 No newsgroup selected 163.2313 - 420 Current article number is invalid 163.2314 - 422 No previous article in this group 163.2315 - 163.2316 - Parameters 163.2317 - n Article number 163.2318 - message-id Article message-id 163.2319 - 163.2320 -6.1.3.2. Description 163.2321 - 163.2322 - If the currently selected newsgroup is valid, the current article 163.2323 - number MUST be set to the previous article in that newsgroup (that 163.2324 - is, the highest existing article number less than the current article 163.2325 - number). If successful, a response indicating the new current 163.2326 - article number and the message-id of that article MUST be returned. 163.2327 - No article text is sent in response to this command. 163.2328 - 163.2329 - There MAY be no previous article in the group, although the current 163.2330 - article number is not the reported low water mark. There MUST NOT be 163.2331 - a previous article when the current article number is the reported 163.2332 - low water mark. 163.2333 - 163.2334 - Because articles can be removed and added, the results of multiple 163.2335 - LAST and NEXT commands MAY not be consistent over the life of a 163.2336 - particular NNTP session. 163.2337 - 163.2338 - If the current article number is already the first article of the 163.2339 - newsgroup, a 422 response MUST be returned. If the current article 163.2340 - number is invalid, a 420 response MUST be returned. If the currently 163.2341 - selected newsgroup is invalid, a 412 response MUST be returned. In 163.2342 - all three cases, the currently selected newsgroup and current article 163.2343 - number MUST NOT be altered. 163.2344 - 163.2345 - 163.2346 - 163.2347 - 163.2348 - 163.2349 - 163.2350 - 163.2351 - 163.2352 -Feather Standards Track [Page 42] 163.2353 - 163.2354 -RFC 3977 Network News Transfer Protocol (NNTP) October 2006 163.2355 - 163.2356 - 163.2357 -6.1.3.3. Examples 163.2358 - 163.2359 - Example of a successful article retrieval using LAST: 163.2360 - 163.2361 - [C] GROUP misc.test 163.2362 - [S] 211 1234 3000234 3002322 misc.test 163.2363 - [C] NEXT 163.2364 - [S] 223 3000237 <668929@example.org> retrieved 163.2365 - [C] LAST 163.2366 - [S] 223 3000234 <45223423@example.com> retrieved 163.2367 - 163.2368 - Example of an attempt to retrieve an article without having selected 163.2369 - a group (via the GROUP command) first: 163.2370 - 163.2371 - [Assumes currently selected newsgroup is invalid.] 163.2372 - [C] LAST 163.2373 - [S] 412 no newsgroup selected 163.2374 - 163.2375 - Example of an attempt to retrieve an article using the LAST command 163.2376 - when the current article number is that of the first article in the 163.2377 - group: 163.2378 - 163.2379 - [C] GROUP misc.test 163.2380 - [S] 211 1234 3000234 3002322 misc.test 163.2381 - [C] LAST 163.2382 - [S] 422 No previous article to retrieve 163.2383 - 163.2384 - Example of an attempt to retrieve an article using the LAST command 163.2385 - when the currently selected newsgroup is empty: 163.2386 - 163.2387 - [C] GROUP example.empty.newsgroup 163.2388 - [S] 211 0 0 0 example.empty.newsgroup 163.2389 - [C] LAST 163.2390 - [S] 420 No current article selected 163.2391 - 163.2392 - 163.2393 - 163.2394 - 163.2395 - 163.2396 - 163.2397 - 163.2398 - 163.2399 - 163.2400 - 163.2401 - 163.2402 - 163.2403 - 163.2404 - 163.2405 - 163.2406 - 163.2407 - 163.2408 -Feather Standards Track [Page 43] 163.2409 - 163.2410 -RFC 3977 Network News Transfer Protocol (NNTP) October 2006 163.2411 - 163.2412 - 163.2413 -6.1.4. NEXT 163.2414 - 163.2415 -6.1.4.1. Usage 163.2416 - 163.2417 - Indicating capability: READER 163.2418 - 163.2419 - Syntax 163.2420 - NEXT 163.2421 - 163.2422 - Responses 163.2423 - 223 n message-id Article found 163.2424 - 412 No newsgroup selected 163.2425 - 420 Current article number is invalid 163.2426 - 421 No next article in this group 163.2427 - 163.2428 - Parameters 163.2429 - n Article number 163.2430 - message-id Article message-id 163.2431 - 163.2432 -6.1.4.2. Description 163.2433 - 163.2434 - If the currently selected newsgroup is valid, the current article 163.2435 - number MUST be set to the next article in that newsgroup (that is, 163.2436 - the lowest existing article number greater than the current article 163.2437 - number). If successful, a response indicating the new current 163.2438 - article number and the message-id of that article MUST be returned. 163.2439 - No article text is sent in response to this command. 163.2440 - 163.2441 - If the current article number is already the last article of the 163.2442 - newsgroup, a 421 response MUST be returned. In all other aspects 163.2443 - (apart, of course, from the lack of 422 response), this command is 163.2444 - identical to the LAST command (Section 6.1.3). 163.2445 - 163.2446 -6.1.4.3. Examples 163.2447 - 163.2448 - Example of a successful article retrieval using NEXT: 163.2449 - 163.2450 - [C] GROUP misc.test 163.2451 - [S] 211 1234 3000234 3002322 misc.test 163.2452 - [C] NEXT 163.2453 - [S] 223 3000237 <668929@example.org> retrieved 163.2454 - 163.2455 - 163.2456 - 163.2457 - 163.2458 - 163.2459 - 163.2460 - 163.2461 - 163.2462 - 163.2463 - 163.2464 -Feather Standards Track [Page 44] 163.2465 - 163.2466 -RFC 3977 Network News Transfer Protocol (NNTP) October 2006 163.2467 - 163.2468 - 163.2469 - Example of an attempt to retrieve an article without having selected 163.2470 - a group (via the GROUP command) first: 163.2471 - 163.2472 - [Assumes currently selected newsgroup is invalid.] 163.2473 - [C] NEXT 163.2474 - [S] 412 no newsgroup selected 163.2475 - 163.2476 - Example of an attempt to retrieve an article using the NEXT command 163.2477 - when the current article number is that of the last article in the 163.2478 - group: 163.2479 - 163.2480 - [C] GROUP misc.test 163.2481 - [S] 211 1234 3000234 3002322 misc.test 163.2482 - [C] STAT 3002322 163.2483 - [S] 223 3002322 <411@example.net> retrieved 163.2484 - [C] NEXT 163.2485 - [S] 421 No next article to retrieve 163.2486 - 163.2487 - Example of an attempt to retrieve an article using the NEXT command 163.2488 - when the currently selected newsgroup is empty: 163.2489 - 163.2490 - [C] GROUP example.empty.newsgroup 163.2491 - [S] 211 0 0 0 example.empty.newsgroup 163.2492 - [C] NEXT 163.2493 - [S] 420 No current article selected 163.2494 - 163.2495 -6.2. Retrieval of Articles and Article Sections 163.2496 - 163.2497 - The ARTICLE, BODY, HEAD, and STAT commands are very similar. They 163.2498 - differ only in the parts of the article that are presented to the 163.2499 - client and in the successful response code. The ARTICLE command is 163.2500 - described here in full, while the other three commands are described 163.2501 - in terms of the differences. As specified in Section 3.6, an article 163.2502 - consists of two parts: the article headers and the article body. 163.2503 - 163.2504 - When responding to one of these commands, the server MUST present the 163.2505 - entire article or appropriate part and MUST NOT attempt to alter or 163.2506 - translate it in any way. 163.2507 - 163.2508 - 163.2509 - 163.2510 - 163.2511 - 163.2512 - 163.2513 - 163.2514 - 163.2515 - 163.2516 - 163.2517 - 163.2518 - 163.2519 - 163.2520 -Feather Standards Track [Page 45] 163.2521 - 163.2522 -RFC 3977 Network News Transfer Protocol (NNTP) October 2006 163.2523 - 163.2524 - 163.2525 -6.2.1. ARTICLE 163.2526 - 163.2527 -6.2.1.1. Usage 163.2528 - 163.2529 - Indicating capability: READER 163.2530 - 163.2531 - Syntax 163.2532 - ARTICLE message-id 163.2533 - ARTICLE number 163.2534 - ARTICLE 163.2535 - 163.2536 - Responses 163.2537 - 163.2538 - First form (message-id specified) 163.2539 - 220 0|n message-id Article follows (multi-line) 163.2540 - 430 No article with that message-id 163.2541 - 163.2542 - Second form (article number specified) 163.2543 - 220 n message-id Article follows (multi-line) 163.2544 - 412 No newsgroup selected 163.2545 - 423 No article with that number 163.2546 - 163.2547 - Third form (current article number used) 163.2548 - 220 n message-id Article follows (multi-line) 163.2549 - 412 No newsgroup selected 163.2550 - 420 Current article number is invalid 163.2551 - 163.2552 - Parameters 163.2553 - number Requested article number 163.2554 - n Returned article number 163.2555 - message-id Article message-id 163.2556 - 163.2557 -6.2.1.2. Description 163.2558 - 163.2559 - The ARTICLE command selects an article according to the arguments and 163.2560 - presents the entire article (that is, the headers, an empty line, and 163.2561 - the body, in that order) to the client. The command has three forms. 163.2562 - 163.2563 - In the first form, a message-id is specified, and the server presents 163.2564 - the article with that message-id. In this case, the server MUST NOT 163.2565 - alter the currently selected newsgroup or current article number. 163.2566 - This is both to facilitate the presentation of articles that may be 163.2567 - referenced within another article being read, and because of the 163.2568 - semantic difficulties of determining the proper sequence and 163.2569 - membership of an article that may have been cross-posted to more than 163.2570 - one newsgroup. 163.2571 - 163.2572 - 163.2573 - 163.2574 - 163.2575 - 163.2576 -Feather Standards Track [Page 46] 163.2577 - 163.2578 -RFC 3977 Network News Transfer Protocol (NNTP) October 2006 163.2579 - 163.2580 - 163.2581 - In the response, the article number MUST be replaced with zero, 163.2582 - unless there is a currently selected newsgroup and the article is 163.2583 - present in that group, in which case the server MAY use the article's 163.2584 - number in that group. (The server is not required to determine 163.2585 - whether the article is in the currently selected newsgroup or, if so, 163.2586 - what article number it has; the client MUST always be prepared for 163.2587 - zero to be specified.) The server MUST NOT provide an article number 163.2588 - unless use of that number in a second ARTICLE command immediately 163.2589 - following this one would return the same article. Even if the server 163.2590 - chooses to return article numbers in these circumstances, it need not 163.2591 - do so consistently; it MAY return zero to any such command (also see 163.2592 - the STAT examples, Section 6.2.4.3). 163.2593 - 163.2594 - In the second form, an article number is specified. If there is an 163.2595 - article with that number in the currently selected newsgroup, the 163.2596 - server MUST set the current article number to that number. 163.2597 - 163.2598 - In the third form, the article indicated by the current article 163.2599 - number in the currently selected newsgroup is used. 163.2600 - 163.2601 - Note that a previously valid article number MAY become invalid if the 163.2602 - article has been removed. A previously invalid article number MAY 163.2603 - become valid if the article has been reinstated, but this article 163.2604 - number MUST be no less than the reported low water mark for that 163.2605 - group. 163.2606 - 163.2607 - The server MUST NOT change the currently selected newsgroup as a 163.2608 - result of this command. The server MUST NOT change the current 163.2609 - article number except when an article number argument was provided 163.2610 - and the article exists; in particular, it MUST NOT change it 163.2611 - following an unsuccessful response. 163.2612 - 163.2613 - Since the message-id is unique for each article, it may be used by a 163.2614 - client to skip duplicate displays of articles that have been posted 163.2615 - more than once, or to more than one newsgroup. 163.2616 - 163.2617 - The article is returned as a multi-line data block following the 220 163.2618 - response code. 163.2619 - 163.2620 - If the argument is a message-id and no such article exists, a 430 163.2621 - response MUST be returned. If the argument is a number or is omitted 163.2622 - and the currently selected newsgroup is invalid, a 412 response MUST 163.2623 - be returned. If the argument is a number and that article does not 163.2624 - exist in the currently selected newsgroup, a 423 response MUST be 163.2625 - returned. If the argument is omitted and the current article number 163.2626 - is invalid, a 420 response MUST be returned. 163.2627 - 163.2628 - 163.2629 - 163.2630 - 163.2631 - 163.2632 -Feather Standards Track [Page 47] 163.2633 - 163.2634 -RFC 3977 Network News Transfer Protocol (NNTP) October 2006 163.2635 - 163.2636 - 163.2637 -6.2.1.3. Examples 163.2638 - 163.2639 - Example of a successful retrieval of an article (explicitly not using 163.2640 - an article number): 163.2641 - 163.2642 - [C] GROUP misc.test 163.2643 - [S] 211 1234 3000234 3002322 misc.test 163.2644 - [C] ARTICLE 163.2645 - [S] 220 3000234 <45223423@example.com> 163.2646 - [S] Path: pathost!demo!whitehouse!not-for-mail 163.2647 - [S] From: "Demo User" <nobody@example.net> 163.2648 - [S] Newsgroups: misc.test 163.2649 - [S] Subject: I am just a test article 163.2650 - [S] Date: 6 Oct 1998 04:38:40 -0500 163.2651 - [S] Organization: An Example Net, Uncertain, Texas 163.2652 - [S] Message-ID: <45223423@example.com> 163.2653 - [S] 163.2654 - [S] This is just a test article. 163.2655 - [S] . 163.2656 - 163.2657 - Example of a successful retrieval of an article by message-id: 163.2658 - 163.2659 - [C] ARTICLE <45223423@example.com> 163.2660 - [S] 220 0 <45223423@example.com> 163.2661 - [S] Path: pathost!demo!whitehouse!not-for-mail 163.2662 - [S] From: "Demo User" <nobody@example.net> 163.2663 - [S] Newsgroups: misc.test 163.2664 - [S] Subject: I am just a test article 163.2665 - [S] Date: 6 Oct 1998 04:38:40 -0500 163.2666 - [S] Organization: An Example Net, Uncertain, Texas 163.2667 - [S] Message-ID: <45223423@example.com> 163.2668 - [S] 163.2669 - [S] This is just a test article. 163.2670 - [S] . 163.2671 - 163.2672 - Example of an unsuccessful retrieval of an article by message-id: 163.2673 - 163.2674 - [C] ARTICLE <i.am.not.there@example.com> 163.2675 - [S] 430 No Such Article Found 163.2676 - 163.2677 - Example of an unsuccessful retrieval of an article by number: 163.2678 - 163.2679 - [C] GROUP misc.test 163.2680 - [S] 211 1234 3000234 3002322 news.groups 163.2681 - [C] ARTICLE 300256 163.2682 - [S] 423 No article with that number 163.2683 - 163.2684 - 163.2685 - 163.2686 - 163.2687 - 163.2688 -Feather Standards Track [Page 48] 163.2689 - 163.2690 -RFC 3977 Network News Transfer Protocol (NNTP) October 2006 163.2691 - 163.2692 - 163.2693 - Example of an unsuccessful retrieval of an article by number because 163.2694 - no newsgroup was selected first: 163.2695 - 163.2696 - [Assumes currently selected newsgroup is invalid.] 163.2697 - [C] ARTICLE 300256 163.2698 - [S] 412 No newsgroup selected 163.2699 - 163.2700 - Example of an attempt to retrieve an article when the currently 163.2701 - selected newsgroup is empty: 163.2702 - 163.2703 - [C] GROUP example.empty.newsgroup 163.2704 - [S] 211 0 0 0 example.empty.newsgroup 163.2705 - [C] ARTICLE 163.2706 - [S] 420 No current article selected 163.2707 - 163.2708 -6.2.2. HEAD 163.2709 - 163.2710 -6.2.2.1. Usage 163.2711 - 163.2712 - This command is mandatory. 163.2713 - 163.2714 - Syntax 163.2715 - HEAD message-id 163.2716 - HEAD number 163.2717 - HEAD 163.2718 - 163.2719 - Responses 163.2720 - 163.2721 - First form (message-id specified) 163.2722 - 221 0|n message-id Headers follow (multi-line) 163.2723 - 430 No article with that message-id 163.2724 - 163.2725 - Second form (article number specified) 163.2726 - 221 n message-id Headers follow (multi-line) 163.2727 - 412 No newsgroup selected 163.2728 - 423 No article with that number 163.2729 - 163.2730 - Third form (current article number used) 163.2731 - 221 n message-id Headers follow (multi-line) 163.2732 - 412 No newsgroup selected 163.2733 - 420 Current article number is invalid 163.2734 - 163.2735 - Parameters 163.2736 - number Requested article number 163.2737 - n Returned article number 163.2738 - message-id Article message-id 163.2739 - 163.2740 - 163.2741 - 163.2742 - 163.2743 - 163.2744 -Feather Standards Track [Page 49] 163.2745 - 163.2746 -RFC 3977 Network News Transfer Protocol (NNTP) October 2006 163.2747 - 163.2748 - 163.2749 -6.2.2.2. Description 163.2750 - 163.2751 - The HEAD command behaves identically to the ARTICLE command except 163.2752 - that, if the article exists, the response code is 221 instead of 220 163.2753 - and only the headers are presented (the empty line separating the 163.2754 - headers and body MUST NOT be included). 163.2755 - 163.2756 -6.2.2.3. Examples 163.2757 - 163.2758 - Example of a successful retrieval of the headers of an article 163.2759 - (explicitly not using an article number): 163.2760 - 163.2761 - [C] GROUP misc.test 163.2762 - [S] 211 1234 3000234 3002322 misc.test 163.2763 - [C] HEAD 163.2764 - [S] 221 3000234 <45223423@example.com> 163.2765 - [S] Path: pathost!demo!whitehouse!not-for-mail 163.2766 - [S] From: "Demo User" <nobody@example.net> 163.2767 - [S] Newsgroups: misc.test 163.2768 - [S] Subject: I am just a test article 163.2769 - [S] Date: 6 Oct 1998 04:38:40 -0500 163.2770 - [S] Organization: An Example Net, Uncertain, Texas 163.2771 - [S] Message-ID: <45223423@example.com> 163.2772 - [S] . 163.2773 - 163.2774 - Example of a successful retrieval of the headers of an article by 163.2775 - message-id: 163.2776 - 163.2777 - [C] HEAD <45223423@example.com> 163.2778 - [S] 221 0 <45223423@example.com> 163.2779 - [S] Path: pathost!demo!whitehouse!not-for-mail 163.2780 - [S] From: "Demo User" <nobody@example.net> 163.2781 - [S] Newsgroups: misc.test 163.2782 - [S] Subject: I am just a test article 163.2783 - [S] Date: 6 Oct 1998 04:38:40 -0500 163.2784 - [S] Organization: An Example Net, Uncertain, Texas 163.2785 - [S] Message-ID: <45223423@example.com> 163.2786 - [S] . 163.2787 - 163.2788 - Example of an unsuccessful retrieval of the headers of an article by 163.2789 - message-id: 163.2790 - 163.2791 - [C] HEAD <i.am.not.there@example.com> 163.2792 - [S] 430 No Such Article Found 163.2793 - 163.2794 - 163.2795 - 163.2796 - 163.2797 - 163.2798 - 163.2799 - 163.2800 -Feather Standards Track [Page 50] 163.2801 - 163.2802 -RFC 3977 Network News Transfer Protocol (NNTP) October 2006 163.2803 - 163.2804 - 163.2805 - Example of an unsuccessful retrieval of the headers of an article by 163.2806 - number: 163.2807 - 163.2808 - [C] GROUP misc.test 163.2809 - [S] 211 1234 3000234 3002322 misc.test 163.2810 - [C] HEAD 300256 163.2811 - [S] 423 No article with that number 163.2812 - 163.2813 - Example of an unsuccessful retrieval of the headers of an article by 163.2814 - number because no newsgroup was selected first: 163.2815 - 163.2816 - [Assumes currently selected newsgroup is invalid.] 163.2817 - [C] HEAD 300256 163.2818 - [S] 412 No newsgroup selected 163.2819 - 163.2820 - Example of an attempt to retrieve the headers of an article when the 163.2821 - currently selected newsgroup is empty: 163.2822 - 163.2823 - [C] GROUP example.empty.newsgroup 163.2824 - [S] 211 0 0 0 example.empty.newsgroup 163.2825 - [C] HEAD 163.2826 - [S] 420 No current article selected 163.2827 - 163.2828 -6.2.3. BODY 163.2829 - 163.2830 -6.2.3.1. Usage 163.2831 - 163.2832 - Indicating capability: READER 163.2833 - 163.2834 - Syntax 163.2835 - BODY message-id 163.2836 - BODY number 163.2837 - BODY 163.2838 - 163.2839 - Responses 163.2840 - 163.2841 - First form (message-id specified) 163.2842 - 222 0|n message-id Body follows (multi-line) 163.2843 - 430 No article with that message-id 163.2844 - 163.2845 - Second form (article number specified) 163.2846 - 222 n message-id Body follows (multi-line) 163.2847 - 412 No newsgroup selected 163.2848 - 423 No article with that number 163.2849 - 163.2850 - 163.2851 - 163.2852 - 163.2853 - 163.2854 - 163.2855 - 163.2856 -Feather Standards Track [Page 51] 163.2857 - 163.2858 -RFC 3977 Network News Transfer Protocol (NNTP) October 2006 163.2859 - 163.2860 - 163.2861 - Third form (current article number used) 163.2862 - 222 n message-id Body follows (multi-line) 163.2863 - 412 No newsgroup selected 163.2864 - 420 Current article number is invalid 163.2865 - 163.2866 - Parameters 163.2867 - number Requested article number 163.2868 - n Returned article number 163.2869 - message-id Article message-id 163.2870 - 163.2871 -6.2.3.2. Description 163.2872 - 163.2873 - The BODY command behaves identically to the ARTICLE command except 163.2874 - that, if the article exists, the response code is 222 instead of 220 163.2875 - and only the body is presented (the empty line separating the headers 163.2876 - and body MUST NOT be included). 163.2877 - 163.2878 -6.2.3.3. Examples 163.2879 - 163.2880 - Example of a successful retrieval of the body of an article 163.2881 - (explicitly not using an article number): 163.2882 - 163.2883 - [C] GROUP misc.test 163.2884 - [S] 211 1234 3000234 3002322 misc.test 163.2885 - [C] BODY 163.2886 - [S] 222 3000234 <45223423@example.com> 163.2887 - [S] This is just a test article. 163.2888 - [S] . 163.2889 - 163.2890 - Example of a successful retrieval of the body of an article by 163.2891 - message-id: 163.2892 - 163.2893 - [C] BODY <45223423@example.com> 163.2894 - [S] 222 0 <45223423@example.com> 163.2895 - [S] This is just a test article. 163.2896 - [S] . 163.2897 - 163.2898 - Example of an unsuccessful retrieval of the body of an article by 163.2899 - message-id: 163.2900 - 163.2901 - [C] BODY <i.am.not.there@example.com> 163.2902 - [S] 430 No Such Article Found 163.2903 - 163.2904 - 163.2905 - 163.2906 - 163.2907 - 163.2908 - 163.2909 - 163.2910 - 163.2911 - 163.2912 -Feather Standards Track [Page 52] 163.2913 - 163.2914 -RFC 3977 Network News Transfer Protocol (NNTP) October 2006 163.2915 - 163.2916 - 163.2917 - Example of an unsuccessful retrieval of the body of an article by 163.2918 - number: 163.2919 - 163.2920 - [C] GROUP misc.test 163.2921 - [S] 211 1234 3000234 3002322 misc.test 163.2922 - [C] BODY 300256 163.2923 - [S] 423 No article with that number 163.2924 - 163.2925 - Example of an unsuccessful retrieval of the body of an article by 163.2926 - number because no newsgroup was selected first: 163.2927 - 163.2928 - [Assumes currently selected newsgroup is invalid.] 163.2929 - [C] BODY 300256 163.2930 - [S] 412 No newsgroup selected 163.2931 - 163.2932 - Example of an attempt to retrieve the body of an article when the 163.2933 - currently selected newsgroup is empty: 163.2934 - 163.2935 - [C] GROUP example.empty.newsgroup 163.2936 - [S] 211 0 0 0 example.empty.newsgroup 163.2937 - [C] BODY 163.2938 - [S] 420 No current article selected 163.2939 - 163.2940 -6.2.4. STAT 163.2941 - 163.2942 -6.2.4.1. Usage 163.2943 - 163.2944 - This command is mandatory. 163.2945 - 163.2946 - Syntax 163.2947 - STAT message-id 163.2948 - STAT number 163.2949 - STAT 163.2950 - 163.2951 - Responses 163.2952 - 163.2953 - First form (message-id specified) 163.2954 - 223 0|n message-id Article exists 163.2955 - 430 No article with that message-id 163.2956 - 163.2957 - Second form (article number specified) 163.2958 - 223 n message-id Article exists 163.2959 - 412 No newsgroup selected 163.2960 - 423 No article with that number 163.2961 - 163.2962 - 163.2963 - 163.2964 - 163.2965 - 163.2966 - 163.2967 - 163.2968 -Feather Standards Track [Page 53] 163.2969 - 163.2970 -RFC 3977 Network News Transfer Protocol (NNTP) October 2006 163.2971 - 163.2972 - 163.2973 - Third form (current article number used) 163.2974 - 223 n message-id Article exists 163.2975 - 412 No newsgroup selected 163.2976 - 420 Current article number is invalid 163.2977 - 163.2978 - Parameters 163.2979 - number Requested article number 163.2980 - n Returned article number 163.2981 - message-id Article message-id 163.2982 - 163.2983 -6.2.4.2. Description 163.2984 - 163.2985 - The STAT command behaves identically to the ARTICLE command except 163.2986 - that, if the article exists, it is NOT presented to the client and 163.2987 - the response code is 223 instead of 220. Note that the response is 163.2988 - NOT multi-line. 163.2989 - 163.2990 - This command allows the client to determine whether an article exists 163.2991 - and, in the second and third forms, what its message-id is, without 163.2992 - having to process an arbitrary amount of text. 163.2993 - 163.2994 -6.2.4.3. Examples 163.2995 - 163.2996 - Example of STAT on an existing article (explicitly not using an 163.2997 - article number): 163.2998 - 163.2999 - [C] GROUP misc.test 163.3000 - [S] 211 1234 3000234 3002322 misc.test 163.3001 - [C] STAT 163.3002 - [S] 223 3000234 <45223423@example.com> 163.3003 - 163.3004 - Example of STAT on an existing article by message-id: 163.3005 - 163.3006 - [C] STAT <45223423@example.com> 163.3007 - [S] 223 0 <45223423@example.com> 163.3008 - 163.3009 - Example of STAT on an article not on the server by message-id: 163.3010 - 163.3011 - [C] STAT <i.am.not.there@example.com> 163.3012 - [S] 430 No Such Article Found 163.3013 - 163.3014 - Example of STAT on an article not in the server by number: 163.3015 - 163.3016 - [C] GROUP misc.test 163.3017 - [S] 211 1234 3000234 3002322 misc.test 163.3018 - [C] STAT 300256 163.3019 - [S] 423 No article with that number 163.3020 - 163.3021 - 163.3022 - 163.3023 - 163.3024 -Feather Standards Track [Page 54] 163.3025 - 163.3026 -RFC 3977 Network News Transfer Protocol (NNTP) October 2006 163.3027 - 163.3028 - 163.3029 - Example of STAT on an article by number when no newsgroup was 163.3030 - selected first: 163.3031 - 163.3032 - [Assumes currently selected newsgroup is invalid.] 163.3033 - [C] STAT 300256 163.3034 - [S] 412 No newsgroup selected 163.3035 - 163.3036 - Example of STAT on an article when the currently selected newsgroup 163.3037 - is empty: 163.3038 - 163.3039 - [C] GROUP example.empty.newsgroup 163.3040 - [S] 211 0 0 0 example.empty.newsgroup 163.3041 - [C] STAT 163.3042 - [S] 420 No current article selected 163.3043 - 163.3044 - Example of STAT by message-id on a server that sometimes reports the 163.3045 - actual article number: 163.3046 - 163.3047 - [C] GROUP misc.test 163.3048 - [S] 211 1234 3000234 3002322 misc.test 163.3049 - [C] STAT 163.3050 - [S] 223 3000234 <45223423@example.com> 163.3051 - [C] STAT <45223423@example.com> 163.3052 - [S] 223 0 <45223423@example.com> 163.3053 - [C] STAT <45223423@example.com> 163.3054 - [S] 223 3000234 <45223423@example.com> 163.3055 - [C] GROUP example.empty.newsgroup 163.3056 - [S] 211 0 0 0 example.empty.newsgroup 163.3057 - [C] STAT <45223423@example.com> 163.3058 - [S] 223 0 <45223423@example.com> 163.3059 - [C] GROUP alt.crossposts 163.3060 - [S] 211 9999 111111 222222 alt.crossposts 163.3061 - [C] STAT <45223423@example.com> 163.3062 - [S] 223 123456 <45223423@example.com> 163.3063 - [C] STAT 163.3064 - [S] 223 111111 <23894720@example.com> 163.3065 - 163.3066 - The first STAT command establishes the identity of an article in the 163.3067 - group. The second and third show that the server may, but need not, 163.3068 - give the article number when the message-id is specified. The fourth 163.3069 - STAT command shows that zero must be specified if the article isn't 163.3070 - in the currently selected newsgroup. The fifth shows that the 163.3071 - number, if provided, must be that relating to the currently selected 163.3072 - newsgroup. The last one shows that the current article number is 163.3073 - still not changed by the use of STAT with a message-id even if it 163.3074 - returns an article number. 163.3075 - 163.3076 - 163.3077 - 163.3078 - 163.3079 - 163.3080 -Feather Standards Track [Page 55] 163.3081 - 163.3082 -RFC 3977 Network News Transfer Protocol (NNTP) October 2006 163.3083 - 163.3084 - 163.3085 -6.3. Article Posting 163.3086 - 163.3087 - Article posting is done in one of two ways: individual article 163.3088 - posting from news-reading clients using POST, and article transfer 163.3089 - from other news servers using IHAVE. 163.3090 - 163.3091 -6.3.1. POST 163.3092 - 163.3093 -6.3.1.1. Usage 163.3094 - 163.3095 - Indicating capability: POST 163.3096 - 163.3097 - This command MUST NOT be pipelined. 163.3098 - 163.3099 - Syntax 163.3100 - POST 163.3101 - 163.3102 - Responses 163.3103 - 163.3104 - Initial responses 163.3105 - 340 Send article to be posted 163.3106 - 440 Posting not permitted 163.3107 - 163.3108 - Subsequent responses 163.3109 - 240 Article received OK 163.3110 - 441 Posting failed 163.3111 - 163.3112 -6.3.1.2. Description 163.3113 - 163.3114 - If posting is allowed, a 340 response MUST be returned to indicate 163.3115 - that the article to be posted should be sent. If posting is 163.3116 - prohibited for some installation-dependent reason, a 440 response 163.3117 - MUST be returned. 163.3118 - 163.3119 - If posting is permitted, the article MUST be in the format specified 163.3120 - in Section 3.6 and MUST be sent by the client to the server as a 163.3121 - multi-line data block (see Section 3.1.1). Thus a single dot (".") 163.3122 - on a line indicates the end of the text, and lines starting with a 163.3123 - dot in the original text have that dot doubled during transmission. 163.3124 - 163.3125 - Following the presentation of the termination sequence by the client, 163.3126 - the server MUST return a response indicating success or failure of 163.3127 - the article transfer. Note that response codes 340 and 440 are used 163.3128 - in direct response to the POST command while 240 and 441 are returned 163.3129 - after the article is sent. 163.3130 - 163.3131 - 163.3132 - 163.3133 - 163.3134 - 163.3135 - 163.3136 -Feather Standards Track [Page 56] 163.3137 - 163.3138 -RFC 3977 Network News Transfer Protocol (NNTP) October 2006 163.3139 - 163.3140 - 163.3141 - A response of 240 SHOULD indicate that, barring unforeseen server 163.3142 - errors, the posted article will be made available on the server 163.3143 - and/or transferred to other servers, as appropriate, possibly 163.3144 - following further processing. In other words, articles not wanted by 163.3145 - the server SHOULD be rejected with a 441 response, rather than being 163.3146 - accepted and then discarded silently. However, the client SHOULD NOT 163.3147 - assume that the article has been successfully transferred unless it 163.3148 - receives an affirmative response from the server and SHOULD NOT 163.3149 - assume that it is being made available to other clients without 163.3150 - explicitly checking (for example, using the STAT command). 163.3151 - 163.3152 - If the session is interrupted before the response is received, it is 163.3153 - possible that an affirmative response was sent but has been lost. 163.3154 - Therefore, in any subsequent session, the client SHOULD either check 163.3155 - whether the article was successfully posted before resending or 163.3156 - ensure that the server will allocate the same message-id to the new 163.3157 - attempt (see Appendix A.2). The latter approach is preferred since 163.3158 - the article might not have been made available for reading yet (for 163.3159 - example, it may have to go through a moderation process). 163.3160 - 163.3161 -6.3.1.3. Examples 163.3162 - 163.3163 - Example of a successful posting: 163.3164 - 163.3165 - [C] POST 163.3166 - [S] 340 Input article; end with <CR-LF>.<CR-LF> 163.3167 - [C] From: "Demo User" <nobody@example.net> 163.3168 - [C] Newsgroups: misc.test 163.3169 - [C] Subject: I am just a test article 163.3170 - [C] Organization: An Example Net 163.3171 - [C] 163.3172 - [C] This is just a test article. 163.3173 - [C] . 163.3174 - [S] 240 Article received OK 163.3175 - 163.3176 - Example of an unsuccessful posting: 163.3177 - 163.3178 - [C] POST 163.3179 - [S] 340 Input article; end with <CR-LF>.<CR-LF> 163.3180 - [C] From: "Demo User" <nobody@example.net> 163.3181 - [C] Newsgroups: misc.test 163.3182 - [C] Subject: I am just a test article 163.3183 - [C] Organization: An Example Net 163.3184 - [C] 163.3185 - [C] This is just a test article. 163.3186 - [C] . 163.3187 - [S] 441 Posting failed 163.3188 - 163.3189 - 163.3190 - 163.3191 - 163.3192 -Feather Standards Track [Page 57] 163.3193 - 163.3194 -RFC 3977 Network News Transfer Protocol (NNTP) October 2006 163.3195 - 163.3196 - 163.3197 - Example of an attempt to post when posting is not allowed: 163.3198 - 163.3199 - [Initial connection set-up completed.] 163.3200 - [S] 201 NNTP Service Ready, posting prohibited 163.3201 - [C] POST 163.3202 - [S] 440 Posting not permitted 163.3203 - 163.3204 -6.3.2. IHAVE 163.3205 - 163.3206 -6.3.2.1. Usage 163.3207 - 163.3208 - Indicating capability: IHAVE 163.3209 - 163.3210 - This command MUST NOT be pipelined. 163.3211 - 163.3212 - Syntax 163.3213 - IHAVE message-id 163.3214 - 163.3215 - Responses 163.3216 - 163.3217 - Initial responses 163.3218 - 335 Send article to be transferred 163.3219 - 435 Article not wanted 163.3220 - 436 Transfer not possible; try again later 163.3221 - 163.3222 - Subsequent responses 163.3223 - 235 Article transferred OK 163.3224 - 436 Transfer failed; try again later 163.3225 - 437 Transfer rejected; do not retry 163.3226 - 163.3227 - Parameters 163.3228 - message-id Article message-id 163.3229 - 163.3230 -6.3.2.2. Description 163.3231 - 163.3232 - The IHAVE command informs the server that the client has an article 163.3233 - with the specified message-id. If the server desires a copy of that 163.3234 - article, a 335 response MUST be returned, instructing the client to 163.3235 - send the entire article. If the server does not want the article 163.3236 - (if, for example, the server already has a copy of it), a 435 163.3237 - response MUST be returned, indicating that the article is not wanted. 163.3238 - Finally, if the article isn't wanted immediately but the client 163.3239 - should retry later if possible (if, for example, another client is in 163.3240 - the process of sending the same article to the server), a 436 163.3241 - response MUST be returned. 163.3242 - 163.3243 - 163.3244 - 163.3245 - 163.3246 - 163.3247 - 163.3248 -Feather Standards Track [Page 58] 163.3249 - 163.3250 -RFC 3977 Network News Transfer Protocol (NNTP) October 2006 163.3251 - 163.3252 - 163.3253 - If transmission of the article is requested, the client MUST send the 163.3254 - entire article, including headers and body, to the server as a 163.3255 - multi-line data block (see Section 3.1.1). Thus, a single dot (".") 163.3256 - on a line indicates the end of the text, and lines starting with a 163.3257 - dot in the original text have that dot doubled during transmission. 163.3258 - The server MUST return a 235 response, indicating that the article 163.3259 - was successfully transferred; a 436 response, indicating that the 163.3260 - transfer failed but should be tried again later; or a 437 response, 163.3261 - indicating that the article was rejected. 163.3262 - 163.3263 - This function differs from the POST command in that it is intended 163.3264 - for use in transferring already-posted articles between hosts. It 163.3265 - SHOULD NOT be used when the client is a personal news-reading 163.3266 - program, since use of this command indicates that the article has 163.3267 - already been posted at another site and is simply being forwarded 163.3268 - from another host. However, despite this, the server MAY elect not 163.3269 - to post or forward the article if, after further examination of the 163.3270 - article, it deems it inappropriate to do so. Reasons for such 163.3271 - subsequent rejection of an article may include problems such as 163.3272 - inappropriate newsgroups or distributions, disc space limitations, 163.3273 - article lengths, garbled headers, and the like. These are typically 163.3274 - restrictions enforced by the server host's news software and not 163.3275 - necessarily by the NNTP server itself. 163.3276 - 163.3277 - The client SHOULD NOT assume that the article has been successfully 163.3278 - transferred unless it receives an affirmative response from the 163.3279 - server. A lack of response (such as a dropped network connection or 163.3280 - a network timeout) SHOULD be treated the same as a 436 response. 163.3281 - 163.3282 - Because some news server software may not immediately be able to 163.3283 - determine whether an article is suitable for posting or forwarding, 163.3284 - an NNTP server MAY acknowledge the successful transfer of the article 163.3285 - (with a 235 response) but later silently discard it. 163.3286 - 163.3287 - 163.3288 - 163.3289 - 163.3290 - 163.3291 - 163.3292 - 163.3293 - 163.3294 - 163.3295 - 163.3296 - 163.3297 - 163.3298 - 163.3299 - 163.3300 - 163.3301 - 163.3302 - 163.3303 - 163.3304 -Feather Standards Track [Page 59] 163.3305 - 163.3306 -RFC 3977 Network News Transfer Protocol (NNTP) October 2006 163.3307 - 163.3308 - 163.3309 -6.3.2.3. Examples 163.3310 - 163.3311 - Example of successfully sending an article to another site: 163.3312 - 163.3313 - [C] IHAVE <i.am.an.article.you.will.want@example.com> 163.3314 - [S] 335 Send it; end with <CR-LF>.<CR-LF> 163.3315 - [C] Path: pathost!demo!somewhere!not-for-mail 163.3316 - [C] From: "Demo User" <nobody@example.com> 163.3317 - [C] Newsgroups: misc.test 163.3318 - [C] Subject: I am just a test article 163.3319 - [C] Date: 6 Oct 1998 04:38:40 -0500 163.3320 - [C] Organization: An Example Com, San Jose, CA 163.3321 - [C] Message-ID: <i.am.an.article.you.will.want@example.com> 163.3322 - [C] 163.3323 - [C] This is just a test article. 163.3324 - [C] . 163.3325 - [S] 235 Article transferred OK 163.3326 - 163.3327 - Example of sending an article to another site that rejects it. Note 163.3328 - that the message-id in the IHAVE command is not the same as the one 163.3329 - in the article headers; while this is bad practice and SHOULD NOT be 163.3330 - done, it is not forbidden. 163.3331 - 163.3332 - [C] IHAVE <i.am.an.article.you.will.want@example.com> 163.3333 - [S] 335 Send it; end with <CR-LF>.<CR-LF> 163.3334 - [C] Path: pathost!demo!somewhere!not-for-mail 163.3335 - [C] From: "Demo User" <nobody@example.com> 163.3336 - [C] Newsgroups: misc.test 163.3337 - [C] Subject: I am just a test article 163.3338 - [C] Date: 6 Oct 1998 04:38:40 -0500 163.3339 - [C] Organization: An Example Com, San Jose, CA 163.3340 - [C] Message-ID: <i.am.an.article.you.have@example.com> 163.3341 - [C] 163.3342 - [C] This is just a test article. 163.3343 - [C] . 163.3344 - [S] 437 Article rejected; don't send again 163.3345 - 163.3346 - 163.3347 - 163.3348 - 163.3349 - 163.3350 - 163.3351 - 163.3352 - 163.3353 - 163.3354 - 163.3355 - 163.3356 - 163.3357 - 163.3358 - 163.3359 - 163.3360 -Feather Standards Track [Page 60] 163.3361 - 163.3362 -RFC 3977 Network News Transfer Protocol (NNTP) October 2006 163.3363 - 163.3364 - 163.3365 - Example of sending an article to another site where the transfer 163.3366 - fails: 163.3367 - 163.3368 - [C] IHAVE <i.am.an.article.you.will.want@example.com> 163.3369 - [S] 335 Send it; end with <CR-LF>.<CR-LF> 163.3370 - [C] Path: pathost!demo!somewhere!not-for-mail 163.3371 - [C] From: "Demo User" <nobody@example.com> 163.3372 - [C] Newsgroups: misc.test 163.3373 - [C] Subject: I am just a test article 163.3374 - [C] Date: 6 Oct 1998 04:38:40 -0500 163.3375 - [C] Organization: An Example Com, San Jose, CA 163.3376 - [C] Message-ID: <i.am.an.article.you.will.want@example.com> 163.3377 - [C] 163.3378 - [C] This is just a test article. 163.3379 - [C] . 163.3380 - [S] 436 Transfer failed 163.3381 - 163.3382 - Example of sending an article to a site that already has it: 163.3383 - 163.3384 - [C] IHAVE <i.am.an.article.you.have@example.com> 163.3385 - [S] 435 Duplicate 163.3386 - 163.3387 - Example of sending an article to a site that requests that the 163.3388 - article be tried again later: 163.3389 - 163.3390 - [C] IHAVE <i.am.an.article.you.defer@example.com> 163.3391 - [S] 436 Retry later 163.3392 - 163.3393 -7. Information Commands 163.3394 - 163.3395 - This section lists other commands that may be used at any time 163.3396 - between the beginning of a session and its termination. Using these 163.3397 - commands does not alter any state information, but the response 163.3398 - generated from their use may provide useful information to clients. 163.3399 - 163.3400 -7.1. DATE 163.3401 - 163.3402 -7.1.1. Usage 163.3403 - 163.3404 - Indicating capability: READER 163.3405 - 163.3406 - Syntax 163.3407 - DATE 163.3408 - 163.3409 - Responses 163.3410 - 111 yyyymmddhhmmss Server date and time 163.3411 - 163.3412 - 163.3413 - 163.3414 - 163.3415 - 163.3416 -Feather Standards Track [Page 61] 163.3417 - 163.3418 -RFC 3977 Network News Transfer Protocol (NNTP) October 2006 163.3419 - 163.3420 - 163.3421 - Parameters 163.3422 - yyyymmddhhmmss Current UTC date and time on server 163.3423 - 163.3424 -7.1.2. Description 163.3425 - 163.3426 - This command exists to help clients find out the current Coordinated 163.3427 - Universal Time [TF.686-1] from the server's perspective. This 163.3428 - command SHOULD NOT be used as a substitute for NTP [RFC1305] but to 163.3429 - provide information that might be useful when using the NEWNEWS 163.3430 - command (see Section 7.4). 163.3431 - 163.3432 - The DATE command MUST return a timestamp from the same clock as is 163.3433 - used for determining article arrival and group creation times (see 163.3434 - Section 6). This clock SHOULD be monotonic, and adjustments SHOULD 163.3435 - be made by running it fast or slow compared to "real" time rather 163.3436 - than by making sudden jumps. A system providing NNTP service SHOULD 163.3437 - keep the system clock as accurate as possible, either with NTP or by 163.3438 - some other method. 163.3439 - 163.3440 - The server MUST return a 111 response specifying the date and time on 163.3441 - the server in the form yyyymmddhhmmss. This date and time is in 163.3442 - Coordinated Universal Time. 163.3443 - 163.3444 -7.1.3. Examples 163.3445 - 163.3446 - [C] DATE 163.3447 - [S] 111 19990623135624 163.3448 - 163.3449 -7.2. HELP 163.3450 - 163.3451 -7.2.1. Usage 163.3452 - 163.3453 - This command is mandatory. 163.3454 - 163.3455 - Syntax 163.3456 - HELP 163.3457 - 163.3458 - Responses 163.3459 - 100 Help text follows (multi-line) 163.3460 - 163.3461 -7.2.2. Description 163.3462 - 163.3463 - This command provides a short summary of the commands that are 163.3464 - understood by this implementation of the server. The help text will 163.3465 - be presented as a multi-line data block following the 100 response 163.3466 - code. 163.3467 - 163.3468 - 163.3469 - 163.3470 - 163.3471 - 163.3472 -Feather Standards Track [Page 62] 163.3473 - 163.3474 -RFC 3977 Network News Transfer Protocol (NNTP) October 2006 163.3475 - 163.3476 - 163.3477 - This text is not guaranteed to be in any particular format (but must 163.3478 - be UTF-8) and MUST NOT be used by clients as a replacement for the 163.3479 - CAPABILITIES command described in Section 5.2. 163.3480 - 163.3481 -7.2.3. Examples 163.3482 - 163.3483 - [C] HELP 163.3484 - [S] 100 Help text follows 163.3485 - [S] This is some help text. There is no specific 163.3486 - [S] formatting requirement for this test, though 163.3487 - [S] it is customary for it to list the valid commands 163.3488 - [S] and give a brief definition of what they do. 163.3489 - [S] . 163.3490 - 163.3491 -7.3. NEWGROUPS 163.3492 - 163.3493 -7.3.1. Usage 163.3494 - 163.3495 - Indicating capability: READER 163.3496 - 163.3497 - Syntax 163.3498 - NEWGROUPS date time [GMT] 163.3499 - 163.3500 - Responses 163.3501 - 231 List of new newsgroups follows (multi-line) 163.3502 - 163.3503 - Parameters 163.3504 - date Date in yymmdd or yyyymmdd format 163.3505 - time Time in hhmmss format 163.3506 - 163.3507 -7.3.2. Description 163.3508 - 163.3509 - This command returns a list of newsgroups created on the server since 163.3510 - the specified date and time. The results are in the same format as 163.3511 - the LIST ACTIVE command (see Section 7.6.3). However, they MAY 163.3512 - include groups not available on the server (and so not returned by 163.3513 - LIST ACTIVE) and MAY omit groups for which the creation date is not 163.3514 - available. 163.3515 - 163.3516 - The date is specified as 6 or 8 digits in the format [xx]yymmdd, 163.3517 - where xx is the first two digits of the year (19-99), yy is the last 163.3518 - two digits of the year (00-99), mm is the month (01-12), and dd is 163.3519 - the day of the month (01-31). Clients SHOULD specify all four digits 163.3520 - of the year. If the first two digits of the year are not specified 163.3521 - (this is supported only for backward compatibility), the year is to 163.3522 - be taken from the current century if yy is smaller than or equal to 163.3523 - the current year, and the previous century otherwise. 163.3524 - 163.3525 - 163.3526 - 163.3527 - 163.3528 -Feather Standards Track [Page 63] 163.3529 - 163.3530 -RFC 3977 Network News Transfer Protocol (NNTP) October 2006 163.3531 - 163.3532 - 163.3533 - The time is specified as 6 digits in the format hhmmss, where hh is 163.3534 - the hours in the 24-hour clock (00-23), mm is the minutes (00-59), 163.3535 - and ss is the seconds (00-60, to allow for leap seconds). The token 163.3536 - "GMT" specifies that the date and time are given in Coordinated 163.3537 - Universal Time [TF.686-1]; if it is omitted, then the date and time 163.3538 - are specified in the server's local timezone. Note that there is no 163.3539 - way of using the protocol specified in this document to establish the 163.3540 - server's local timezone. 163.3541 - 163.3542 - Note that an empty list is a possible valid response and indicates 163.3543 - that there are no new newsgroups since that date-time. 163.3544 - 163.3545 - Clients SHOULD make all queries using Coordinated Universal Time 163.3546 - (i.e., by including the "GMT" argument) when possible. 163.3547 - 163.3548 -7.3.3. Examples 163.3549 - 163.3550 - Example where there are new groups: 163.3551 - 163.3552 - [C] NEWGROUPS 19990624 000000 GMT 163.3553 - [S] 231 list of new newsgroups follows 163.3554 - [S] alt.rfc-writers.recovery 4 1 y 163.3555 - [S] tx.natives.recovery 89 56 y 163.3556 - [S] . 163.3557 - 163.3558 - Example where there are no new groups: 163.3559 - 163.3560 - [C] NEWGROUPS 19990624 000000 GMT 163.3561 - [S] 231 list of new newsgroups follows 163.3562 - [S] . 163.3563 - 163.3564 -7.4. NEWNEWS 163.3565 - 163.3566 -7.4.1. Usage 163.3567 - 163.3568 - Indicating capability: NEWNEWS 163.3569 - 163.3570 - Syntax 163.3571 - NEWNEWS wildmat date time [GMT] 163.3572 - 163.3573 - Responses 163.3574 - 230 List of new articles follows (multi-line) 163.3575 - 163.3576 - Parameters 163.3577 - wildmat Newsgroups of interest 163.3578 - date Date in yymmdd or yyyymmdd format 163.3579 - time Time in hhmmss format 163.3580 - 163.3581 - 163.3582 - 163.3583 - 163.3584 -Feather Standards Track [Page 64] 163.3585 - 163.3586 -RFC 3977 Network News Transfer Protocol (NNTP) October 2006 163.3587 - 163.3588 - 163.3589 -7.4.2. Description 163.3590 - 163.3591 - This command returns a list of message-ids of articles posted or 163.3592 - received on the server, in the newsgroups whose names match the 163.3593 - wildmat, since the specified date and time. One message-id is sent 163.3594 - on each line; the order of the response has no specific significance 163.3595 - and may vary from response to response in the same session. A 163.3596 - message-id MAY appear more than once; if it does, it has the same 163.3597 - meaning as if it appeared only once. 163.3598 - 163.3599 - Date and time are in the same format as the NEWGROUPS command (see 163.3600 - Section 7.3). 163.3601 - 163.3602 - Note that an empty list is a possible valid response and indicates 163.3603 - that there is currently no new news in the relevant groups. 163.3604 - 163.3605 - Clients SHOULD make all queries in Coordinated Universal Time (i.e., 163.3606 - by using the "GMT" argument) when possible. 163.3607 - 163.3608 -7.4.3. Examples 163.3609 - 163.3610 - Example where there are new articles: 163.3611 - 163.3612 - [C] NEWNEWS news.*,sci.* 19990624 000000 GMT 163.3613 - [S] 230 list of new articles by message-id follows 163.3614 - [S] <i.am.a.new.article@example.com> 163.3615 - [S] <i.am.another.new.article@example.com> 163.3616 - [S] . 163.3617 - 163.3618 - Example where there are no new articles: 163.3619 - 163.3620 - [C] NEWNEWS alt.* 19990624 000000 GMT 163.3621 - [S] 230 list of new articles by message-id follows 163.3622 - [S] . 163.3623 - 163.3624 -7.5. Time 163.3625 - 163.3626 - As described in Section 6, each article has an arrival timestamp. 163.3627 - Each newsgroup also has a creation timestamp. These timestamps are 163.3628 - used by the NEWNEWS and NEWGROUP commands to construct their 163.3629 - responses. 163.3630 - 163.3631 - Clients can ensure that they do not have gaps in lists of articles or 163.3632 - groups by using the DATE command in the following manner: 163.3633 - 163.3634 - First session: 163.3635 - Issue DATE command and record result. 163.3636 - Issue NEWNEWS command using a previously chosen timestamp. 163.3637 - 163.3638 - 163.3639 - 163.3640 -Feather Standards Track [Page 65] 163.3641 - 163.3642 -RFC 3977 Network News Transfer Protocol (NNTP) October 2006 163.3643 - 163.3644 - 163.3645 - Subsequent sessions: 163.3646 - Issue DATE command and hold result in temporary storage. 163.3647 - Issue NEWNEWS command using timestamp saved from previous session. 163.3648 - Overwrite saved timestamp with that currently in temporary 163.3649 - storage. 163.3650 - 163.3651 - In order to allow for minor errors, clients MAY want to adjust the 163.3652 - timestamp back by two or three minutes before using it in NEWNEWS. 163.3653 - 163.3654 -7.5.1. Examples 163.3655 - 163.3656 - First session: 163.3657 - 163.3658 - [C] DATE 163.3659 - [S] 111 20010203112233 163.3660 - [C] NEWNEWS local.chat 20001231 235959 GMT 163.3661 - [S] 230 list follows 163.3662 - [S] <article.1@local.service> 163.3663 - [S] <article.2@local.service> 163.3664 - [S] <article.3@local.service> 163.3665 - [S] . 163.3666 - 163.3667 - Second session (the client has subtracted 3 minutes from the 163.3668 - timestamp returned previously): 163.3669 - 163.3670 - [C] DATE 163.3671 - [S] 111 20010204003344 163.3672 - [C] NEWNEWS local.chat 20010203 111933 GMT 163.3673 - [S] 230 list follows 163.3674 - [S] <article.3@local.service> 163.3675 - [S] <article.4@local.service> 163.3676 - [S] <article.5@local.service> 163.3677 - [S] . 163.3678 - 163.3679 - Note how <article.3@local.service> arrived in the 3 minute gap and so 163.3680 - is listed in both responses. 163.3681 - 163.3682 -7.6. The LIST Commands 163.3683 - 163.3684 - The LIST family of commands all return information that is multi-line 163.3685 - and that can, in general, be expected not to change during the 163.3686 - session. Often the information is related to newsgroups, in which 163.3687 - case the response has one line per newsgroup and a wildmat MAY be 163.3688 - provided to restrict the groups for which information is returned. 163.3689 - 163.3690 - The set of available keywords (including those provided by 163.3691 - extensions) is given in the capability list with capability label 163.3692 - LIST. 163.3693 - 163.3694 - 163.3695 - 163.3696 -Feather Standards Track [Page 66] 163.3697 - 163.3698 -RFC 3977 Network News Transfer Protocol (NNTP) October 2006 163.3699 - 163.3700 - 163.3701 -7.6.1. LIST 163.3702 - 163.3703 -7.6.1.1. Usage 163.3704 - 163.3705 - Indicating capability: LIST 163.3706 - 163.3707 - Syntax 163.3708 - LIST [keyword [wildmat|argument]] 163.3709 - 163.3710 - Responses 163.3711 - 215 Information follows (multi-line) 163.3712 - 163.3713 - Parameters 163.3714 - keyword Information requested [1] 163.3715 - argument Specific to keyword 163.3716 - wildmat Groups of interest 163.3717 - 163.3718 - [1] If no keyword is provided, it defaults to ACTIVE. 163.3719 - 163.3720 -7.6.1.2. Description 163.3721 - 163.3722 - The LIST command allows the server to provide blocks of information 163.3723 - to the client. This information may be global or may be related to 163.3724 - newsgroups; in the latter case, the information may be returned 163.3725 - either for all groups or only for those matching a wildmat. Each 163.3726 - block of information is represented by a different keyword. The 163.3727 - command returns the specific information identified by the keyword. 163.3728 - 163.3729 - If the information is available, it is returned as a multi-line data 163.3730 - block following the 215 response code. The format of the information 163.3731 - depends on the keyword. The information MAY be affected by the 163.3732 - additional argument, but the format MUST NOT be. 163.3733 - 163.3734 - If the information is based on newsgroups and the optional wildmat 163.3735 - argument is specified, the response is limited to only the groups (if 163.3736 - any) whose names match the wildmat and for which the information is 163.3737 - available. 163.3738 - 163.3739 - Note that an empty list is a possible valid response; for a 163.3740 - newsgroup-based keyword, it indicates that there are no groups 163.3741 - meeting the above criteria. 163.3742 - 163.3743 - If the keyword is not recognised, or if an argument is specified and 163.3744 - the keyword does not expect one, a 501 response code MUST BE 163.3745 - returned. If the keyword is recognised but the server does not 163.3746 - maintain the information, a 503 response code MUST BE returned. 163.3747 - 163.3748 - 163.3749 - 163.3750 - 163.3751 - 163.3752 -Feather Standards Track [Page 67] 163.3753 - 163.3754 -RFC 3977 Network News Transfer Protocol (NNTP) October 2006 163.3755 - 163.3756 - 163.3757 - The LIST command MUST NOT change the visible state of the server in 163.3758 - any way; that is, the behaviour of subsequent commands MUST NOT be 163.3759 - affected by whether the LIST command was issued. For example, it 163.3760 - MUST NOT make groups available that otherwise would not have been. 163.3761 - 163.3762 -7.6.1.3. Examples 163.3763 - 163.3764 - Example of LIST with the ACTIVE keyword: 163.3765 - 163.3766 - [C] LIST ACTIVE 163.3767 - [S] 215 list of newsgroups follows 163.3768 - [S] misc.test 3002322 3000234 y 163.3769 - [S] comp.risks 442001 441099 m 163.3770 - [S] alt.rfc-writers.recovery 4 1 y 163.3771 - [S] tx.natives.recovery 89 56 y 163.3772 - [S] tx.natives.recovery.d 11 9 n 163.3773 - [S] . 163.3774 - 163.3775 - Example of LIST with no keyword: 163.3776 - 163.3777 - [C] LIST 163.3778 - [S] 215 list of newsgroups follows 163.3779 - [S] misc.test 3002322 3000234 y 163.3780 - [S] comp.risks 442001 441099 m 163.3781 - [S] alt.rfc-writers.recovery 4 1 y 163.3782 - [S] tx.natives.recovery 89 56 y 163.3783 - [S] tx.natives.recovery.d 11 9 n 163.3784 - [S] . 163.3785 - 163.3786 - The output is identical to that of the previous example. 163.3787 - 163.3788 - Example of LIST on a newsgroup-based keyword with and without 163.3789 - wildmat: 163.3790 - 163.3791 - [C] LIST ACTIVE.TIMES 163.3792 - [S] 215 information follows 163.3793 - [S] misc.test 930445408 <creatme@isc.org> 163.3794 - [S] alt.rfc-writers.recovery 930562309 <m@example.com> 163.3795 - [S] tx.natives.recovery 930678923 <sob@academ.com> 163.3796 - [S] . 163.3797 - [C] LIST ACTIVE.TIMES tx.* 163.3798 - [S] 215 information follows 163.3799 - [S] tx.natives.recovery 930678923 <sob@academ.com> 163.3800 - [S] . 163.3801 - 163.3802 - 163.3803 - 163.3804 - 163.3805 - 163.3806 - 163.3807 - 163.3808 -Feather Standards Track [Page 68] 163.3809 - 163.3810 -RFC 3977 Network News Transfer Protocol (NNTP) October 2006 163.3811 - 163.3812 - 163.3813 - Example of LIST returning an error where the keyword is recognized 163.3814 - but the software does not maintain this information: 163.3815 - 163.3816 - [C] CAPABILITIES 163.3817 - [S] 101 Capability list: 163.3818 - [S] VERSION 2 163.3819 - [S] READER 163.3820 - [S] LIST ACTIVE NEWSGROUPS ACTIVE.TIMES XTRA.DATA 163.3821 - [S] . 163.3822 - [C] LIST XTRA.DATA 163.3823 - [S] 503 Data item not stored 163.3824 - 163.3825 - Example of LIST where the keyword is not recognised: 163.3826 - 163.3827 - [C] CAPABILITIES 163.3828 - [S] 101 Capability list: 163.3829 - [S] VERSION 2 163.3830 - [S] READER 163.3831 - [S] LIST ACTIVE NEWSGROUPS ACTIVE.TIMES XTRA.DATA 163.3832 - [S] . 163.3833 - [C] LIST DISTRIB.PATS 163.3834 - [S] 501 Syntax Error 163.3835 - 163.3836 -7.6.2. Standard LIST Keywords 163.3837 - 163.3838 - This specification defines the following LIST keywords: 163.3839 - 163.3840 - +--------------+---------------+------------------------------------+ 163.3841 - | Keyword | Definition | Status | 163.3842 - +--------------+---------------+------------------------------------+ 163.3843 - | ACTIVE | Section 7.6.3 | Mandatory if the READER capability | 163.3844 - | | | is advertised | 163.3845 - | | | | 163.3846 - | ACTIVE.TIMES | Section 7.6.4 | Optional | 163.3847 - | | | | 163.3848 - | DISTRIB.PATS | Section 7.6.5 | Optional | 163.3849 - | | | | 163.3850 - | HEADERS | Section 8.6 | Mandatory if the HDR capability is | 163.3851 - | | | advertised | 163.3852 - | | | | 163.3853 - | NEWSGROUPS | Section 7.6.6 | Mandatory if the READER capability | 163.3854 - | | | is advertised | 163.3855 - | | | | 163.3856 - | OVERVIEW.FMT | Section 8.4 | Mandatory if the OVER capability | 163.3857 - | | | is advertised | 163.3858 - +--------------+---------------+------------------------------------+ 163.3859 - 163.3860 - 163.3861 - 163.3862 - 163.3863 - 163.3864 -Feather Standards Track [Page 69] 163.3865 - 163.3866 -RFC 3977 Network News Transfer Protocol (NNTP) October 2006 163.3867 - 163.3868 - 163.3869 - Where one of these LIST keywords is supported by a server, it MUST 163.3870 - have the meaning given in the relevant sub-section. 163.3871 - 163.3872 -7.6.3. LIST ACTIVE 163.3873 - 163.3874 - This keyword MUST be supported by servers advertising the READER 163.3875 - capability. 163.3876 - 163.3877 - LIST ACTIVE returns a list of valid newsgroups and associated 163.3878 - information. If no wildmat is specified, the server MUST include 163.3879 - every group that the client is permitted to select with the GROUP 163.3880 - command (Section 6.1.1). Each line of this list consists of four 163.3881 - fields separated from each other by one or more spaces: 163.3882 - 163.3883 - o The name of the newsgroup. 163.3884 - o The reported high water mark for the group. 163.3885 - o The reported low water mark for the group. 163.3886 - o The current status of the group on this server. 163.3887 - 163.3888 - The reported high and low water marks are as described in the GROUP 163.3889 - command (see Section 6.1.1), but note that they are in the opposite 163.3890 - order to the 211 response to that command. 163.3891 - 163.3892 - The status field is typically one of the following: 163.3893 - 163.3894 - "y" Posting is permitted. 163.3895 - 163.3896 - "n" Posting is not permitted. 163.3897 - 163.3898 - "m" Postings will be forwarded to the newsgroup moderator. 163.3899 - 163.3900 - The server SHOULD use these values when these meanings are required 163.3901 - and MUST NOT use them with any other meaning. Other values for the 163.3902 - status may exist; the definition of these other values and the 163.3903 - circumstances under which they are returned may be specified in an 163.3904 - extension or may be private to the server. A client SHOULD treat an 163.3905 - unrecognized status as giving no information. 163.3906 - 163.3907 - The status of a newsgroup only indicates how posts to that newsgroup 163.3908 - are normally processed and is not necessarily customised to the 163.3909 - specific client. For example, if the current client is forbidden 163.3910 - from posting, then this will apply equally to groups with status "y". 163.3911 - Conversely, a client with special privileges (not defined by this 163.3912 - specification) might be able to post to a group with status "n". 163.3913 - 163.3914 - 163.3915 - 163.3916 - 163.3917 - 163.3918 - 163.3919 - 163.3920 -Feather Standards Track [Page 70] 163.3921 - 163.3922 -RFC 3977 Network News Transfer Protocol (NNTP) October 2006 163.3923 - 163.3924 - 163.3925 - For example: 163.3926 - 163.3927 - [C] LIST ACTIVE 163.3928 - [S] 215 list of newsgroups follows 163.3929 - [S] misc.test 3002322 3000234 y 163.3930 - [S] comp.risks 442001 441099 m 163.3931 - [S] alt.rfc-writers.recovery 4 1 y 163.3932 - [S] tx.natives.recovery 89 56 y 163.3933 - [S] tx.natives.recovery.d 11 9 n 163.3934 - [S] . 163.3935 - 163.3936 - or, on an implementation that includes leading zeroes: 163.3937 - 163.3938 - [C] LIST ACTIVE 163.3939 - [S] 215 list of newsgroups follows 163.3940 - [S] misc.test 0003002322 0003000234 y 163.3941 - [S] comp.risks 0000442001 0000441099 m 163.3942 - [S] alt.rfc-writers.recovery 0000000004 0000000001 y 163.3943 - [S] tx.natives.recovery 0000000089 0000000056 y 163.3944 - [S] tx.natives.recovery.d 0000000011 0000000009 n 163.3945 - [S] . 163.3946 - 163.3947 - The information is newsgroup based, and a wildmat MAY be specified, 163.3948 - in which case the response is limited to only the groups (if any) 163.3949 - whose names match the wildmat. For example: 163.3950 - 163.3951 - [C] LIST ACTIVE *.recovery 163.3952 - [S] 215 list of newsgroups follows 163.3953 - [S] alt.rfc-writers.recovery 4 1 y 163.3954 - [S] tx.natives.recovery 89 56 y 163.3955 - [S] . 163.3956 - 163.3957 -7.6.4. LIST ACTIVE.TIMES 163.3958 - 163.3959 - This keyword is optional. 163.3960 - 163.3961 - The active.times list is maintained by some NNTP servers to contain 163.3962 - information about who created a particular newsgroup and when. Each 163.3963 - line of this list consists of three fields separated from each other 163.3964 - by one or more spaces. The first field is the name of the newsgroup. 163.3965 - The second is the time when this group was created on this news 163.3966 - server, measured in seconds since the start of January 1, 1970. The 163.3967 - third is plain text intended to describe the entity that created the 163.3968 - newsgroup; it is often a mailbox as defined in RFC 2822 [RFC2822]. 163.3969 - For example: 163.3970 - 163.3971 - 163.3972 - 163.3973 - 163.3974 - 163.3975 - 163.3976 -Feather Standards Track [Page 71] 163.3977 - 163.3978 -RFC 3977 Network News Transfer Protocol (NNTP) October 2006 163.3979 - 163.3980 - 163.3981 - [C] LIST ACTIVE.TIMES 163.3982 - [S] 215 information follows 163.3983 - [S] misc.test 930445408 <creatme@isc.org> 163.3984 - [S] alt.rfc-writers.recovery 930562309 <m@example.com> 163.3985 - [S] tx.natives.recovery 930678923 <sob@academ.com> 163.3986 - [S] . 163.3987 - 163.3988 - The list MAY omit newsgroups for which the information is unavailable 163.3989 - and MAY include groups not available on the server; in particular, it 163.3990 - MAY omit all groups created before the date and time of the oldest 163.3991 - entry. The client MUST NOT assume that the list is complete or that 163.3992 - it matches the list returned by the LIST ACTIVE command 163.3993 - (Section 7.6.3). The NEWGROUPS command (Section 7.3) may provide a 163.3994 - better way to access this information, and the results of the two 163.3995 - commands SHOULD be consistent except that, if the latter is invoked 163.3996 - with a date and time earlier than the oldest entry in active.times 163.3997 - list, its result may include extra groups. 163.3998 - 163.3999 - The information is newsgroup based, and a wildmat MAY be specified, 163.4000 - in which case the response is limited to only the groups (if any) 163.4001 - whose names match the wildmat. 163.4002 - 163.4003 -7.6.5. LIST DISTRIB.PATS 163.4004 - 163.4005 - This keyword is optional. 163.4006 - 163.4007 - The distrib.pats list is maintained by some NNTP servers to assist 163.4008 - clients to choose a value for the content of the Distribution header 163.4009 - of a news article being posted. Each line of this list consists of 163.4010 - three fields separated from each other by a colon (":"). The first 163.4011 - field is a weight, the second field is a wildmat (which may be a 163.4012 - simple newsgroup name), and the third field is a value for the 163.4013 - Distribution header content. For example: 163.4014 - 163.4015 - [C] LIST DISTRIB.PATS 163.4016 - [S] 215 information follows 163.4017 - [S] 10:local.*:local 163.4018 - [S] 5:*:world 163.4019 - [S] 20:local.here.*:thissite 163.4020 - [S] . 163.4021 - 163.4022 - The client MAY use this information to construct an appropriate 163.4023 - Distribution header given the name of a newsgroup. To do so, it 163.4024 - should determine the lines whose second field matches the newsgroup 163.4025 - name, select from among them the line with the highest weight (with 0 163.4026 - being the lowest), and use the value of the third field to construct 163.4027 - the Distribution header. 163.4028 - 163.4029 - 163.4030 - 163.4031 - 163.4032 -Feather Standards Track [Page 72] 163.4033 - 163.4034 -RFC 3977 Network News Transfer Protocol (NNTP) October 2006 163.4035 - 163.4036 - 163.4037 - The information is not newsgroup based, and an argument MUST NOT be 163.4038 - specified. 163.4039 - 163.4040 -7.6.6. LIST NEWSGROUPS 163.4041 - 163.4042 - This keyword MUST be supported by servers advertising the READER 163.4043 - capability. 163.4044 - 163.4045 - The newsgroups list is maintained by NNTP servers to contain the name 163.4046 - of each newsgroup that is available on the server and a short 163.4047 - description about the purpose of the group. Each line of this list 163.4048 - consists of two fields separated from each other by one or more space 163.4049 - or TAB characters (the usual practice is a single TAB). The first 163.4050 - field is the name of the newsgroup, and the second is a short 163.4051 - description of the group. For example: 163.4052 - 163.4053 - [C] LIST NEWSGROUPS 163.4054 - [S] 215 information follows 163.4055 - [S] misc.test General Usenet testing 163.4056 - [S] alt.rfc-writers.recovery RFC Writers Recovery 163.4057 - [S] tx.natives.recovery Texas Natives Recovery 163.4058 - [S] . 163.4059 - 163.4060 - The list MAY omit newsgroups for which the information is unavailable 163.4061 - and MAY include groups not available on the server. The client MUST 163.4062 - NOT assume that the list is complete or that it matches the list 163.4063 - returned by LIST ACTIVE. 163.4064 - 163.4065 - The description SHOULD be in UTF-8. However, servers often obtain 163.4066 - the information from external sources. These sources may have used 163.4067 - different encodings (ones that use octets in the range 128 to 255 in 163.4068 - some other manner) and, in that case, the server MAY pass it on 163.4069 - unchanged. Therefore, clients MUST be prepared to receive such 163.4070 - descriptions. 163.4071 - 163.4072 - The information is newsgroup based, and a wildmat MAY be specified, 163.4073 - in which case the response is limited to only the groups (if any) 163.4074 - whose names match the wildmat. 163.4075 - 163.4076 -8. Article Field Access Commands 163.4077 - 163.4078 - This section lists commands that may be used to access specific 163.4079 - article fields; that is, headers of articles and metadata about 163.4080 - articles. These commands typically fetch data from an "overview 163.4081 - database", which is a database of headers extracted from incoming 163.4082 - articles plus metadata determined as the article arrives. Only 163.4083 - certain fields are included in the database. 163.4084 - 163.4085 - 163.4086 - 163.4087 - 163.4088 -Feather Standards Track [Page 73] 163.4089 - 163.4090 -RFC 3977 Network News Transfer Protocol (NNTP) October 2006 163.4091 - 163.4092 - 163.4093 - This section is based on the Overview/NOV database [ROBE1995] 163.4094 - developed by Geoff Collyer. 163.4095 - 163.4096 -8.1. Article Metadata 163.4097 - 163.4098 - Article "metadata" is data about articles that does not occur within 163.4099 - the article itself. Each metadata item has a name that MUST begin 163.4100 - with a colon (and that MUST NOT contain a colon elsewhere within it). 163.4101 - As with header names, metadata item names are not case sensitive. 163.4102 - 163.4103 - When generating a metadata item, the server MUST compute it for 163.4104 - itself and MUST NOT trust any related value provided in the article. 163.4105 - (In particular, a Lines or Bytes header in the article MUST NOT be 163.4106 - assumed to specify the correct number of lines or bytes in the 163.4107 - article.) If the server has access to several non-identical copies 163.4108 - of an article, the value returned MUST be correct for any copy of 163.4109 - that article retrieved during the same session. 163.4110 - 163.4111 - This specification defines two metadata items: ":bytes" and ":lines". 163.4112 - Other metadata items may be defined by extensions. The names of 163.4113 - metadata items defined by registered extensions MUST NOT begin with 163.4114 - ":x-". To avoid the risk of a clash with a future registered 163.4115 - extension, the names of metadata items defined by private extensions 163.4116 - SHOULD begin with ":x-". 163.4117 - 163.4118 -8.1.1. The :bytes Metadata Item 163.4119 - 163.4120 - The :bytes metadata item for an article is a decimal integer. It 163.4121 - SHOULD equal the number of octets in the entire article: headers, 163.4122 - body, and separating empty line (counting a CRLF pair as two octets, 163.4123 - and excluding both the "." CRLF terminating the response and any "." 163.4124 - added for "dot-stuffing" purposes). 163.4125 - 163.4126 - Note to client implementers: some existing servers return a value 163.4127 - different from that above. The commonest reasons for this are as 163.4128 - follows: 163.4129 - 163.4130 - o Counting a CRLF pair as one octet. 163.4131 - 163.4132 - o Including the "." character used for dot-stuffing in the number. 163.4133 - 163.4134 - o Including the terminating "." CRLF in the number. 163.4135 - 163.4136 - o Using one copy of an article for counting the octets but then 163.4137 - returning another one that differs in some (permitted) manner. 163.4138 - 163.4139 - Implementations should be prepared for such variation and MUST NOT 163.4140 - rely on the value being accurate. 163.4141 - 163.4142 - 163.4143 - 163.4144 -Feather Standards Track [Page 74] 163.4145 - 163.4146 -RFC 3977 Network News Transfer Protocol (NNTP) October 2006 163.4147 - 163.4148 - 163.4149 -8.1.2. The :lines Metadata Item 163.4150 - 163.4151 - The :lines metadata item for an article is a decimal integer. It 163.4152 - MUST equal the number of lines in the article body (excluding the 163.4153 - empty line separating headers and body). Equivalently, it is two 163.4154 - less than the number of CRLF pairs that the BODY command would return 163.4155 - for that article (the extra two are those following the response code 163.4156 - and the termination octet). 163.4157 - 163.4158 -8.2. Database Consistency 163.4159 - 163.4160 - The information stored in the overview database may change over time. 163.4161 - If the database records the content or absence of a given field (that 163.4162 - is, a header or metadata item) for all articles, it is said to be 163.4163 - "consistent" for that field. If it records the content of a header 163.4164 - for some articles but not for others that nevertheless included that 163.4165 - header, or if it records a metadata item for some articles but not 163.4166 - for others to which that item applies, it is said to be 163.4167 - "inconsistent" for that field. 163.4168 - 163.4169 - The LIST OVERVIEW.FMT command SHOULD list all the fields for which 163.4170 - the database is consistent at that moment. It MAY omit such fields 163.4171 - (for example, if it is not known whether the database is consistent 163.4172 - or inconsistent). It MUST NOT include fields for which the database 163.4173 - is inconsistent or that are not stored in the database. Therefore, 163.4174 - if a header appears in the LIST OVERVIEW.FMT output but not in the 163.4175 - OVER output for a given article, that header does not appear in the 163.4176 - article (similarly for metadata items). 163.4177 - 163.4178 - These rules assume that the fields being stored in the database 163.4179 - remain constant for long periods of time, and therefore the database 163.4180 - will be consistent. When the set of fields to be stored is changed, 163.4181 - it will be inconsistent until either the database is rebuilt or the 163.4182 - only articles remaining are those received since the change. 163.4183 - Therefore, the output from LIST OVERVIEW.FMT needs to be altered 163.4184 - twice. Firstly, before any fields stop being stored they MUST be 163.4185 - removed from the output; then, when the database is once more known 163.4186 - to be consistent, the new fields SHOULD be added to the output. 163.4187 - 163.4188 - If the HDR command uses the overview database rather than taking 163.4189 - information directly from the articles, the same issues of 163.4190 - consistency and inconsistency apply, and the LIST HEADERS command 163.4191 - SHOULD take the same approach as the LIST OVERVIEW.FMT command in 163.4192 - resolving them. 163.4193 - 163.4194 - 163.4195 - 163.4196 - 163.4197 - 163.4198 - 163.4199 - 163.4200 -Feather Standards Track [Page 75] 163.4201 - 163.4202 -RFC 3977 Network News Transfer Protocol (NNTP) October 2006 163.4203 - 163.4204 - 163.4205 -8.3. OVER 163.4206 - 163.4207 -8.3.1. Usage 163.4208 - 163.4209 - Indicating capability: OVER 163.4210 - 163.4211 - Syntax 163.4212 - OVER message-id 163.4213 - OVER range 163.4214 - OVER 163.4215 - 163.4216 - Responses 163.4217 - 163.4218 - First form (message-id specified) 163.4219 - 224 Overview information follows (multi-line) 163.4220 - 430 No article with that message-id 163.4221 - 163.4222 - Second form (range specified) 163.4223 - 224 Overview information follows (multi-line) 163.4224 - 412 No newsgroup selected 163.4225 - 423 No articles in that range 163.4226 - 163.4227 - Third form (current article number used) 163.4228 - 224 Overview information follows (multi-line) 163.4229 - 412 No newsgroup selected 163.4230 - 420 Current article number is invalid 163.4231 - 163.4232 - Parameters 163.4233 - range Number(s) of articles 163.4234 - message-id Message-id of article 163.4235 - 163.4236 -8.3.2. Description 163.4237 - 163.4238 - The OVER command returns the contents of all the fields in the 163.4239 - database for an article specified by message-id, or from a specified 163.4240 - article or range of articles in the currently selected newsgroup. 163.4241 - 163.4242 - The message-id argument indicates a specific article. The range 163.4243 - argument may be any of the following: 163.4244 - 163.4245 - o An article number. 163.4246 - 163.4247 - o An article number followed by a dash to indicate all following. 163.4248 - 163.4249 - o An article number followed by a dash followed by another article 163.4250 - number. 163.4251 - 163.4252 - If neither is specified, the current article number is used. 163.4253 - 163.4254 - 163.4255 - 163.4256 -Feather Standards Track [Page 76] 163.4257 - 163.4258 -RFC 3977 Network News Transfer Protocol (NNTP) October 2006 163.4259 - 163.4260 - 163.4261 - Support for the first (message-id) form is optional. If it is 163.4262 - supported, the OVER capability line MUST include the argument 163.4263 - "MSGID". Otherwise, the capability line MUST NOT include this 163.4264 - argument, and the OVER command MUST return the generic response code 163.4265 - 503 when this form is used. 163.4266 - 163.4267 - If the information is available, it is returned as a multi-line data 163.4268 - block following the 224 response code and contains one line per 163.4269 - article, sorted in numerical order of article number. (Note that 163.4270 - unless the argument is a range including a dash, there will be 163.4271 - exactly one line in the data block.) Each line consists of a number 163.4272 - of fields separated by a TAB. A field may be empty (in which case 163.4273 - there will be two adjacent TABs), and a sequence of trailing TABs may 163.4274 - be omitted. 163.4275 - 163.4276 - The first 8 fields MUST be the following, in order: 163.4277 - 163.4278 - "0" or article number (see below) 163.4279 - Subject header content 163.4280 - From header content 163.4281 - Date header content 163.4282 - Message-ID header content 163.4283 - References header content 163.4284 - :bytes metadata item 163.4285 - :lines metadata item 163.4286 - 163.4287 - If the article is specified by message-id (the first form of the 163.4288 - command), the article number MUST be replaced with zero, except that 163.4289 - if there is a currently selected newsgroup and the article is present 163.4290 - in that group, the server MAY use the article's number in that group. 163.4291 - (See the ARTICLE command (Section 6.2.1) and STAT examples 163.4292 - (Section 6.2.4.3) for more details.) In the other two forms of the 163.4293 - command, the article number MUST be returned. 163.4294 - 163.4295 - Any subsequent fields are the contents of the other headers and 163.4296 - metadata held in the database. 163.4297 - 163.4298 - For the five mandatory headers, the content of each field MUST be 163.4299 - based on the content of the header (that is, with the header name and 163.4300 - following colon and space removed). If the article does not contain 163.4301 - that header, or if the content is empty, the field MUST be empty. 163.4302 - For the two mandatory metadata items, the content of the field MUST 163.4303 - be just the value, with no other text. 163.4304 - 163.4305 - For all subsequent fields that contain headers, the content MUST be 163.4306 - the entire header line other than the trailing CRLF. For all 163.4307 - subsequent fields that contain metadata, the field consists of the 163.4308 - metadata name, a single space, and then the value. 163.4309 - 163.4310 - 163.4311 - 163.4312 -Feather Standards Track [Page 77] 163.4313 - 163.4314 -RFC 3977 Network News Transfer Protocol (NNTP) October 2006 163.4315 - 163.4316 - 163.4317 - For all fields, the value is processed by first removing all CRLF 163.4318 - pairs (that is, undoing any folding and removing the terminating 163.4319 - CRLF) and then replacing each TAB with a single space. If there is 163.4320 - no such header in the article, no such metadata item, or no header or 163.4321 - item stored in the database for that article, the corresponding field 163.4322 - MUST be empty. 163.4323 - 163.4324 - Note that, after unfolding, the characters NUL, LF, and CR cannot 163.4325 - occur in the header of an article offered by a conformant server. 163.4326 - Nevertheless, servers SHOULD check for these characters and replace 163.4327 - each one by a single space (so that, for example, CR LF LF TAB will 163.4328 - become two spaces, since the CR and first LF will be removed by the 163.4329 - unfolding process). This will encourage robustness in the face of 163.4330 - non-conforming data; it is also possible that future versions of this 163.4331 - specification could permit these characters to appear in articles. 163.4332 - 163.4333 - The server SHOULD NOT produce output for articles that no longer 163.4334 - exist. 163.4335 - 163.4336 - If the argument is a message-id and no such article exists, a 430 163.4337 - response MUST be returned. If the argument is a range or is omitted 163.4338 - and the currently selected newsgroup is invalid, a 412 response MUST 163.4339 - be returned. If the argument is a range and no articles in that 163.4340 - number range exist in the currently selected newsgroup, including the 163.4341 - case where the second number is less than the first one, a 423 163.4342 - response MUST be returned. If the argument is omitted and the 163.4343 - current article number is invalid, a 420 response MUST be returned. 163.4344 - 163.4345 -8.3.3. Examples 163.4346 - 163.4347 - In the first four examples, TAB has been replaced by vertical bar and 163.4348 - some lines have been folded for readability. 163.4349 - 163.4350 - Example of a successful retrieval of overview information for an 163.4351 - article (explicitly not using an article number): 163.4352 - 163.4353 - [C] GROUP misc.test 163.4354 - [S] 211 1234 3000234 3002322 misc.test 163.4355 - [C] OVER 163.4356 - [S] 224 Overview information follows 163.4357 - [S] 3000234|I am just a test article|"Demo User" 163.4358 - <nobody@example.com>|6 Oct 1998 04:38:40 -0500| 163.4359 - <45223423@example.com>|<45454@example.net>|1234| 163.4360 - 17|Xref: news.example.com misc.test:3000363 163.4361 - [S] . 163.4362 - 163.4363 - 163.4364 - 163.4365 - 163.4366 - 163.4367 - 163.4368 -Feather Standards Track [Page 78] 163.4369 - 163.4370 -RFC 3977 Network News Transfer Protocol (NNTP) October 2006 163.4371 - 163.4372 - 163.4373 - Example of a successful retrieval of overview information for an 163.4374 - article by message-id: 163.4375 - 163.4376 - [C] CAPABILITIES 163.4377 - [S] 101 Capability list: 163.4378 - [S] VERSION 2 163.4379 - [S] READER 163.4380 - [S] OVER MSGID 163.4381 - [S] LIST ACTIVE NEWSGROUPS OVERVIEW.FMT 163.4382 - [S] . 163.4383 - [C] OVER <45223423@example.com> 163.4384 - [S] 224 Overview information follows 163.4385 - [S] 0|I am just a test article|"Demo User" 163.4386 - <nobody@example.com>|6 Oct 1998 04:38:40 -0500| 163.4387 - <45223423@example.com>|<45454@example.net>|1234| 163.4388 - 17|Xref: news.example.com misc.test:3000363 163.4389 - [S] . 163.4390 - 163.4391 - Note that the article number has been replaced by "0". 163.4392 - 163.4393 - Example of the same commands on a system that does not implement 163.4394 - retrieval by message-id: 163.4395 - 163.4396 - [C] CAPABILITIES 163.4397 - [S] 101 Capability list: 163.4398 - [S] VERSION 2 163.4399 - [S] READER 163.4400 - [S] OVER 163.4401 - [S] LIST ACTIVE NEWSGROUPS OVERVIEW.FMT 163.4402 - [S] . 163.4403 - [C] OVER <45223423@example.com> 163.4404 - [S] 503 Overview by message-id unsupported 163.4405 - 163.4406 - 163.4407 - 163.4408 - 163.4409 - 163.4410 - 163.4411 - 163.4412 - 163.4413 - 163.4414 - 163.4415 - 163.4416 - 163.4417 - 163.4418 - 163.4419 - 163.4420 - 163.4421 - 163.4422 - 163.4423 - 163.4424 -Feather Standards Track [Page 79] 163.4425 - 163.4426 -RFC 3977 Network News Transfer Protocol (NNTP) October 2006 163.4427 - 163.4428 - 163.4429 - Example of a successful retrieval of overview information for a range 163.4430 - of articles: 163.4431 - 163.4432 - [C] GROUP misc.test 163.4433 - [S] 211 1234 3000234 3002322 misc.test 163.4434 - [C] OVER 3000234-3000240 163.4435 - [S] 224 Overview information follows 163.4436 - [S] 3000234|I am just a test article|"Demo User" 163.4437 - <nobody@example.com>|6 Oct 1998 04:38:40 -0500| 163.4438 - <45223423@example.com>|<45454@example.net>|1234| 163.4439 - 17|Xref: news.example.com misc.test:3000363 163.4440 - [S] 3000235|Another test article|nobody@nowhere.to 163.4441 - (Demo User)|6 Oct 1998 04:38:45 -0500|<45223425@to.to>|| 163.4442 - 4818|37||Distribution: fi 163.4443 - [S] 3000238|Re: I am just a test article|somebody@elsewhere.to| 163.4444 - 7 Oct 1998 11:38:40 +1200|<kfwer3v@elsewhere.to>| 163.4445 - <45223423@to.to>|9234|51 163.4446 - [S] . 163.4447 - 163.4448 - Note the missing "References" and Xref headers in the second line, 163.4449 - the missing trailing fields in the first and last lines, and that 163.4450 - there are only results for those articles that still exist. 163.4451 - 163.4452 - Example of an unsuccessful retrieval of overview information on an 163.4453 - article by number: 163.4454 - 163.4455 - [C] GROUP misc.test 163.4456 - [S] 211 1234 3000234 3002322 misc.test 163.4457 - [C] OVER 300256 163.4458 - [S] 423 No such article in this group 163.4459 - 163.4460 - Example of an invalid range: 163.4461 - 163.4462 - [C] GROUP misc.test 163.4463 - [S] 211 1234 3000234 3002322 misc.test 163.4464 - [C] OVER 3000444-3000222 163.4465 - [S] 423 Empty range 163.4466 - 163.4467 - Example of an unsuccessful retrieval of overview information by 163.4468 - number because no newsgroup was selected first: 163.4469 - 163.4470 - [Assumes currently selected newsgroup is invalid.] 163.4471 - [C] OVER 163.4472 - [S] 412 No newsgroup selected 163.4473 - 163.4474 - 163.4475 - 163.4476 - 163.4477 - 163.4478 - 163.4479 - 163.4480 -Feather Standards Track [Page 80] 163.4481 - 163.4482 -RFC 3977 Network News Transfer Protocol (NNTP) October 2006 163.4483 - 163.4484 - 163.4485 - Example of an attempt to retrieve information when the currently 163.4486 - selected newsgroup is empty: 163.4487 - 163.4488 - [C] GROUP example.empty.newsgroup 163.4489 - [S] 211 0 0 0 example.empty.newsgroup 163.4490 - [C] OVER 163.4491 - [S] 420 No current article selected 163.4492 - 163.4493 -8.4. LIST OVERVIEW.FMT 163.4494 - 163.4495 -8.4.1. Usage 163.4496 - 163.4497 - Indicating capability: OVER 163.4498 - 163.4499 - Syntax 163.4500 - LIST OVERVIEW.FMT 163.4501 - 163.4502 - Responses 163.4503 - 215 Information follows (multi-line) 163.4504 - 163.4505 -8.4.2. Description 163.4506 - 163.4507 - See Section 7.6.1 for general requirements of the LIST command. 163.4508 - 163.4509 - The LIST OVERVIEW.FMT command returns a description of the fields in 163.4510 - the database for which it is consistent (as described above). The 163.4511 - information is returned as a multi-line data block following the 215 163.4512 - response code. The information contains one line per field in the 163.4513 - order in which they are returned by the OVER command; the first 7 163.4514 - lines MUST (except for the case of letters) be exactly as follows: 163.4515 - 163.4516 - Subject: 163.4517 - From: 163.4518 - Date: 163.4519 - Message-ID: 163.4520 - References: 163.4521 - :bytes 163.4522 - :lines 163.4523 - 163.4524 - For compatibility with existing implementations, the last two lines 163.4525 - MAY instead be: 163.4526 - 163.4527 - Bytes: 163.4528 - Lines: 163.4529 - 163.4530 - even though they refer to metadata, not headers. 163.4531 - 163.4532 - 163.4533 - 163.4534 - 163.4535 - 163.4536 -Feather Standards Track [Page 81] 163.4537 - 163.4538 -RFC 3977 Network News Transfer Protocol (NNTP) October 2006 163.4539 - 163.4540 - 163.4541 - All subsequent lines MUST consist of either a header name followed by 163.4542 - ":full", or the name of a piece of metadata. 163.4543 - 163.4544 - There are no leading or trailing spaces in the output. 163.4545 - 163.4546 - Note that the 7 fixed lines describe the 2nd to 8th fields of the 163.4547 - OVER output. The "full" suffix (which may use either uppercase, 163.4548 - lowercase, or a mix) is a reminder that the corresponding fields 163.4549 - include the header name. 163.4550 - 163.4551 - This command MAY generate different results if it is used more than 163.4552 - once in a session. 163.4553 - 163.4554 - If the OVER command is not implemented, the meaning of the output 163.4555 - from this command is not specified, but it must still meet the above 163.4556 - syntactic requirements. 163.4557 - 163.4558 -8.4.3. Examples 163.4559 - 163.4560 - Example of LIST OVERVIEW.FMT output corresponding to the example OVER 163.4561 - output above, in the preferred format: 163.4562 - 163.4563 - [C] LIST OVERVIEW.FMT 163.4564 - [S] 215 Order of fields in overview database. 163.4565 - [S] Subject: 163.4566 - [S] From: 163.4567 - [S] Date: 163.4568 - [S] Message-ID: 163.4569 - [S] References: 163.4570 - [S] :bytes 163.4571 - [S] :lines 163.4572 - [S] Xref:full 163.4573 - [S] Distribution:full 163.4574 - [S] . 163.4575 - 163.4576 - 163.4577 - 163.4578 - 163.4579 - 163.4580 - 163.4581 - 163.4582 - 163.4583 - 163.4584 - 163.4585 - 163.4586 - 163.4587 - 163.4588 - 163.4589 - 163.4590 - 163.4591 - 163.4592 -Feather Standards Track [Page 82] 163.4593 - 163.4594 -RFC 3977 Network News Transfer Protocol (NNTP) October 2006 163.4595 - 163.4596 - 163.4597 - Example of LIST OVERVIEW.FMT output corresponding to the example OVER 163.4598 - output above, in the alternative format: 163.4599 - 163.4600 - [C] LIST OVERVIEW.FMT 163.4601 - [S] 215 Order of fields in overview database. 163.4602 - [S] Subject: 163.4603 - [S] From: 163.4604 - [S] Date: 163.4605 - [S] Message-ID: 163.4606 - [S] References: 163.4607 - [S] Bytes: 163.4608 - [S] Lines: 163.4609 - [S] Xref:FULL 163.4610 - [S] Distribution:FULL 163.4611 - [S] . 163.4612 - 163.4613 -8.5. HDR 163.4614 - 163.4615 -8.5.1. Usage 163.4616 - 163.4617 - Indicating capability: HDR 163.4618 - 163.4619 - Syntax 163.4620 - HDR field message-id 163.4621 - HDR field range 163.4622 - HDR field 163.4623 - 163.4624 - Responses 163.4625 - 163.4626 - First form (message-id specified) 163.4627 - 225 Headers follow (multi-line) 163.4628 - 430 No article with that message-id 163.4629 - 163.4630 - Second form (range specified) 163.4631 - 225 Headers follow (multi-line) 163.4632 - 412 No newsgroup selected 163.4633 - 423 No articles in that range 163.4634 - 163.4635 - Third form (current article number used) 163.4636 - 225 Headers follow (multi-line) 163.4637 - 412 No newsgroup selected 163.4638 - 420 Current article number is invalid 163.4639 - 163.4640 - Parameters 163.4641 - field Name of field 163.4642 - range Number(s) of articles 163.4643 - message-id Message-id of article 163.4644 - 163.4645 - 163.4646 - 163.4647 - 163.4648 -Feather Standards Track [Page 83] 163.4649 - 163.4650 -RFC 3977 Network News Transfer Protocol (NNTP) October 2006 163.4651 - 163.4652 - 163.4653 -8.5.2. Description 163.4654 - 163.4655 - The HDR command provides access to specific fields from an article 163.4656 - specified by message-id, or from a specified article or range of 163.4657 - articles in the currently selected newsgroup. It MAY take the 163.4658 - information directly from the articles or from the overview database. 163.4659 - In the case of headers, an implementation MAY restrict the use of 163.4660 - this command to a specific list of headers or MAY allow it to be used 163.4661 - with any header; it may behave differently when it is used with a 163.4662 - message-id argument and when it is used with a range or no argument. 163.4663 - 163.4664 - The required field argument is the name of a header with the colon 163.4665 - omitted (e.g., "subject") or the name of a metadata item including 163.4666 - the leading colon (e.g., ":bytes"), and is case insensitive. 163.4667 - 163.4668 - The message-id argument indicates a specific article. The range 163.4669 - argument may be any of the following: 163.4670 - 163.4671 - o An article number. 163.4672 - 163.4673 - o An article number followed by a dash to indicate all following. 163.4674 - 163.4675 - o An article number followed by a dash followed by another article 163.4676 - number. 163.4677 - 163.4678 - If neither is specified, the current article number is used. 163.4679 - 163.4680 - If the information is available, it is returned as a multi-line data 163.4681 - block following the 225 response code and contains one line for each 163.4682 - article in the range that exists. (Note that unless the argument is 163.4683 - a range including a dash, there will be exactly one line in the data 163.4684 - block.) The line consists of the article number, a space, and then 163.4685 - the contents of the field. In the case of a header, the header name, 163.4686 - the colon, and the first space after the colon are all omitted. 163.4687 - 163.4688 - If the article is specified by message-id (the first form of the 163.4689 - command), the article number MUST be replaced with zero, except that 163.4690 - if there is a currently selected newsgroup and the article is present 163.4691 - in that group, the server MAY use the article's number in that group. 163.4692 - (See the ARTICLE command (Section 6.2.1) and STAT examples 163.4693 - (Section 6.2.4.3) for more details.) In the other two forms of the 163.4694 - command, the article number MUST be returned. 163.4695 - 163.4696 - Header contents are modified as follows: all CRLF pairs are removed, 163.4697 - and then each TAB is replaced with a single space. (Note that this 163.4698 - is the same transformation as is performed by the OVER command 163.4699 - (Section 8.3.2), and the same comment concerning NUL, CR, and LF 163.4700 - applies.) 163.4701 - 163.4702 - 163.4703 - 163.4704 -Feather Standards Track [Page 84] 163.4705 - 163.4706 -RFC 3977 Network News Transfer Protocol (NNTP) October 2006 163.4707 - 163.4708 - 163.4709 - Note the distinction between headers and metadata appearing to have 163.4710 - the same meaning. Headers are always taken unchanged from the 163.4711 - article; metadata are always calculated. For example, a request for 163.4712 - "Lines" returns the contents of the "Lines" header of the specified 163.4713 - articles, if any, no matter whether they accurately state the number 163.4714 - of lines, while a request for ":lines" returns the line count 163.4715 - metadata, which is always the actual number of lines irrespective of 163.4716 - what any header may state. 163.4717 - 163.4718 - If the requested header is not present in the article, or if it is 163.4719 - present but empty, a line for that article is included in the output, 163.4720 - but the header content portion of the line is empty (the space after 163.4721 - the article number MAY be retained or omitted). If the header occurs 163.4722 - in a given article more than once, only the content of the first 163.4723 - occurrence is returned by HDR. If any article number in the provided 163.4724 - range does not exist in the group, no line for that article number is 163.4725 - included in the output. 163.4726 - 163.4727 - If the second argument is a message-id and no such article exists, a 163.4728 - 430 response MUST be returned. If the second argument is a range or 163.4729 - is omitted and the currently selected newsgroup is invalid, a 412 163.4730 - response MUST be returned. If the second argument is a range and no 163.4731 - articles in that number range exist in the currently selected 163.4732 - newsgroup, including the case where the second number is less than 163.4733 - the first one, a 423 response MUST be returned. If the second 163.4734 - argument is omitted and the current article number is invalid, a 420 163.4735 - response MUST be returned. 163.4736 - 163.4737 - A server MAY only allow HDR commands for a limited set of fields; it 163.4738 - may behave differently in this respect for the first (message-id) 163.4739 - form from how it would for the other forms. If so, it MUST respond 163.4740 - with the generic 503 response to attempts to request other fields, 163.4741 - rather than return erroneous results, such as a successful empty 163.4742 - response. 163.4743 - 163.4744 - If HDR uses the overview database and it is inconsistent for the 163.4745 - requested field, the server MAY return what results it can, or it MAY 163.4746 - respond with the generic 503 response. In the latter case, the field 163.4747 - MUST NOT appear in the output from LIST HEADERS. 163.4748 - 163.4749 - 163.4750 - 163.4751 - 163.4752 - 163.4753 - 163.4754 - 163.4755 - 163.4756 - 163.4757 - 163.4758 - 163.4759 - 163.4760 -Feather Standards Track [Page 85] 163.4761 - 163.4762 -RFC 3977 Network News Transfer Protocol (NNTP) October 2006 163.4763 - 163.4764 - 163.4765 -8.5.3. Examples 163.4766 - 163.4767 - Example of a successful retrieval of subject lines from a range of 163.4768 - articles (3000235 has no Subject header, and 3000236 is missing): 163.4769 - 163.4770 - [C] GROUP misc.test 163.4771 - [S] 211 1234 3000234 3002322 misc.test 163.4772 - [C] HDR Subject 3000234-3000238 163.4773 - [S] 225 Headers follow 163.4774 - [S] 3000234 I am just a test article 163.4775 - [S] 3000235 163.4776 - [S] 3000237 Re: I am just a test article 163.4777 - [S] 3000238 Ditto 163.4778 - [S] . 163.4779 - 163.4780 - Example of a successful retrieval of line counts from a range of 163.4781 - articles: 163.4782 - 163.4783 - [C] GROUP misc.test 163.4784 - [S] 211 1234 3000234 3002322 misc.test 163.4785 - [C] HDR :lines 3000234-3000238 163.4786 - [S] 225 Headers follow 163.4787 - [S] 3000234 42 163.4788 - [S] 3000235 5 163.4789 - [S] 3000237 11 163.4790 - [S] 3000238 2378 163.4791 - [S] . 163.4792 - 163.4793 - Example of a successful retrieval of the subject line from an article 163.4794 - by message-id: 163.4795 - 163.4796 - [C] GROUP misc.test 163.4797 - [S] 211 1234 3000234 3002322 misc.test 163.4798 - [C] HDR subject <i.am.a.test.article@example.com> 163.4799 - [S] 225 Header information follows 163.4800 - [S] 0 I am just a test article 163.4801 - [S] . 163.4802 - 163.4803 - Example of a successful retrieval of the subject line from the 163.4804 - current article: 163.4805 - 163.4806 - [C] GROUP misc.test 163.4807 - [S] 211 1234 3000234 3002322 misc.test 163.4808 - [C] HDR subject 163.4809 - [S] 225 Header information follows 163.4810 - [S] 3000234 I am just a test article 163.4811 - [S] . 163.4812 - 163.4813 - 163.4814 - 163.4815 - 163.4816 -Feather Standards Track [Page 86] 163.4817 - 163.4818 -RFC 3977 Network News Transfer Protocol (NNTP) October 2006 163.4819 - 163.4820 - 163.4821 - Example of an unsuccessful retrieval of a header from an article by 163.4822 - message-id: 163.4823 - 163.4824 - [C] HDR subject <i.am.not.there@example.com> 163.4825 - [S] 430 No Such Article Found 163.4826 - 163.4827 - Example of an unsuccessful retrieval of headers from articles by 163.4828 - number because no newsgroup was selected first: 163.4829 - 163.4830 - [Assumes currently selected newsgroup is invalid.] 163.4831 - [C] HDR subject 300256- 163.4832 - [S] 412 No newsgroup selected 163.4833 - 163.4834 - Example of an unsuccessful retrieval of headers because the currently 163.4835 - selected newsgroup is empty: 163.4836 - 163.4837 - [C] GROUP example.empty.newsgroup 163.4838 - [S] 211 0 0 0 example.empty.newsgroup 163.4839 - [C] HDR subject 1- 163.4840 - [S] 423 No articles in that range 163.4841 - 163.4842 - Example of an unsuccessful retrieval of headers because the server 163.4843 - does not allow HDR commands for that header: 163.4844 - 163.4845 - [C] GROUP misc.test 163.4846 - [S] 211 1234 3000234 3002322 misc.test 163.4847 - [C] HDR Content-Type 3000234-3000238 163.4848 - [S] 503 HDR not permitted on Content-Type 163.4849 - 163.4850 -8.6. LIST HEADERS 163.4851 - 163.4852 -8.6.1. Usage 163.4853 - 163.4854 - Indicating capability: HDR 163.4855 - 163.4856 - Syntax 163.4857 - LIST HEADERS [MSGID|RANGE] 163.4858 - 163.4859 - Responses 163.4860 - 215 Field list follows (multi-line) 163.4861 - 163.4862 - Parameters 163.4863 - MSGID Requests list for access by message-id 163.4864 - RANGE Requests list for access by range 163.4865 - 163.4866 - 163.4867 - 163.4868 - 163.4869 - 163.4870 - 163.4871 - 163.4872 -Feather Standards Track [Page 87] 163.4873 - 163.4874 -RFC 3977 Network News Transfer Protocol (NNTP) October 2006 163.4875 - 163.4876 - 163.4877 -8.6.2. Description 163.4878 - 163.4879 - See Section 7.6.1 for general requirements of the LIST command. 163.4880 - 163.4881 - The LIST HEADERS command returns a list of fields that may be 163.4882 - retrieved using the HDR command. 163.4883 - 163.4884 - The information is returned as a multi-line data block following the 163.4885 - 215 response code and contains one line for each field name 163.4886 - (excluding the trailing colon for headers and including the leading 163.4887 - colon for metadata items). If the implementation allows any header 163.4888 - to be retrieved, it MUST NOT include any header names in the list but 163.4889 - MUST include the special entry ":" (a single colon on its own). It 163.4890 - MUST still explicitly list any metadata items that are available. 163.4891 - The order of items in the list is not significant; the server need 163.4892 - not even consistently return the same order. The list MAY be empty 163.4893 - (though in this circumstance there is little point in providing the 163.4894 - HDR command). 163.4895 - 163.4896 - An implementation that also supports the OVER command SHOULD at least 163.4897 - permit all the headers and metadata items listed in the output from 163.4898 - the LIST OVERVIEW.FMT command. 163.4899 - 163.4900 - If the server treats the first form of the HDR command (message-id 163.4901 - specified) differently from the other two forms (range specified or 163.4902 - current article number used) in respect of which headers or metadata 163.4903 - items are available, then the following apply: 163.4904 - 163.4905 - o If the MSGID argument is specified, the results MUST be those 163.4906 - available for the first form of the HDR command. 163.4907 - 163.4908 - o If the RANGE argument is specified, the results MUST be those 163.4909 - available for the second and third forms of the HDR command. 163.4910 - 163.4911 - o If no argument is specified, the results MUST be those available 163.4912 - in all forms of the HDR command (that is, it MUST only list those 163.4913 - items listed in both the previous cases). 163.4914 - 163.4915 - If the server does not treat the various forms differently, then it 163.4916 - MUST ignore any argument and always produce the same results (though 163.4917 - not necessarily always in the same order). 163.4918 - 163.4919 - If the HDR command is not implemented, the meaning of the output from 163.4920 - this command is not specified, but it must still meet the above 163.4921 - syntactic requirements. 163.4922 - 163.4923 - 163.4924 - 163.4925 - 163.4926 - 163.4927 - 163.4928 -Feather Standards Track [Page 88] 163.4929 - 163.4930 -RFC 3977 Network News Transfer Protocol (NNTP) October 2006 163.4931 - 163.4932 - 163.4933 -8.6.3. Examples 163.4934 - 163.4935 - Example of an implementation providing access to only a few headers: 163.4936 - 163.4937 - [C] LIST HEADERS 163.4938 - [S] 215 headers supported: 163.4939 - [S] Subject 163.4940 - [S] Message-ID 163.4941 - [S] Xref 163.4942 - [S] . 163.4943 - 163.4944 - Example of an implementation providing access to the same fields as 163.4945 - the first example in Section 8.4.3: 163.4946 - 163.4947 - [C] CAPABILITIES 163.4948 - [S] 101 Capability list: 163.4949 - [S] VERSION 2 163.4950 - [S] READER 163.4951 - [S] OVER 163.4952 - [S] HDR 163.4953 - [S] LIST ACTIVE NEWSGROUPS HEADERS OVERVIEW.FMT 163.4954 - [S] . 163.4955 - [C] LIST HEADERS 163.4956 - [S] 215 headers and metadata items supported: 163.4957 - [S] Date 163.4958 - [S] Distribution 163.4959 - [S] From 163.4960 - [S] Message-ID 163.4961 - [S] References 163.4962 - [S] Subject 163.4963 - [S] Xref 163.4964 - [S] :bytes 163.4965 - [S] :lines 163.4966 - [S] . 163.4967 - 163.4968 - Example of an implementation providing access to all headers: 163.4969 - 163.4970 - [C] LIST HEADERS 163.4971 - [S] 215 metadata items supported: 163.4972 - [S] : 163.4973 - [S] :lines 163.4974 - [S] :bytes 163.4975 - [S] :x-article-number 163.4976 - [S] . 163.4977 - 163.4978 - 163.4979 - 163.4980 - 163.4981 - 163.4982 - 163.4983 - 163.4984 -Feather Standards Track [Page 89] 163.4985 - 163.4986 -RFC 3977 Network News Transfer Protocol (NNTP) October 2006 163.4987 - 163.4988 - 163.4989 - Example of an implementation distinguishing the first form of the HDR 163.4990 - command from the other two forms: 163.4991 - 163.4992 - [C] LIST HEADERS RANGE 163.4993 - [S] 215 metadata items supported: 163.4994 - [S] : 163.4995 - [S] :lines 163.4996 - [S] :bytes 163.4997 - [S] . 163.4998 - [C] LIST HEADERS MSGID 163.4999 - [S] 215 headers and metadata items supported: 163.5000 - [S] Date 163.5001 - [S] Distribution 163.5002 - [S] From 163.5003 - [S] Message-ID 163.5004 - [S] References 163.5005 - [S] Subject 163.5006 - [S] :lines 163.5007 - [S] :bytes 163.5008 - [S] :x-article-number 163.5009 - [S] . 163.5010 - [C] LIST HEADERS 163.5011 - [S] 215 headers and metadata items supported: 163.5012 - [S] Date 163.5013 - [S] Distribution 163.5014 - [S] From 163.5015 - [S] Message-ID 163.5016 - [S] References 163.5017 - [S] Subject 163.5018 - [S] :lines 163.5019 - [S] :bytes 163.5020 - [S] . 163.5021 - 163.5022 - Note that :x-article-number does not appear in the last set of 163.5023 - output. 163.5024 - 163.5025 -9. Augmented BNF Syntax for NNTP 163.5026 - 163.5027 -9.1. Introduction 163.5028 - 163.5029 - Each of the following sections describes the syntax of a major 163.5030 - element of NNTP. This syntax extends and refines the descriptions 163.5031 - elsewhere in this specification and should be given precedence when 163.5032 - resolving apparent conflicts. Note that ABNF [RFC4234] strings are 163.5033 - case insensitive. Non-terminals used in several places are defined 163.5034 - in a separate section at the end. 163.5035 - 163.5036 - 163.5037 - 163.5038 - 163.5039 - 163.5040 -Feather Standards Track [Page 90] 163.5041 - 163.5042 -RFC 3977 Network News Transfer Protocol (NNTP) October 2006 163.5043 - 163.5044 - 163.5045 - Between them, the non-terminals <command-line>, <command-datastream>, 163.5046 - <command-continuation>, and <response> specify the text that flows 163.5047 - between client and server. A consistent naming scheme is used in 163.5048 - this document for the non-terminals relating to each command, and 163.5049 - SHOULD be used by the specification of registered extensions. 163.5050 - 163.5051 - For each command, the sequence is as follows: 163.5052 - 163.5053 - o The client sends an instance of <command-line>; the syntax for the 163.5054 - EXAMPLE command is <example-command>. 163.5055 - 163.5056 - o If the client is one that immediately streams data, it sends an 163.5057 - instance of <command-datastream>; the syntax for the EXAMPLE 163.5058 - command is <example-datastream>. 163.5059 - 163.5060 - o The server sends an instance of <response>. 163.5061 - 163.5062 - * The initial response line is independent of the command that 163.5063 - generated it; if the 000 response has arguments, the syntax of 163.5064 - the initial line is <response-000-content>. 163.5065 - 163.5066 - * If the response is multi-line, the initial line is followed by 163.5067 - a <multi-line-data-block>. The syntax for the contents of this 163.5068 - block after "dot-stuffing" has been removed is (for the 000 163.5069 - response to the EXAMPLE command) <example-000-ml-content> and 163.5070 - is an instance of <multi-line-response-content>. 163.5071 - 163.5072 - o While the latest response is one that indicates more data is 163.5073 - required (in general, a 3xx response): 163.5074 - 163.5075 - * the client sends an instance of <command-continuation>; the 163.5076 - syntax for the EXAMPLE continuation following a 333 response is 163.5077 - <example-333-continuation>; 163.5078 - 163.5079 - * the server sends another instance of <response>, as above. 163.5080 - 163.5081 - (There are no commands in this specification that immediately stream 163.5082 - data, but this non-terminal is defined for the convenience of 163.5083 - extensions.) 163.5084 - 163.5085 - 163.5086 - 163.5087 - 163.5088 - 163.5089 - 163.5090 - 163.5091 - 163.5092 - 163.5093 - 163.5094 - 163.5095 - 163.5096 -Feather Standards Track [Page 91] 163.5097 - 163.5098 -RFC 3977 Network News Transfer Protocol (NNTP) October 2006 163.5099 - 163.5100 - 163.5101 -9.2. Commands 163.5102 - 163.5103 - This syntax defines the non-terminal <command-line>, which represents 163.5104 - what is sent from the client to the server (see section 3.1 for 163.5105 - limits on lengths). 163.5106 - 163.5107 - command-line = command EOL 163.5108 - command = X-command 163.5109 - X-command = keyword *(WS token) 163.5110 - 163.5111 - command =/ article-command / 163.5112 - body-command / 163.5113 - capabilities-command / 163.5114 - date-command / 163.5115 - group-command / 163.5116 - hdr-command / 163.5117 - head-command / 163.5118 - help-command / 163.5119 - ihave-command / 163.5120 - last-command / 163.5121 - list-command / 163.5122 - listgroup-command / 163.5123 - mode-reader-command / 163.5124 - newgroups-command / 163.5125 - newnews-command / 163.5126 - next-command / 163.5127 - over-command / 163.5128 - post-command / 163.5129 - quit-command / 163.5130 - stat-command 163.5131 - 163.5132 - article-command = "ARTICLE" [WS article-ref] 163.5133 - body-command = "BODY" [WS article-ref] 163.5134 - capabilities-command = "CAPABILITIES" [WS keyword] 163.5135 - date-command = "DATE" 163.5136 - group-command = "GROUP" [WS newsgroup-name] 163.5137 - hdr-command = "HDR" WS header-meta-name [WS range-ref] 163.5138 - head-command = "HEAD" [WS article-ref] 163.5139 - help-command = "HELP" 163.5140 - ihave-command = "IHAVE" WS message-id 163.5141 - last-command = "LAST" 163.5142 - list-command = "LIST" [WS list-arguments] 163.5143 - listgroup-command = "LISTGROUP" [WS newsgroup-name [WS range]] 163.5144 - mode-reader-command = "MODE" WS "READER" 163.5145 - newgroups-command = "NEWGROUPS" WS date-time 163.5146 - newnews-command = "NEWNEWS" WS wildmat WS date-time 163.5147 - next-command = "NEXT" 163.5148 - over-command = "OVER" [WS range-ref] 163.5149 - 163.5150 - 163.5151 - 163.5152 -Feather Standards Track [Page 92] 163.5153 - 163.5154 -RFC 3977 Network News Transfer Protocol (NNTP) October 2006 163.5155 - 163.5156 - 163.5157 - post-command = "POST" 163.5158 - quit-command = "QUIT" 163.5159 - stat-command = "STAT" [WS article-ref] 163.5160 - 163.5161 - article-ref = article-number / message-id 163.5162 - date = date2y / date4y 163.5163 - date4y = 4DIGIT 2DIGIT 2DIGIT 163.5164 - date2y = 2DIGIT 2DIGIT 2DIGIT 163.5165 - date-time = date WS time [WS "GMT"] 163.5166 - header-meta-name = header-name / metadata-name 163.5167 - list-arguments = keyword [WS token] 163.5168 - metadata-name = ":" 1*A-NOTCOLON 163.5169 - range = article-number ["-" [article-number]] 163.5170 - range-ref = range / message-id 163.5171 - time = 2DIGIT 2DIGIT 2DIGIT 163.5172 - 163.5173 -9.3. Command Continuation 163.5174 - 163.5175 - This syntax defines the further material sent by the client in the 163.5176 - case of multi-stage commands and those that stream data. 163.5177 - 163.5178 - command-datastream = UNDEFINED 163.5179 - ; not used, provided as a hook for extensions 163.5180 - command-continuation = ihave-335-continuation / 163.5181 - post-340-continuation 163.5182 - 163.5183 - ihave-335-continuation = encoded-article 163.5184 - post-340-continuation = encoded-article 163.5185 - 163.5186 - encoded-article = multi-line-data-block 163.5187 - ; after undoing the "dot-stuffing", this MUST match <article> 163.5188 - 163.5189 -9.4. Responses 163.5190 - 163.5191 -9.4.1. Generic Responses 163.5192 - 163.5193 - This syntax defines the non-terminal <response>, which represents the 163.5194 - generic form of responses; that is, what is sent from the server to 163.5195 - the client in response to a <command> or a <command-continuation>. 163.5196 - 163.5197 - response = simple-response / multi-line-response 163.5198 - simple-response = initial-response-line 163.5199 - multi-line-response = initial-response-line multi-line-data-block 163.5200 - 163.5201 - initial-response-line = 163.5202 - initial-response-content [SP trailing-comment] CRLF 163.5203 - initial-response-content = X-initial-response-content 163.5204 - X-initial-response-content = 3DIGIT *(SP response-argument) 163.5205 - 163.5206 - 163.5207 - 163.5208 -Feather Standards Track [Page 93] 163.5209 - 163.5210 -RFC 3977 Network News Transfer Protocol (NNTP) October 2006 163.5211 - 163.5212 - 163.5213 - response-argument = 1*A-CHAR 163.5214 - trailing-comment = *U-CHAR 163.5215 - 163.5216 -9.4.2. Initial Response Line Contents 163.5217 - 163.5218 - This syntax defines the specific initial response lines for the 163.5219 - various commands in this specification (see section 3.1 for limits on 163.5220 - lengths). Only those response codes with arguments are listed. 163.5221 - 163.5222 - initial-response-content =/ response-111-content / 163.5223 - response-211-content / 163.5224 - response-220-content / 163.5225 - response-221-content / 163.5226 - response-222-content / 163.5227 - response-223-content / 163.5228 - response-401-content 163.5229 - 163.5230 - response-111-content = "111" SP date4y time 163.5231 - response-211-content = "211" 3(SP article-number) SP newsgroup-name 163.5232 - response-220-content = "220" SP article-number SP message-id 163.5233 - response-221-content = "221" SP article-number SP message-id 163.5234 - response-222-content = "222" SP article-number SP message-id 163.5235 - response-223-content = "223" SP article-number SP message-id 163.5236 - response-401-content = "401" SP capability-label 163.5237 - 163.5238 -9.4.3. Multi-line Response Contents 163.5239 - 163.5240 - This syntax defines the content of the various multi-line responses; 163.5241 - more precisely, it defines the part of the response in the multi-line 163.5242 - data block after any "dot-stuffing" has been undone. The numeric 163.5243 - portion of each non-terminal name indicates the response code that is 163.5244 - followed by this data. 163.5245 - 163.5246 - multi-line-response-content = article-220-ml-content / 163.5247 - body-222-ml-content / 163.5248 - capabilities-101-ml-content / 163.5249 - hdr-225-ml-content / 163.5250 - head-221-ml-content / 163.5251 - help-100-ml-content / 163.5252 - list-215-ml-content / 163.5253 - listgroup-211-ml-content / 163.5254 - newgroups-231-ml-content / 163.5255 - newnews-230-ml-content / 163.5256 - over-224-ml-content 163.5257 - 163.5258 - article-220-ml-content = article 163.5259 - body-222-ml-content = body 163.5260 - capabilities-101-ml-content = version-line CRLF 163.5261 - 163.5262 - 163.5263 - 163.5264 -Feather Standards Track [Page 94] 163.5265 - 163.5266 -RFC 3977 Network News Transfer Protocol (NNTP) October 2006 163.5267 - 163.5268 - 163.5269 - *(capability-line CRLF) 163.5270 - hdr-225-ml-content = *(article-number SP hdr-content CRLF) 163.5271 - head-221-ml-content = 1*header 163.5272 - help-100-ml-content = *(*U-CHAR CRLF) 163.5273 - list-215-ml-content = list-content 163.5274 - listgroup-211-ml-content = *(article-number CRLF) 163.5275 - newgroups-231-ml-content = active-groups-list 163.5276 - newnews-230-ml-content = *(message-id CRLF) 163.5277 - over-224-ml-content = *(article-number over-content CRLF) 163.5278 - 163.5279 - active-groups-list = *(newsgroup-name SPA article-number 163.5280 - SPA article-number SPA newsgroup-status CRLF) 163.5281 - hdr-content = *S-NONTAB 163.5282 - hdr-n-content = [(header-name ":" / metadata-name) SP hdr-content] 163.5283 - list-content = body 163.5284 - newsgroup-status = %x79 / %x6E / %x6D / private-status 163.5285 - over-content = 1*6(TAB hdr-content) / 163.5286 - 7(TAB hdr-content) *(TAB hdr-n-content) 163.5287 - private-status = token ; except the values in newsgroup-status 163.5288 - 163.5289 -9.5. Capability Lines 163.5290 - 163.5291 - This syntax defines the generic form of a capability line in the 163.5292 - capabilities list (see Section 3.3.1). 163.5293 - 163.5294 - capability-line = capability-entry 163.5295 - capability-entry = X-capability-entry 163.5296 - X-capability-entry = capability-label *(WS capability-argument) 163.5297 - capability-label = keyword 163.5298 - capability-argument = token 163.5299 - 163.5300 - This syntax defines the specific capability entries for the 163.5301 - capabilities in this specification. 163.5302 - 163.5303 - capability-entry =/ 163.5304 - hdr-capability / 163.5305 - ihave-capability / 163.5306 - implementation-capability / 163.5307 - list-capability / 163.5308 - mode-reader-capability / 163.5309 - newnews-capability / 163.5310 - over-capability / 163.5311 - post-capability / 163.5312 - reader-capability 163.5313 - 163.5314 - hdr-capability = "HDR" 163.5315 - ihave-capability = "IHAVE" 163.5316 - implementation-capability = "IMPLEMENTATION" *(WS token) 163.5317 - 163.5318 - 163.5319 - 163.5320 -Feather Standards Track [Page 95] 163.5321 - 163.5322 -RFC 3977 Network News Transfer Protocol (NNTP) October 2006 163.5323 - 163.5324 - 163.5325 - list-capability = "LIST" 1*(WS keyword) 163.5326 - mode-reader-capability = "MODE-READER" 163.5327 - newnews-capability = "NEWNEWS" 163.5328 - over-capability = "OVER" [WS "MSGID"] 163.5329 - post-capability = "POST" 163.5330 - reader-capability = "READER" 163.5331 - 163.5332 - version-line = "VERSION" 1*(WS version-number) 163.5333 - version-number = nzDIGIT *5DIGIT 163.5334 - 163.5335 -9.6. LIST Variants 163.5336 - 163.5337 - This section defines more specifically the keywords for the LIST 163.5338 - command and the syntax of the corresponding response contents. 163.5339 - 163.5340 - ; active 163.5341 - list-arguments =/ "ACTIVE" [WS wildmat] 163.5342 - list-content =/ list-active-content 163.5343 - list-active-content = active-groups-list 163.5344 - 163.5345 - 163.5346 - ; active.times 163.5347 - list-arguments =/ "ACTIVE.TIMES" [WS wildmat] 163.5348 - list-content =/ list-active-times-content 163.5349 - list-active-times-content = 163.5350 - *(newsgroup-name SPA 1*DIGIT SPA newsgroup-creator CRLF) 163.5351 - newsgroup-creator = U-TEXT 163.5352 - 163.5353 - 163.5354 - ; distrib.pats 163.5355 - list-arguments =/ "DISTRIB.PATS" 163.5356 - list-content =/ list-distrib-pats-content 163.5357 - list-distrib-pats-content = 163.5358 - *(1*DIGIT ":" wildmat ":" distribution CRLF) 163.5359 - distribution = token 163.5360 - 163.5361 - 163.5362 - ; headers 163.5363 - list-arguments =/ "HEADERS" [WS ("MSGID" / "RANGE")] 163.5364 - list-content =/ list-headers-content 163.5365 - list-headers-content = *(header-meta-name CRLF) / 163.5366 - *((metadata-name / ":") CRLF) 163.5367 - 163.5368 - 163.5369 - ; newsgroups 163.5370 - list-arguments =/ "NEWSGROUPS" [WS wildmat] 163.5371 - list-content =/ list-newsgroups-content 163.5372 - list-newsgroups-content = 163.5373 - 163.5374 - 163.5375 - 163.5376 -Feather Standards Track [Page 96] 163.5377 - 163.5378 -RFC 3977 Network News Transfer Protocol (NNTP) October 2006 163.5379 - 163.5380 - 163.5381 - *(newsgroup-name WS newsgroup-description CRLF) 163.5382 - newsgroup-description = S-TEXT 163.5383 - 163.5384 - 163.5385 - ; overview.fmt 163.5386 - list-arguments =/ "OVERVIEW.FMT" 163.5387 - list-content =/ list-overview-fmt-content 163.5388 - list-overview-fmt-content = "Subject:" CRLF 163.5389 - "From:" CRLF 163.5390 - "Date:" CRLF 163.5391 - "Message-ID:" CRLF 163.5392 - "References:" CRLF 163.5393 - ( ":bytes" CRLF ":lines" / "Bytes:" CRLF "Lines:") CRLF 163.5394 - *((header-name ":full" / metadata-name) CRLF) 163.5395 - 163.5396 -9.7. Articles 163.5397 - 163.5398 - This syntax defines the non-terminal <article>, which represents the 163.5399 - format of an article as described in Section 3.6. 163.5400 - 163.5401 - article = 1*header CRLF body 163.5402 - header = header-name ":" [CRLF] SP header-content CRLF 163.5403 - header-content = *(S-CHAR / [CRLF] WS) 163.5404 - body = *(*B-CHAR CRLF) 163.5405 - 163.5406 -9.8. General Non-terminals 163.5407 - 163.5408 - These non-terminals are used at various places in the syntax and are 163.5409 - collected here for convenience. A few of these non-terminals are not 163.5410 - used in this specification but are provided for the consistency and 163.5411 - convenience of extension authors. 163.5412 - 163.5413 - multi-line-data-block = content-lines termination 163.5414 - content-lines = *([content-text] CRLF) 163.5415 - content-text = (".." / B-NONDOT) *B-CHAR 163.5416 - termination = "." CRLF 163.5417 - 163.5418 - article-number = 1*16DIGIT 163.5419 - header-name = 1*A-NOTCOLON 163.5420 - keyword = ALPHA 2*(ALPHA / DIGIT / "." / "-") 163.5421 - message-id = "<" 1*248A-NOTGT ">" 163.5422 - newsgroup-name = 1*wildmat-exact 163.5423 - token = 1*P-CHAR 163.5424 - 163.5425 - wildmat = wildmat-pattern *("," ["!"] wildmat-pattern) 163.5426 - wildmat-pattern = 1*wildmat-item 163.5427 - wildmat-item = wildmat-exact / wildmat-wild 163.5428 - wildmat-exact = %x22-29 / %x2B / %x2D-3E / %x40-5A / %x5E-7E / 163.5429 - 163.5430 - 163.5431 - 163.5432 -Feather Standards Track [Page 97] 163.5433 - 163.5434 -RFC 3977 Network News Transfer Protocol (NNTP) October 2006 163.5435 - 163.5436 - 163.5437 - UTF8-non-ascii ; exclude ! * , ? [ \ ] 163.5438 - wildmat-wild = "*" / "?" 163.5439 - 163.5440 - base64 = *(4base64-char) [base64-terminal] 163.5441 - base64-char = UPPER / LOWER / DIGIT / "+" / "/" 163.5442 - base64-terminal = 2base64-char "==" / 3base64-char "=" 163.5443 - 163.5444 - ; Assorted special character sets 163.5445 - ; A- means based on US-ASCII, excluding controls and SP 163.5446 - ; P- means based on UTF-8, excluding controls and SP 163.5447 - ; U- means based on UTF-8, excluding NUL CR and LF 163.5448 - ; B- means based on bytes, excluding NUL CR and LF 163.5449 - A-CHAR = %x21-7E 163.5450 - A-NOTCOLON = %x21-39 / %x3B-7E ; exclude ":" 163.5451 - A-NOTGT = %x21-3D / %x3F-7E ; exclude ">" 163.5452 - P-CHAR = A-CHAR / UTF8-non-ascii 163.5453 - U-CHAR = CTRL / TAB / SP / A-CHAR / UTF8-non-ascii 163.5454 - U-NONTAB = CTRL / SP / A-CHAR / UTF8-non-ascii 163.5455 - U-TEXT = P-CHAR *U-CHAR 163.5456 - B-CHAR = CTRL / TAB / SP / %x21-FF 163.5457 - B-NONDOT = CTRL / TAB / SP / %x21-2D / %x2F-FF ; exclude "." 163.5458 - 163.5459 - ALPHA = UPPER / LOWER ; use only when case-insensitive 163.5460 - CR = %x0D 163.5461 - CRLF = CR LF 163.5462 - CTRL = %x01-08 / %x0B-0C / %x0E-1F 163.5463 - DIGIT = %x30-39 163.5464 - nzDIGIT = %x31-39 163.5465 - EOL = *(SP / TAB) CRLF 163.5466 - LF = %x0A 163.5467 - LOWER = %x61-7A 163.5468 - SP = %x20 163.5469 - SPA = 1*SP 163.5470 - TAB = %x09 163.5471 - UPPER = %x41-5A 163.5472 - UTF8-non-ascii = UTF8-2 / UTF8-3 / UTF8-4 163.5473 - UTF8-2 = %xC2-DF UTF8-tail 163.5474 - UTF8-3 = %xE0 %xA0-BF UTF8-tail / %xE1-EC 2UTF8-tail / 163.5475 - %xED %x80-9F UTF8-tail / %xEE-EF 2UTF8-tail 163.5476 - UTF8-4 = %xF0 %x90-BF 2UTF8-tail / %xF1-F3 3UTF8-tail / 163.5477 - %xF4 %x80-8F 2UTF8-tail 163.5478 - UTF8-tail = %x80-BF 163.5479 - WS = 1*(SP / TAB) 163.5480 - 163.5481 - The following non-terminals require special consideration. They 163.5482 - represent situations where material SHOULD be restricted to UTF-8, 163.5483 - but implementations MUST be able to cope with other character 163.5484 - encodings. Therefore, there are two sets of definitions for them. 163.5485 - 163.5486 - 163.5487 - 163.5488 -Feather Standards Track [Page 98] 163.5489 - 163.5490 -RFC 3977 Network News Transfer Protocol (NNTP) October 2006 163.5491 - 163.5492 - 163.5493 - Implementations MUST accept any content that meets this syntax: 163.5494 - 163.5495 - S-CHAR = %x21-FF 163.5496 - S-NONTAB = CTRL / SP / S-CHAR 163.5497 - S-TEXT = (CTRL / S-CHAR) *B-CHAR 163.5498 - 163.5499 - and MAY pass such content on unaltered. 163.5500 - 163.5501 - When generating new content or re-encoding existing content, 163.5502 - implementations SHOULD conform to this syntax: 163.5503 - 163.5504 - S-CHAR = P-CHAR 163.5505 - S-NONTAB = U-NONTAB 163.5506 - S-TEXT = U-TEXT 163.5507 - 163.5508 -9.9. Extensions and Validation 163.5509 - 163.5510 - The specification of a registered extension MUST include formal 163.5511 - syntax that defines additional forms for the following non-terminals: 163.5512 - 163.5513 - command 163.5514 - for each new command other than a variant of the LIST command - 163.5515 - the syntax of each command MUST be compatible with the definition 163.5516 - of <X-command>; 163.5517 - 163.5518 - command-datastream 163.5519 - for each new command that immediately streams data; 163.5520 - 163.5521 - command-continuation 163.5522 - for each new command that sends further material after the initial 163.5523 - command line - the syntax of each continuation MUST be exactly 163.5524 - what is sent to the server, including any escape mechanisms such 163.5525 - as "dot-stuffing"; 163.5526 - 163.5527 - initial-response-content 163.5528 - for each new response code that has arguments - the syntax of each 163.5529 - response MUST be compatible with the definition of <X-initial- 163.5530 - response-content>; 163.5531 - 163.5532 - multi-line-response-content 163.5533 - for each new response code that has a multi-line response - the 163.5534 - syntax MUST show the response after the lines containing the 163.5535 - response code and the terminating octet have been removed and any 163.5536 - "dot-stuffing" undone; 163.5537 - 163.5538 - capability-entry 163.5539 - for each new capability label - the syntax of each entry MUST be 163.5540 - compatible with the definition of <X-capability-entry>; 163.5541 - 163.5542 - 163.5543 - 163.5544 -Feather Standards Track [Page 99] 163.5545 - 163.5546 -RFC 3977 Network News Transfer Protocol (NNTP) October 2006 163.5547 - 163.5548 - 163.5549 - list-arguments 163.5550 - for each new variant of the LIST command - the syntax of each 163.5551 - entry MUST be compatible with the definition of <X-command>; 163.5552 - 163.5553 - list-content 163.5554 - for each new variant of the LIST command - the syntax MUST show 163.5555 - the response after the lines containing the 215 response code and 163.5556 - the terminating octet have been removed and any "dot-stuffing" 163.5557 - undone. 163.5558 - 163.5559 - The =/ notation of ABNF [RFC4234] and the naming conventions 163.5560 - described in Section 9.1 SHOULD be used for this. 163.5561 - 163.5562 - When the syntax in this specification, or syntax based on it, is 163.5563 - validated, it should be noted that: 163.5564 - 163.5565 - o the non-terminals <command-line>, <command-datastream>, 163.5566 - <command-continuation>, <response>, and 163.5567 - <multi-line-response-content> describe basic concepts of the 163.5568 - protocol and are not referred to by any other rule; 163.5569 - 163.5570 - o the non-terminal <base64> is provided for the convenience of 163.5571 - extension authors and is not referred to by any rule in this 163.5572 - specification; 163.5573 - 163.5574 - o for the reasons given above, the non-terminals <S-CHAR>, 163.5575 - <S-NONTAB>, and <S-TEXT> each have two definitions; and 163.5576 - 163.5577 - o the non-terminal <UNDEFINED> is deliberately not defined. 163.5578 - 163.5579 -10. Internationalisation Considerations 163.5580 - 163.5581 -10.1. Introduction and Historical Situation 163.5582 - 163.5583 - RFC 977 [RFC977] was written at a time when internationalisation was 163.5584 - not seen as a significant issue. As such, it was written on the 163.5585 - assumption that all communication would be in ASCII and use only a 163.5586 - 7-bit transport layer, although in practice just about all known 163.5587 - implementations are 8-bit clean. 163.5588 - 163.5589 - Since then, Usenet and NNTP have spread throughout the world. In the 163.5590 - absence of standards for handling the issues of language and 163.5591 - character sets, countries, newsgroup hierarchies, and individuals 163.5592 - have found a variety of solutions that work for them but that are not 163.5593 - necessarily appropriate elsewhere. For example, some have adopted a 163.5594 - default 8-bit character set appropriate to their needs (such as 163.5595 - ISO/IEC 8859-1 in Western Europe or KOI-8 in Russia), others have 163.5596 - used ASCII (either US-ASCII or national variants) in headers but 163.5597 - 163.5598 - 163.5599 - 163.5600 -Feather Standards Track [Page 100] 163.5601 - 163.5602 -RFC 3977 Network News Transfer Protocol (NNTP) October 2006 163.5603 - 163.5604 - 163.5605 - local 16-bit character sets in article bodies, and still others have 163.5606 - gone for a combination of MIME [RFC2045] and UTF-8. With the 163.5607 - increased use of MIME in email, it is becoming more common to find 163.5608 - NNTP articles containing MIME headers that identify the character set 163.5609 - of the body, but this is far from universal. 163.5610 - 163.5611 - The resulting confusion does not help interoperability. 163.5612 - 163.5613 - One point that has been generally accepted is that articles can 163.5614 - contain octets with the top bit set, and NNTP is only expected to 163.5615 - operate on 8-bit clean transport paths. 163.5616 - 163.5617 -10.2. This Specification 163.5618 - 163.5619 - Part of the role of this present specification is to eliminate this 163.5620 - confusion and promote interoperability as far as possible. At the 163.5621 - same time, it is necessary to accept the existence of the present 163.5622 - situation and not break existing implementations and arrangements 163.5623 - gratuitously, even if they are less than optimal. Therefore, the 163.5624 - current practice described above has been taken into consideration in 163.5625 - producing this specification. 163.5626 - 163.5627 - This specification extends NNTP from US-ASCII [ANSI1986] to UTF-8 163.5628 - [RFC3629]. Except in the two areas discussed below, UTF-8 (which is 163.5629 - a superset of US-ASCII) is mandatory, and implementations MUST NOT 163.5630 - use any other encoding. 163.5631 - 163.5632 - Firstly, the use of MIME for article headers and bodies is strongly 163.5633 - recommended. However, given widely divergent existing practices, an 163.5634 - attempt to require a particular encoding and tagging standard would 163.5635 - be premature at this time. Accordingly, this specification allows 163.5636 - the use of arbitrary 8-bit data in articles subject to the following 163.5637 - requirements and recommendations. 163.5638 - 163.5639 - o The names of headers (e.g., "From" or "Subject") MUST be in 163.5640 - US-ASCII. 163.5641 - 163.5642 - o Header values SHOULD use US-ASCII or an encoding based on it, such 163.5643 - as RFC 2047 [RFC2047], until such time as another approach has 163.5644 - been standardised. At present, 8-bit encodings (including UTF-8) 163.5645 - SHOULD NOT be used because they are likely to cause 163.5646 - interoperability problems. 163.5647 - 163.5648 - o The character set of article bodies SHOULD be indicated in the 163.5649 - article headers, and this SHOULD be done in accordance with MIME. 163.5650 - 163.5651 - o Where an article is obtained from an external source, an 163.5652 - implementation MAY pass it on and derive data from it (such as the 163.5653 - 163.5654 - 163.5655 - 163.5656 -Feather Standards Track [Page 101] 163.5657 - 163.5658 -RFC 3977 Network News Transfer Protocol (NNTP) October 2006 163.5659 - 163.5660 - 163.5661 - response to the HDR command), even though the article or the data 163.5662 - does not meet the above requirements. Implementations MUST 163.5663 - transfer such articles and data correctly and unchanged; they MUST 163.5664 - NOT attempt to convert or re-encode the article or derived data. 163.5665 - (Nevertheless, a client or server MAY elect not to post or forward 163.5666 - the article if, after further examination of the article, it deems 163.5667 - it inappropriate to do so.) 163.5668 - 163.5669 - This requirement affects the ARTICLE (Section 6.2.1), BODY 163.5670 - (Section 6.2.3), HDR (Section 8.5), HEAD (Section 6.2.2), IHAVE 163.5671 - (Section 6.3.2), OVER (Section 8.3), and POST (Section 6.3.1) 163.5672 - commands. 163.5673 - 163.5674 - Secondly, the following requirements are placed on the newsgroups 163.5675 - list returned by the LIST NEWSGROUPS command (Section 7.6.6): 163.5676 - 163.5677 - o Although this specification allows UTF-8 for newsgroup names, they 163.5678 - SHOULD be restricted to US-ASCII until a successor to RFC 1036 163.5679 - [RFC1036] standardises another approach. 8-bit encodings SHOULD 163.5680 - NOT be used because they are likely to cause interoperability 163.5681 - problems. 163.5682 - 163.5683 - o The newsgroup description SHOULD be in US-ASCII or UTF-8 unless 163.5684 - and until a successor to RFC 1036 standardises other encoding 163.5685 - arrangements. 8-bit encodings other than UTF-8 SHOULD NOT be used 163.5686 - because they are likely to cause interoperability problems. 163.5687 - 163.5688 - o Implementations that obtain this data from an external source MUST 163.5689 - handle it correctly even if it does not meet the above 163.5690 - requirements. Implementations (in particular, clients) MUST 163.5691 - handle such data correctly. 163.5692 - 163.5693 -10.3. Outstanding Issues 163.5694 - 163.5695 - While the primary use of NNTP is for transmitting articles that 163.5696 - conform to RFC 1036 (Netnews articles), it is also used for other 163.5697 - formats (see Appendix A). It is therefore most appropriate that 163.5698 - internationalisation issues related to article formats be addressed 163.5699 - in the relevant specifications. For Netnews articles, this is any 163.5700 - successor to RFC 1036. For email messages, it is RFC 2822 [RFC2822]. 163.5701 - 163.5702 - Of course, any article transmitted via NNTP needs to conform to this 163.5703 - specification as well. 163.5704 - 163.5705 - Restricting newsgroup names to UTF-8 is not a complete solution. In 163.5706 - particular, when new newsgroup names are created or a user is asked 163.5707 - to enter a newsgroup name, some scheme of canonicalisation will need 163.5708 - to take place. This specification does not attempt to define that 163.5709 - 163.5710 - 163.5711 - 163.5712 -Feather Standards Track [Page 102] 163.5713 - 163.5714 -RFC 3977 Network News Transfer Protocol (NNTP) October 2006 163.5715 - 163.5716 - 163.5717 - canonicalization; further work is needed in this area, in conjunction 163.5718 - with the article format specifications. Until such specifications 163.5719 - are published, implementations SHOULD match newsgroup names octet by 163.5720 - octet. It is anticipated that any approved scheme will be applied 163.5721 - "at the edges", and therefore octet-by-octet comparison will continue 163.5722 - to apply to most, if not all, uses of newsgroup names in NNTP. 163.5723 - 163.5724 - In the meantime, any implementation experimenting with UTF-8 163.5725 - newsgroup names is strongly cautioned that a future specification may 163.5726 - require that those names be canonicalized when used with NNTP in a 163.5727 - way that is not compatible with their experiments. 163.5728 - 163.5729 - Since the primary use of NNTP is with Netnews, and since newsgroup 163.5730 - descriptions are normally distributed through specially formatted 163.5731 - articles, it is recommended that the internationalisation issues 163.5732 - related to them be addressed in any successor to RFC 1036. 163.5733 - 163.5734 -11. IANA Considerations 163.5735 - 163.5736 - This specification requires IANA to keep a registry of capability 163.5737 - labels. The initial contents of this registry are specified in 163.5738 - Section 3.3.4. As described in Section 3.3.3, labels beginning with 163.5739 - X are reserved for private use, while all other names are expected to 163.5740 - be associated with a specification in an RFC on the standards track 163.5741 - or defining an IESG-approved experimental protocol. 163.5742 - 163.5743 - Different entries in the registry MUST use different capability 163.5744 - labels. 163.5745 - 163.5746 - Different entries in the registry MUST NOT use the same command name. 163.5747 - For this purpose, variants distinguished by a second or subsequent 163.5748 - keyword (e.g., "LIST HEADERS" and "LIST OVERVIEW.FMT") count as 163.5749 - different commands. If there is a need for two extensions to use the 163.5750 - same command, a single harmonised specification MUST be registered. 163.5751 - 163.5752 -12. Security Considerations 163.5753 - 163.5754 - This section is meant to inform application developers, information 163.5755 - providers, and users of the security limitations in NNTP as described 163.5756 - by this document. The discussion does not include definitive 163.5757 - solutions to the problems revealed, though it does make some 163.5758 - suggestions for reducing security risks. 163.5759 - 163.5760 - 163.5761 - 163.5762 - 163.5763 - 163.5764 - 163.5765 - 163.5766 - 163.5767 - 163.5768 -Feather Standards Track [Page 103] 163.5769 - 163.5770 -RFC 3977 Network News Transfer Protocol (NNTP) October 2006 163.5771 - 163.5772 - 163.5773 -12.1. Personal and Proprietary Information 163.5774 - 163.5775 - NNTP, because it was created to distribute network news articles, 163.5776 - will forward whatever information is stored in those articles. 163.5777 - Specification of that information is outside this scope of this 163.5778 - document, but it is likely that some personal and/or proprietary 163.5779 - information is available in some of those articles. It is very 163.5780 - important that designers and implementers provide informative 163.5781 - warnings to users so that personal and/or proprietary information in 163.5782 - material that is added automatically to articles (e.g., in headers) 163.5783 - is not disclosed inadvertently. Additionally, effective and easily 163.5784 - understood mechanisms to manage the distribution of news articles 163.5785 - SHOULD be provided to NNTP Server administrators, so that they are 163.5786 - able to report with confidence the likely spread of any particular 163.5787 - set of news articles. 163.5788 - 163.5789 -12.2. Abuse of Server Log Information 163.5790 - 163.5791 - A server is in the position to save session data about a user's 163.5792 - requests that might identify their reading patterns or subjects of 163.5793 - interest. This information is clearly confidential in nature, and 163.5794 - its handling can be constrained by law in certain countries. People 163.5795 - using this protocol to provide data are responsible for ensuring that 163.5796 - such material is not distributed without the permission of any 163.5797 - individuals that are identifiable by the published results. 163.5798 - 163.5799 -12.3. Weak Authentication and Access Control 163.5800 - 163.5801 - There is no user-based or token-based authentication in the basic 163.5802 - NNTP specification. Access is normally controlled by server 163.5803 - configuration files. Those files specify access by using domain 163.5804 - names or IP addresses. However, this specification does permit the 163.5805 - creation of extensions to NNTP for such purposes; one such extension 163.5806 - is [NNTP-AUTH]. While including such mechanisms is optional, doing 163.5807 - so is strongly encouraged. 163.5808 - 163.5809 - Other mechanisms are also available. For example, a proxy server 163.5810 - could be put in place that requires authentication before connecting 163.5811 - via the proxy to the NNTP server. 163.5812 - 163.5813 -12.4. DNS Spoofing 163.5814 - 163.5815 - Many existing NNTP implementations authorize incoming connections by 163.5816 - checking the IP address of that connection against the IP addresses 163.5817 - obtained via DNS lookups of lists of domain names given in local 163.5818 - configuration files. Servers that use this type of authentication 163.5819 - and clients that find a server by doing a DNS lookup of the server 163.5820 - name rely very heavily on the Domain Name Service, and are thus 163.5821 - 163.5822 - 163.5823 - 163.5824 -Feather Standards Track [Page 104] 163.5825 - 163.5826 -RFC 3977 Network News Transfer Protocol (NNTP) October 2006 163.5827 - 163.5828 - 163.5829 - generally prone to security attacks based on the deliberate 163.5830 - misassociation of IP addresses and DNS names. Clients and servers 163.5831 - need to be cautious in assuming the continuing validity of an IP 163.5832 - number/DNS name association. 163.5833 - 163.5834 - In particular, NNTP clients and servers SHOULD rely on their name 163.5835 - resolver for confirmation of an IP number/DNS name association, 163.5836 - rather than cache the result of previous host name lookups. Many 163.5837 - platforms already can cache host name lookups locally when 163.5838 - appropriate, and they SHOULD be configured to do so. It is proper 163.5839 - for these lookups to be cached, however, only when the TTL (Time To 163.5840 - Live) information reported by the name server makes it likely that 163.5841 - the cached information will remain useful. 163.5842 - 163.5843 - If NNTP clients or servers cache the results of host name lookups in 163.5844 - order to achieve a performance improvement, they MUST observe the TTL 163.5845 - information reported by DNS. If NNTP clients or servers do not 163.5846 - observe this rule, they could be spoofed when a previously accessed 163.5847 - server's IP address changes. As network renumbering is expected to 163.5848 - become increasingly common, the possibility of this form of attack 163.5849 - will increase. Observing this requirement thus reduces this 163.5850 - potential security vulnerability. 163.5851 - 163.5852 - This requirement also improves the load-balancing behaviour of 163.5853 - clients for replicated servers using the same DNS name and reduces 163.5854 - the likelihood of a user's experiencing failure in accessing sites 163.5855 - that use that strategy. 163.5856 - 163.5857 -12.5. UTF-8 Issues 163.5858 - 163.5859 - UTF-8 [RFC3629] permits only certain sequences of octets and 163.5860 - designates others as either malformed or "illegal". The Unicode 163.5861 - standard identifies a number of security issues related to illegal 163.5862 - sequences and forbids their generation by conforming implementations. 163.5863 - 163.5864 - Implementations of this specification MUST NOT generate malformed or 163.5865 - illegal sequences and SHOULD detect them and take some appropriate 163.5866 - action. This could include the following: 163.5867 - 163.5868 - o Generating a 501 response code. 163.5869 - 163.5870 - o Replacing such sequences by the sequence %xEF.BF.BD, which encodes 163.5871 - the "replacement character" U+FFFD. 163.5872 - 163.5873 - o Closing the connection. 163.5874 - 163.5875 - o Replacing such sequences by a "guessed" valid sequence (based on 163.5876 - properties of the UTF-8 encoding). 163.5877 - 163.5878 - 163.5879 - 163.5880 -Feather Standards Track [Page 105] 163.5881 - 163.5882 -RFC 3977 Network News Transfer Protocol (NNTP) October 2006 163.5883 - 163.5884 - 163.5885 - In the last case, the implementation MUST ensure that any replacement 163.5886 - cannot be used to bypass validity or security checks. For example, 163.5887 - the illegal sequence %xC0.A0 is an over-long encoding for space 163.5888 - (%x20). If it is replaced by the correct encoding in a command line, 163.5889 - this needs to happen before the command line is parsed into 163.5890 - individual arguments. If the replacement came after parsing, it 163.5891 - would be possible to generate an argument with an embedded space, 163.5892 - which is forbidden. Use of the "replacement character" does not have 163.5893 - this problem, since it is permitted wherever non-US-ASCII characters 163.5894 - are. Implementations SHOULD use one of the first two solutions where 163.5895 - the general structure of the NNTP stream remains intact and SHOULD 163.5896 - close the connection if it is no longer possible to parse it 163.5897 - sensibly. 163.5898 - 163.5899 -12.6. Caching of Capability Lists 163.5900 - 163.5901 - The CAPABILITIES command provides a capability list, which is 163.5902 - information about the current capabilities of the server. Whenever 163.5903 - there is a relevant change to the server state, the results of this 163.5904 - command are required to change accordingly. 163.5905 - 163.5906 - In most situations, the capabilities list in a given server state 163.5907 - will not change from session to session; for example, a given 163.5908 - extension will be installed permanently on a server. Some clients 163.5909 - may therefore wish to remember which extensions a server supports to 163.5910 - avoid the delay of an additional command and response, particularly 163.5911 - if they open multiple connections in the same session. 163.5912 - 163.5913 - However, information about extensions related to security and privacy 163.5914 - MUST NOT be cached, since this could allow a variety of attacks. 163.5915 - 163.5916 - For example, consider a server that permits the use of cleartext 163.5917 - passwords on links that are encrypted but not otherwise: 163.5918 - 163.5919 - [Initial connection set-up completed.] 163.5920 - [S] 200 NNTP Service Ready, posting permitted 163.5921 - [C] CAPABILITIES 163.5922 - [S] 101 Capability list: 163.5923 - [S] VERSION 2 163.5924 - [S] READER 163.5925 - [S] NEWNEWS 163.5926 - [S] POST 163.5927 - [S] XENCRYPT 163.5928 - [S] LIST ACTIVE NEWSGROUPS 163.5929 - [S] . 163.5930 - [C] XENCRYPT 163.5931 - [Client and server negotiate encryption on the link] 163.5932 - [S] 283 Encrypted link established 163.5933 - 163.5934 - 163.5935 - 163.5936 -Feather Standards Track [Page 106] 163.5937 - 163.5938 -RFC 3977 Network News Transfer Protocol (NNTP) October 2006 163.5939 - 163.5940 - 163.5941 - [C] CAPABILITIES 163.5942 - [S] 101 Capability list: 163.5943 - [S] VERSION 2 163.5944 - [S] READER 163.5945 - [S] NEWNEWS 163.5946 - [S] POST 163.5947 - [S] XSECRET 163.5948 - [S] LIST ACTIVE NEWSGROUPS 163.5949 - [S] . 163.5950 - [C] XSECRET fred flintstone 163.5951 - [S] 290 Password for fred accepted 163.5952 - 163.5953 - If the client caches the last capabilities list, then on the next 163.5954 - session it will attempt to use XSECRET on an unencrypted link: 163.5955 - 163.5956 - [Initial connection set-up completed.] 163.5957 - [S] 200 NNTP Service Ready, posting permitted 163.5958 - [C] XSECRET fred flintstone 163.5959 - [S] 483 Only permitted on secure links 163.5960 - 163.5961 - This exposes the password to any eavesdropper. While the primary 163.5962 - cause of this is passing a secret without first checking the security 163.5963 - of the link, caching of capability lists can increase the risk. 163.5964 - 163.5965 - Any security extension should include requirements to check the 163.5966 - security state of the link in a manner appropriate to that extension. 163.5967 - 163.5968 - Caching should normally only be considered for anonymous clients that 163.5969 - do not use any security or privacy extensions and for which the time 163.5970 - required for an additional command and response is a noticeable 163.5971 - issue. 163.5972 - 163.5973 -13. Acknowledgements 163.5974 - 163.5975 - This document is the result of much effort by the present and past 163.5976 - members of the NNTP Working Group, chaired by Russ Allbery and Ned 163.5977 - Freed. It could not have been produced without them. 163.5978 - 163.5979 - The author acknowledges the original authors of NNTP as documented in 163.5980 - RFC 977 [RFC977]: Brian Kantor and Phil Lapsey. 163.5981 - 163.5982 - The author gratefully acknowledges the following: 163.5983 - 163.5984 - o The work of the NNTP committee chaired by Eliot Lear. The 163.5985 - organization of this document was influenced by the last available 163.5986 - version from this working group. A special thanks to Eliot for 163.5987 - generously providing the original machine-readable sources for 163.5988 - that document. 163.5989 - 163.5990 - 163.5991 - 163.5992 -Feather Standards Track [Page 107] 163.5993 - 163.5994 -RFC 3977 Network News Transfer Protocol (NNTP) October 2006 163.5995 - 163.5996 - 163.5997 - o The work of the DRUMS working group, specifically RFC 1869 163.5998 - [RFC1869], that drove the original thinking that led to the 163.5999 - CAPABILITIES command and the extensions mechanism detailed in this 163.6000 - document. 163.6001 - 163.6002 - o The authors of RFC 2616 [RFC2616] for providing specific and 163.6003 - relevant examples of security issues that should be considered for 163.6004 - HTTP. Since many of the same considerations exist for NNTP, those 163.6005 - examples that are relevant have been included here with some minor 163.6006 - rewrites. 163.6007 - 163.6008 - o The comments and additional information provided by the following 163.6009 - individuals in preparing one or more of the progenitors of this 163.6010 - document: 163.6011 - 163.6012 - Russ Allbery <rra@stanford.edu> 163.6013 - Wayne Davison <davison@armory.com> 163.6014 - Chris Lewis <clewis@bnr.ca> 163.6015 - Tom Limoncelli <tal@mars.superlink.net> 163.6016 - Eric Schnoebelen <eric@egsner.cirr.com> 163.6017 - Rich Salz <rsalz@osf.org> 163.6018 - 163.6019 - This work was motivated by the work of various news reader authors 163.6020 - and news server authors, including those listed below: 163.6021 - 163.6022 - Rick Adams 163.6023 - Original author of the NNTP extensions to the RN news reader and 163.6024 - last maintainer of Bnews. 163.6025 - 163.6026 - Stan Barber 163.6027 - Original author of the NNTP extensions to the news readers that 163.6028 - are part of Bnews. 163.6029 - 163.6030 - Geoff Collyer 163.6031 - Original author of the OVERVIEW database proposal and one of the 163.6032 - original authors of CNEWS. 163.6033 - 163.6034 - Dan Curry 163.6035 - Original author of the xvnews news reader. 163.6036 - 163.6037 - Wayne Davison 163.6038 - Author of the first threading extensions to the RN news reader 163.6039 - (commonly called TRN). 163.6040 - 163.6041 - Geoff Huston 163.6042 - Original author of ANU NEWS. 163.6043 - 163.6044 - 163.6045 - 163.6046 - 163.6047 - 163.6048 -Feather Standards Track [Page 108] 163.6049 - 163.6050 -RFC 3977 Network News Transfer Protocol (NNTP) October 2006 163.6051 - 163.6052 - 163.6053 - Phil Lapsey 163.6054 - Original author of the UNIX reference implementation for NNTP. 163.6055 - 163.6056 - Iain Lea 163.6057 - Original maintainer of the TIN news reader. 163.6058 - 163.6059 - Chris Lewis 163.6060 - First known implementer of the AUTHINFO GENERIC extension. 163.6061 - 163.6062 - Rich Salz 163.6063 - Original author of INN. 163.6064 - 163.6065 - Henry Spencer 163.6066 - One of the original authors of CNEWS. 163.6067 - 163.6068 - Kim Storm 163.6069 - Original author of the NN news reader. 163.6070 - 163.6071 - Other people who contributed to this document include: 163.6072 - 163.6073 - Matthias Andree 163.6074 - Greg Andruk 163.6075 - Daniel Barclay 163.6076 - Maurizio Codogno 163.6077 - Mark Crispin 163.6078 - Andrew Gierth 163.6079 - Juergen Helbing 163.6080 - Scott Hollenbeck 163.6081 - Urs Janssen 163.6082 - Charles Lindsey 163.6083 - Ade Lovett 163.6084 - David Magda 163.6085 - Ken Murchison 163.6086 - Francois Petillon 163.6087 - Peter Robinson 163.6088 - Rob Siemborski 163.6089 - Howard Swinehart 163.6090 - Ruud van Tol 163.6091 - Jeffrey Vinocur 163.6092 - Erik Warmelink 163.6093 - 163.6094 - The author thanks them all and apologises to anyone omitted. 163.6095 - 163.6096 - Finally, the present author gratefully acknowledges the vast amount 163.6097 - of work put into previous versions by the previous author: 163.6098 - 163.6099 - Stan Barber <sob@academ.com> 163.6100 - 163.6101 - 163.6102 - 163.6103 - 163.6104 -Feather Standards Track [Page 109] 163.6105 - 163.6106 -RFC 3977 Network News Transfer Protocol (NNTP) October 2006 163.6107 - 163.6108 - 163.6109 -14. References 163.6110 - 163.6111 -14.1. Normative References 163.6112 - 163.6113 - [ANSI1986] American National Standards Institute, "Coded Character 163.6114 - Set - 7-bit American Standard Code for Information 163.6115 - Interchange", ANSI X3.4, 1986. 163.6116 - 163.6117 - [RFC977] Kantor, B. and P. Lapsley, "Network News Transfer 163.6118 - Protocol", RFC 977, February 1986. 163.6119 - 163.6120 - [RFC2045] Freed, N. and N. Borenstein, "Multipurpose Internet 163.6121 - Mail Extensions (MIME) Part One: Format of Internet 163.6122 - Message Bodies", RFC 2045, November 1996. 163.6123 - 163.6124 - [RFC2047] Moore, K., "MIME (Multipurpose Internet Mail 163.6125 - Extensions) Part Three: Message Header Extensions for 163.6126 - Non-ASCII Text", RFC 2047, November 1996. 163.6127 - 163.6128 - [RFC2119] Bradner, S., "Key words for use in RFCs to Indicate 163.6129 - Requirement Levels", BCP 14, RFC 2119, March 1997. 163.6130 - 163.6131 - [RFC3629] Yergeau, F., "UTF-8, a transformation format of ISO 163.6132 - 10646", STD 63, RFC 3629, November 2003. 163.6133 - 163.6134 - [RFC4234] Crocker, D., Ed. and P. Overell, "Augmented BNF for 163.6135 - Syntax Specifications: ABNF", RFC 4234, October 2005. 163.6136 - 163.6137 - [RFC4648] Josefsson, S., "The Base16, Base32, and Base64 Data 163.6138 - Encodings", RFC 4648, October 2006. 163.6139 - 163.6140 - [TF.686-1] International Telecommunications Union - Radio, 163.6141 - "Glossary, ITU-R Recommendation TF.686-1", 163.6142 - ITU-R Recommendation TF.686-1, October 1997. 163.6143 - 163.6144 -14.2. Informative References 163.6145 - 163.6146 - [NNTP-AUTH] Vinocur, J., Murchison, K., and C. Newman, "Network 163.6147 - News Transfer Protocol (NNTP) Extension for 163.6148 - Authentication", 163.6149 - RFC 4643, October 2006. 163.6150 - 163.6151 - [NNTP-STREAM] Vinocur, J. and K. Murchison, "Network News Transfer 163.6152 - Protocol (NNTP) Extension for Streaming Feeds", 163.6153 - RFC 4644, October 2006. 163.6154 - 163.6155 - 163.6156 - 163.6157 - 163.6158 - 163.6159 - 163.6160 -Feather Standards Track [Page 110] 163.6161 - 163.6162 -RFC 3977 Network News Transfer Protocol (NNTP) October 2006 163.6163 - 163.6164 - 163.6165 - [NNTP-TLS] Murchison, K., Vinocur, J., and C. Newman, "Using 163.6166 - Transport Layer Security (TLS) with Network News 163.6167 - Transfer Protocol (NNTP)", RFC 4642, October 2006. 163.6168 - 163.6169 - [RFC1036] Horton, M. and R. Adams, "Standard for interchange of 163.6170 - USENET messages", RFC 1036, December 1987. 163.6171 - 163.6172 - [RFC1305] Mills, D., "Network Time Protocol (Version 3) 163.6173 - Specification, Implementation and Analysis", RFC 1305, 163.6174 - March 1992. 163.6175 - 163.6176 - [RFC1869] Klensin, J., Freed, N., Rose, M., Stefferud, E., and D. 163.6177 - Crocker, "SMTP Service Extensions", STD 10, RFC 1869, 163.6178 - November 1995. 163.6179 - 163.6180 - [RFC2616] Fielding, R., Gettys, J., Mogul, J., Frystyk, H., 163.6181 - Masinter, L., Leach, P., and T. Berners-Lee, "Hypertext 163.6182 - Transfer Protocol -- HTTP/1.1", RFC 2616, June 1999. 163.6183 - 163.6184 - [RFC2629] Rose, M., "Writing I-Ds and RFCs using XML", RFC 2629, 163.6185 - June 1999. 163.6186 - 163.6187 - [RFC2822] Resnick, P., "Internet Message Format", RFC 2822, April 163.6188 - 2001. 163.6189 - 163.6190 - [RFC2980] Barber, S., "Common NNTP Extensions", RFC 2980, October 163.6191 - 2000. 163.6192 - 163.6193 - [ROBE1995] Robertson, R., "FAQ: Overview database / NOV General 163.6194 - Information", January 1995. 163.6195 - 163.6196 - There is no definitive copy of this document known to 163.6197 - the author. It was previously posted as the Usenet 163.6198 - article <news:nov-faq-1-930909720@agate.Berkeley.EDU> 163.6199 - 163.6200 - [SALZ1992] Salz, R., "Manual Page for wildmat(3) from the INN 1.4 163.6201 - distribution, Revision 1.10", April 1992. 163.6202 - 163.6203 - There is no definitive copy of this document known to 163.6204 - the author. 163.6205 - 163.6206 - 163.6207 - 163.6208 - 163.6209 - 163.6210 - 163.6211 - 163.6212 - 163.6213 - 163.6214 - 163.6215 - 163.6216 -Feather Standards Track [Page 111] 163.6217 - 163.6218 -RFC 3977 Network News Transfer Protocol (NNTP) October 2006 163.6219 - 163.6220 - 163.6221 -Appendix A. Interaction with Other Specifications 163.6222 - 163.6223 - NNTP is most often used for transferring articles that conform to 163.6224 - RFC 1036 [RFC1036] (such articles are called "Netnews articles" 163.6225 - here). It is also sometimes used for transferring email messages 163.6226 - that conform to RFC 2822 [RFC2822] (such articles are called "email 163.6227 - articles" here). In this situation, articles must conform both to 163.6228 - this specification and to that other one; this appendix describes 163.6229 - some relevant issues. 163.6230 - 163.6231 -A.1. Header Folding 163.6232 - 163.6233 - NNTP allows a header line to be folded (by inserting a CRLF pair) 163.6234 - before any space or TAB character. 163.6235 - 163.6236 - Both email and Netnews articles are required to have at least one 163.6237 - octet other than space or TAB on each header line. Thus, folding can 163.6238 - only happen at one point in each sequence of consecutive spaces or 163.6239 - TABs. Netnews articles are further required to have the header name, 163.6240 - colon, and following space all on the first line; folding may only 163.6241 - happen beyond that space. Finally, some non-conforming software will 163.6242 - remove trailing spaces and TABs from a line. Therefore, it might be 163.6243 - inadvisable to fold a header after a space or TAB. 163.6244 - 163.6245 - For maximum safety, header lines SHOULD conform to the following 163.6246 - syntax rather than to that in Section 9.7. 163.6247 - 163.6248 - 163.6249 - header = header-name ":" SP [header-content] CRLF 163.6250 - header-content = [WS] token *( [CRLF] WS token ) 163.6251 - 163.6252 -A.2. Message-IDs 163.6253 - 163.6254 - Every article handled by an NNTP server MUST have a unique 163.6255 - message-id. For the purposes of this specification, a message-id is 163.6256 - an arbitrary opaque string that merely needs to meet certain 163.6257 - syntactic requirements and is just a way to refer to the article. 163.6258 - 163.6259 - Because there is a significant risk that old articles will be 163.6260 - reinjected into the global Usenet system, RFC 1036 [RFC1036] requires 163.6261 - that message-ids are globally unique for all time. 163.6262 - 163.6263 - This specification states that message-ids are the same if and only 163.6264 - if they consist of the same sequence of octets. Other specifications 163.6265 - may define two different sequences as being equal because they are 163.6266 - putting an interpretation on particular characters. RFC 2822 163.6267 - [RFC2822] has a concept of "quoted" and "escaped" characters. It 163.6268 - therefore considers the three message-ids: 163.6269 - 163.6270 - 163.6271 - 163.6272 -Feather Standards Track [Page 112] 163.6273 - 163.6274 -RFC 3977 Network News Transfer Protocol (NNTP) October 2006 163.6275 - 163.6276 - 163.6277 - <ab.cd@example.com> 163.6278 - <"ab.cd"@example.com> 163.6279 - <"ab.\cd"@example.com> 163.6280 - 163.6281 - as being identical. Therefore, an NNTP implementation handing email 163.6282 - articles must ensure that only one of these three appears in the 163.6283 - protocol and that the other two are converted to it as and when 163.6284 - necessary, such as when a client checks the results of a NEWNEWS 163.6285 - command against an internal database of message-ids. Note that 163.6286 - RFC 1036 [RFC1036] never treats two different strings as being 163.6287 - identical. Its successor (as of the time of writing) restricts the 163.6288 - syntax of message-ids so that, whenever RFC 2822 would treat two 163.6289 - strings as equivalent, only one of them is valid (in the above 163.6290 - example, only the first string is valid). 163.6291 - 163.6292 - This specification does not describe how the message-id of an article 163.6293 - is determined; it may be deduced from the contents of the article or 163.6294 - derived from some external source. If the server is also conforming 163.6295 - to another specification that contains a definition of message-id 163.6296 - compatible with this one, the server SHOULD use those message-ids. A 163.6297 - common approach, and one that SHOULD be used for email and Netnews 163.6298 - articles, is to extract the message-id from the contents of a header 163.6299 - with name "Message-ID". This may not be as simple as copying the 163.6300 - entire header contents; it may be necessary to strip off comments and 163.6301 - undo quoting, or to reduce "equivalent" message-ids to a canonical 163.6302 - form. 163.6303 - 163.6304 - If an article is obtained through the IHAVE command, there will be a 163.6305 - message-id provided with the command. The server MAY either use it 163.6306 - or determine one from the article contents. However, whichever it 163.6307 - does, it SHOULD ensure that, if the IHAVE command is repeated with 163.6308 - the same argument and article, it will be recognized as a duplicate. 163.6309 - 163.6310 - If an article does not contain a message-id that the server can 163.6311 - identify, it MUST synthesize one. This could, for example, be a 163.6312 - simple sequence number or be based on the date and time when the 163.6313 - article arrived. When email or Netnews articles are handled, a 163.6314 - Message-ID header SHOULD be added to ensure global consistency and 163.6315 - uniqueness. 163.6316 - 163.6317 - Note that, because the message-id might not have been derived from 163.6318 - the Message-ID header in the article, the following example is 163.6319 - legitimate (though unusual): 163.6320 - 163.6321 - 163.6322 - 163.6323 - 163.6324 - 163.6325 - 163.6326 - 163.6327 - 163.6328 -Feather Standards Track [Page 113] 163.6329 - 163.6330 -RFC 3977 Network News Transfer Protocol (NNTP) October 2006 163.6331 - 163.6332 - 163.6333 - [C] HEAD <45223423@example.com> 163.6334 - [S] 221 0 <45223423@example.com> 163.6335 - [S] Path: pathost!demo!whitehouse!not-for-mail 163.6336 - [S] Message-ID: <1234@example.net> 163.6337 - [S] From: "Demo User" <nobody@example.net> 163.6338 - [S] Newsgroups: misc.test 163.6339 - [S] Subject: I am just a test article 163.6340 - [S] Date: 6 Oct 1998 04:38:40 -0500 163.6341 - [S] Organization: An Example Net, Uncertain, Texas 163.6342 - [S] . 163.6343 - 163.6344 -A.3. Article Posting 163.6345 - 163.6346 - As far as NNTP is concerned, the POST and IHAVE commands provide the 163.6347 - same basic facilities in a slightly different way. However, they 163.6348 - have rather different intentions. 163.6349 - 163.6350 - The IHAVE command is intended for transmitting conforming articles 163.6351 - between a system of NNTP servers, with all articles perhaps also 163.6352 - conforming to another specification (e.g., all articles are Netnews 163.6353 - articles). It is expected that the client will already have done any 163.6354 - necessary validation (or that it has in turn obtained the article 163.6355 - from a third party that has done so); therefore, the contents SHOULD 163.6356 - be left unchanged. 163.6357 - 163.6358 - In contrast, the POST command is intended for use when an end-user is 163.6359 - injecting a newly created article into a such a system. The article 163.6360 - being transferred might not be a conforming email or Netnews article, 163.6361 - and the server is expected to validate it and, if necessary, to 163.6362 - convert it to the right form for onward distribution. This is often 163.6363 - done by a separate piece of software on the server installation; if 163.6364 - so, the NNTP server SHOULD pass the incoming article to that software 163.6365 - unaltered, making no attempt to filter characters, to fold or limit 163.6366 - lines, or to process the incoming text otherwise. 163.6367 - 163.6368 - The POST command can fail in various ways, and clients should be 163.6369 - prepared to re-send an article. When doing so, however, it is often 163.6370 - important to ensure (as far as possible) that the same message-id is 163.6371 - allocated to both attempts so that the server, or other servers, can 163.6372 - recognize the two articles as duplicates. In the case of email or 163.6373 - Netnews articles, therefore, the posted article SHOULD contain a 163.6374 - header with the name "Message-ID", and the contents of this header 163.6375 - SHOULD be identical on each attempt. The server SHOULD ensure that 163.6376 - two POSTed articles with the same contents for this header are 163.6377 - recognized as identical and that the same message-id is allocated, 163.6378 - whether or not those contents are suitable for use as the message-id. 163.6379 - 163.6380 - 163.6381 - 163.6382 - 163.6383 - 163.6384 -Feather Standards Track [Page 114] 163.6385 - 163.6386 -RFC 3977 Network News Transfer Protocol (NNTP) October 2006 163.6387 - 163.6388 - 163.6389 -Appendix B. Summary of Commands 163.6390 - 163.6391 - This section contains a list of every command defined in this 163.6392 - document, ordered by command name and by indicating capability. 163.6393 - 163.6394 - Ordered by command name: 163.6395 - 163.6396 - +-------------------+-----------------------+---------------+ 163.6397 - | Command | Indicating capability | Definition | 163.6398 - +-------------------+-----------------------+---------------+ 163.6399 - | ARTICLE | READER | Section 6.2.1 | 163.6400 - | BODY | READER | Section 6.2.3 | 163.6401 - | CAPABILITIES | mandatory | Section 5.2 | 163.6402 - | DATE | READER | Section 7.1 | 163.6403 - | GROUP | READER | Section 6.1.1 | 163.6404 - | HDR | HDR | Section 8.5 | 163.6405 - | HEAD | mandatory | Section 6.2.2 | 163.6406 - | HELP | mandatory | Section 7.2 | 163.6407 - | IHAVE | IHAVE | Section 6.3.2 | 163.6408 - | LAST | READER | Section 6.1.3 | 163.6409 - | LIST | LIST | Section 7.6.1 | 163.6410 - | LIST ACTIVE.TIMES | LIST | Section 7.6.4 | 163.6411 - | LIST ACTIVE | LIST | Section 7.6.3 | 163.6412 - | LIST DISTRIB.PATS | LIST | Section 7.6.5 | 163.6413 - | LIST HEADERS | HDR | Section 8.6 | 163.6414 - | LIST NEWSGROUPS | LIST | Section 7.6.6 | 163.6415 - | LIST OVERVIEW.FMT | OVER | Section 8.4 | 163.6416 - | LISTGROUP | READER | Section 6.1.2 | 163.6417 - | MODE READER | MODE-READER | Section 5.3 | 163.6418 - | NEWGROUPS | READER | Section 7.3 | 163.6419 - | NEWNEWS | NEWNEWS | Section 7.4 | 163.6420 - | NEXT | READER | Section 6.1.4 | 163.6421 - | OVER | OVER | Section 8.3 | 163.6422 - | POST | POST | Section 6.3.1 | 163.6423 - | QUIT | mandatory | Section 5.4 | 163.6424 - | STAT | mandatory | Section 6.2.4 | 163.6425 - +-------------------+-----------------------+---------------+ 163.6426 - 163.6427 - 163.6428 - 163.6429 - 163.6430 - 163.6431 - 163.6432 - 163.6433 - 163.6434 - 163.6435 - 163.6436 - 163.6437 - 163.6438 - 163.6439 - 163.6440 -Feather Standards Track [Page 115] 163.6441 - 163.6442 -RFC 3977 Network News Transfer Protocol (NNTP) October 2006 163.6443 - 163.6444 - 163.6445 - Ordered by indicating capability: 163.6446 - 163.6447 - +-------------------+-----------------------+---------------+ 163.6448 - | Command | Indicating capability | Definition | 163.6449 - +-------------------+-----------------------+---------------+ 163.6450 - | CAPABILITIES | mandatory | Section 5.2 | 163.6451 - | HEAD | mandatory | Section 6.2.2 | 163.6452 - | HELP | mandatory | Section 7.2 | 163.6453 - | QUIT | mandatory | Section 5.4 | 163.6454 - | STAT | mandatory | Section 6.2.4 | 163.6455 - | HDR | HDR | Section 8.5 | 163.6456 - | LIST HEADERS | HDR | Section 8.6 | 163.6457 - | IHAVE | IHAVE | Section 6.3.2 | 163.6458 - | LIST | LIST | Section 7.6.1 | 163.6459 - | LIST ACTIVE | LIST | Section 7.6.3 | 163.6460 - | LIST ACTIVE.TIMES | LIST | Section 7.6.4 | 163.6461 - | LIST DISTRIB.PATS | LIST | Section 7.6.5 | 163.6462 - | LIST NEWSGROUPS | LIST | Section 7.6.6 | 163.6463 - | MODE READER | MODE-READER | Section 5.3 | 163.6464 - | NEWNEWS | NEWNEWS | Section 7.4 | 163.6465 - | OVER | OVER | Section 8.3 | 163.6466 - | LIST OVERVIEW.FMT | OVER | Section 8.4 | 163.6467 - | POST | POST | Section 6.3.1 | 163.6468 - | ARTICLE | READER | Section 6.2.1 | 163.6469 - | BODY | READER | Section 6.2.3 | 163.6470 - | DATE | READER | Section 7.1 | 163.6471 - | GROUP | READER | Section 6.1.1 | 163.6472 - | LAST | READER | Section 6.1.3 | 163.6473 - | LISTGROUP | READER | Section 6.1.2 | 163.6474 - | NEWGROUPS | READER | Section 7.3 | 163.6475 - | NEXT | READER | Section 6.1.4 | 163.6476 - +-------------------+-----------------------+---------------+ 163.6477 - 163.6478 - 163.6479 - 163.6480 - 163.6481 - 163.6482 - 163.6483 - 163.6484 - 163.6485 - 163.6486 - 163.6487 - 163.6488 - 163.6489 - 163.6490 - 163.6491 - 163.6492 - 163.6493 - 163.6494 - 163.6495 - 163.6496 -Feather Standards Track [Page 116] 163.6497 - 163.6498 -RFC 3977 Network News Transfer Protocol (NNTP) October 2006 163.6499 - 163.6500 - 163.6501 -Appendix C. Summary of Response Codes 163.6502 - 163.6503 - This section contains a list of every response code defined in this 163.6504 - document and indicates whether it is multi-line, which commands can 163.6505 - generate it, what arguments it has, and what its meaning is. 163.6506 - 163.6507 - Response code 100 (multi-line) 163.6508 - Generated by: HELP 163.6509 - Meaning: help text follows. 163.6510 - 163.6511 - Response code 101 (multi-line) 163.6512 - Generated by: CAPABILITIES 163.6513 - Meaning: capabilities list follows. 163.6514 - 163.6515 - Response code 111 163.6516 - Generated by: DATE 163.6517 - 1 argument: yyyymmddhhmmss 163.6518 - Meaning: server date and time. 163.6519 - 163.6520 - Response code 200 163.6521 - Generated by: initial connection, MODE READER 163.6522 - Meaning: service available, posting allowed. 163.6523 - 163.6524 - Response code 201 163.6525 - Generated by: initial connection, MODE READER 163.6526 - Meaning: service available, posting prohibited. 163.6527 - 163.6528 - Response code 205 163.6529 - Generated by: QUIT 163.6530 - Meaning: connection closing (the server immediately closes the 163.6531 - connection). 163.6532 - 163.6533 - Response code 211 163.6534 - The 211 response code has two completely different forms, 163.6535 - depending on which command generated it: 163.6536 - 163.6537 - (not multi-line) 163.6538 - Generated by: GROUP 163.6539 - 4 arguments: number low high group 163.6540 - Meaning: group selected. 163.6541 - 163.6542 - (multi-line) 163.6543 - Generated by: LISTGROUP 163.6544 - 4 arguments: number low high group 163.6545 - Meaning: article numbers follow. 163.6546 - 163.6547 - 163.6548 - 163.6549 - 163.6550 - 163.6551 - 163.6552 -Feather Standards Track [Page 117] 163.6553 - 163.6554 -RFC 3977 Network News Transfer Protocol (NNTP) October 2006 163.6555 - 163.6556 - 163.6557 - Response code 215 (multi-line) 163.6558 - Generated by: LIST 163.6559 - Meaning: information follows. 163.6560 - 163.6561 - Response code 220 (multi-line) 163.6562 - Generated by: ARTICLE 163.6563 - 2 arguments: n message-id 163.6564 - Meaning: article follows. 163.6565 - 163.6566 - Response code 221 (multi-line) 163.6567 - Generated by: HEAD 163.6568 - 2 arguments: n message-id 163.6569 - Meaning: article headers follow. 163.6570 - 163.6571 - Response code 222 (multi-line) 163.6572 - Generated by: BODY 163.6573 - 2 arguments: n message-id 163.6574 - Meaning: article body follows. 163.6575 - 163.6576 - Response code 223 163.6577 - Generated by: LAST, NEXT, STAT 163.6578 - 2 arguments: n message-id 163.6579 - Meaning: article exists and selected. 163.6580 - 163.6581 - Response code 224 (multi-line) 163.6582 - Generated by: OVER 163.6583 - Meaning: overview information follows. 163.6584 - 163.6585 - Response code 225 (multi-line) 163.6586 - Generated by: HDR 163.6587 - Meaning: headers follow. 163.6588 - 163.6589 - Response code 230 (multi-line) 163.6590 - Generated by: NEWNEWS 163.6591 - Meaning: list of new articles follows. 163.6592 - 163.6593 - Response code 231 (multi-line) 163.6594 - Generated by: NEWGROUPS 163.6595 - Meaning: list of new newsgroups follows. 163.6596 - 163.6597 - Response code 235 163.6598 - Generated by: IHAVE (second stage) 163.6599 - Meaning: article transferred OK. 163.6600 - 163.6601 - Response code 240 163.6602 - Generated by: POST (second stage) 163.6603 - Meaning: article received OK. 163.6604 - 163.6605 - 163.6606 - 163.6607 - 163.6608 -Feather Standards Track [Page 118] 163.6609 - 163.6610 -RFC 3977 Network News Transfer Protocol (NNTP) October 2006 163.6611 - 163.6612 - 163.6613 - Response code 335 163.6614 - Generated by: IHAVE (first stage) 163.6615 - Meaning: send article to be transferred. 163.6616 - 163.6617 - Response code 340 163.6618 - Generated by: POST (first stage) 163.6619 - Meaning: send article to be posted. 163.6620 - 163.6621 - Response code 400 163.6622 - Generic response and generated by initial connection 163.6623 - Meaning: service not available or no longer available (the server 163.6624 - immediately closes the connection). 163.6625 - 163.6626 - Response code 401 163.6627 - Generic response 163.6628 - 1 argument: capability-label 163.6629 - Meaning: the server is in the wrong mode; the indicated capability 163.6630 - should be used to change the mode. 163.6631 - 163.6632 - Response code 403 163.6633 - Generic response 163.6634 - Meaning: internal fault or problem preventing action being taken. 163.6635 - 163.6636 - Response code 411 163.6637 - Generated by: GROUP, LISTGROUP 163.6638 - Meaning: no such newsgroup. 163.6639 - 163.6640 - Response code 412 163.6641 - Generated by: ARTICLE, BODY, GROUP, HDR, HEAD, LAST, LISTGROUP, 163.6642 - NEXT, OVER, STAT 163.6643 - Meaning: no newsgroup selected. 163.6644 - 163.6645 - Response code 420 163.6646 - Generated by: ARTICLE, BODY, HDR, HEAD, LAST, NEXT, OVER, STAT 163.6647 - Meaning: current article number is invalid. 163.6648 - 163.6649 - Response code 421 163.6650 - Generated by: NEXT 163.6651 - Meaning: no next article in this group. 163.6652 - 163.6653 - Response code 422 163.6654 - Generated by: LAST 163.6655 - Meaning: no previous article in this group. 163.6656 - 163.6657 - Response code 423 163.6658 - Generated by: ARTICLE, BODY, HDR, HEAD, OVER, STAT 163.6659 - Meaning: no article with that number or in that range. 163.6660 - 163.6661 - 163.6662 - 163.6663 - 163.6664 -Feather Standards Track [Page 119] 163.6665 - 163.6666 -RFC 3977 Network News Transfer Protocol (NNTP) October 2006 163.6667 - 163.6668 - 163.6669 - Response code 430 163.6670 - Generated by: ARTICLE, BODY, HDR, HEAD, OVER, STAT 163.6671 - Meaning: no article with that message-id. 163.6672 - 163.6673 - Response code 435 163.6674 - Generated by: IHAVE (first stage) 163.6675 - Meaning: article not wanted. 163.6676 - 163.6677 - Response code 436 163.6678 - Generated by: IHAVE (either stage) 163.6679 - Meaning: transfer not possible (first stage) or failed (second 163.6680 - stage); try again later. 163.6681 - 163.6682 - Response code 437 163.6683 - Generated by: IHAVE (second stage) 163.6684 - Meaning: transfer rejected; do not retry. 163.6685 - 163.6686 - Response code 440 163.6687 - Generated by: POST (first stage) 163.6688 - Meaning: posting not permitted. 163.6689 - 163.6690 - Response code 441 163.6691 - Generated by: POST (second stage) 163.6692 - Meaning: posting failed. 163.6693 - 163.6694 - Response code 480 163.6695 - Generic response 163.6696 - Meaning: command unavailable until the client has authenticated 163.6697 - itself. 163.6698 - 163.6699 - Response code 483 163.6700 - Generic response 163.6701 - Meaning: command unavailable until suitable privacy has been 163.6702 - arranged. 163.6703 - 163.6704 - Response code 500 163.6705 - Generic response 163.6706 - Meaning: unknown command. 163.6707 - 163.6708 - Response code 501 163.6709 - Generic response 163.6710 - Meaning: syntax error in command. 163.6711 - 163.6712 - 163.6713 - 163.6714 - 163.6715 - 163.6716 - 163.6717 - 163.6718 - 163.6719 - 163.6720 -Feather Standards Track [Page 120] 163.6721 - 163.6722 -RFC 3977 Network News Transfer Protocol (NNTP) October 2006 163.6723 - 163.6724 - 163.6725 - Response code 502 163.6726 - Generic response and generated by initial connection 163.6727 - 163.6728 - Meaning for the initial connection and the MODE READER command: 163.6729 - service permanently unavailable (the server immediately closes the 163.6730 - connection). 163.6731 - 163.6732 - Meaning for all other commands: command not permitted (and there 163.6733 - is no way for the client to change this). 163.6734 - 163.6735 - Response code 503 163.6736 - Generic response 163.6737 - Meaning: feature not supported. 163.6738 - 163.6739 - Response code 504 163.6740 - Generic response 163.6741 - Meaning: error in base64-encoding [RFC4648] of an argument. 163.6742 - 163.6743 -Appendix D. Changes from RFC 977 163.6744 - 163.6745 - In general every attempt has been made to ensure that the protocol 163.6746 - specification in this document is compatible with the version 163.6747 - specified in RFC 977 [RFC977] and the various facilities adopted from 163.6748 - RFC 2980 [RFC2980]. However, there have been a number of changes, 163.6749 - some compatible and some not. 163.6750 - 163.6751 - This appendix lists these changes. It is not guaranteed to be 163.6752 - exhaustive or correct and MUST NOT be relied on. 163.6753 - 163.6754 - o A formal syntax specification (Section 9) has been added. 163.6755 - 163.6756 - o The default character set is changed from US-ASCII [ANSI1986] to 163.6757 - UTF-8 [RFC3629] (note that US-ASCII is a subset of UTF-8). This 163.6758 - matter is discussed further in Section 10. 163.6759 - 163.6760 - o All articles are required to have a message-id, eliminating the 163.6761 - "<0>" placeholder used in RFC 977 in some responses. 163.6762 - 163.6763 - o The newsgroup name matching capabilities already documented in 163.6764 - RFC 977 ("wildmats", Section 4) are clarified and extended. The 163.6765 - new facilities (e.g., the use of commas and exclamation marks) are 163.6766 - allowed wherever wildmats appear in the protocol. 163.6767 - 163.6768 - o Support for pipelining of commands (Section 3.5) is made 163.6769 - mandatory. 163.6770 - 163.6771 - 163.6772 - 163.6773 - 163.6774 - 163.6775 - 163.6776 -Feather Standards Track [Page 121] 163.6777 - 163.6778 -RFC 3977 Network News Transfer Protocol (NNTP) October 2006 163.6779 - 163.6780 - 163.6781 - o The principles behind response codes (Section 3.2) have been 163.6782 - tidied up. In particular: 163.6783 - 163.6784 - * the x8x response code family, formerly used for private 163.6785 - extensions, is now reserved for authentication and privacy 163.6786 - extensions; 163.6787 - 163.6788 - * the x9x response code family, formerly intended for debugging 163.6789 - facilities, are now reserved for private extensions; 163.6790 - 163.6791 - * the 502 and 503 generic response codes (Section 3.2.1) have 163.6792 - been redefined; 163.6793 - 163.6794 - * new 401, 403, 480, 483, and 504 generic response codes have 163.6795 - been added. 163.6796 - 163.6797 - o The rules for article numbering (Section 6) have been clarified 163.6798 - (also see Section 6.1.1.2). 163.6799 - 163.6800 - o The SLAVE command (which was ill-defined) is removed from the 163.6801 - protocol. 163.6802 - 163.6803 - o Four-digit years are permitted in the NEWNEWS (Section 7.4) and 163.6804 - NEWGROUPS (Section 7.3) commands (two-digit years are still 163.6805 - permitted). The optional distribution parameter to these commands 163.6806 - has been removed. 163.6807 - 163.6808 - o The LIST command (Section 7.6.1) is greatly extended; the original 163.6809 - is available as LIST ACTIVE, while new variants include 163.6810 - ACTIVE.TIMES, DISTRIB.PATS, and NEWSGROUPS. A new "m" status flag 163.6811 - is added to the LIST ACTIVE response. 163.6812 - 163.6813 - o A new CAPABILITIES command (Section 5.2) allows clients to 163.6814 - determine what facilities are supported by a server. 163.6815 - 163.6816 - o The DATE command (Section 7.1) is adopted from RFC 2980 163.6817 - effectively unchanged. 163.6818 - 163.6819 - o The LISTGROUP command (Section 6.1.2) is adopted from RFC 2980. 163.6820 - An optional range argument has been added, and the 211 initial 163.6821 - response line now has the same format as the 211 response from the 163.6822 - GROUP command. 163.6823 - 163.6824 - o The MODE READER command (Section 5.3) is adopted from RFC 2980 and 163.6825 - its meaning and effects clarified. 163.6826 - 163.6827 - o The XHDR command in RFC 2980 has been formalised as the new HDR 163.6828 - (Section 8.5) and LIST HEADERS (Section 8.6) commands. 163.6829 - 163.6830 - 163.6831 - 163.6832 -Feather Standards Track [Page 122] 163.6833 - 163.6834 -RFC 3977 Network News Transfer Protocol (NNTP) October 2006 163.6835 - 163.6836 - 163.6837 - o The XOVER command in RFC 2980 has been formalised as the new OVER 163.6838 - (Section 8.3) and LIST OVERVIEW.FMT (Section 8.4) commands. The 163.6839 - former can be applied to a message-id as well as to a range. 163.6840 - 163.6841 - o The concept of article metadata (Section 8.1) has been formalised, 163.6842 - allowing the Bytes and Lines pseudo-headers to be deprecated. 163.6843 - 163.6844 - Client authors should note in particular that lack of support for the 163.6845 - CAPABILITIES command is a good indication that the server does not 163.6846 - support this specification. 163.6847 - 163.6848 - 163.6849 - 163.6850 - 163.6851 - 163.6852 - 163.6853 - 163.6854 - 163.6855 - 163.6856 - 163.6857 - 163.6858 - 163.6859 - 163.6860 - 163.6861 - 163.6862 - 163.6863 - 163.6864 - 163.6865 - 163.6866 - 163.6867 - 163.6868 - 163.6869 - 163.6870 - 163.6871 - 163.6872 - 163.6873 - 163.6874 - 163.6875 - 163.6876 - 163.6877 - 163.6878 - 163.6879 - 163.6880 - 163.6881 - 163.6882 - 163.6883 - 163.6884 - 163.6885 - 163.6886 - 163.6887 - 163.6888 -Feather Standards Track [Page 123] 163.6889 - 163.6890 -RFC 3977 Network News Transfer Protocol (NNTP) October 2006 163.6891 - 163.6892 - 163.6893 -Author's Address 163.6894 - 163.6895 - Clive D.W. Feather 163.6896 - THUS plc 163.6897 - 322 Regents Park Road 163.6898 - London 163.6899 - N3 2QQ 163.6900 - United Kingdom 163.6901 - 163.6902 - Phone: +44 20 8495 6138 163.6903 - Fax: +44 870 051 9937 163.6904 - EMail: clive@demon.net 163.6905 - URI: http://www.davros.org/ 163.6906 - 163.6907 - 163.6908 - 163.6909 - 163.6910 - 163.6911 - 163.6912 - 163.6913 - 163.6914 - 163.6915 - 163.6916 - 163.6917 - 163.6918 - 163.6919 - 163.6920 - 163.6921 - 163.6922 - 163.6923 - 163.6924 - 163.6925 - 163.6926 - 163.6927 - 163.6928 - 163.6929 - 163.6930 - 163.6931 - 163.6932 - 163.6933 - 163.6934 - 163.6935 - 163.6936 - 163.6937 - 163.6938 - 163.6939 - 163.6940 - 163.6941 - 163.6942 - 163.6943 - 163.6944 -Feather Standards Track [Page 124] 163.6945 - 163.6946 -RFC 3977 Network News Transfer Protocol (NNTP) October 2006 163.6947 - 163.6948 - 163.6949 -Full Copyright Statement 163.6950 - 163.6951 -Copyright (C) The Internet Society (2006). 163.6952 - 163.6953 - This document is subject to the rights, licenses and restrictions 163.6954 - contained in BCP 78, and except as set forth therein, the authors 163.6955 - retain all their rights. 163.6956 - 163.6957 - This document and the information contained herein are provided on an 163.6958 - "AS IS" basis and THE CONTRIBUTOR, THE ORGANIZATION HE/SHE REPRESENTS 163.6959 - OR IS SPONSORED BY (IF ANY), THE INTERNET SOCIETY AND THE INTERNET 163.6960 - ENGINEERING TASK FORCE DISCLAIM ALL WARRANTIES, EXPRESS OR IMPLIED, 163.6961 - INCLUDING BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE 163.6962 - INFORMATION HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED 163.6963 - WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. 163.6964 - 163.6965 -Intellectual Property 163.6966 - 163.6967 - The IETF takes no position regarding the validity or scope of any 163.6968 - Intellectual Property Rights or other rights that might be claimed to 163.6969 - pertain to the implementation or use of the technology described in 163.6970 - this document or the extent to which any license under such rights 163.6971 - might or might not be available; nor does it represent that it has 163.6972 - made any independent effort to identify any such rights. Information 163.6973 - on the procedures with respect to rights in RFC documents can be 163.6974 - found in BCP 78 and BCP 79. 163.6975 - 163.6976 - Copies of IPR disclosures made to the IETF Secretariat and any 163.6977 - assurances of licenses to be made available, or the result of an 163.6978 - attempt made to obtain a general license or permission for the use of 163.6979 - such proprietary rights by implementers or users of this 163.6980 - specification can be obtained from the IETF on-line IPR repository at 163.6981 - http://www.ietf.org/ipr. 163.6982 - 163.6983 - The IETF invites any interested party to bring to its attention any 163.6984 - copyrights, patents or patent applications, or other proprietary 163.6985 - rights that may cover technology that may be required to implement 163.6986 - this standard. Please address the information to the IETF at ietf- 163.6987 - ipr@ietf.org. 163.6988 - 163.6989 -Acknowledgement 163.6990 - 163.6991 - Funding for the RFC Editor function is provided by the IETF 163.6992 - Administrative Support Activity (IASA). 163.6993 - 163.6994 - 163.6995 - 163.6996 - 163.6997 - 163.6998 - 163.6999 - 163.7000 -Feather Standards Track [Page 125] 163.7001 -
164.1 --- a/trunk/test/StringTemplateTest.java Tue Jan 20 10:21:03 2009 +0100 164.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 164.3 @@ -1,26 +0,0 @@ 164.4 -/* 164.5 - * To change this template, choose Tools | Templates 164.6 - * and open the template in the editor. 164.7 - */ 164.8 - 164.9 -package test; 164.10 - 164.11 -import com.so.news.util.StringTemplate; 164.12 - 164.13 -/** 164.14 - * 164.15 - * @author chris 164.16 - */ 164.17 -public class StringTemplateTest 164.18 -{ 164.19 - public static void main(String[] args) 164.20 - { 164.21 - StringTemplate templ 164.22 - = new StringTemplate("SELECT %row FROM %table WHERE %row = ich"); 164.23 - 164.24 - templ.set("row", "name"); 164.25 - templ.set("table", "UserTable"); 164.26 - 164.27 - System.out.println(templ.toString()); 164.28 - } 164.29 -}