#include #include #include #include #include #include class CgiGet { public: typedef std::map params_t; void init() { char* query_env = getenv("QUERY_STRING"); if(!query_env) return; parse(query_env); } const params_t& get_params() const { return params; } private: int from_hex(char d) { if(d >= '0' && d <= '9') { return (d-'0'); } else if(d >= 'A' && d <= 'F') { return (d-'A'+10); } else if(d >= 'a' && d <= 'f') { return (d-'a'+10); } else { return -1; } } bool parse(const std::string& query) { params.clear(); std::string key, value; bool in_value = false; for(std::string::size_type i = 0, l = query.size(); i < l; ++i) { char c = query[i]; switch(c) { case '&': if(key.empty()) return false; params[key] = value; key.clear(); value.clear(); in_value = false; break; case '=': if(in_value) return false; else in_value = true; break; case '%': if(i + 2 >= l) return false; { int d1 = from_hex(query[i+1]), d2 = from_hex(query[i+2]); i += 2; if(d1 < 0 || d2 < 0) return false; c = (char)(d1 << 4 | d2); } // continue default: if(in_value) value.append(1, c); else key.append(1, c); } } if(!key.empty()) { params[key] = value; } return true; } private: params_t params; }; bool is_symbol(char c) { return ((c == '_') || (c >= '0' && c <= '9') || (c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z')); } std::string demangle(const std::string& in) { std::string res; int l_iStatus = 0; char* l_pszDemangledName = abi::__cxa_demangle(in.c_str(), NULL, 0, &l_iStatus); if(l_pszDemangledName) { res = l_pszDemangledName; free(l_pszDemangledName); } return res; } std::string replace_mangle(const std::string& in) { std::string res; for(std::string::size_type i = 0, l = in.size(); i < l; ++i) { char c = in[i]; if(is_symbol(c)) { int j = i+1; for(; j < l && is_symbol(in[j]); ++j); std::string sub(in, i, j-i); std::string de_sub = demangle(sub); if(de_sub.empty()) { res.append(sub); } else { res.append(de_sub); } i = j-1; } else { res.append(1, c); } } return res; } std::string escape_html(const std::string& in) { std::string out; for(std::string::size_type i = 0, l = in.size(); i < l; ++i) { char c = in[i]; switch(c) { case '<': out.append("<"); break; case '>': out.append(">"); break; case '&': out.append("&"); break; default: out.append(1, c); } } return out; } void http_header() { printf("Content-Type: text/html;charset=UTF-8\n\n"); } void http_body(const std::string& lines) { printf("" "" "" " 26th.net - public demangle script" " " " " " " " " " " " " "" "" "

public demangle script

" "

the script can be used to demangle c++ (gcc) method names, e.g. _ZN1AIiE4funcESt3mapISsPiSt4lessISsESaISt4pairIKSsS2_EEE

" "
" "

" "

" "
", escape_html(lines).c_str()); } void http_footer() { printf( "
see also: c++ code
" "" "" ""); } void process_http_get() { http_header(); CgiGet cgi_get; cgi_get.init(); std::string lines_in; std::string lines_out; CgiGet::params_t::const_iterator lines_iter = cgi_get.get_params().find("lines"); if(lines_iter != cgi_get.get_params().end()) { lines_in = lines_iter->second; } if(!lines_in.empty()) { lines_out = replace_mangle(lines_in); } http_body(lines_in); if(!lines_out.empty()) { printf("

result

" "
%s
", escape_html(lines_out).c_str()); } http_footer(); } void process_stdin() { std::string line; while (std::getline(std::cin, line)) { std::cout << replace_mangle(line) << std::endl; } } int main() { process_http_get(); return 0; }