LinuxQuestions.org

LinuxQuestions.org (/questions/)
-   Programming (https://www.linuxquestions.org/questions/programming-9/)
-   -   How can I post data with POST method in C programming. (https://www.linuxquestions.org/questions/programming-9/how-can-i-post-data-with-post-method-in-c-programming-542700/)

haxpor 04-02-2007 12:37 PM

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.

Guttorm 04-02-2007 01:02 PM

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 :)

haxpor 04-02-2007 01:18 PM

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.

slzckboy 04-02-2007 07:05 PM

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

Guttorm 04-03-2007 08:52 AM

An example of libcurl HTTP post:
http://curl.haxx.se/lxr/source/docs/examples/postit2.c

haxpor 04-03-2007 08:56 AM

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.

haxpor 04-04-2007 10:10 AM

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?

slzckboy 04-04-2007 10:30 AM

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
?

haxpor 04-04-2007 11:04 AM

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.

slzckboy 04-04-2007 11:17 AM

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"


haxpor 04-04-2007 11:27 AM

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.

haxpor 04-04-2007 11:47 AM

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.

slzckboy 04-06-2007 04:15 AM

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

haxpor 04-06-2007 11:48 PM

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

haxpor 04-07-2007 04:18 AM

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.


All times are GMT -5. The time now is 05:39 PM.