同事做的一个web系统,想让别人来提交数据,具体操作就是访问一个URL地址,提交用户名和主机等信息。
而且在这之余,想记下操作的用户ID,因此建议俺搞一个命令行工具来给他用。
一开始俺想到用system封装CURL,但是这样比较弱智,而且这样做了哪些操作,系统是能够记录下来的,用官方正式一点的话说就是不太安全,有安全隐患,呵呵。
于是乎,下载了curl的源码,生成命令行工具之后,查看curl源码,结合命令行测试,最终目的,就是怎么把
curl --digest -u user:pass url地址
转换成另外一个接口,比如
./auto_http --auth cme:cme -u jigang.djg -n testhost
这样的,这样做的话,就能够在auto_http的源码中提取uid,IP等等相关信息,而且提交人也不知道我怎么实现提交的,不知道我采用了url,不知道我记录下了他的uid,不知道我们web系统的相关信息。
实现代码如下:
//---------auto.c----------created by cme
#include <stdio.h>
#include <stdarg.h>
#include <string.h>
#include <curl/curl.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#define my_setopt(x,y,z) _my_setopt(x, 0, #y, y, z)
#define my_setopt_str(x,y,z) _my_setopt(x, 1, #y, y, z)
static CURLcode _my_setopt(CURL *curl, int str,const char *name, CURLoption tag, ...);
//#define URL "http://account.tbsite.net:9999/api/websubmits?"
#define URL "http://afang.org/cme_digest/?"
int main(int argc, char *argv[])
{
CURL *curl;
CURLcode res;
char strurl[1024] = {0};
unsigned int uid = getuid();
if(argc != 7)
{
printf("Usage:%s --auth name:pass -u user -n host\n", argv[0]);
exit(1);
}
if (strncmp(argv[1], "--auth", 6) != 0)
{
printf("Usage:%s --auth name:pass -u user -n host\n", argv[0]);
exit(1);
}
char * str = strchr (argv[2], ':');
if (!str)
{
printf("Usage:%s --auth name:pass -u user -n host\n", argv[0]);
exit(1);
}
if (strncmp(argv[3], "-u", 2) != 0)
{
printf("Usage:%s --auth name:pass -u user -n host\n", argv[0]);
exit(1);
}
if (strncmp(argv[5], "-n", 2) != 0)
{
printf("Usage:%s --auth name:pass -u user -n host\n", argv[0]);
exit(1);
}
curl = curl_easy_init();
if(curl!=NULL)
{
my_setopt(curl, CURLOPT_HTTPAUTH, CURLAUTH_DIGEST);
//my_setopt_str(curl, CURLOPT_USERPWD, "cme:cme");
my_setopt_str(curl, CURLOPT_USERPWD, argv[2]);
//my_setopt_str(curl, CURLOPT_PROXYUSERPWD, "cne:cme");
//curl_easy_setopt(curl, CURLOPT_TLSAUTH_USERNAME, "cme");
//curl_easy_setopt(curl, CURLOPT_TLSAUTH_PASSWORD, "cme");
sprintf (strurl, "%suser=%s&host=%s&submitby=%u", URL, argv[4], argv[6], uid);
printf ("get url:%s\n", strurl);
curl_easy_setopt(curl, CURLOPT_URL, strurl);
res = curl_easy_perform(curl);
}
return 0;
}
CURLcode _my_setopt(CURL *curl, int str,const char *name, CURLoption tag, ...)
{
va_list arg;
CURLcode ret;
char *bufp;
char value[256];
int remark = 0;
int skip = 0;
va_start(arg, tag);
if(tag < CURLOPTTYPE_OBJECTPOINT)
{
long lval = va_arg(arg, long);
snprintf(value, sizeof(value), "%ldL", lval);
ret = curl_easy_setopt(curl, tag, lval);
if(!lval)
skip = 1;
}
else if(tag < CURLOPTTYPE_OFF_T)
{
void *pval = va_arg(arg, void *);
unsigned char *ptr = (unsigned char *)pval;
// function pointers are never printable
if(tag >= CURLOPTTYPE_FUNCTIONPOINT)
{
if(pval)
{
strcpy(value, "functionpointer"); // 'value' fits 256 bytes
remark = 1;
}
else
skip = 1;
}
else if(pval && str)
snprintf(value, sizeof(value), "\"%s\"", (char *)ptr);
else if(pval)
{
strcpy(value, "objectpointer"); // 'value' fits 256 bytes
remark = 1;
}
else
skip = 1;
ret = curl_easy_setopt(curl, tag, pval);
}
else
{
curl_off_t oval = va_arg(arg, curl_off_t);
snprintf(value, sizeof(value),
"(curl_off_t)%" CURL_FORMAT_CURL_OFF_T, oval);
ret = curl_easy_setopt(curl, tag, oval);
if(!oval)
skip = 1;
}
va_end(arg);
return ret;
}
总结了下,还是curl的代码写得好,一个operate函数中嵌套了通用的set_opt,甚是好用啊。
简单的几行代码,就实现了。哈哈。
附上makefile
default:
gcc -c -g auto.c
gcc -o auto_http auto.o -lcurl
clean:
rm -fr auto_http *.o