// Copyright (c) 1999-2001 David Muse
// See the COPYING file for more information

#ifndef GROUNDWORK_H
#define GROUNDWORK_H

#include <groundwork/cgi.h>

// The groundwork class provides functionality essential to build 
// simple web based programs.

class   groundwork: public cgi {
        public:
                        groundwork(void *apistruct);
                        // Instantiates cgi class.
                        //
                        // Parses environment variables
                        //
                        // Processes the 
                        // files: /usr/local/web/"application"/"skin".var
                        //   and  /usr/local/web/"application"/"skin"/prefix.var
                        // for skin variables.
                        // Skin variable files should look like this:
                        //
                        // attribute1 = "value1"
                        // attribute2 = "value2"
                        // attribute3 = "value3"
                        //
                        // If a value must contain a " then it can be escaped
                        // with a \.  If a value must contain a \ then it too
                        // can be escaped by a \.
                        // Values are taken to be anything between the quotes,
                        // including carriage returns.
                virtual ~groundwork();


                int     execute();
                        // Calls allowed() and if the client is allowed to
                        // connect, calls sendHeader() from the cgi class,
                        // calls parseTemplate() on the template corresponding
                        // to the cgi in the specified skin directory and
                        // returns the value of the parseTemplate() call.


                // Dir variables are derived from the SCRIPT_NAME 
                // environment variable. Groundwork assumes that the 
                // SCRIPT_NAME is constructed as follows:
                // /usr/local/web/"application"/modules/"module"/"program".cgi
                char    *application();
                char    *applicationFileDir();
                char    *applicationUrlDir();
                char    *module();
                char    *moduleFileDir();
                char    *moduleUrlDir();
                char    *skin();
                char    *templateFileDir();
                char    *templateUrlDir();
                char    *program();
                char    *templateFileName();
                char    *programFileName();

                // page processing methods
                void    rewriteBase(char *protocol, char *hostname,
                                                char *path, char *file);
                void    rewriteBase(char *base);
                void    rewriteBase();
                        // Provokes the parsing routines to
                        // replace the value of the href attribute
                        // in the <base> tag (should there be one) 
                        // with the provided base or with 
                        // http://$(SERVER_NAME)/$(templateUrlDir)/
                        // if none is provided.
                void    dontRewriteBase();
                        // turns off base-rewriting behavior (default)
                void    rewriteFrames(char *extension);
                        // Provokes the parsing routines to
                        // replace the value of the src attribute
                        // in all <frame> tags with the corresponding
                        // cgi, should that cgi exist. This allows a
                        // frameset page to reference html files for
                        // development purposes.  The cgi is assumed
                        // to have the same name as the html file but
                        // a different extension as defined by 
                        // "extension".
                void    dontRewriteFrames();
                        // turns off frame-rewriting behavior (default)

                int     sendFile(char *path, char *filename);
                        // sends "path"/"filename" to the browser

                int     parseTemplate(strstream *container,
                                        char *path, char *filename, ...);
                        // Parses template page "path"/"filename".
                        //
                        // A variable in the page is denoted as
                        // $(variable) and replaced with either a value
                        // specified in the method call, the named
                        // environment variable, or the named form 
                        // entry passed from the previous page.
                        //
                        // To specify replacement values for variables,
                        // use the method as follows:
                        //
                        // parseTemplate(container,path,filename,
                        //      variable_name_array1,
                        //              replacement_value_array1,
                        //      variable_name_array2,
                        //              replacement_value_array2,
                        //      NULL,
                        //      variable_name1,
                        //              replacement_value1,
                        //      variable_name2,
                        //              replacement_value2,
                        //      NULL);
                        // 
                        // Any number of array and individual value
                        // replacements may be specified.
                        //
                        // In addition, for each 
                        // <!-- start segment -->
                        // ...
                        // <!-- end segment -->
                        // in the page, handleSegment() is called
                        // and passed the html between the comments
                        // and the "segment" name.
                        //
                        // handleSegment() is a protected, virtual
                        // method which is expected to be overriden and 
                        // contain a block of condition statements to 
                        // handle each possible segment.
                        //
                        // The resulting, parsed page is returned in
                        // "container".  If container is NULL, then
                        // the result is written directly to the
                        // browser.

                int     parseSegment(strstream *container, char *string, ...);
                        // This method works the same way as parseTemplate,
                        // but instead of parsing a file, it parses a string
                        // passed into "string" and returns the result in
                        // "container".  If container is NULL, then the result
                        // is written to the browser directly.

                virtual int     handleSegment(strstream *container,
                                                char *name, char *segment);
                        // This method should be overridden in the derived
                        // class.  By default, it writes "segment" to
                        // "container" or to the browser if "container"
                        // is NULL.

                char    *skinVariable(char *name);
                        // returns the value of skin variable: "name"
                void    writeSkinVariable(char *name);
                        // writes the value of skin variable: "name"
                        // to the browser

                void    dumpVariables();
                        // dumps environment variables, form entries,
                        // file entries, cookies, skin variable entries and
                        // reserved variables to the browser


                // security methods
                virtual int     allowed();
                        // Calls methodAllowed(), ipAllowed and
                        // refererAllowed().  Returns 1 if all succeed.
                        // If any method fails, invalidMethod(), invalidIp()
                        // or invalidReferer() is called and 0 is returned.
                        //
                        // This method may be overriden to provide customized
                        // security.
                virtual int     methodAllowed();
                        // Matches the REQUEST_METHOD environment variable
                        // against the "denied-methods" and "allowed-methods"
                        // skin variables (in that order) using regular
                        // expression syntax to determine whether the client's
                        // IP address is allowed to access this cgi.
                        //
                        // This method may be overriden to provide customized
                        // ip-based security.
                virtual int     ipAllowed();
                        // Matches the REMOTE_ADDR environment variable against
                        // the "denied-ips" and "allowed-ips" skin
                        // variables (in that order) using regular expression 
                        // syntax to determine whether the client's IP address
                        // is allowed to access this cgi.
                        //
                        // This method may be overriden to provide customized
                        // ip-based security.
                virtual int     refererAllowed();
                        // Matches the HTTP_REFERER environment variable against
                        // the "denied-referers" and "allowed-referers" 
                        // skin variables (in that order) using regular 
                        // expression syntax to determine whether the client's 
                        // IP address is allowed to access this cgi.
                        //
                        // This method may be overriden to provide customized
                        // referer-based security.
                int     requiredFormEntries(char *path, char *filename, ...);
                        // Sends "path"/"filename" to the browser if the
                        // NULL terminated list of form entry variables
                        // weren't sent from the previous page.  Returns 1
                        // if the form entries were there and 0 if they were 
                        // not.
                        //
                        // The format of the list of form entries should be 
                        // as follows:  a form entry variable name, followed
                        // by a 1 or 0 indicating whether that variable can
                        // be empty.  These pairs can be repeated over and
                        // over and must ultimately be terminated with a NULL.
                        //
                        // For example.  The following call requires that
                        // "first", "last", "address", "city", "state" and
                        // "phone" be present but allows "address", "city" and
                        // "state" to be blank.
                        //
                        // success=requiredFormEntries(path,filename,
                        //                              "first",0,
                        //                              "last",0,
                        //                              "address",1,
                        //                              "city",1,
                        //                              "state",1,
                        //                              "phone",0,
                        //                              NULL);

                virtual void    invalidMethod();
                        // Sends a Forbidden status header.
                        //
                        // This method may be overriden to a provide customized
                        // response to an invalid method.
                virtual void    invalidIp();
                        // Sends a Forbidden status header.
                        //
                        // This method may be overriden to a provide customized
                        // response to an invalid IP address.
                virtual void    invalidReferer();
                        // Sends a Forbidden status header.
                        //
                        // This method may be overriden to a provide customized
                        // response to an invalid referrer.


                void    *getApiStruct();
                        // returns a pointer to the API struct passed in by
                        // the constructor

        private:
                #include <groundwork/private/groundwork.h>

};

#endif