热门 购物 团购 理财 文学 人才 体育 汽车 游戏 软件 军事 音乐 视频 媒体 论坛 博客 银行 交友 综合
一起购 唯品会 梦芭莎 趣玩网 凡客诚品 麦考林 乐淘鞋网 弗克尚品 绿盒子 俏物悄语 新蛋网 当当网 玛萨玛索
拉手网 糯米网 爱帮团 聚划算 58团购 美团网 QQ团购 大众点评团 窝窝团 美淘网 满座网 团宝网 饭统饭团
起点网 榕树下 小说阅读 潇湘书院 红袖添香 幻剑书盟 新浪游戏 太平洋游戏 163邮箱 中国游戏 游戏中国 霏凡软件 铁血军事
访问本站赠送红包啦!凡在支付宝搜索数字口令 528131323 都将获得红包,天天搜索此口令天天得红包^_^
Health Sitology Family Finance Appliances Shopping Clothing Education Legal Rituals Beauty Property Travel Pet Medical Cyclopedia History Military Computers Sports Job Anecdote Geographic Mixed Entertain Literature Emotion Agriculture
/**
 * 任何人任何机构皆可用于任何项目,此软件免费无需书面授权
 * 在软件和软件的所有副本中都必须包含版权声明和软件相关注解
 *
 * 模块: http.c
 * 简述: HTTP分析头与GET POST 生成GET或POST格式串
 * 作者: woods zhang  ->  hoojar@163.com -> http://www.hecart.com/
 * 版权: 2006-2018, 张树林 拥有此源码所有版权 (MIT许可协议)
 * Copyright 2006-2018, Woods Zhang All Rights Reserved (The MIT License)
 */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>
#include "../lib/htkv.h"
#include "../lib/cstring.h"

typedef struct
{
    char *http_head;
    char *http_body;
    char user_agent[100];
    char request_method[10];
    char request_uri[1024];
    char http_version[30];
} http_request;

/**
 * 十六进制转换为十进制
 *
 * @param code 要转换的十六进制字符
 * @return 转码后的十进制
 */
static char hexdec(char ch)
{
    return (char)(isdigit(ch) ? ch - '0' : toupper(ch) - 'A' + 10);
}

/**
 * 统计将普通字符串转成URLENCODE字符串需要多少字节
 *
 * @param p 要组合普通的字符串
 * @return 转换好后需要多少字节数
 */
static int url_count(const char *p)
{
    int k;
    for (k = 0; *p != 0; p++)
    {
        if (isalnum(*p) || *p == '-' || *p == '_' || *p == '.' || *p == '~' || *p == ' ')
        {
            k++;
        }
        else
        {
            k += 3;
        }
    }

    return k;
}

/**
 * 编码 URL 字符串
 *
 * @param in 要编码的字符串
 * @param out 编码后的字符串
 * @return 编码后的字符串
 */
static char *build_encode(const char *in, char *out)
{
    if (NULL == in || *in == 0)
    {
        return out;
    }

    const char hexdigit[] = "0123456789ABCDEF";
    for (; *in != 0; in++)
    {
        if (isalnum(*in) || *in == '-' || *in == '_' || *in == '.' || *in == '~')
        {
            *out++ = *in;
        }
        else if (*in == ' ')
        {
            *out++ = '+';
        }
        else
        {
            *out++ = '%';
            *out++ = hexdigit[(*in >> 4) & 0xf];
            *out++ = hexdigit[*in & 0xf];
        }
    }
    *out = 0;

    return out;
}

/**
 * 编码 URL 字符串
 *
 * @param in 要编码的字符串
 * @param out 编码后的字符串
 * @return 编码后的字符串
 */
char *urlencode(const char *in, char *out)
{
    build_encode(in, out);

    return out;
}

/**
 * 解码 URL 字符串
 *
 * @param in 要编码的字符串
 * @param out 解码后的字符串
 * @return 解码后的字符串
 */
char *urldecode(const char *in, char *out)
{
    if (NULL == in || *in == 0)
    {
        return out;
    }

    char *ret = out;
    while (*in)
    {
        if (*in == '%')
        {
            if (in[1] && in[2])
            {
                *out++ = hexdec(in[1]) << 4 | hexdec(in[2]);
                in += 2;
            }
        }
        else if (*in == '+')
        {
            *out++ = ' ';
        }
        else
        {
            *out++ = *in;
        }
        in++;
    }
    *out = '';

    return ret;
}

/**
 * 分析HTTP请求内容
 *
 * @param haystack 字符串
 * @param hrq 请求协议头
 * @return 请求协议头
 */
http_request *http_parse_request(char *haystack, http_request *hrq)
{
    int rnlen = strpos(haystack, " ");
    if (rnlen <= 0)
    {
        return hrq;
    }

    hrq->http_body = haystack + rnlen + 4;
    hrq->http_head = strleft(haystack, rnlen);

    int ualen = strpos(hrq->http_head, "User-Agent");
    if (ualen > 0)
    {
        strncpy(hrq->user_agent, hrq->http_head + ualen + 11, 100);
        int uarn = strpos(hrq->user_agent, " ");
        if (uarn > 0)
        {
            hrq->user_agent[uarn] = '';
        }
        else
        {
            hrq->user_agent[100] = '';
        }
    }

    int i = 0, j = 0;
    hrq->request_method[0] = '';
    hrq->request_uri[0] = '';
    hrq->http_version[0] = '';

    char *str = hrq->http_head;
    while (*str != ' ')
    {
        if (*str == ' ')
        {
            if (hrq->request_method[0] == 0)
            {
                memcpy(hrq->request_method, hrq->http_head + j, (i - j));
                hrq->request_method[i] = '';
                j = i;
            }
            else if (hrq->request_uri[0] == 0)
            {
                memcpy(hrq->request_uri, hrq->http_head + j, (i - j));
                hrq->request_uri[(i - j)] = '';
                j = i;
            }
        }

        i++;
        str++;
    }

    memcpy(hrq->http_version, hrq->http_head + j, (i - j));
    hrq->http_version[(i - j)] = '';

    trim(hrq->user_agent);
    trim(hrq->request_uri);
    trim(hrq->http_version);
    trim(hrq->request_method);

    return hrq;
}

/**
 * 分析有规律格式的数据内容
 *
 * @param query 要分析的字符串
 * @param equaler KEY与VAL之间的等于符
 * @param separator 下一个元素的分隔符
 * @param prefix 存储到HTKV中KEY的前缀
 * @return 分析成功返回true反知为false
 */
bool http_parse_data(char *query, const char equaler, const char separator, const char *prefix)
{
    if (query == NULL || *query == 0)
    {
        return false;
    }

    htkv *node = NULL;
    char *stmp = query;
    register size_t i = 0, clen = 0;
    register size_t p = 0, qsize = strlen(query);

    for (p = 0; p <= qsize; p++)
    {
        if (query[p] == equaler)
        {
            clen = p - i;
            clen = (clen >= HTKV_KEY_SIZE) ? HTKV_KEY_SIZE - 1 : clen;
            node = (htkv *) calloc(sizeof(htkv), 1);
            strncpy(node->key, stmp + i, clen);
            trim(node->key);//保证KEY两端无空格
            if (prefix != NULL && *prefix != 0)
            {
                str_insert(node->key, prefix, 0);
            }
            i = p + 1;
        }
        else if (query[p] == separator || query[p] == '')
        {
            if (node == NULL)
            {
                i = p + 1;
                continue;
            }

            clen = p - i;
            node->val = (char *) calloc(1, clen + 1);
            strncpy(node->val, stmp + i, clen);
            node->next = NULL;
            htkv_put(node);
            i = p + 1;
            node = NULL;
        }
    }

    return true;
}

/**
 * 建立有规律的数据格式
 *
 * @param equaler KEY与VAL之间的等于符
 * @param separator 下一个元素的分隔符
 * @param prefix 存储到HTKV中KEY的前缀
 * @return 组建好的规律数据
 */
char *http_build_data(const char equaler, const char separator, const char *prefix)
{
    int i, bsize = 0;
    int psize = strlen(prefix);
    htkv *item = NULL;
    htkv *kvres = htkv_res();
    for (i = 0; i < HTKV_SIZE; i++)
    {
        item = kvres + i;
        while (item)
        {
            if (strncmp(item->key, prefix, psize) == 0)
            {
                bsize += url_count(item->key) + url_count(item->val);
            }
            item = item->next;
        }
    }

    if (bsize == 0)
    {
        return NULL;
    }

    char *query = (char *)malloc(bsize + 1);
    char *ret = query;
    for (i = 0; i < HTKV_SIZE; i++)
    {
        item = kvres + i;
        while (item)
        {
            if (strncmp(item->key, prefix, psize) == 0)
            {
                query = build_encode(item->key + psize, query);
                *query++ = equaler;
                query = build_encode(item->val, query);
                *query++ = separator;
            }
            item = item->next;
        }
    }
    *(--query) = '';

    return ret;
}

/**
 * 获取GET参数数据
 *
 * @param name 参数名称
 * @return 参数值
 */
char *http_get_val(char *name)
{
    if (name == NULL || *name == 0)
    {
        return name;
    }

    char key[HTKV_KEY_SIZE] = "GET-";
    strcat(key, name);

    return htkv_get(key);
}

/**
 * 获取POST参数数据
 *
 * @param name 参数名称
 * @return 参数值
 */
char *http_post_val(char *name)
{
    if (name == NULL || *name == 0)
    {
        return name;
    }

    char key[HTKV_KEY_SIZE] = "POST-";
    strcat(key, name);

    return htkv_get(key);
}

/**
 * 获取COOKIE参数数据
 *
 * @param name 参数名称
 * @return 参数值
 */
char *http_cookie_val(char *name)
{
    if (name == NULL || *name == 0)
    {
        return name;
    }

    char key[HTKV_KEY_SIZE] = "COOKIE-";
    strcat(key, name);

    return htkv_get(key);
}

/* gcc -Wall -o http http.c ../lib/cstring.c ../lib/htkv.c */
int main()
{
    char buf[] = "GET /gprs/alert/update?gprs_val=1024&gprs_alert_id=5 HTTP/1.1 "
                 "Host: tllpt.yunovo.cn "
                 "User-Agent: Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:64.0) Gecko/20100101 Firefox/64.0 "
                 "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8 "
                 "Accept-Language: en-US,en;q=0.5 "
                 "Accept-Encoding: gzip, deflate "
                 "Referer: http://tllpt.yunovo.cn/gprs/alert/update "
                 "Content-Type: application/x-www-form-urlencoded "
                 "Content-Length: 47 "
                 "Connection: keep-alive "
                 "Cookie: currency=CNY; language=cn; groupid=1; gprsid=ws88fpy97kk4rk; token=fddf4cb38c7c36c15499e27458bfbadc "
                 "Upgrade-Insecure-Requests: 1 "
                 "alert_value=50&alert_tpl1=alert&alert_tpl2=over";

    http_request hrq;
    http_parse_request(buf, &hrq);

    /**
     * 分析HTTP数据
     */
    printf("------------------------------- http head ------------------------------- %s ", hrq.http_head);
    printf("------------------------------- http body ------------------------------- %s ", hrq.http_body);
    printf("------------------------------- request method -------------------------- %s ", hrq.request_method);
    printf("------------------------------- request uri ----------------------------- %s ", hrq.request_uri);
    printf("------------------------------- user agent ------------------------------ %s ", hrq.user_agent);
    printf("------------------------------- http version ---------------------------- %s ", hrq.http_version);

    /**
     * 分析HTTP HEADER
     */
    char *str = (char *) malloc(strlen(hrq.http_head));
    strcpy(str, hrq.http_head + strpos(hrq.http_head, " ") + 2);
    strrpl(str, ": ", "|");
    strrpl(str, " ", " ");
    http_parse_data(str, '|', ' ', "");
    free(str);
    str = NULL;
    htkv_case(false);//设置HTKV根据KEY不区分大小写

    /**
     * 分析COOKIE
     */
    str = htkv_get("Cookie");
    if (str != NULL)
    {
        http_parse_data(str, '=', ';', "COOKIE-");
    }

    /**
     * 分析GET
     */
    str = strrchr(hrq.request_uri, '?');
    if (str != NULL)
    {
        http_parse_data(str + 1, '=', '&', "GET-");
    }

    /**
     * 分析POST
     */
    str = htkv_get("Content-Type");
    if (strncasecmp(str, "application/x-www-form-urlencoded", 33) == 0)
    {
        http_parse_data(hrq.http_body, '=', '&', "POST-");
    }
    htkv_case(true);//设置HTKV根据KEY不区分大小写

    printf("GET gprs val:%s ", http_get_val("gprs_val"));
    printf("POST alert tip:%s ", http_post_val("alert_tpl1"));
    printf("COOKIE token:%s ", http_cookie_val("token"));

    htkv_print();
    htkv_free();
    printf("------------------------------------------------------------- ");

    /**
     * 组建key=val规律格式字符串
     */
    http_parse_data("name=woods&sex=man&age=38&nation=China", '=', '&', "GET-");
    char *query = http_build_data('=', '&', "GET-");
    printf("query:%s ", query);
    free(query);

    /**
     * URLENCODE与URLDECODE
     */
    char *url = "domain=hecart.com&url=http://www.hecart.com";
    char encode[100], decode[100];
    printf("url encode:%s ", urlencode(url, encode));
    printf("url decode:%s ", urldecode(encode, decode));
    htkv_free();

    return 0;
}
Reply content :
Photo link :
There never was such a wide variety available in the market of security camerasA hidden camera could be there right in front of you in the form of a pen, toy, wallet, or most unsuspected a cell phone, and nobody would be able to tell, while the device…  Details
By Lisa RobertsParticipating in discussion forums can mean profit for your business. How so? Any business with a website aims for traffic. The more people visit your business website the more chances you have of making more sales and acquiring n…  Details
 一提到FlashGet你会想到什么?的确,它是我们上网时的一把下载利器。但是今天我要颠覆传统,告诉你FlashGet不只是会下载。1.信息备忘录不知道现在你是不是也和笔者一样下载并…  Details
根据提供的路径说明返回明确完整的路径。object.GetAbsolutePathName(pathspec) 参数 object必需 应为 FileSystemObject 的名称。pathspec必选项。 要变为明确完整路径的路径说明说明 如果路径提供了从指…  Details
My important apps are: (1) Desktop Search (2) My Video Camera Software & My VB5.0 compiler (3) Net Browser (4) Paint & NotePad (5) Operating Systems (6) PrintKey 2000 (7) Games-----------------Individual preferences may change the above …  Details
(PHP 3>= 3.0.3, 4.0.5 - 4.3.0 only)com_get -- 获取 COM 组件的属性值 描述 mixed com_get ( resource com_object, string property) 返回由 com_object 所引用的 COM 对象的 property 属性值,出错则返回 FALSE。 com_get…  Details
我们要在新窗口中打开链接通常的做法是在链接后面加target="_blank",我们采用过渡型的DOCTYPE(xhtml1-transitional. dtd)时没有问题,但是当我们使用严格的DOCTYPE(xhtml1-strict.dtd)时,这个方法…  Details
问:我用成批添加下载列表的方式在FlashGet中添加了许多下载任务,下载文件直接存放在局域网上的另一台电脑的硬盘中。由于下载过程中这台用来存储下载文件的电脑突然重启,…  Details
Day after day, I am forced to face computer users who have just lost some data that was important to themComputer backup was the last thing on their mind, if on their mind at allAlmost every single one of them knew that they should have been backin…  Details
问:我在多次安装卸载FlashGet的不同版本后,现在无论下载什么版本的简体中文版网际快车,都变成英文版本的界面了,但我以前也没有安装过英文版本的网际快车呀。我把注册表…  Details