root/uri.cc

Revision 43f521291669f483d361949fa6c886c0fbd94daf, 5.9 KB (checked in by Antti-Juhani Kaijanaho <antti-juhani@…>, 21 months ago)

Add support for paginating thread and article lists.

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 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 "util.hh"
21#include "uri.hh"
22
23#include <boost/lexical_cast.hpp>
24
25const char uri::invalid::msgprefix[] =
26        "Uniform Resource Identifier (URI) invalid";
27
28uri::uri(std::string str)
29        : port(-1)
30{
31        using util::split1L;
32        using util::split1R;
33
34        scheme = split1L(str, ":");
35
36        if (str.substr(0, 2) == "//")
37        {
38                str.erase(0, 2);
39                std::string authority = split1R(str, "/");
40                userinfo = split1L(authority, "@");
41                host = split1R(authority, ":");
42                if (!authority.empty())
43                {
44                        if (!util::is_number(authority))
45                                throw invalid("invalid port");
46                        port = boost::lexical_cast<int>(authority);
47                }
48        }
49
50        path = split1R(str, "?");
51        query = str;
52}
53
54std::string uri::percent_decode(std::string s)
55{
56        std::string rv;
57        rv.reserve(s.length());
58        for (size_t i = 0; i < s.length(); i++)
59        {
60                if (s[i] == '%')
61                {
62                        if (i + 2 >= s.length())
63                                throw uri::invalid("percent encoding "
64                                                   "truncated");
65                        int val = 0;
66                        for (size_t j = 1; j <= 2; j++)
67                        {
68                                val *= 16;
69                                char c = s[i+j];
70                                /**/ if ('0' <= c && c <= '9') val += c-'0';
71                                else if ('a' <= c && c <= 'f') val += c-'a'+10;
72                                else if ('A' <= c && c <= 'F') val += c-'A'+10;
73                                else throw uri::invalid("percent encoding "
74                                                        "invalid");
75                        }
76                        rv += char(val);
77                        i += 2;
78                }
79                else
80                        rv += s[i];
81        }
82        return rv;
83}
84
85std::string uri::percent_encode(std::string s)
86{
87        std::string rv;
88        rv.reserve(s.length());
89        for (size_t i = 0; i < s.length(); i++)
90        {
91                char c = s[i];
92                if ( ('a' <= c && c <= 'z') ||
93                     ('A' <= c && c <= 'Z') ||
94                     ('0' <= c && c <= '9') ||
95                     (c == '/') ||
96                     c == '-' ||
97                     c == '.' ||
98                     c == '_' ||
99                     c == '~')
100                {
101                        rv += c;
102                        continue;
103                }
104                rv += '%';
105                static const char hexdig[] = "0123456789ABCDEF";
106                rv += hexdig[c / 16];
107                rv += hexdig[c % 16];
108        }
109        return rv;
110}
111
112void uri::replace_query_param(std::string name, std::string new_value)
113{
114        remove_query_param(name);
115        if (!query.empty())
116                query += '&';
117        query += name + "=" + percent_encode(new_value);
118}
119
120void uri::replace_query_param(std::string name, int val)
121{
122        std::ostringstream os;
123        os << val;
124        replace_query_param(name, os.str());
125}
126
127void uri::remove_query_param(std::string name)
128{
129        for (size_t ix = 0; ix < query.length(); /**/)
130        {
131                size_t nix = query.find("&", ix+1);
132                if (query.substr(ix, name.length()+1) == name + "=")
133                        query.erase(ix, nix - ix);
134                else
135                {
136                        ix = nix;
137                        if (ix + 1 != 0) ix++;
138                }
139        }
140        for (size_t i = 0; i < query.length(); i++)
141        {
142                if (i > 0 && query[i] == '&' && query[i-1] == '&')
143                {
144                        query.erase(i, 1);
145                        i--;
146                }
147
148        }
149        if (!query.empty() && query[query.length()-1] == '&')
150                query.erase(query.length()-1, 1);
151}
152
153std::string uri::get_query_param(std::string name) const
154{
155        for (size_t ix = 0; ix < query.length(); /**/)
156        {
157                size_t nix = query.find("&", ix+1);
158                size_t eq = ix+name.length();
159                if (eq < query.length() && query[eq] == '=' &&
160                    query.substr(ix, name.length()) == name)
161                {
162                        std::string rv = eq + 1 < query.length()
163                                ? query.substr(eq + 1, nix - eq - 1)
164                                : "";
165                        return percent_decode(rv);
166                }
167                else
168                {
169                        ix = nix;
170                        if (ix + 1 != 0) ix++;
171                }
172        }       
173        return "";
174}
175
176std::string uri::to_string() const
177{
178        std::ostringstream os;
179        if (!scheme.empty()) os << scheme << "://";
180        if (!userinfo.empty()) os << userinfo << "@";
181        if (!host.empty()) os << host;
182        if (port >= 0) os << ":" << port;
183        if (path.empty()) os << "/"; else os << path;
184        if (!query.empty()) os << "?" << query;
185        return os.str();
186}
Note: See TracBrowser for help on using the browser.