ASPN ActiveState Programmer Network
ActiveState
/ Home / Perl / PHP / Python / Tcl / XSLT /
/ Safari / My ASPN /
Cookbooks | Documentation | Mailing Lists | Modules | News Feeds | Products | User Groups


Recent Messages
List Archives
About the List
List Leaders
Subscription Options

View Subscriptions
Help

View by Topic
ActiveState
.NET Framework
Open Source
Perl
PHP
Python
Tcl
Web Services
XML & XSLT

View by Category
Database
General
SOAP
System Administration
Tools
User Interfaces
Web Programming
XML Programming


MyASPN >> Mail Archive >> php-dev
php-dev
#50078 [Com]: file upload to the thttpd (with php patch) fails
by Nishantkumar05 At Gmail Dot Com other posts by this author
Nov 4 2009 7:36AM messages near this date
#50078 [Com]: [PATCH] file upload fails with thttpd | #50075 [NEW]: Provide single value difference in DateInterval->diff()
ID:               50078
 Comment by:       nishantkumar05 at gmail dot com
 Reported By:      nishantkumar05 at gmail dot com
 Status:           Open
 Bug Type:         Other web server
 Operating System: ubuntu 8.10
 PHP Version:      5.3.0
 New Comment:

This is the patch available.
=============================================================
diff -Nur php-5.3.0/sapi/thttpd/thttpd.c php-
5.3.0_mod/sapi/thttpd/thttpd.c
--- php-5.3.0/sapi/thttpd/thttpd.c	2008-12-31 03:15:49.000000000 
-0800
+++ php-5.3.0_mod/sapi/thttpd/thttpd.c	2009-11-02 19:02:28.000000000 
-0800
@@ -64,6 +64,9 @@
 #define TG(v) (thttpd_globals.v)
 #endif
 
+
+int read_pending_content( void ); 
+
 static int sapi_thttpd_ub_write(const char *str, uint str_length 
TSRMLS_DC)
 {
 	int n;
@@ -247,16 +250,77 @@
 
 static int sapi_thttpd_read_post(char *buffer, uint count_bytes 
TSRMLS_DC)
 {
-	size_t read_bytes = 0;
+	size_t read_bytes = 0, send2php_bytes = 0 ;
+	size_t buff_bytes = TG(hc)-> read_idx - TG(hc)->checked_idx ;
 
-	if (TG(unconsumed_length) >  0) {
-		read_bytes = MIN(TG(unconsumed_length), count_bytes);
-		memcpy(buffer, TG(hc)-> read_buf + TG(hc)->checked_idx, 
read_bytes);
-		TG(unconsumed_length) -= read_bytes;
-		CONSUME_BYTES(read_bytes);
+
+	if ( buff_bytes >  0 ) {
+		/*we might already have some bytes in read_buf to be 
sent to php module*/
+		read_bytes = buff_bytes;
+	}else if ( TG(hc)-> contentlength > 0 ){
+		read_bytes=read_pending_content();	
+	}
+
+	if ( read_bytes ) {
+			send2php_bytes = MIN ( read_bytes, 
count_bytes);
+			memcpy(buffer, TG(hc)-> read_buf + TG(hc)-
> checked_idx, send2php_bytes);
+			TG(hc)-> contentlength -= send2php_bytes;
+			/*bringing the read_idx back to checked_idx, 
so we have more room to read
+			  the pending bytes from connection*/
+			if ( send2php_bytes == read_bytes ) {
+				TG(hc)-> read_idx = TG(hc)->checked_idx 
;
+			} else {
+				/*memmove is costly: but for small 
devices we cant increase the buffer
+  				  size substantially. presuming that 
memmove doesnt use extra buffer
+				  internally*/
+				memmove(TG(hc)-> read_buf + TG(hc)-
> checked_idx, 
+							TG(hc)-
> read_buf + TG(hc)->checked_idx + send2php_bytes ,
+							read_bytes-
count_bytes);
+				TG(hc)-> read_idx = TG(hc)->checked_idx 
+ ( read_bytes - count_bytes )  ;
+			}
+
+			TG(unconsumed_length) -= send2php_bytes;
 	}
-	
-	return read_bytes;
+
+	return send2php_bytes;
+}
+
+
+/*
+ * Read the max possible (limited by the available buffer ) pending 
data
+ * from the network. hc-> contenlength has been used to tell about the

+ * pending data to be read from the network, hence onus is on the 
caller
+ * to modify it accordingly.
+ * It starts reading from checked_idx and updates the read_idx after 
reading.
+ * -nishant
+ * */
+int read_pending_content( void ) 
+{
+	int avail_buf= TG(hc)-> read_size - TG(hc)->read_idx; 
+	int act_to_read=0,total_read=0,ctr=0;
+
+
+	if ( TG(hc)-> contentlength < avail_buf ){
+		act_to_read = TG(hc)-> contentlength;
+	} else {
+		act_to_read = avail_buf - 2;
+	}
+
+	while(total_read != act_to_read)
+	{
+		ctr = read(TG(hc)-> conn_fd, &(TG(hc)->read_buf[TG(hc)-
> checked_idx]), act_to_read );
+		if(ctr < 0){
+			if( ( errno == EINTR ) || ( errno == EAGAIN ) 
){
+				continue;
+			}else{
+				break;
+			}
+		}
+		total_read += ctr;
+	}
+
+	TG(hc)-> read_idx += total_read;
+	return total_read;
 }
 
 static char *sapi_thttpd_read_cookies(TSRMLS_D)
@@ -663,12 +727,14 @@
 		hc-> do_keep_alive = 0;
 	}
 	
+#if 0
+	/*Its ok to have unconsumed bytes. We will consum in read_post 
function*/
 	if (hc-> contentlength != -1
 			&& SIZEOF_UNCONSUMED_BYTES() < hc-
> contentlength) {
 		hc-> read_body_into_mem = 1;
 		return 0;
 	}
-	
+#endif
 	thttpd_request_ctor(TSRMLS_C);
 
 	thttpd_module_main(show_source TSRMLS_CC);
=============================================================

thanks
Nishant


Previous Comments:
------------------------------------------------------------------------

[2009-11-04 15:27:21] nishantkumar05 at gmail dot com

Description:
------------
I have thttpd 2.1b patched with php-5.3.0. Try to upload file using
POST 
request to this web server. Small files ( max of 600 bytes or so ) can

be transferred, but big files, for which POST request will span
multiple 
packets fails.

Reproduce code:
---------------
.php web page that reproduces this bug is: (upload.php) 
<form enctype="multipart/form-data" action="uploader.php"
method="POST"> 
<input type="hidden" name="MAX_FILE_SIZE" value="2000000" /> 
Choose a file to upload: <input name="uploadedfile" type="file" /> <br
/> 
<input type="submit" value="Upload File" /> 
</form> 

Expected result:
----------------
It should be able to upload file of any size successfully.



------------------------------------------------------------------------


-- 
Edit this bug report at http://bugs.php.net/?id=50078&edit=1
Thread:
Nishantkumar05 At Gmail Dot Com
Asure007 At Hotmail Dot Com
Nishantkumar05 At Gmail Dot Com

Privacy Policy | Email Opt-out | Feedback | Syndication
© ActiveState Software Inc. All rights reserved