LinuxQuestions.org
Download your favorite Linux distribution at LQ ISO.
Home Forums Tutorials Articles Register
Go Back   LinuxQuestions.org > Forums > Non-*NIX Forums > Programming
User Name
Password
Programming This forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.

Notices


Reply
  Search this Thread
Old 04-02-2007, 12:37 PM   #1
haxpor
Member
 
Registered: Dec 2006
Distribution: Ubuntu 20.04
Posts: 87

Rep: Reputation: 15
How can I post data with POST method in C programming.


I extreamly want to how can we program in C code to perform post data (such as login to some website which we send the username and pass data to web server, or any type of this kind which involve POST method).
I have try to program with GET method, it's work fine. Also i search through the net all day today, but i found info that can't immediately go into the real situaion here.

Below is C Code with GET Method, you can try with
# ./httpgetconnect <IPaddress> <relative_url> => ./httpgetconnect 210.1.13.198 /

this result will print the content in html to STDOUT
Please save from this link: [HTML]http://210.1.13.198/haxpor/httpgetconnect[/HTML]


the source is below.

Code:
#include <stdio.h>
#include <stdlib.h>
#include <usr/mynetwork.h>

int
main(int argc, char** argv) {
    int sockfd, n;
    char buff[MAXLINE],recvline[MAXLINE];
    struct sockaddr_in servaddr;
    
    if(argc != 3){
        printf("usage: httpgetconnect <ipaddress> <relative_url>");
        exit(0);
    }
    
    if( (sockfd = socket(AF_INET,SOCK_STREAM,IPPROTO_TCP)) == -1 ){
        printf("socket: error");
        exit(0);
    }
    
    bzero(&servaddr,sizeof(servaddr));
    servaddr.sin_family = AF_INET;
    servaddr.sin_port = htons(80);  //connect to http server
    
    if(inet_pton(AF_INET,argv[1],&servaddr.sin_addr) < 0){
        printf("port: assigned invalid");
        exit(0);
    }
    if( connect(sockfd,(struct sockaddr *)&servaddr,sizeof(servaddr)) == -1){
        printf("connect: error");
        exit(0);
    }
    
    //Sending Http header
    bzero(&buff,sizeof(buff));

    sprintf(buff,"GET %s HTTP1.1\nAccept: */*\nUser-Agent: Mozilla/4.0\nContent-Type: text/html\nPragma: no-cache\nConnection: keep-alive\n\n",argv[2]);
    if(write(sockfd,buff,sizeof(buff)) == -1)
        err_exit("write");
    
    while ((n =read(sockfd,recvline,sizeof(recvline))) > 0){
        recvline[n] = 0;
        if(fputs(recvline,stdout) == EOF)
            err_abort("read error");            
    }
    
    return (EXIT_SUCCESS);
 }

Any suggesstion that the code would be modify to "Perform POST Method" would be appreciate.
I guess it might be something about header.

Thanks.


NOTE
mynetwork.h is nothing special, it just include socket and relate header files and it contained err_exit() function only.
 
Old 04-02-2007, 01:02 PM   #2
Guttorm
Senior Member
 
Registered: Dec 2003
Location: Trondheim, Norway
Distribution: Debian and Ubuntu
Posts: 1,453

Rep: Reputation: 447Reputation: 447Reputation: 447Reputation: 447Reputation: 447
Hi

I don't know, is this for learning or a practical issue? Anyway, why not use libcurl, wget, or some other tool? If it's for learning, why not look at the source?

What I really like about opensource is the huge amount of examples - I have source code for everything
 
Old 04-02-2007, 01:18 PM   #3
haxpor
Member
 
Registered: Dec 2006
Distribution: Ubuntu 20.04
Posts: 87

Original Poster
Rep: Reputation: 15
I also download curl to my computer not long ago, but I go into it search through the source but I cant found the API function that perform for Post Method in curl. Maybe I miss something but I try it so long to keep finding it.

Maybe you can show me that section of sourcecode then (if you have time)
Thank very much. It's great to be helped.
 
Old 04-02-2007, 07:05 PM   #4
slzckboy
Member
 
Registered: May 2005
Location: uk - Reading
Distribution: slackware 14.2 kernel 4.19.43
Posts: 462

Rep: Reputation: 30
Your best bet is to read the HTTP rfc to see how to properly form a POST request.
Once you understand the protocol properly you can then translate this to C code.
I have done a bit of http/https programing and that is how I approach it.

http://www.w3.org/Protocols/rfc2616/rfc2616.html
 
Old 04-03-2007, 08:52 AM   #5
Guttorm
Senior Member
 
Registered: Dec 2003
Location: Trondheim, Norway
Distribution: Debian and Ubuntu
Posts: 1,453

Rep: Reputation: 447Reputation: 447Reputation: 447Reputation: 447Reputation: 447
An example of libcurl HTTP post:
http://curl.haxx.se/lxr/source/docs/examples/postit2.c
 
Old 04-03-2007, 08:56 AM   #6
haxpor
Member
 
Registered: Dec 2006
Distribution: Ubuntu 20.04
Posts: 87

Original Poster
Rep: Reputation: 15
slzckboy, do you have some sample sourcecode (POST Method) if then, could you show me right away.

I really want it.

This can save my time alot and also the others who want to know too.

Thanks in advance.
 
Old 04-04-2007, 10:10 AM   #7
haxpor
Member
 
Registered: Dec 2006
Distribution: Ubuntu 20.04
Posts: 87

Original Poster
Rep: Reputation: 15
After a long time for trying and experimenting the code with c. I decide to see the header in http which sending between my computer and server (that trap with Proxomitron 4.5 in Windows), I take that info and adapt it then try it with perl (usually very close with C), and it work with POST Method.

The sourcecode for Perl which connect to Any web server with POST Method is below.

Code:
#!/usr/bin/perl -w

use IO::Socket;

$socket = IO::Socket::INET->new(

Proto => 'tcp',

PeerAddr => '<IPofWebserver>',

PeerPort => 80,

Timeout => 10

);



$header = "POST <Link> HTTP/1.1\n";
$header .= "Accept: */*\n";
$header .= "Referer: <FullUrlLink>\n";
$header .= "Accept-Language: */*\n";
$header .= "Content-Type: application/x-www-form-urlencoded\n";
$header .= "Accept-Encoding: gzip, deflate\n";
$header .= "User-Agent: Mozilla/4.0\n";
$header .= "Content-Length: <SizeofData>\n";
$header .= "Pragma: no-cache\n";
$header .= "Connection: keep-alive\n\n";
$header .= "param1=value1&param2=value2";  #Calculate size here plus 1 byte for null-terminate string



unless($socket){

  print "Could not connect...\n";

  exit(0);

}

$socket->autoflush(1);

print $socket($header);



while(<$socket>){

s/\r\n//;

s/\n//;

last if($_ eq "");

}



while(<$socket>){

	print $_;

}

close $socket;

print "Success";

Note
You must fill in the infomation by yourself with that bold string(url of web server, data to send, etc)
Also be careful with the line that I commented, not include '&' in calculation so you have your data plus 1 byte to fill in Content-Length: header.
_Example_
<LINK> => /member.php?act=login
<FullUrlLink> => http://www.something.org

After this perl code is work fine, then I jump it concept to C immediately but I found it wont work.

Any suggestion?
 
Old 04-04-2007, 10:30 AM   #8
slzckboy
Member
 
Registered: May 2005
Location: uk - Reading
Distribution: slackware 14.2 kernel 4.19.43
Posts: 462

Rep: Reputation: 30
what is the server replying with?

are theyjust closing the connection straight away,or are the sending
a http response code


if so what code.


All my http code is for the GET method,but I will have
a go at figuring it out with you.

Is this to interact with cgi programs on servers;i.e for login info
?
 
Old 04-04-2007, 11:04 AM   #9
haxpor
Member
 
Registered: Dec 2006
Distribution: Ubuntu 20.04
Posts: 87

Original Poster
Rep: Reputation: 15
Yes, this interact with CGI script hosted on the web server.

The server return with 400 Bad Request code, still now I figuring it out what my header in C code is wrong. I do change it to be the same as Perl code above and modify it a little but the result is same it return 400 code every time.
IT MUST BE WRONG WITH HEADER, i guess that, other part is fine.

I am sure you have some account with some web server, if possible you can test this thing with the C Code above that i post
but change the line -> "GET %s .... to 'POST header' in Perl code above and run it with web server ip.

Thanks again.
 
Old 04-04-2007, 11:17 AM   #10
slzckboy
Member
 
Registered: May 2005
Location: uk - Reading
Distribution: slackware 14.2 kernel 4.19.43
Posts: 462

Rep: Reputation: 30
one thing i notice about your header is that it is non
standard in that you are suppose to have
\r\n between each header element as per the rfc

This is the header I use.
Note:you should terminate your header with \r\n\r\n

Code:
GET %s HTTP/1.1\r\nHost: %s\r\nConnection:"\
"keep-alive\r\nAccept: text/html\r\nAccept: image/gif\r\nAccept: image/x-xbitmap\r\n"\
"Accept: image/jpeg\r\nAccept: image/png\r\n\r\n"
 
Old 04-04-2007, 11:27 AM   #11
haxpor
Member
 
Registered: Dec 2006
Distribution: Ubuntu 20.04
Posts: 87

Original Poster
Rep: Reputation: 15
thanks for that point.
I fix as per slzckboy suggest but it still wont work with POST Method.

Keep it coming, i calmly waiting.

Thanks again.
 
Old 04-04-2007, 11:47 AM   #12
haxpor
Member
 
Registered: Dec 2006
Distribution: Ubuntu 20.04
Posts: 87

Original Poster
Rep: Reputation: 15
OK i will make it more comfortable for you all who trying to help.
You can download the sourcecode in .tar package (include main source and header file) for httpgetconnect, for this you can modify it to test with POST Method.

http://210.1.13.198/haxpor/httpgetconnect.tar

Hope this will provide more convenient.
 
Old 04-06-2007, 04:15 AM   #13
slzckboy
Member
 
Registered: May 2005
Location: uk - Reading
Distribution: slackware 14.2 kernel 4.19.43
Posts: 462

Rep: Reputation: 30
I't would be more helpful if you Just post the C code section relevant to
the POST request.
You havn't posted that yet.
Only you GET code.


thnx
 
Old 04-06-2007, 11:48 PM   #14
haxpor
Member
 
Registered: Dec 2006
Distribution: Ubuntu 20.04
Posts: 87

Original Poster
Rep: Reputation: 15
In fact the POST code is the same as GET code but instead you must change the HEADER section of the line 'sprint("GET...' to POST Specific header.

But as you wish, Below is the code for POST Method.

Code:
#include <stdio.h>
#include <stdlib.h>
#include <usr/mynetwork.h>

/*
 * 
 */
int
main(int argc, char** argv) {
    int sockfd, n;
    char buff[MAXLINE],recvline[MAXLINE];
    struct sockaddr_in servaddr;
    
    if(argc != 3){
        printf("usage: httppostconnect <ipaddress> <relative_url>");
        exit(0);
    }
    
    if( (sockfd = socket(AF_INET,SOCK_STREAM,IPPROTO_TCP)) == -1 ){
        printf("socket: error");
        exit(0);
    }
    
    bzero(&servaddr,sizeof(servaddr));
    servaddr.sin_family = AF_INET;
    servaddr.sin_port = htons(80);  //connect to http server
    
    if(inet_pton(AF_INET,argv[1],&servaddr.sin_addr) < 0){
        printf("port: assigned invalid");
        exit(0);
    }
    if( connect(sockfd,(struct sockaddr *)&servaddr,sizeof(servaddr)) == -1){
        printf("connect: error");
        exit(0);
    }
    
    //Sending Http header
    bzero(&buff,sizeof(buff));
    
    char postdata[] = "param1=value1&param2=value";  /* Change param and value here */

    sprintf(buff,"POST %s HTTP1.1\r\nAccept: */*\r\nReferer: <REFERER HERE>\r\nAccept-Language: en-us\r\nContent-Type: application/x-www-form-urlencoded\r\nAccept-Encoding: gzip,deflate\r\nUser-Agent: Mozilla/4.0\r\nContent-Length: %d\r\nPragma: no-cache\r\nConnection: keep-alive\r\n\r\n%s",argv[2],strlen(postdata),postdata);
    
    if(write(sockfd,buff,strlen(buff)+1) == -1)
        err_exit("write");
    
    while ((n =read(sockfd,recvline,sizeof(recvline))) > 0){
        recvline[n] = 0;
        if(fputs(recvline,stdout) == EOF)
            err_abort("read error");            
    }
    return (EXIT_SUCCESS);
}
The header line is depand on what data to be send to server such as 'username' = 'something' to send to server, etc.

This is the link for httppostconnect (include header fies and sourcecode)
http://210.1.13.198/haxpor/httppostconnect.tar
 
Old 04-07-2007, 04:18 AM   #15
haxpor
Member
 
Registered: Dec 2006
Distribution: Ubuntu 20.04
Posts: 87

Original Poster
Rep: Reputation: 15
Ok everyone, i want to tell you all that the problem is the HEADER as I suggest, and it is true.
It is my mistake not to calmly and slowly see at the header. The header is wrong.
As you can see from GET Method code from above the line 'sprintf(..'
you will see "GET %s HTTP1.1.." this is wrong, the correct is "GET %s HTTP/1.1". Although that mistake work with GET Method but it wont work with POST Method.

So after all, you can try this by correct that line of header to the correct one as i tell you, then run it. (NOTE: you must fill in the info of the server and data you want to send by yourself)

Tell me if it work!

PS.
-Thanks to you all that work along and together figure it out the problem. Guttorm, slzckboy.
 
  


Reply



Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off



Similar Threads
Thread Thread Starter Forum Replies Last Post
Method Not Allowed: The requested method POST is not allowed for the URL /writedhcp.p WiWa Linux - Networking 15 01-06-2011 01:20 PM
squid: getting data from post method hiren_bhatt Linux - Software 0 09-11-2006 11:44 AM
SlackWare :Method Not Allowed The requested method POST is not allowed for the URL slack31337 Linux - Software 0 04-08-2006 06:09 PM
Problem with POST method in BOA estratos Linux - Networking 0 03-13-2006 03:49 PM
PHP Post and GET method dai Programming 4 02-26-2003 09:45 AM

LinuxQuestions.org > Forums > Non-*NIX Forums > Programming

All times are GMT -5. The time now is 01:37 AM.

Main Menu
Advertisement
My LQ
Write for LQ
LinuxQuestions.org is looking for people interested in writing Editorials, Articles, Reviews, and more. If you'd like to contribute content, let us know.
Main Menu
Syndicate
RSS1  Latest Threads
RSS1  LQ News
Twitter: @linuxquestions
Open Source Consulting | Domain Registration