# Using libcurl to login to fetch sql table data

This topic is 4031 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

## Recommended Posts

So, yeah, like the subject says, I want to allow my server programs to take a user name and password, login to a core stats site (for instance), and modify or read mysql table data. So right now I'm trying to get the first part working, logging in. Using libcurl, I'm attempting to login using a form in a php-nuke site that looks like this:
<br>
<table width="100%" border="0" cellspacing="1" cellpadding="0" bgcolor="#0026FD"><tr><td>
<table width="100%" border="0" cellspacing="1" cellpadding="8" background="themes/Solaris/forums/images/bg_space_one_layer.jpg"><tr><td>
<form action="modules.php?name=Your_Account" method="post">
<table border="0"><tr><td>
</table><input type="hidden" name="redirect" value=>
<input type="hidden" name="mode" value=>
<input type="hidden" name="f" value=>
<input type="hidden" name="t" value=>



##### Share on other sites
Change the form method to GET and pass the user name/password as part of the URL. I don't think your -d data is properly formatted as a form post document.

##### Share on other sites
No, I definitely want to use POST. If you read here you'll see what I mean: http://curl.haxx.se/docs/httpscripting.html.

Specifically this part:
Quote:
 4.2 POST The GET method makes all input field names get displayed in the URL field of your browser. That's generally a good thing when you want to be able to bookmark that page with your given data, but it is an obvious disadvantage if you entered secret information in one of the fields or if there are a large amount of fields creating a very long and unreadable URL. The HTTP protocol then offers the POST method. This way the client sends the data separated from the URL and thus you won't see any of it in the URL address field. The form would look very similar to the previous one:
And to use curl to post this form with the same data filled in as before, we could do it like: curl -d "birthyear=1905&press=%20OK%20" www.hotmail.com/when/junk.cgi This kind of POST will use the Content-Type application/x-www-form-urlencoded and is the most widely used POST kind. The data you send to the server MUST already be properly encoded, curl will not do that for you. For example, if you want the data to contain a space, you need to replace that space with %20 etc. Failing to comply with this will most likely cause your data to be received wrongly and messed up.

I think you're right though, my post is definitely not formatted properly, but I'm not sure why. Anyone?

##### Share on other sites
Okay, its 3.20am here in NZ, and I was up watching america's cup, what does this have to do you with you? nothing, appart from me not having the concentration to look at your problem in detail.

Hope this helps (it's MFC but should be easy to translate):
struct HttpRequestObj{	CURL *sessionHandle;		std::vector<char> tempWriteBuffer;	size_t numBytesWritten;	HttpRequestObj() : sessionHandle(NULL), numBytesWritten(0)	{}	void resetWriteBuffer()	{		tempWriteBuffer.resize(0);		numBytesWritten = 0;	}	static size_t writeDataCB(void *buffer, size_t size, size_t nmemb, void *userp)	{		if( userp == NULL )			return 0;		HttpRequestObj *self = static_cast<HttpRequestObj*> (userp);		size_t oldSize = self->tempWriteBuffer.size();		char *p = NULL;		self->tempWriteBuffer.resize( self->tempWriteBuffer.size() + (size * nmemb) );		p = &self->tempWriteBuffer[0] + oldSize;		memcpy( p, buffer, (size * nmemb) );		self->numBytesWritten += (size * nmemb);		return size * nmemb;	}} httpReq;void HttpRequestInit() {	if( curl_global_init( CURL_GLOBAL_ALL ) != 0 )	{		AfxMessageBox("Error initializing HTTP library", MB_ICONERROR|MB_OK);		return;	}}CString HttpRequestPost(CString url, CString pd, CStatusDlg& st){	if( httpReq.sessionHandle == NULL )	{		httpReq.sessionHandle = curl_easy_init();		if( httpReq.sessionHandle == NULL ) 		{			AfxMessageBox("Error initializing HTTP session handle", MB_ICONERROR|MB_OK);			return "";		}	}	curl_slist *headers = NULL;	headers = curl_slist_append( headers, "Content-Type: application/x-www-form-urlencoded");	int len = pd.GetLength();	curl_easy_setopt( httpReq.sessionHandle, CURLOPT_POSTFIELDS, pd );	curl_easy_setopt( httpReq.sessionHandle, CURLOPT_HTTPHEADER, headers );	curl_easy_setopt( httpReq.sessionHandle, CURLOPT_URL, url ); 	curl_easy_setopt( httpReq.sessionHandle, CURLOPT_WRITEFUNCTION, httpReq.writeDataCB ); 	curl_easy_setopt( httpReq.sessionHandle, CURLOPT_WRITEDATA, (void*) &httpReq );		httpReq.resetWriteBuffer();	CURLcode r = curl_easy_perform( httpReq.sessionHandle ); 	curl_slist_free_all( headers );	if( r != 0 ) 	{		CString msg;		msg.Format("Error performing HTTP request: Code %i", (int)r );		AfxMessageBox( msg, MB_ICONERROR|MB_OK );		return "";	}	CString response( (LPCSTR) &httpReq.tempWriteBuffer[0] );	return response;}

where pd is a string like "msg=hello%20world&blah=bleh"

FYI > it definitely works, but it probably won't compile.

##### Share on other sites
Quote:
 it is an obvious disadvantage if you entered secret information

While that may be true for browsers that store previous URL lines, I believe libcurl doesn't integrate with your browser history (and if it does, it should be re-educated :-)

On the wire, there is no security difference between GET and POST. However, if the destination requires POST, and you can't change the destination, then that's a good reason to want to POST.

##### Share on other sites
Quote:
 Original post by hplus0603Change the form method to GET and pass the user name/password as part of the URL. I don't think your -d data is properly formatted as a form post document.

Big no-no, if I understand the intentions of the OP right.

GET is designated for idempotent operations. It must never mutate the state, or very weird things can happen (see thedailywtf.com for examples). While it may work for the login itself, it really shouldn't be used for updating the stats.

http://www.cs.tut.fi/~jkorpela/forms/methods.html

Note that as always, YMMV, but I feel that problems associated with this method are dangerous enough to be worth mentioning.

##### Share on other sites
Quote:
 GET is designated for idempotent operations. It must never mutate the state

The result of a GET is the login data, in this case. That doesn't mutate the state -- the state mutates of itself. Or are you saying that if I have a web page that displays the time when the page was generated, or the number of page views, cannot be served by a GET request? After all, the page view counter goes up by each GET request.

In practice, there are some web caches that will cache GET requests (but you cannot cache POST requests) -- however, with the appropriate cache validators (or de-validators) in the headers, GET is fine for this purpose. Again, assuming the target application will actually accept a GET.

##### Share on other sites
Quote:
Original post by hplus0603
Quote:
 GET is designated for idempotent operations. It must never mutate the state

The result of a GET is the login data, in this case. That doesn't mutate the state -- the state mutates of itself. Or are you saying that if I have a web page that displays the time when the page was generated, or the number of page views, cannot be served by a GET request? After all, the page view counter goes up by each GET request.

In practice, there are some web caches that will cache GET requests (but you cannot cache POST requests) -- however, with the appropriate cache validators (or de-validators) in the headers, GET is fine for this purpose. Again, assuming the target application will actually accept a GET.

The most dangerous situation comes from bots, who may, by following links, affect the internal state.

The idempotent here refers to the server's internal state, not the generated page. The counter itself is prone to abuse due to not following the rule - hence some counters restrict itself to unique IPs when determining the visitors.

The basic guideline is, that issuing a GET once or one million times should have no ill-effect on the server (it would however taint the counter). Not so in the case of updating a database using POST, where it's expected for some internal state to be affected by design.

This example isn't directly limited to GET vs. POST (involves cookies), but it does demonstrate the dangers of allowing GET requests to mutate the state:

##### Share on other sites
silvermace: That code works great, and I definitely get a response back from the server, but it's still not the one I'm expecting.

Can anyone tell me how I can actually submit the form data. '&op=Login' doesn't work, and a field name for the 'submit' element doesn't exist, only the 'Login' value. How do you submit to a form with an anonymous submit element. If this is more of an html question I apologize, but I figure someone around here must know.

BTW, thanks everyone for your feedback, I appreciate it.

##### Share on other sites
Quote:
 Spider of Doom

Right. Don't build a site that's broken. I think we all agree on that :-)

Quote:
 How do you submit to a form with an anonymous submit element.

The anonymous submit element is not by itself a problem.

Try this form in your browser, and see what the URL comes out as. Yes, it uses GET, just so you can easily see the URL!

<html><head><title>Test Form</title></head><body><form method='get'><input type='text' name='foo'/><input type='submit' value='Button'/></form></body></html>

(And, no, I didn't run it through the validator, and it doesn't have a doctype, etc -- it's just an illustration, that will happen to work)

1. 1
2. 2
Rutin
22
3. 3
JoeJ
20
4. 4
5. 5

• 27
• 40
• 23
• 13
• 13
• ### Forum Statistics

• Total Topics
631735
• Total Posts
3001940
×