summaryrefslogtreecommitdiff
path: root/src/cgi.h
blob: 01142b5b62b9fd9427c366c6b04b85bfde944b95 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
/**\file cgi.h
 * Describes extra params needed to use the Cgi class as well as the class
 * itself.
 *@author Mike Buland
 */

#include "linkedlist.h"
#include "hashtable.h"
#include "hashfunctionstring.h"

#define VAR_STDINPUT		0x01 /**< Variable came from stdinput, web form */
#define VAR_COOKIE			0x02 /**< Variable came from a cookie */
#define VAR_CMDLINE			0x04 /**< Variable came from commandline / uri */
#define VAR_ANY				0xFF /**< Mask including all other types */

/**
 * Cgi header processor originally designed for apache cgi programs.  When used
 * from apache with what I beleive are some sort of standard set of command
 * line parameters and environment variables.  This always worked for all of my
 * purposes.  This class will automatically extract all data from the system
 * that you need and places it into tables and things for easy access.
 * There are three types of input that data can come from, StandardInput,
 * CommandLine, and Cookies.  StandardInput is when you get formdata in
 * multi-part forms, Cookies should usually be cookies that you set, and
 * command line is everything after the question mark in the URL.
 * This also contains some simple helpers for putting templated data into the
 * HTTP data feed.
 *@author Mike Buland
 */
class Cgi
{
public:
	/**
	 * Create a complete CGI object, this object will automatically read data
	 * from all available sources and be ready for use on the very next line!
	 * If strSource is filled in it will also automatically read in a content
	 * file, which is a simple file format containing named blocks of reusable
	 * templates.
	 *@param strSource Set to a filename in order to load up a content file.
	 */
	Cgi( const char *strSource = NULL );

	/**
	 * Destroy the cgi object.
	 */
	virtual ~Cgi(  );

	/**
	 * Get's the value for a variable as a character string.  The name is the
	 * name that was given on the URL or in the form or cookie.  Skip can be
	 * set to any value above zero to retreive subsequent variables with the
	 * same name.  The most obvious use of this is when dealing with file
	 * uploads, each file upload sends you three variables with the same name
	 * and different content.  Finally the variable type determines where you
	 * will accept this variable from.  This is generally a bit of a security
	 * thing, if you store login info in a cookie and don't want people getting
	 * in by faking the appropriate URL.
	 *@param name The name of the variable you wish to retreive.
	 *@param skip THe number of variables with the given name to skip before
	 * returning something meaningful.  The only way to determine how many
	 * variables with the same name there are is to skip until you get a NULL
	 * value returned.
	 *@param type Can be set to any combination of VAR_STDINPUT, VAR_COOKIE,
	 * VAR_CMDLINE, or just VAR_ANY.  This takes bitflags, so you can or the
	 * values together.  If a variable is found but came from the wrong source
	 * it won't match any other criteria and will be treated as though it
	 * doesn't exist.
	 *@returns A null-terminated string representing the value of the requested
	 * variable, or NULL if the variable did not exist.  If a variable does
	 * exist but has no value the string returned will start with a NULL char,
	 * but be a valid string.
	 */
	char *getVarValue( const char *name, int skip=0, unsigned char type=VAR_ANY );

	/**
	 * This functions identically in every way to getVarValue, except that
	 * instead of returning a pointer to the variable's value, it returns the
	 * length of the variable's value string.  The params are the same and so
	 * a call to both functions with the same params should yeild a value and
	 * a corresponding length.
	 *@param name The name of the variable you wish to retreive.
	 *@param skip THe number of variables with the given name to skip before
	 * returning something meaningful.  The only way to determine how many
	 * variables with the same name there are is to skip until you get a NULL
	 * value returned.
	 *@param type Can be set to any combination of VAR_STDINPUT, VAR_COOKIE,
	 * VAR_CMDLINE, or just VAR_ANY.  This takes bitflags, so you can or the
	 * values together.  If a variable is found but came from the wrong source
	 * it won't match any other criteria and will be treated as though it
	 * doesn't exist.
	 *@returns The length of the value-string of the requested variable.  If
	 * the requested variable is not found, -1 is returned.
	 */
	int getVarLength( const char *name, int skip=0, unsigned char type=VAR_ANY );

	/**
	 * A handy little function that writes a load of debug info related to
	 * parsing CGI params to the standard output in html.  This is generally
	 * best used at the end of a page.
	 */
	void writeDebugInfo();

	/**
	 * Write a content header to the standard output.  This should also be the
	 * first thing that you do (except for writing cookies) after initializing
	 * the Cgi class.  You can select a type of header or content from the
	 * header enum, and a properly formatted header will show up on the
	 * standard output.
	 *@param type Any value from the header enum in this class.  The default is
	 * to write an html header, probably the most common as well.
	 */
	void writeContentHeader( int type=headerHTML );

	/**
	 * Write content to the stnadard output.  The content variable should have
	 * been loaded during construction of the Cgi object or with the
	 * loadContent function.  The content variable should be formatted just like
	 * a printf string, so that anything you want to put into it will have a %
	 * symbol replacement code, like %s, %d, etc.  Since this actually uses a
	 * type of printf function everything from those docs work here.
	 *@param name The name of the content variable to format and write to
	 * stnadard output.
	 *@param ... As many params as you want to include, ala printf.
	 */
	void writeContent( const char *name, ...);

	/**
	 * Load a content file.  I don't want to describe the format here, you can
	 * just read the code or find an example for now.  Sorry.
	 *@param strSource The name of the file to open and read in to get the
	 * content loaded.
	 */
	void loadContent( const char *strSource = NULL );

	/**
	 * Write a cookie-set header to the output stream.  This should be done
	 * before any other content-headers are written.  The specifics of this
	 * function are very simple, since I rely on the user's understanding of
	 * how standard HTTP/1.1 or HTTP/1.0 cookie syntax works.  If you don't
	 * care then just use the name and value and the defaults should keep you
	 * in good stead for a long time.
	 *@param name The name of the cookie variable to set.
	 *@param value The value to set to that variable.
	 *@param expires The formatted string value for the date and time this
	 * cookie should expire.  A NULL here will put a "until the browser closes"
	 * tag in.
	 *@param path The path (URL) that this cookie belongs to.  If you run a lot
	 * of hosted servers or sub-sites that may have some shared URL bits then
	 * you may want to set this.  The cookie should only be sent to URL's that
	 * match this as their first part.
	 *@param domain The domain that is allowed to read this, if not set, it's
	 * the domain the web browser contacted when they got the cookie.
	 *@param secure I'm not sure, I think it's something to tell if the cookie
	 * is safe to keep because any potentially valuable data is encypted or
	 * otherwise unusable.  I could be wrong.
	 */
	void writeCookie( char const *name, char const *value, char const *expires=NULL, char const *path=NULL, char const *domain=NULL, bool secure=false );
	
	/**
	 * A simple helper class to contain variable data.
	 */
	class Item
	{
	public:
		/**
		 * Build an empty Item.
		 */
		Item(  )
		{
			name = NULL;
			value = NULL;
			len = 0;
			type = 0;
		}
		/** The name of the item.  */
		char *name;
		/** The value of the item. */
		char *value;
		/** The length of the item's value. */
		unsigned long len;
		/** The type of the item (where it came from). */
		unsigned char type;
	};
    
	/** Header values */
	enum
	{
		headerHTML
	};

private:
	/** Keeps track of all contained variables. */
    LinkedList aVars;
	/** Keeps track of all content variables. */
	HashTable aContent;
};