D CGI Hang with fgets
Morgan McDermott
morganmcdermott at gmail.com
Mon Nov 27 22:35:50 PST 2006
Morgan McDermott wrote:
> Carlos Santander wrote:
>> Morgan McDermott escribió:
>>> Hi there!
>>> I'm trying to make a D CGI script, and one of the essential things
>>> it should do is to get POST data. My attempt below in D hangs at
>>> fgets()... I've made it output to a file so that it may be tested on
>>> a webserver (where I've been testing it). When the script has POST
>>> data to get, it performs exactly the same as it does in the console
>>> (hangs at fgets()).
>>>
>>> I've been using a guide to C and CGI as my reference here:
>>> http://www.cs.tut.fi/~jkorpela/forms/cgic.html
>>>
>>> <code>
>>> //Imports
>>> import std.stdio; //writefln()
>>> import std.string; //toString()
>>> import std.date : getUTCtime; // time + benchmarking
>>> import std.conv; //toInt()
>>> import std.stream; //testing only
>>> alias char[] string; //ease of use
>>>
>>> void writeNewLine(string line, string filename) {
>>> std.file.append(filename, line~"\n");
>>> }
>>>
>>> extern (C)
>>> {
>>> char* getPOSTData(uint len = 2048){
>>> char *prawData;
>>>
>>
>> Have you tried initializing prawData?
>> prawData = new char [len]; // or similar
>>
>>> printf("hang?");
>>> writeNewLine("Hanging point entered \n", "baz.txt");
>>>
>>> prawData = fgets(prawData, len+1, stdin);
>>>
>>> writeNewLine("Hanging point exited \n", "baz.txt");
>>> printf("Not hanging.. =-)");
>>>
>>> return prawData;
>>> }
>>> }
>>> extern (C) char* getenv(char*);
>>>
>>> void main() {
>>> string introduction = "New test at " ~ toString(getUTCtime());
>>> writeNewLine(introduction, "baz.txt");
>>> char *pdataLength= getenv("CONTENT_LENGTH");
>>> string scontentLength = toString(pdataLength);
>>> //Ensure no conversion error when no post data is passed
>>> if(scontentLength == ""){
>>> scontentLength = "0";
>>> }
>>> uint contentLength = toInt(scontentLength);
>>> char *ppostData = getPOSTData();
>>> writefln("Post Data: %s", toString(ppostData));
>>> writeNewLine("Post Data: " ~ toString(ppostData), "baz.txt");
>>> }
>>> </code>
>>>
>>> Any ideas?
>>>
>>> Thank you very much for your time,
>>> ~Morgan McDermott
>>
>>
> Carlos,
> Good idea, and thanks for the reply. Unfortunately, the script still
> hangs at the same point. I've done a bit more work and an essentially
> equivilant C script also hangs at this point, so I doubt that this is a
> D-problem. All the same, any help from this great community is very much
> appreciated :).
>
> Thanks again,
> ~Morgan McDermott
Further research leads me to conclude that the problem is giving fgets a
pointer instead of a char array. When I replace prawData with something
like rawData[1000], everything works as planned.
<code>
char rawData[1000];
fgets(rawData, len+1, stdin);
</code>
Although this works, I would really rather put the data from stdin into
something of variable size. I got my C-code to work with this
modification, so I ported it over to D and allowed it to take as much
data as you want it to by looping through the stdin data. I haven't
optimized buffer size for anything in particular... If you plan on using
this function, then you probably want to play around with that.
To use this in a CGI environment, you're going to need to:
1) split apart the data into key value pairs
2) decode the data with an unencode function ( Cashew has one )
<code>
//Imports
import std.stdio; //writefln
import std.string;
import std.c.stdlib; //Environmental Vars
import std.c.stdio; //fgets
import std.c.string;
alias char[] string;
extern (C) char* getenv(char*);
char[] d_getPOSTData(uint maxlen = 2048){
//Buffer info
char dataBuffer[512];
ulong bufferSize = dataBuffer.length;
//Define some pointers
char *lenstr;
char *pblank;
char[] error;
//Variable to hold lenstr in int form
long len;
lenstr = getenv("CONTENT_LENGTH");
//Test for null length
if(lenstr == pblank){
//throw error
error = "No POST data";
return error;
}
else {
//copy lenstr into len with format width=long, type = decimal integer
sscanf(lenstr,"%ld",&len);
}
if( len > maxlen ){
error = "POST data has exceeded size limits";
return error;
}
else {
char *ptmpData;
char[] tempString;
char[] dataStorage;
//While stream pointer is at a valid location, [stdin has more data
to give us]
while(fgets(dataBuffer, bufferSize, stdin)){
//Set pointer to buffer
ptmpData = dataBuffer;
//Get the contents of the buffer into tempString
tempString = toString(ptmpData);
//Append tempString to dataStorage
dataStorage ~= tempString;
}
if(dataStorage.length >= len){
dataStorage.length = len - 1;
}
return dataStorage;
}
}
void main(){
//Output HTTP headers -- Necessary when testing on Apache
string ctype = "Content-Type:text/html;charset=";
string encoding = "iso-8859-1";
string char1 = "\x0D";
string char2 = "\x0A";
writef("%s%s%s%s\n", ctype, encoding,char1,char2);
char[] postData = d_getPOSTData();
writefln("Post Data: %s", postData);
}
</code>
**Problem solved**
Thank you for your help, D Community ^_~.
More information about the Digitalmars-d-learn
mailing list