cgicc query string parsing
I'm new to C++ and cgicc, and I want to know if there is an easy way to parse the get parameters to the cgi script? ?action=yes&fu开发者_如何学Pythonnction=no
into an array or something like that?
Here's a simple function using the regular expression library included in C++11.
#include <regex>
// ...
std::map<std::string, std::string> Foo::Parse(const std::string& query)
{
std::map<std::string, std::string> data;
std::regex pattern("([\\w+%]+)=([^&]*)");
auto words_begin = std::sregex_iterator(query.begin(), query.end(), pattern);
auto words_end = std::sregex_iterator();
for (std::sregex_iterator i = words_begin; i != words_end; i++)
{
std::string key = (*i)[1].str();
std::string value = (*i)[2].str();
data[key] = value;
}
return data;
}
A possible solution
read_cgi_input(&items);
http://eekim.com/software/cgihtml/index.html
http://eekim.com/software/cgihtml/cgihtml-5.html#ss5.1
I'd recommend having a look at boost regex library. http://www.boost.org/doc/libs/release/libs/regex/
I designed a program in C++ that may help you
// (c) 2011 enthusiasticgeek
// The code is adapted from James Marshall's getcgivars.c
// tested with the following webservers
// This code is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
// Mongoose and LIGHTTPD
// Feel Free to use leave credits intact
// Compile:
// g++ -g testparse.cpp -o testparse.cgi
// To run:
// place cgi file in the appropriate directory depending on server configuration
// Start webserver and then open internet browser and (assuming script running on localserver, port 8080 under 'cgi_bin' directory) enter something similar to
// http://localhost:8080/cgi_bin/testparse.cgi?name1=value1&name2=value2&name3=value3
#include <iostream>
#include <string>
#include <vector>
#include <algorithm>
#include <iterator>
#include <sstream>
#include <cstdio>
#include <map>
#include <stdlib.h>
#include <cstring>
#include <cctype>
#include <ctype.h>
using namespace std;
vector<string> split(const string& s, const string& delim, const bool keep_empty = true)
{
vector<string> result;
if (delim.empty()) {
result.push_back(s);
return result;
}
string::const_iterator substart = s.begin(), subend;
while (true) {
subend = search(substart, s.end(), delim.begin(), delim.end());
string temp(substart, subend);
if (keep_empty || !temp.empty()) {
result.push_back(temp);
}
if (subend == s.end()) {
break;
}
substart = subend + delim.size();
}
return result;
}
std::map<std::string, std::string>& map_pairs(char* character, std::map<std::string, std::string>& Elements)
{
string test;
string key;
string value;
vector<string>::iterator it;
string character_string = character;
vector<string> words;
//Elements.insert(std::pair<string,string>("0","0"));
//cout << "########## SPLITTING STRING INTO SMALLER CHUNKS ################## " << endl;
words = split(character_string, "&");
//cout << "########## GENERATING KEY VALUE PAIRS ################## " << endl;
for (it=words.begin(); it!=words.end(); ++it)
{
test = *it;
cout<< "string:" << test << endl;
const string::size_type pos_eq = test.find ('=');
if (pos_eq != string::npos)
{
//Assign Key and Value Respectively
key = test.substr (0, pos_eq);
value = test.substr (pos_eq + 1);
//cout << "key = " << key << " and value = " << value << endl;
Elements.insert(std::pair<string,string>(key,value));
}
}
return Elements;
}
std::map<std::string, std::string>& getcgivars(std::map<std::string, std::string>& Elements)
{
register int i ;
char *request_method = NULL;
int content_length;
char *cgiinput = NULL;
// Depending on the request method, read all CGI input into cgiinput
// (really should produce HTML error messages, instead of exit()ing)
request_method= getenv("REQUEST_METHOD") ;
if (!strcmp(request_method, "GET") || !strcmp(request_method, "HEAD") ) {
// Some servers apparently don't provide QUERY_STRING if it's empty,
// so avoid strdup()'ing a NULL pointer here.
char *qs ;
qs= getenv("QUERY_STRING") ;
cgiinput= strdup(qs ? qs : "") ;
}
else if (!strcmp(request_method, "POST")) {
// strcasecmp() is not supported in Windows-- use strcmpi() instead
if ( strcasecmp(getenv("CONTENT_TYPE"), "application/x-www-form-urlencoded")) {
printf("getcgivars(): Unsupported Content-Type.\n") ;
exit(1) ;
}
if ( !(content_length = atoi(getenv("CONTENT_LENGTH"))) ) {
printf("getcgivars(): No Content-Length was sent with the POST request.\n") ;
exit(1) ;
}
if ( !(cgiinput = new char[content_length+1] )) {
printf("getcgivars(): Could not \"new\" for cgiinput.\n") ;
exit(1) ;
}
if (!fread(cgiinput, content_length, 1, stdin)) {
printf("Couldn't read CGI input from STDIN.\n") ;
exit(1) ;
}
cgiinput[content_length]='\0' ;
}
else {
printf("getcgivars(): unsupported REQUEST_METHOD\n") ;
exit(1) ;
}
map_pairs(cgiinput,Elements);
return Elements;
}
int main(int argc, char *argv[])
{
int i ;
std::map<std::string, std::string> Elements;
getcgivars(Elements);
// Print the CGI response header, required for all HTML output.
// Note the extra \n, to send the blank line.
printf("Content-type: text/html\n\n") ;
// HTML response page.
printf("<html>\n") ;
printf("<head><title>CGI Results</title></head>\n") ;
printf("<body>\n") ;
printf("<center><h1>CGI FORM TEST</h1></center>\n") ;
printf("<center>HTML form sent the following variables\n");
printf("to the testparse.cgi program:</center>\n") ;
printf("<ul>\n") ;
// Print the CGI variables sent by the user. Note the list of
// variables alternates names and values, and ends in NULL.
for( map<string,string>::iterator ii=Elements.begin(); ii!=Elements.end(); ++ii)
{
cout << "<li>" << (*ii).first << "=" << (*ii).second;
}
printf("</ul>\n") ;
printf("<p>This data is available to you in testparse.cpp<br>\n");
printf("as the contents of \"key\" and \"value\"\n");
printf("</body>\n") ;
printf("</html>\n") ;
Elements.clear();
return 0;
}
精彩评论