ソフトウェア開発 C++

C++で2ちゃんねるに書き込む

戻る


C++で2ちゃんねるに書き込むコードは以下の通り。

// write2ch.cpp --- Write a message to 2ch.net thread
// Copyleft 2012 Katayama Hirofumi MZ. No rights reserved.
// 2012.03.22 created
#define _CRT_SECURE_NO_WARNINGS
#include <cstdlib>
#include <cctype>
#include <iostream>
#include <string>
#include <list>
#include <map>
#include <curl/curl.h>
using namespace std;
 
#pragma comment(lib, "libcurl.lib")

const int g_timeout = 5;    // in seconds
char *g_user_agent = "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0)";
char *g_tmpname = NULL;
char *g_cookie_file = "cookie.txt";
 
size_t writefn(char *ptr, size_t size, size_t nmemb, void *userdata)
{
    return fwrite(ptr, size, nmemb, (FILE *)userdata);
}
 
string urlencode(string str)
{
    string t;
    size_t i, size = str.size();
    char fmt[4];
 
    for(i = 0; i < size; i++) {
        char ch = str[i];
        if (ch == ' ') {
            t += '+';
        } else if (isalnum(ch) || ch == '-' || ch == '_' || ch == '.') {
            t += ch;
        } else {
            ::wsprintf(fmt, "%%%02X", (unsigned char)ch);
            t += fmt;
        }
    }
    return t;
}
 
string urldecode(string str)
{
    string t;
    size_t i, size = str.size();
    char fmt[4];
 
    for(i = 0; i < size; i++) {
        char ch = str[i];
        if (ch == '+') {
            t += ' ';
        } else if (ch == '%') {
            fmt[0] = str[++i];
            fmt[1] = str[++i];
            fmt[2] = 0;
            t += (char)strtol(fmt, NULL, 16);
        } else {
            t += ch;
        }
    }
    return t;
}
 
string htmlspecialchars(string str)
{
    string t;
    size_t i, size = str.size();
 
    for(i = 0; i < size; i++) {
        char ch = str[i];
        switch(ch) {
        case '&':   t += "&amp;";   break;
        case '"':   t += "&quot;";  break;
        case '\'':  t += "&#039;";  break;
        case '<':   t += "&lt;";    break;
        case '>':   t += "&gt;";    break;
        default:    t += ch;        break;
        }
    }
    return t;
}
 
string htmlspecialchars_decode(string str)
{
    string t;
    size_t i, size = str.size();
 
    for(i = 0; i < size; i++) {
        char ch = str[i];
        if (ch == '&') {
            ch = str[++i];
            if (ch == '#') {
                if (str[i + 1] == 'x' || str[i + 1] == 'X') {
                    // &#x0F; etc.
                    i++;
                    ch = (char)strtol(&str[i], NULL, 16);
                    t += ch;
                    while(isxdigit(str[i])) i++;
                } else {
                    // &#15; etc.
                    ch = (char)strtol(&str[i], NULL, 10);
                    t += ch;
                    while(isdigit(str[i])) i++;
                }
            } else if (
                str[i + 0] == 'l' && str[i + 1] == 't' &&
                str[i + 2] == ';')
            {
                t += '<';   // &lt;
                i += 2;
            } else if (
                str[i + 0] == 'g' && str[i + 1] == 't' &&
                str[i + 2] == ';')
            {
                t += '>';   // &gt;
                i += 2;
            } else if (
                str[i + 0] == 'a' && str[i + 1] == 'm' &&
                str[i + 2] == 'p' && str[i + 3] == ';')
            {
                t += '&';   // &amp;
                i += 3;
            }
            else if (
                str[i + 0] == 'q' && str[i + 1] == 'u' &&
                str[i + 2] == 'o' && str[i + 3] == 't' &&
                str[i + 3] == ';')
            {
                t += '"';   // &quot;
                i += 4;
            }
        } else {
            t += ch;
        }
    }
    return t;
}
 
bool print_cookies(
    CURL* curl)
{
    CURLcode res;
    struct curl_slist *cookies, *node;
 
    res = curl_easy_getinfo(curl, CURLINFO_COOKIELIST, &cookies);
    if (res == CURLE_OK) {
        node = cookies;
        while(node) {
            printf("cookie: %s\n", node->data);
            node = node->next;
        }
        curl_slist_free_all(cookies);
        return true;
    } else {
        fprintf(
            stderr, "curl_easy_getinfo failed: %s\n", curl_easy_strerror(res));
        return false;
    }
}
 
bool parse_input(
    const char* s,
    string& strName,
    string& strValue)
{
    const char *p, *q;
 
    strName.clear();
    strValue.clear();
 
    p = strstr(s, " name=");
    if (p == NULL) p = strstr(s, " NAME=");
 
    if (p != NULL) {
        p += strlen(" name=");
        if (*p == '"') {
            p++;
            q = strchr(p, '"');
        } else q = strchr(p, ' ');
        if (q == NULL) q = p + strlen(p);
        strName.assign(p, q - p);
    }
    else
        return false;
 
    if (strName.empty()) return false;
 
    p = strstr(s, " value=");
    if (p == NULL) p = strstr(s, " VALUE=");
 
    if (p != NULL) {
        p += strlen(" value=");
        if (*p == '"') {
            p++;
            q = strchr(p, '"');
        } else q = strchr(p, ' ');
        if (q == NULL) q = p + strlen(p);
        strValue.assign(p, q - p);
        strValue = htmlspecialchars_decode(strValue);
    }
 
    return true;
}
 
bool parse_fields(
    const char* s,
    map<string, string>& mapFields)
{
    const char *p, *q, *r;
    string strForm, strInput, strName, strValue;
 
    mapFields.clear();
 
    // <form> .. </form>
    p = strstr(s, "<form");
    if (p == NULL) p = strstr(s, "<FORM");
    if (p == NULL) return false;
    p = strchr(p, '>');
    if (p == NULL) return false;
    p++;
    q = strstr(p, "</form");
    if (q == NULL) q = strstr(p, "</FORM");
    strForm.assign(p, q - p);
 
    p = strForm.c_str();
    for(;;) {
        // <input ...>
        q = strstr(p, "<input");
        if (q == NULL) q = strstr(p, "<INPUT");
        if (q == NULL) break;
        r = strchr(q, '>');
        if (r == NULL) break;
        strInput.assign(q, r - q);
        if (parse_input(strInput.c_str(), strName, strValue))
        {
            mapFields.insert(make_pair(strName, strValue));
        }
        p = r + 1;
    }
    return true;
}
 
bool map_to_string(
    const map<string, string>& m,
    string& str)
{
    // key1=value1&key2=value2&...
    map<string, string>::const_iterator it, end = m.end();
    it = m.begin();
    if (it != end) {
        str += it->first;
        str += "=";
        str += urlencode(it->second);
        for( ; it != end; it++) {
            str += '&';
            str += it->first;
            str += "=";
            str += urlencode(it->second);
        }
        return true;
    }
    return false;
}
 
char* file_get_contents(const char* file)
{
    char *ptr = NULL;
    FILE *fp = fopen(file, "rb");
    if (fp == NULL) return NULL;
 
    if (fseek(fp, 0, SEEK_END) == 0) {
        long size = ftell(fp);
        if (fseek(fp, 0, SEEK_SET) == 0) {
            ptr = (char *)malloc(size + 1);
            if (ptr != NULL) {
                if (fread(ptr, size, 1, fp)) {
                    ptr[size] = 0;  // success
                } else {
                    free(ptr);
                    ptr = NULL;
                }
            }
        }
    }
    fclose(fp);
    return ptr;
}
 
void print_map(const map<string, string>& m)
{
    map<string, string>::const_iterator it, end = m.end();
    for(it = m.begin(); it != end; it++) {
        printf("%s: %s\n", it->first.c_str(), it->second.c_str());
    }
}
 
bool parse_file_1(const char* file, map<string, string>& mapFields)
{
    char* contents = file_get_contents(file);
    if (contents) {
        bool ret = parse_fields(contents, mapFields);
        //printf("%s\n", contents);
        free(contents);
        return ret;
    }
    return false;
}
 
int parse_file_2(const char* file, string& strResult)
{
    int result = -1;
    char* contents = file_get_contents(file);
    if (contents) {
        if (strstr(contents, "<title>■ 書き込み確認 ■</title>") ||
            strstr(contents, "<title>投稿確認</title>"))
        {
            result = 1;
            strResult = "書き込み確認";
        } else if (strstr(contents, "<title>書きこみました。</title>")) {
            result = 0;
            strResult = "書き込みました。";
        } else {
            result = -1;
            strResult = contents;
        }
        free(contents);
    }
    return result;
}
 
CURLcode do_http_post(
    const char* url,
    map<string, string>& mapFields,
    const char* referer = NULL)
{
    CURLcode res;
    FILE *fp;
 
    CURL* curl = curl_easy_init();
 
    // set options
    curl_easy_setopt(curl, CURLOPT_URL, url);
    curl_easy_setopt(curl, CURLOPT_POST, 1);
    curl_easy_setopt(curl, CURLOPT_USERAGENT, g_user_agent);
    curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1);
    curl_easy_setopt(curl, CURLOPT_MAXREDIRS, 3);
    curl_easy_setopt(curl, CURLOPT_AUTOREFERER, 1);
    curl_easy_setopt(curl, CURLOPT_FAILONERROR, 1);
 
    // timeout (in seconds)
    curl_easy_setopt(curl, CURLOPT_TIMEOUT, g_timeout);
 
    // set referer
    if (referer)
        curl_easy_setopt(curl, CURLOPT_REFERER, referer);
 
    // create cookie file if not existed
    fp = fopen(g_cookie_file, "rb");
    if (fp == NULL) fp = fopen(g_cookie_file, "wb");
    if (fp != NULL) fclose(fp);
 
    // set cookie file
    curl_easy_setopt(curl, CURLOPT_COOKIEFILE, g_cookie_file);
    curl_easy_setopt(curl, CURLOPT_COOKIEJAR, g_cookie_file);
 
    // set fields
    string strFields;
    map_to_string(mapFields, strFields);
    curl_easy_setopt(curl, CURLOPT_POSTFIELDS, strFields.c_str());
 
    // open temporary file
    fp = fopen(g_tmpname, "wb");
    curl_easy_setopt(curl, CURLOPT_WRITEDATA, fp);
    curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, writefn);
 
    // do it
    res = curl_easy_perform(curl);
    fclose(fp);
 
    // get cookies
    //print_cookies(curl);
 
    // parse loaded file
    parse_file_1(g_tmpname, mapFields);
 
    curl_easy_cleanup(curl);
 
    return res;
}
 
bool write_2ch_thread(
    const char* server,
    const char* bbs,
    const char* thread,
    const char* from,
    const char* mail,
    const char* message)
{
    CURLcode res;
    string strUrl, strReferer, strResult;
    map<string, string> mapFields;
    int result;
 
    // first try
    //printf("first try\n");
    strUrl = "http://";
    strUrl += server;
    strUrl += "/test/read.cgi/";
    strUrl += bbs;
    strUrl += "/";
    strUrl += thread;
    strUrl += "/1";
    res = do_http_post(strUrl.c_str(), mapFields);
    if (res != CURLE_OK) {
        fprintf(stderr, "cURL failed: %s\n", curl_easy_strerror(res));
        return false;
    }
    //print_map(mapFields);
 
    // set fields
    mapFields.erase("FROM");
    mapFields.insert(make_pair("FROM", from));
 
    mapFields.erase("mail");
    mapFields.insert(make_pair("mail", mail));
 
    mapFields.erase("MESSAGE");
    mapFields.insert(make_pair("MESSAGE", message));
 
    // second try
    //printf("second try\n");
    strReferer = strUrl;
    strUrl = "http://";
    strUrl += server;
    strUrl += "/test/bbs.cgi?guid=ON";
    res = do_http_post(
        strUrl.c_str(), mapFields, strReferer.c_str());
    if (res != CURLE_OK) {
        fprintf(stderr, "cURL failed: %s\n", curl_easy_strerror(res));
        return false;
    }
    //print_map(mapFields);

    result = parse_file_2(g_tmpname, strResult);
    if (result == 0)
    {
        printf("%s\n", strResult.c_str());
        return true;
    }
    if (result != 1) {
        return false;
    }
 
    // third try
    //printf("third try\n");
    strReferer = strUrl;
    res = do_http_post(
        strUrl.c_str(), mapFields, strReferer.c_str());
    if (res != CURLE_OK) {
        fprintf(stderr, "cURL failed: %s\n", curl_easy_strerror(res));
        return false;
    }
    //print_map(mapFields);

    result = parse_file_2(g_tmpname, strResult);
    printf("%s\n", strResult.c_str());
    if (result == 0)
        return true;
 
    return false;
}
 
int main(void)
{
    curl_global_init(CURL_GLOBAL_ALL);
 
    // set temporary file name
    g_tmpname = _tempnam(NULL, "w2ch");
 
    // write 2ch thread
    write_2ch_thread(
        "toro.2ch.net",
        "tech",
        "1156332916",
        "書き込みテスト",
        "",
        "テスト書き込みです&#x2665;\n\n改行のテスト");
 
    // delete temporary file
    _unlink(g_tmpname);
 
    curl_global_cleanup();
    free(g_tmpname);
 
    return 0;
}

HTTP通信にcURLというライブラリを使った。

ソース: write2ch.zip


国内格安航空券サイトe航空券.com

戻る

©片山博文MZ
katayama.hirofumi.mz@gmail.com

inserted by FC2 system