00001 #ifndef DVCGI_CGI_H 00002 #define DVCGI_CGI_H 00003 // $Id: cgi.h,v 1.23 2005/07/06 09:17:31 dvermeir Exp $ 00004 #include <iostream> 00005 00006 #include <dvutil/props.h> 00007 #include <dvutil/logstream.h> 00008 #include <dvcgi/cgierror.h> 00009 #include <dvcgi/httphead.h> 00010 00011 /** The Dv namespace is shared by all dvxyz packages. */ 00012 namespace Dv { 00013 /** Dv::Cgi is the namespace for this package. */ 00014 namespace Cgi { 00015 00016 /** @file 00017 * The class Cgi serves as an I/O interface for a cgi 00018 * application. It is a thin wrapper around lower level (but reusable) 00019 * facilities. 00020 */ 00021 00022 00023 /** A wrapper class that represents the http interface to a cgi 00024 * program. The constructor stores any form data and cookies in a 00025 * property list. Dv::Cgi::operator<<(ostream&,const Dv::Cgi::Cgi& ) 00026 * outputs the header lines set in Cgi::header(). 00027 * 00028 * A typical usage could be: 00029 * 00030 * @code 00031 * try { 00032 * Cgi cgi("myapplication.cgi"); 00033 * cgi.header().content_type("text/plain"); 00034 * cgi << cgi.props() << endl; 00035 * } 00036 * catch (std::exception& e) { 00037 * cerr << e.what() << endl; 00038 * } 00039 * @endcode 00040 */ 00041 class Cgi: public std::ostream { 00042 public: 00043 /** Constructor takes encoding type of response as parameter. 00044 * @param name of application, will be used as a prefix in 00045 * output to cgi.log() [i.e. the http server log file] 00046 * @param reply_format default is "text/html" 00047 * @param debug flag to be passed to Dv::Cgi::HttpHeader 00048 * 00049 * The constructor does not throw any exception. This supports the 00050 * following template code. 00051 * @code 00052 * Cgi cgi("myapplication.cgi", "text/html", true); 00053 * try { 00054 * } 00055 * catch (exception& e) { 00056 * cgi.header().content_type("text/plain"); 00057 * cgi << e.what(); 00058 * } 00059 * @encode 00060 * 00061 * which ensure that there is always proper output to cout. 00062 * 00063 * Even the following will work because the destructor will 00064 * output something. 00065 * 00066 * @code 00067 * { 00068 * Cgi cgi("myapplication.cgi"); 00069 * try { 00070 * } 00071 * catch (std::exception& e) { 00072 * } 00073 * } // Cgi::~Cgi() will output something. 00074 * @endcode 00075 */ 00076 Cgi(const std::string& name, const std::string& reply_format="text/html", 00077 bool debug=false) throw (); 00078 00079 /** Destructor. The destructor will output a header and some 00080 * standard error message, if nothing else was output yet. */ 00081 virtual ~Cgi(); 00082 00083 /** @return form data in Dv::Util::Props form */ 00084 const Dv::Util::Props& props() const { return formdata_; } 00085 /** @return value of form data variable 00086 * @exception std::runtime_error if variable is not defined 00087 */ 00088 const std::string& props(const std::string& name) const throw (std::runtime_error) { 00089 return props()[name].str(); 00090 } 00091 /** @return form data in Dv::Util::Props form */ 00092 Dv::Util::Props& props() { return formdata_; } 00093 /** @return value of form data variable 00094 * @exception std::runtime_error if variable is not defined 00095 */ 00096 std::string& props(const std::string& name) throw (std::runtime_error) { return props()[name].str(); } 00097 /** @return cookies in Dv::Util::Props form */ 00098 const Dv::Util::Props& cookies() const { return cookies_; } 00099 /** @return value of cookie variable 00100 * @exception std::runtime_error if variable is not defined 00101 */ 00102 const std::string& cookies(const std::string& name) const throw (std::runtime_error) { 00103 return (cookies()[name]).str() ; } 00104 /** @return environment (REQUEST_URI etc.) in Dv::Util::Props form */ 00105 const Util::Props& env() const { return env_; } 00106 /** @return value of environment variable (REQUEST_URI etc.) 00107 * @exception std::runtime_error if variable is not defined 00108 */ 00109 const std::string& env(const std::string& name) const throw (std::runtime_error) { 00110 return (env()[name]).str() ; } 00111 00112 /** Easy access to HttpHeader 00113 * @return pointer to HTTP header object. 00114 * @deprecated Use cgi.header().f().g(). 00115 * @sa Dv::Cgi::Cgi::header 00116 */ 00117 HttpHeader* operator->() { return &header_; } 00118 /** Easy check for formdata. 00119 * @param key of value in formdata. 00120 * @return value associated with key or 0 if none found. 00121 */ 00122 const std::string* operator()(const std::string& key) const { return props().find(key); } 00123 00124 /** @return raw data as received from HTTP server */ 00125 const std::string& data() const { return data_; } 00126 00127 /** @return HTTP header. */ 00128 HttpHeader& header() { return header_; } 00129 /** @return HTTP header (const version). */ 00130 const HttpHeader& header() const { return header_; } 00131 00132 /** @return name (constructor parameter) of the program. 00133 * @sa Dv::Cgi::Cgi::Cgi */ 00134 const std::string& name() const { return name_; } 00135 00136 /** @return log stream 00137 * This logstream is linked to cerr. The prefix is the name of the program. 00138 * @sa Dv::Cgi::Cgi::Cgi */ 00139 std::ostream& log() { return log_; } 00140 00141 /** @return this url. 00142 * The return value is the string obtained from the environment 00143 * variable REQUEST_URI. 00144 */ 00145 const std::string& here() const { return here_; } 00146 /** @return this url without arguments. 00147 * The return value is obtained from the result of 00148 * Dv::Cgi::Cgi::here by removing everything after the first 00149 * occurrence of '?'. 00150 * @sa Dv::Cgi::Cgi::here 00151 */ 00152 const std::string& here_base() const {return here_base_; } 00153 /** @return client host dot address. 00154 * The return value is the value of the REMOTE_ADDR environment 00155 * variable. If the client host is the localhost, the real "dot 00156 * address" of this host is returned. 00157 */ 00158 const std::string& client_host() const { return client_host_; } 00159 /** @return client host name. 00160 * The return value is obtained from the result of 00161 * Dv::Cgi::Cgi::client_host by resolving the result. 00162 * @sa Dv::Cgi::Cgi::client_host 00163 */ 00164 const std::string& client_host_name() const { return client_host_name_; } 00165 /** @return dot address of this host. 00166 * The return value is the value of the SERVER_ADDR environment 00167 * variable. 00168 */ 00169 const std::string& this_host() const { return this_host_; } 00170 /** @return name of this host. 00171 * The return value is obtained from the SERVER_NAME environment 00172 * variable or, if this variable is not available, resolving the result of 00173 * Dv::Cgi::Cgi::this_host. 00174 * @sa Dv::Cgi::Cgi::this_host 00175 */ 00176 const std::string& this_host_name() const { return this_host_name_; } 00177 00178 /** Print props as url-arguments. 00179 * Convert a property list of a string suitable for inclusion in 00180 * a url. E.g. abc=123&key=blabla. Both keys and values will 00181 * be encoded using Dv::Cgi::www_encode. 00182 * @param props property list to be printed as url arguments 00183 * @return string suitable for appending to a url as arguments 00184 * @sa Dv::Util::Props Dv::Cgi::www_encode 00185 */ 00186 static std::string props_as_url_args(const Dv::Util::Props& props); 00187 00188 /** Extend the base url of this Cgi object with formdata from props. 00189 * @param props property list to be printed as url arguments of here_base(). 00190 * @return here_base() + "?" + props_as_url_args(props) 00191 * @sa Dv::Cgi::Cgi::props_as_url_args Dv::Cgi::Cgi::here_base 00192 */ 00193 std::string url(const Dv::Util::Props& props) const; 00194 00195 /** Extend a url with arguments from props. 00196 * @param url url to be extended 00197 * @param props property list to be added to this url 00198 * @return url extended with arguments from props. 00199 * @warning the input url should not contain a fragment ('#') and 00200 * probably should not end with '/'. 00201 * @sa Dv::Cgi::Cgi::props_as_url_args 00202 */ 00203 static std::string url(const std::string& url, const Dv::Util::Props& props); 00204 00205 /** Write debug info on output stream. */ 00206 void debug(std::ostream& os) const; 00207 private: 00208 00209 /** Filter class which ensures that header_ is output before 00210 * anything else. */ 00211 class Filter { 00212 public: 00213 Filter(Cgi&); 00214 int get(); 00215 int put(int c); 00216 int sync(); 00217 void close(); 00218 int count() const { return count_; } 00219 private: 00220 unsigned int count_; 00221 Cgi& cgi_; 00222 }; 00223 const std::string name_; 00224 Filter filter_; 00225 Dv::Util::Props cookies_; 00226 Dv::Util::Props env_; 00227 Dv::Util::Props formdata_; 00228 std::string data_; 00229 Dv::Util::logstream log_; 00230 /** url of this program */ 00231 std::string here_; 00232 /** base of url of this program: anything before '?' */ 00233 std::string here_base_; 00234 /** dot address of client host */ 00235 std::string client_host_; 00236 /** name of client host */ 00237 std::string client_host_name_; 00238 /** dot address of this host */ 00239 std::string this_host_; 00240 /** name of this host */ 00241 std::string this_host_name_; 00242 /** header to be sent before reply */ 00243 Dv::Cgi::HttpHeader header_; 00244 }; 00245 00246 }} 00247 #endif
dvcgi-0.5.14 | [22 January, 2006] |