www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - D CGI Hang with fgets

reply Morgan McDermott <morganmcdermott gmail.com> writes:
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;

			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
Nov 26 2006
next sibling parent reply Carlos Santander <csantander619 gmail.com> writes:
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 Santander Bernal
Nov 27 2006
parent reply Morgan McDermott <morganmcdermott gmail.com> writes:
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


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
Nov 27 2006
parent Morgan McDermott <morganmcdermott gmail.com> writes:
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


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 ^_~.
Nov 27 2006
prev sibling parent Thomas Kuehne <thomas-dloop kuehne.cn> writes:
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

Morgan McDermott schrieb am 2006-11-27:
 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;

 			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?

Change # char *prawData; to # char *prawData = (new char[len]).ptr; And send intput to stdin e.g.: # # programm < some_file # Thomas -----BEGIN PGP SIGNATURE----- iD8DBQFFa+H9LK5blCcjpWoRAo0sAKCk1D2u61K+G0r3N5iLc6LAtXzhvQCgjp5q gh0GeTpX+kJmy+w8tJ6LDVU= =LJup -----END PGP SIGNATURE-----
Nov 27 2006