root/nntp/hdr.cc

Revision b4f0cdb42e637fd017a965937ff7dd3170eb55ac, 6.4 KB (checked in by Antti-Juhani Kaijanaho <antti-juhani@…>, 16 months ago)

#77: Fix XRef handling in NNTP

Signed-off-by: Antti-Juhani Kaijanaho <antti-juhani@…>

  • Property mode set to 100644
Line 
1/*  This file is part of Alue, the multiprotocol Internet discussion daemon
2
3    Copyright © 2009, 2010, 2011 Antti-Juhani Kaijanaho
4
5    Alue is free software: you can redistribute it and/or modify it
6    under the terms of the GNU General Public License as published by
7    the Free Software Foundation, either version 3 of the License, or
8    (at your option) any later version.
9
10    Alue is distributed in the hope that it will be useful, but
11    WITHOUT ANY WARRANTY; without even the implied warranty of
12    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13    General Public License for more details.
14
15    You should have received a copy of the GNU General Public License
16    along with Alue.  If not, see <http://www.gnu.org/licenses/>.
17
18 */
19
20#include "connection.hh"
21#include "hdrutil.hh"
22#include "lexutils.hh"
23
24#include "../db/db.hh"
25#include "../db/msg.hh"
26#include "../msg/entity.hh"
27
28namespace nntp
29{
30        class hdr : public connection::command
31        {
32        public:
33                enum cmd_type { HDR, XHDR };
34
35                hdr(const char *s, cmd_type cmd) : cmd(cmd) {
36                        connection::register_command(s, this);
37                }
38
39                connection::continuation::ptr
40                perform(connection::cb, const std::string [],  size_t) const;
41
42                void write_capability_line(connection::cb c) const {
43                        if (cmd != HDR) return;
44                        c.send_line("HDR MSGID");
45                }
46        private:
47                void write_article_line(connection::cb,
48                                        std::string hname,
49                                        db::group::number,
50                                        boost::shared_ptr<db::msg> m) const;
51
52                cmd_type cmd;
53        };
54
55        connection::continuation::ptr
56        hdr::perform(connection::cb c, const std::string args[], size_t nargs)
57                const
58        {
59                db::group::number rl = c.current_article(),
60                        rh = c.current_article();
61                std::string hname;
62                switch (nargs) {
63                case 1:
64                        hname = args[0];
65                        break;
66                case 2:
67                        hname = args[0];
68                        if (args[1][0] == '<')
69                        {
70                                boost::shared_ptr<db::msg> m;
71                                try
72                                {
73                                        m = c.dbase().lookup_msgid(args[1]);
74                                }
75                                catch (db::no_such_article)
76                                {
77                                        c.send_line("430 no such article");
78                                        return c.dispatch();
79                                }
80                                if (!m->reading_authz(c.identity()))
81                                {
82                                        c.send_line("480 " + m->msgid() +
83                                                    " is restricted");
84                                        return c.dispatch();
85                                }
86                                if (m->is_censured())
87                                {
88                                        c.send_line("430 no such article");
89                                        return c.dispatch();
90                                }
91
92
93                                c.send_line("221 " + hname + " follows:");
94                                write_article_line(c, hname, 0, m);
95                                c.send_line(".");
96                                return c.dispatch();
97                        }
98                        try {
99                                boost::tie(rl, rh) = parse_range(args[1]);
100                        } catch (parse_exception) {
101                                c.send_line("501 malformed range");
102                                return c.dispatch();
103                        }
104                        break;
105                        /*passthrough*/
106                default:
107                        c.send_line("501 too many parameters");
108                        return c.dispatch();
109                }
110
111
112                if (!c.current_group()) {
113                        c.send_line("412 no group selected");
114                        return c.dispatch();
115                }
116
117                if (rl < c.current_group()->low_mark())
118                        rl = c.current_group()->low_mark();
119                if (rh > c.current_group()->high_mark())
120                        rh = c.current_group()->high_mark();
121
122                c.send_line("221 " + hname + " list follows:");
123
124                for (db::group::number i = rl; i <= rh; i++) {
125                        if (!c.current_group()->is_article(i)) continue;
126                        write_article_line(c, hname, i,
127                                           c.current_group()->get_article(i));
128                }
129                c.send_line(".");
130                return c.dispatch();
131        }
132
133        void hdr::write_article_line(connection::cb c,
134                                     std::string hname,
135                                     db::group::number artnum,
136                                     boost::shared_ptr<db::msg> m)
137                const
138        {
139                if (!m->reading_authz(c.identity()))
140                        return;
141                if (m->is_censured()) return;
142
143                std::string hn = util::to_lower(hname);
144
145                std::ostringstream os;
146                os << artnum << " ";
147                std::string s;
148                if (hn == "lines" || hn == ":lines")
149                        s = boost::lexical_cast<std::string>
150                                (m->get_entity()->get_body_lines());
151                else if (hn == "bytes" || hn == ":bytes")
152                        s = boost::lexical_cast<std::string>
153                                (m->get_entity()->get_size() +
154                                 m->get_xref_field(true).length());
155                else if (hn == "xref")
156                        s = m->get_xref_field(false);
157                else
158                        s = m->get_entity()->get_field(hname, false);
159                over_output_header(os, s);
160                c.send_line(os.str());
161        }
162}
163namespace {
164//        nntp::hdr  hdr("hdr",  nntp::hdr::HDR);
165        nntp::hdr xhdr("xhdr", nntp::hdr::XHDR);
166}
Note: See TracBrowser for help on using the browser.