Twitter / Faith and BraveCLXは実は前から知っていて何度か捨てコードに使わせて頂いていたのですが、SSL越しにproxyが使えなかったので、ネットワーク関連のコードには使ってませんでした。
CLX or Message-Pack or Pocoあたりでしょうか RT @mattn_jp: STL以上、Boost未満な使い心地のライブラリが欲しい。ネットワーク関連込みの。
http://twitter.com/cpp_akira/status/21234425525
まぁでも一応書いて判断すべきかなと思って、僕的な答えとして、さらーーーっと書いた。
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でも言えるか。