1 /*=============================================================================
2     Copyright (c) 2002 2004 2006 Joel de Guzman
3     Copyright (c) 2004 Eric Niebler
4     http://spirit.sourceforge.net/
5 
6     Use, modification and distribution is subject to the Boost Software
7     License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
8     http://www.boost.org/LICENSE_1_0.txt)
9 =============================================================================*/
10 #include "utils.hpp"
11 
12 #include <cctype>
13 #include <cstring>
14 #include <map>
15 
16 namespace quickbook { namespace detail
17 {
encode_string(boost::string_ref str)18     std::string encode_string(boost::string_ref str)
19     {
20         std::string result;
21         result.reserve(str.size());
22 
23         for (boost::string_ref::const_iterator it = str.begin();
24             it != str.end(); ++it)
25         {
26             switch (*it)
27             {
28                 case '<': result += "&lt;";    break;
29                 case '>': result += "&gt;";    break;
30                 case '&': result += "&amp;";   break;
31                 case '"': result += "&quot;";  break;
32                 default:  result += *it;       break;
33             }
34         }
35 
36         return result;
37     }
38 
print_char(char ch,std::ostream & out)39     void print_char(char ch, std::ostream& out)
40     {
41         switch (ch)
42         {
43             case '<': out << "&lt;";    break;
44             case '>': out << "&gt;";    break;
45             case '&': out << "&amp;";   break;
46             case '"': out << "&quot;";  break;
47             default:  out << ch;        break;
48             // note &apos; is not included. see the curse of apos:
49             // http://fishbowl.pastiche.org/2003/07/01/the_curse_of_apos
50         }
51     }
52 
print_string(boost::string_ref str,std::ostream & out)53     void print_string(boost::string_ref str, std::ostream& out)
54     {
55         for (boost::string_ref::const_iterator cur = str.begin();
56             cur != str.end(); ++cur)
57         {
58             print_char(*cur, out);
59         }
60     }
61 
filter_identifier_char(char ch)62     char filter_identifier_char(char ch)
63     {
64         if (!std::isalnum(static_cast<unsigned char>(ch)))
65             ch = '_';
66         return static_cast<char>(std::tolower(static_cast<unsigned char>(ch)));
67     }
68 
escape_uri_impl(std::string & uri_param,char const * mark)69     static std::string escape_uri_impl(std::string& uri_param, char const* mark)
70     {
71         // Extra capital characters for validating percent escapes.
72         static char const hex[] = "0123456789abcdefABCDEF";
73 
74         std::string uri;
75         uri.swap(uri_param);
76 
77         for (std::string::size_type n = 0; n < uri.size(); ++n)
78         {
79             if (static_cast<unsigned char>(uri[n]) > 127 ||
80                     (!std::isalnum(static_cast<unsigned char>(uri[n])) &&
81                      !std::strchr(mark, uri[n])) ||
82                     (uri[n] == '%' && !(n + 2 < uri.size() &&
83                                         std::strchr(hex, uri[n+1]) &&
84                                         std::strchr(hex, uri[n+2]))))
85             {
86                 char escape[] = { hex[uri[n] / 16], hex[uri[n] % 16] };
87                 uri.insert(n + 1, escape, 2);
88                 uri[n] = '%';
89                 n += 2;
90             }
91             else if (uri[n] == '%')
92             {
93                 n += 2;
94             }
95         }
96 
97         return uri;
98     }
99 
escape_uri(std::string uri_param)100     std::string escape_uri(std::string uri_param)
101     {
102         // TODO: I don't understand this choice of characters.....
103         return escape_uri_impl(uri_param, "-_.!~*'()?\\/");
104     }
105 
partially_escape_uri(std::string uri_param)106     std::string partially_escape_uri(std::string uri_param)
107     {
108         return escape_uri_impl(uri_param, "-_.!~*'()?\\/:&=#%+");
109     }
110 }}
111