Hooray... sonews/0.5.0 final
HG: Enter commit message. Lines beginning with 'HG:' are removed.
HG: Remove all lines to abort the collapse operation.
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 -}