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 += "<"; break; 29 case '>': result += ">"; break; 30 case '&': result += "&"; break; 31 case '"': result += """; 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 << "<"; break; 44 case '>': out << ">"; break; 45 case '&': out << "&"; break; 46 case '"': out << """; break; 47 default: out << ch; break; 48 // note ' 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