Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | File List | Namespace Members | Class Members | File Members | Related Pages

cgi.h

Go to the documentation of this file.
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]