Commit | Line | Data |
c124bb9b |
1 | // |
0a62d748 |
2 | // $Id: fcgio.h,v 1.5 2001/06/22 13:15:10 robs Exp $ |
c124bb9b |
3 | // |
98e2ddaa |
4 | // Allows you communicate with FastCGI streams using C++ iostream |
5 | // objects |
6 | // |
7 | // defines classes fcgi_streambuf, fcgi_ostream, fcgi_istream |
8 | // you can redefine cin, cout, cerr or use your own custom |
9 | // FCGI stream names. |
10 | // |
11 | // ORIGINAL AUTHOR: George Feinberg |
12 | // |
13 | // |
14 | // REWRITTEN BY: Michael Richards 06/20/1999 |
15 | // -added cin support |
16 | // -added ability to replace cin/cout so existing code only |
17 | // needs to include the header file and use the normal |
18 | // cin/cout. This has been altered as of 2/2000, see below. |
19 | // -added buffered read support which is required for ungets. |
20 | // |
21 | // |
22 | // REWRITTEN AGAIN BY: Michael Shell 02/23/2000 |
23 | // |
24 | // Previous versions of this code had problems. |
25 | // Two hellish bugs have been fixed and there is now full |
26 | // buffering for both input and output streams. |
27 | // |
28 | // - fixed signed char bug in underflow() that would |
29 | // cause a false EOF to be flagged when reading binary |
30 | // data. Uploading short binary files via <input type=file |
31 | // which uses multipart/form-data encoding would reveal |
32 | // this bug. Also could be triggered by hackers |
33 | // sending binary data instead of legitimate form data, |
34 | // in which case the hung network connection, depending on |
35 | // how the FCGI application server handles things, could |
36 | // form the basis for a stupid denial of service attack. |
37 | // - fixed code to properly use the get and put buffers via |
38 | // underflow() and overflow() NOT xsgetn() and xsputn() as |
39 | // was done before. Because of this, the previous |
40 | // version would often drop data, especially if the |
41 | // user did an initial getline() followed by a read(). |
42 | // - added the attach() method and a parameterless |
43 | // constructor so that you can declare fcgi_iostream |
44 | // objects and attach() to them later - after accept(). |
45 | // - enhanced docs to include examples that actually work. |
46 | // - removed any predefined redefinitions of cin,cout,cerr. |
47 | // The example shows how you can use these names if you |
48 | // want (via properly placed #undefs) or use ones of your |
49 | // choosing (such as fin,fout,ferr). This may be very |
50 | // helpful when testing code. Also, as a result, you |
51 | // no longer have to place fcgio2.h in any special |
52 | // order in your #includes. |
53 | // - added an experimental method drain() to istream which |
54 | // allows the user to drain the get buffer. This is |
55 | // designed to provide users with a way to drain the get |
56 | // buffer prior to using a read function from the FCGI |
57 | // library in applications which mix I/O methods. i.e. |
58 | // it is the input equivalent to flush(). It does not |
59 | // read from the FCGI stream, but gets only characters |
60 | // already in the istream buffer. Mixing I/O methods is |
61 | // not recommended since this iostream implementation |
62 | // is complete and should provide you with everything |
63 | // you need. |
64 | // |
65 | // |
66 | // NOTES: encapsulates the FastCGI protocol in an iostream via a |
67 | // nice custom streambuf. Very nice, very robust, and very powerful. |
68 | // |
69 | // This work is based on routines written by George Feinberg. They |
70 | // have been mostly re-written and extensively changed by |
c124bb9b |
71 | // Michael Richards. |
72 | // |
98e2ddaa |
73 | // Rewritten again with bug fixes and numerous enhancements by |
74 | // Michael Shell. |
75 | // |
76 | // Special Thanks to Dietmar Kuehl for his help and the numerous custom |
77 | // streambuf examples on his web site. |
78 | // |
79 | // Copyright (c) 2000 Tux the Linux Penguin |
c124bb9b |
80 | // |
81 | // You are free to use this software without charge or royalty |
98e2ddaa |
82 | // as long as this notice is not removed or altered, and recognition |
c124bb9b |
83 | // is given to the author(s) |
84 | // |
98e2ddaa |
85 | // This code is offered as-is without any warranty either expressed or |
86 | // implied; without even the implied warranty of MERCHANTABILITY or |
87 | // FITNESS FOR A PARTICULAR PURPOSE. |
88 | // If it breaks, you get to keep both halves. |
89 | |
90 | |
91 | // BEGIN EXAMPLE CODE: test_fcgio2.cpp |
92 | /* |
93 | // This code uses the fcgiapp interface to show a little bit more |
94 | // complexity and to demonstrate the fact that with fcgio2 and just |
95 | // a few more lines of code (like FCGX_Init etc.) you can easily |
96 | // make FastCGI programs without needing wrapper functions. |
97 | // You can use the fcgi_stdio interface if you you want a |
98 | // simpler accept(). However note that the fcgio2 interface |
99 | // removes the need for the fcgi_stdio wrapper functions. |
100 | // i.e. Why override printf when you aren't going to use it anyway? |
101 | // Also, be aware that because of iostream buffering, you must take |
102 | // care when mixing FCGI iostream I/O with the FCGI library I/O |
103 | // commands (such as printf). Be sure to flush() any open |
104 | // fcgi_ostreams prior to using commands such as printf. This is true |
105 | // even on systems which have the C I/O commands synced with C++ |
106 | // iostreams, such as Linux, because the FCGI wrapper printf, etc. are |
107 | // not the same as the "normal" printf etc. It is recommended that you |
108 | // not use any FCGI library input (read) commands if you use |
109 | // fcgi_istream (cin) input as there is no easy way to "flush" (drain) |
110 | // an istream get buffer. However, an experimental istream method |
111 | // drain() has been provided to istream for those of you who need to |
112 | // do mixed input. There should be no need to do mixed I/O as the |
113 | // fcgio2 iostream implementation is complete. |
114 | |
115 | #include <stdlib.h> |
02089704 |
116 | #include "fcgio.h" // fcgio.h includes fcgiapp.h |
98e2ddaa |
117 | // however you must include fcgi_stdio.h if |
02089704 |
118 | // you want to use it as fcgio.h does not |
98e2ddaa |
119 | // include it for you |
120 | |
121 | #undef cin // remember you have to undo the stuff predefined |
122 | #undef cout // for cin, cout, cerr if you wish to use these |
123 | #undef cerr // names for your FastCGI streams |
124 | |
125 | int main(void) |
126 | { |
127 | |
128 | int count = 0; |
129 | |
130 | // I can create/declare my objects here, but I don't dare use them |
131 | // until I set them up with attach(). |
132 | |
133 | // note that version 1.0 of fcgio used fcgio_istream & fcgio_ostream |
134 | // we made a little change to the names in V2.00 for clarity. |
135 | fcgi_istream cin; // you do not *HAVE* to use these names, you |
136 | fcgi_ostream cout; // could use other stream names of your choice |
137 | fcgi_ostream cerr; // don't forget that the input is |
138 | // fcgi_*I*stream class |
139 | |
140 | FCGX_Request request; // here is our request structure |
141 | |
142 | // get everything ready for the customers |
143 | FCGX_Init(); |
144 | |
145 | FCGX_InitRequest(&request,0,0); |
146 | |
147 | |
148 | // let the games begin |
149 | while(FCGX_Accept_r(&request) >= 0) |
150 | { |
151 | count++; |
152 | |
153 | cout.attach(request.out); // now I know my pointer values for |
154 | cerr.attach(request.err); // this request. attach to them |
155 | cin.attach(request.in); |
156 | // attach will initialize everything |
157 | // alternatively, you could declare the streams here and the |
158 | // constructor with the (FCGX_Stream *str) parameter would |
159 | // do the same job as attach |
160 | |
161 | // If you are using fcgi_stdio.h, the equivalent command would |
162 | // be cout.attach(FCGI_stdout->fcgx_stream); |
163 | // and so forth for cin,cerr using FCGI_stdin and FCGI_stderr |
164 | // respectively. |
165 | |
166 | |
167 | // now I can fire at will: |
168 | cout << "Content-type: text/html\r\n\r\n" |
169 | << "<title> FastCGI cin, cout, cerr tester </title>\r\n" |
170 | << "<h1><center> FastCGI C++ IOstream test: " |
171 | << "It works! </center></h1>\r\n"; |
172 | cout << "<h4><center><i> Total served by this task: " |
173 | << count << "</i></center></h4>\r\n"; |
174 | |
175 | // didn't use cin or cerr in this example. |
176 | |
177 | // it is good practice to flush the buffers. |
178 | // use cout.flush() if you don't want the line feed. |
179 | |
180 | cout << endl; |
181 | |
182 | // there is no cxxx.close() and you do not need it with the fcgio |
183 | // interface. You would need to call cxxx.close() if cxxx was an |
184 | // fstream based object and attached to a file descripter you got |
185 | // from a command like fd=open(blah). (GNU (Linux) based fstreams |
186 | // support this) Then you need to call cxxx.close() before you |
187 | // close the physical file with close(fd). If doing this with |
188 | // fstream objects, you should call cxxx.clear() after |
189 | // attach(fd) as the file descriptor attach is not as complete in |
190 | // initialization as our fcgi_iostream attach() |
191 | // If you don't understand any of this, don't worry about it and |
192 | // forget I even mentioned it. |
193 | |
194 | // all done with this request |
195 | FCGX_Finish_r(&request); |
196 | |
197 | // do the next request |
198 | } |
199 | return (1); |
200 | } |
201 | |
202 | */ |
203 | |
204 | // END EXAMPLE CODE |
205 | |
206 | /*------------------------------------------------------------------*/ |
207 | |
208 | |
c124bb9b |
209 | #ifndef FCGIO_H |
210 | #define FCGIO_H |
98e2ddaa |
211 | |
c124bb9b |
212 | #include <iostream.h> |
02089704 |
213 | |
0a62d748 |
214 | #include "fcgiapp.h" |
02089704 |
215 | |
0a62d748 |
216 | // we aren't pulling from the heap, so it is best not to make it too big |
02089704 |
217 | #define FCGIO_BUFSIZE 200 |
98e2ddaa |
218 | |
219 | // FastCGI streambuf replacement. Implements low level I/O to the |
220 | // FastCGI C functions so our higher level iostreams will talk |
221 | // in the FastCGI protocol |
222 | class fcgi_streambuf : public streambuf |
223 | { |
c124bb9b |
224 | public: |
98e2ddaa |
225 | // constructor |
226 | fcgi_streambuf(void); |
227 | ~fcgi_streambuf(); |
228 | |
229 | // handles allocation of buffers by doing nothing since buffer |
230 | // allocation isn't needed |
231 | virtual int doallocate(); |
232 | |
233 | // gets data (upto the given maximum) from the get buffer and |
234 | // copies it to the given char array. Returns the number of chars |
235 | // written or -1 on error. A returned value less than the given |
236 | // maximum, assuming the user requested at least one char, |
237 | // indicates that the get buffer is empty. The underflow() method |
238 | // is never called to refill the get buffer, so this method can be |
239 | // used to drain the get buffer. It is used to form an istream |
240 | // drain() method which is the input equivalent to flush(). |
241 | virtual int drain_strm(char *,int); |
242 | |
243 | // let's us know if this strembuf has been initialized |
244 | virtual int isstrmdefined(void); |
245 | |
246 | // (for writers) empties the put buffer and possibly an |
247 | // overflow char into the FCGI interface |
c124bb9b |
248 | virtual int overflow(int); |
98e2ddaa |
249 | |
250 | // bogus routine in case somebody thinks they know |
251 | // better and calls it. We currently are happy with |
252 | // our static buffer. |
253 | virtual streambuf * setbuf(char *, int); |
254 | |
255 | // initializes the buffering and FCGI interface |
256 | virtual void stream_initialize(FCGX_Stream *,int); |
257 | |
258 | // (for writers) flushes the put buffer into the FCGI |
259 | // interface and then flushes the FCGI interface |
260 | virtual int sync(); |
261 | |
262 | // (for readers) fills the get buffer with data from the |
263 | // FCGI interface |
c124bb9b |
264 | virtual int underflow(); |
98e2ddaa |
265 | |
c124bb9b |
266 | private: |
98e2ddaa |
267 | // pointer to our underlying FCGI interface |
268 | FCGX_Stream * fcgx_strm; |
c124bb9b |
269 | |
98e2ddaa |
270 | // our buffer |
378bd843 |
271 | static int buffersize; |
02089704 |
272 | char buffer[FCGIO_BUFSIZE]; |
c124bb9b |
273 | |
98e2ddaa |
274 | // little flag so that we can tell if the |
275 | // fcgi_str pointer was ever set |
276 | int defined; |
c124bb9b |
277 | }; |
278 | |
378bd843 |
279 | int fcgi_streambuf::buffersize = FCGIO_BUFSIZE; |
98e2ddaa |
280 | |
281 | // Here's the istream class definition. |
282 | class fcgi_istream : public istream |
283 | { |
c124bb9b |
284 | public: |
98e2ddaa |
285 | fcgi_istream(); |
286 | fcgi_istream(FCGX_Stream *str); |
287 | ~fcgi_istream(); |
288 | |
289 | // connects the fcgi_streambuf of an existing fcgi_istream |
290 | // object to a given FCGI interface |
291 | virtual void attach(FCGX_Stream *str); |
292 | |
293 | // allows you to drain down the streambuf buffer. It will not |
294 | // read any chars from the FCGI interface. You can repeatedly |
295 | // call drain() to empty the get buffer prior to using a |
296 | // FCGI library function to ensure syncronization of the |
297 | // reads. i.e. it flushes the input stream |
298 | // This method should be considered both nonstandard and |
299 | // experimental. It's use is entirely optional to the user, |
300 | // but could be very helpful for applications which use |
301 | // both istream and FCGI library based reads on a single |
302 | // FCGI interface and need a way to sync the reads. |
303 | // It copies upto the given number of chars into the given |
304 | // char array. It returns the number of chars written or |
305 | // -1 on error. If the number of chars written is less than |
306 | // the number the user requested, the get buffer is empty. |
307 | // This method does not alter or check any of the input |
308 | // status flags such as EOF or FAIL since it does not interact |
309 | // with the underlying FCGI interface at all - it only reads from |
310 | // the get buffer. |
311 | virtual int drain(char *,int); |
312 | |
313 | // lets us know if this object has been initialized |
314 | virtual int isdefined(void); |
c124bb9b |
315 | |
316 | private: |
98e2ddaa |
317 | // FastCGI streambuf |
318 | fcgi_streambuf fcgi_strmbuf; |
319 | |
c124bb9b |
320 | }; |
321 | |
322 | |
c124bb9b |
323 | |
98e2ddaa |
324 | // Here's the ostream class definition. |
325 | class fcgi_ostream : public ostream |
326 | { |
327 | public: |
328 | fcgi_ostream(void); |
329 | fcgi_ostream(FCGX_Stream *str); |
330 | ~fcgi_ostream(); |
331 | |
332 | // connects the fcgi_streambuf of an existing fcgi_ostream |
333 | // object to a given FCGI interface |
334 | virtual void attach(FCGX_Stream *str); |
335 | |
336 | // lets us know if this object has been initialized |
337 | virtual int isdefined(void); |
c124bb9b |
338 | |
98e2ddaa |
339 | private: |
340 | // FastCGI streambuf |
341 | fcgi_streambuf fcgi_strmbuf; |
342 | }; |
c124bb9b |
343 | |
98e2ddaa |
344 | #endif FCGIO_H |