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
}