开发者

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;
}
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜