2010/09/11

Recent entries from same category

  1. C++ 用 SQLite3 ORM 「sqlite_orm」が便利。
  2. zsh で PATH に相対パスを含んだ場合にコマンドが補完できないのは意図的かどうか。
  3. mruby-tflite を Coral Edge TPU 対応した。
  4. Go 言語の Language Server「gopls」が completeUnimported に対応した。
  5. sudo の特権昇格バグはなぜ起こったのか

以前、twitter上で「STL以上、Boost未満な使い心地のライブラリが欲しい。ネットワーク関連込みの。」とつぶやいた所、id:faith_and_braveさんから返事貰った。
Faith and Brave Twitter / Faith and Brave

CLX or Message-Pack or Pocoあたりでしょうか RT @mattn_jp: STL以上、Boost未満な使い心地のライブラリが欲しい。ネットワーク関連込みの。

http://twitter.com/cpp_akira/status/21234425525
CLXは実は前から知っていて何度か捨てコードに使わせて頂いていたのですが、SSL越しにproxyが使えなかったので、ネットワーク関連のコードには使ってませんでした。
まぁでも一応書いて判断すべきかなと思って、僕的な答えとして、さらーーーっと書いた。
CONSUMER_KEY と CONSUMER_SECRET を書き換えて実行して下さい。xAuth認証を使ってtwitterにステータスをポストします。

#include <iostream>
#include <sstream>
#include <clx/base64.h>
#include <clx/hexdump.h>
#include <clx/date_time.h>
#include <clx/format.h>
#include <clx/hmac.h>
#include <clx/https.h>
#include <clx/random.h>
#include <clx/salgorithm.h>
#include <clx/sha1.h>
#include <clx/uri.h>

std::string url_encode(const std::string& url) {
    std::ostringstream rets;
    for(size_t n = 0; n < url.size(); n++) {
        unsigned char c = (unsigned char)url[n];
        if (isalnum(c) || c == '_' || c == '.' || c == '-')
            rets << c;
        else {
            char buf[8];
            sprintf(buf, "%02X", (int)c);
            rets << '%' << buf[0] << buf[1];
        }
    }
    return rets.str();
}


int main(int argc, char* argv[]) {

    if (argc != 4) {
        std::cerr << "usage: " << argv[0]
            << " [username] [password] [message]" << std::endl;
        return -1;
    }

    clx::date_time now;
    clx::random<unsigned int> randgen;
    randgen.engine().seed(time(0));

    std::string consumer_key = "CONSUMER_KEY";
    std::string consumer_secret = "CONSUMER_SECRET";
    std::string username = argv[1];
    std::string password = argv[2];
    std::string message = argv[3];

    std::stringstream ss;
    std::string times = clx::str(clx::format("%s") % now.c_time());
    std::string nonce = clx::hexdump(times);

    ss << "oauth_consumer_key=" << consumer_key
       << "&oauth_nonce=" << nonce
       << "&oauth_signature_method=" << "HMAC-SHA1"
       << "&oauth_timestamp=" << times
       << "&oauth_version=" << "1.0"
       << "&x_auth_mode=" << "client_auth"
       << "&x_auth_password=" << password
       << "&x_auth_username=" << username;

    std::string key = consumer_secret + "&";
    std::string val = "POST&";

    val += url_encode("https://api.twitter.com/oauth/access_token");
    val += "&";
    val += url_encode(ss.str());
    char* hmac = (char*)clx::hmac<clx::sha1>(
            key.c_str(), key.size(), val.c_str(), val.size()).code();
    std::string hm = clx::base64::encode(hmac, 20);

    ss << "&oauth_signature=" << url_encode(hm);

    clx::https session(clx::uri::encode("api.twitter.com"), 443);
    session.post(clx::uri::encode("/oauth/access_token"), ss.str());

    std::vector<std::string> item;
    std::map<std::string, std::string> params;
    clx::split_if(session.body(), item, clx::is_any_of(LITERAL("&")));
    for (unsigned int i = 0; i < item.size(); i++) {
        std::string tok = item.at(i);
        size_t pos = tok.find_first_of("=");
        params[tok.substr(0, pos)] = clx::uri::decode(tok.substr(pos+1));
    }


    ss.str("");
    ss.clear(std::stringstream::goodbit);

    ss << "oauth_consumer_key=" << consumer_key
       << "&oauth_nonce=" << nonce
       << "&oauth_signature_method=" << "HMAC-SHA1"
       << "&oauth_timestamp=" << times
       << "&oauth_token=" << params["oauth_token"]
       << "&oauth_version=" << "1.0"
       << "&status=" << url_encode(message);

    key = consumer_secret + "&" + params["oauth_token_secret"];
    val = "POST&";

    val += url_encode("https://api.twitter.com/1/statuses/update.json");
    val += "&";
    val += url_encode(ss.str());
    hmac = (char*)clx::hmac<clx::sha1>(
            key.c_str(), key.size(), val.c_str(), val.size()).code();
    hm= clx::base64::encode(hmac, 20);

    ss << "&oauth_signature=" << url_encode(hm);

    session.post(clx::uri::encode("/1/statuses/update.json"), ss.str());
    std::cout << session.body() << std::endl;

    return 0;
}

/* vim:set et sw=4: */
URLまわりと、POSTパラメータ構築に便利なのがあっても良いかなと思った。あーそれboost::asioでも言えるか。
Posted at by | Edit


blog comments powered by Disqus