Tài liệu hạn chế xem trước, để xem đầy đủ mời bạn chọn Tải xuống
1
/ 52 trang
THÔNG TIN TÀI LIỆU
Thông tin cơ bản
Định dạng
Số trang
52
Dung lượng
149,42 KB
Nội dung
(Without the line break, of course.) Here you see a little bit of the way that data is encoded to send to CGI For one thing, spaces are not allowed (since spaces typically separate commandline arguments) Spaces are replaced by ‘+’ signs In addition, each field contains the field name (which is determined by the form on the HTML page) followed by an ‘=‘ and the field data, and terminated by a ‘&’ At this point, you might wonder about the ‘+’, ‘=,’ and ‘&’ What if those are used in the field, as in “John & Marsha Smith”? This is encoded to: John+%26+Marsha+Smith That is, the special character is turned into a ‘%’ followed by its ASCII value in hex Fortunately, the web browser automatically performs all encoding for you The CGI parser There are many examples of CGI programs written using Standard C One argument for doing this is that Standard C can be found virtually everywhere However, C++ has become quite ubiquitous, especially in the form of the GNU C++ Compiler29 (g++) that can be downloaded free from the Internet for virtually any platform (and often comes pre-installed with operating systems such as Linux) As you will see, this means that you can get the benefit of objectoriented programming in a CGI program Since what we’re concerned with when parsing the CGI information is the field name-value pairs, one class (CGIpair) will be used to represent a single name-value pair and a second class (CGImap) will use CGIpair to parse each name-value pair that is submitted from the HTML form into keys and values that it will hold in a map of strings so you can easily fetch the value for each field at your leisure One of the reasons for using C++ here is the convenience of the STL, in particular the map class Since map has the operator[ ], you have a nice syntax for extracting the data for each field The map template will be used in the creation of CGImap, which you’ll see is a fairly short definition considering how powerful it is The project will start with a reusable portion, which consists of CGIpair and CGImap in a header file Normally you should avoid cramming this much code into a header file, but for these examples it’s convenient and it doesn’t hurt anything: //: C10:CGImap.h // Tools for extracting and decoding data from // from CGI GETs and POSTs 29 GNU stands for “Gnu’s Not Unix.” The project, created by the Free Software Foundation, was originally intended to replace the Unix operating system with a free version of that OS Linux appears to have replaced this initiative, but the GNU tools have played an integral part in the development of Linux, which comes packaged with many GNU components Appendix B: Programming Guidelines 541 #include #include #include using namespace std; class CGIpair : public pair { public: CGIpair() {} CGIpair(string name, string value) { first = decodeURLString(name); second = decodeURLString(value); } // Automatic type conversion for boolean test: operator bool() const { return (first.length() != 0); } private: static string decodeURLString(string URLstr) { const int len = URLstr.length(); string result; for(int i = 0; i < len; i++) { if(URLstr[i] == '+') result += ' '; else if(URLstr[i] == '%') { result += translateHex(URLstr[i + 1]) * 16 + translateHex(URLstr[i + 2]); i += 2; // Move past hex code } else // An ordinary character result += URLstr[i]; } return result; } // Translate a single hex character; used by // decodeURLString(): static char translateHex(char hex) { if(hex >= 'A') return (hex & 0xdf) - 'A' + 10; else return hex - '0'; } }; Appendix B: Programming Guidelines 542 // Parses any CGI query and turns it into an // STL vector of CGIpair which has an associative // lookup operator[] like a map A vector is used // instead of a map because it keeps the original // ordering of the fields in the Web page form class CGImap : public vector { string gq; int index; // Prevent assignment and copy-construction: void operator=(CGImap&); CGImap(CGImap&); public: CGImap(string query): index(0), gq(query){ CGIpair p; while((p = nextPair()) != 0) push_back(p); } // Look something up, as if it were a map: string operator[](const string& key) { iterator i = begin(); while(i != end()) { if((*i).first == key) return (*i).second; i++; } return string(); // Empty string == not found } void dump(ostream& o, string nl = "") { for(iterator i = begin(); i != end(); i++) { o