A long time ago when I still had (some) hair and hadn’t bitten the PHP bullet I played around with C++ CGIs. Owing to a lack of then available HOW-TO docs I went on to write a (badly written and error-filled) CGI in C/C++ HOW-TO and also a CGI Variable Wrapper. The HOW-TO did what it said on the tin and the wrapper provided an easy API to read/write GET and POST variables as well as cookies.
Surprisingly both the HOW-TO and the wrapper are still in use and I get contacted form time to time with queries. The most common query regards file upload which the wrapper doesn’t support. To illustrate a simple file upload I cobbled together a quick and dirty C example which I’ve provided via email ever since.
So here, for general reference, is my demonstration C code. Please note this is very untested and unrobust, even dodgier than my usual fare. I keep meddling with the idea of finding time to do a proper job either of a standalone file upload API or integrating support into the CGI wrapper. All of this is really just for kicks though as there are better solutions available.
/** Very rough-and-ready CGI file upload in C/C++ This is demonstration code only really and, of course, no liability accepted for anything! David Cutting http://www.purplepixie.org/dave/ http://blog.purplepixie.org/ dcutting [at] purplepixie [dot] org Code Copyright DMC 22/05/2011 **/ #include <stdio.h> #include <stdlib.h> #include <string.h> int main(void) { FILE *out; char *rawdata; // pointer for rawdata char *data; // will be an offset of rawdata after the two newlines unsigned long length; // length of data to be read used for malloc unsigned long writelength; // use for the length of the write char *pos; // used in the loop printf("Content-type: text/html\n\n<HTML><PRE>"); // for debug output // Various bits of debug output are included - comment out for live // and replace with whatever output you'd like to send to the client out=fopen("/var/www/test.jpg","wb+"); // open the output file length=atol(getenv("CONTENT_LENGTH")); writelength=length; printf("Content Length: %u\n",length); rawdata=malloc(length+1); // malloc required buffer fread(rawdata, length, 1, stdin); // read into buffer // now comes the loop, there are better ways but not that I can find quickly enough for (pos=rawdata; pos<(rawdata+length-4); pos++) { writelength--; // decrement the write length printf("%c %d\n",pos[0],pos[0]); // used for debug output (comment out for live) if ( (pos[0]==13) && (pos[1]==10) && (pos[2]==13) && (pos[3]==10) && ( (pos[4]<32)||(pos[4]>127) ) ) // pattern to find two double-newlines { data=pos+4; // move data pointer forward 4 to start of actual data pos=rawdata+length+2; // break loop printf("Found\n"); // another debug line - comment out for live writelength-=3; // decrement writelength by three (done one already above for this loop) } } printf("Writelength: %u\n",writelength); // yet another debug // write the data to the file fwrite(data, 1, writelength, out); // close the file fclose(out); free(rawdata); // free memory printf("Upload Complete"); // debug - comment out for live return 0; // exit }
Für die Linuxer muss der Befehl in Zeile 35 & 55 (bei Printf) nicht nur %u heißen, sondern %lu (long unsigned).
English:
For Linux Operating Systems the “%u” in line 35 & 55 (printf) replaced by “%lu” (–> long unsigned int)
Nice write up. But, I see this only handles one single input which is of the file. Can you give a more elaborate example when a resume upload form is handled? I mean multiple text input and one file input.