2010年1月7日木曜日

ロシア版ポトリスのハッシュ値等

自分がダウンロードしたゲームクライアントのサイズやハッシュ値を調べて署名してみました。検証用。

ロシア版ポトリス公式ダウンロードリンク
http://files.fortress2.ru/fotress2_v1.0.1_installer.exe


遅い場合はこちらなら早いかも。
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

Filename: fotress2_v1.0.1_installer.exe
Size: 41977670
MD5sum: 2b2ce63753ea5f54ca5d10a4a475afe9
SHA1: f40b35bc0fe8366474b90d7975153dc7703e890b
SHA256: 8db84baede244bd5329a24738fcc8dba90c0c4c1e3682d7ca4dac9096032cbf1
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.9 (GNU/Linux)

iEYEARECAAYFAktEsJsACgkQZaieldfhGSv2xwCeN+uVXDQOSzufWWVd9kEWyKkq
bzwAoIT3rflHNneFhIA0etTrJY0ucCYY
=FM0T
-----END PGP SIGNATURE-----

以下は以前に書いたポトリスに関する記事です。

ロシアでポトリス
ロシアでポトリス2
Wineでロシアでポトリス
ロシア版ポトリスのDLが遅い原因
 

p2pobの公開鍵

-----BEGIN PGP PUBLIC KEY BLOCK-----
Version: GnuPG v1.4.9 (GNU/Linux)

mQGiBEtErZwRBACiMsZajO2plYZsYBZquNS8sO50utWswc2XgKurDF59YMNC8Q+6
n4SCj9UUMLwDQ3+00KDu8vjFQFmItIgex4pgbvAHyY7j9FxxlMfcgPDA7uk1Opd1
SF0VgxQux/Xm9QiBJZ/8Ym8ANzq8xu9b/IQtD7zvorfXn7eZRmsqsYiWNwCg993e
hKIfUpaEx+wkLdbBMMlF9v8D/3kbyAxHE6CwFw/YQuHhFVSs+hAIurbdjadjxyqQ
5br26FdXCDsNrjmaGrtsrBMSV9U9vPJHdPsVkZGpBI3dHKLzswHECozyYNM8/tNC
72SgZCsENymSCMlA02Pb/77lrDfns+epuG7sQIoVNRMMzAOWHIUoX4s5AM9l3B/z
vA37A/9Xm6y/YfA2W5LGa3ZWOKL3yTbafvsFAx3pkiLqYLrXXfb8ra+Hh0yv1tn3
mjAmDQI9Jl5ww4lXqKhFioi+ilPSSR0+E/aStiX6XUKZV8aZ/IqAwkjaU17KsZNg
0hQHMjEXjdOXjFsJT1FpRMUO2BXej6L3W18b28JehrpmXu7NWLQ1cDJwb2IgKGh0
dHA6Ly9wMnBvYi5ibG9nc3BvdC5jb20vKSA8cDJwb2IwQGdtYWlsLmNvbT6IZgQT
EQIAJgUCS0StnAIbAwUJA8JnAAYLCQgHAwIEFQIIAwQWAgMBAh4BAheAAAoJEGWo
npXX4Rkr6SoAoOUo98fVHjHd4OTSBPrl3JtXq9JiAJ98x5FJJfMLld7PvwztYxXy
q9FCYLkCDQRLRK2cEAgAyHaBoFDK+t3k9aF5O5sNtwWcK28JO0yKtqYTCpu9VlOm
xf+WTQdp/v3a/pa7MU2ZQ3CYugh7do0J1Ix6NJb5wPDMc/iEgGkEP2moIKVPuFcg
Zxq6F0YYi5hji7Zc/MZJkINR2H+MR2zODSfc0FoHRzQB5h83nBsa3dPfu8gBeO3C
EV/LCRchBMb4w6SXtAP5rBf067HGjs7RxMW0DW/MISykKCGl5Rv1735HYfuTqoLU
O8vLpY/65dNDU6mA9dTrO+FIK3DCVjq7NFb3gsYO1/vOvg6wjefE6r2eCtwyLznd
DJ4mTkdqgFWPyGIeL+f1L7CRHhIR05ILIHKGJvLchwADBwf/VPhTHI/KrInIRKuw
vb/TIqwecAxeqMzt93MeNhl8jloiOoBHUW5F4ZRG7OMwiD3PpRIK22TObhSqUBBm
K/RE2mlIoi8F9mx8hYgIhplPQlB3/Ef6J63hXn5r19Dca6Q2xgVXW5zTO5n3Vk4n
xsh/vD4rxABds7inhDFoptmQsHH184vCQsy2CrmrFP4F8BEQasY1ZqBcOOWRL37z
CB4y4s7E498yN+FHAInK/vL+siBke4dljkHbnfkwp2JiQNOr3TkFrFIsb0YHEANl
aq1ZvC2wnf/0QAvFwwzgsJRnqFRFTc9aRda9vvP82Wr8pl76sgV35/diYF2Yg0CG
b1rWTohPBBgRAgAPBQJLRK2cAhsMBQkDwmcAAAoJEGWonpXX4RkrAOIAoJ22nYd2
xRqILLIBZebXg2s1F8YoAJsEEkW5dAADBS9BByb4xrQpUznk6g==
=jPfw
-----END PGP PUBLIC KEY BLOCK-----

2010年1月1日金曜日

fluxboxのレビュー

Twitterでつぶやいたりポトリスしたり…他愛ないことですがないと困るのがOS、Linuxを使っています。
ウインドウマネージャーをfluxboxにしてみました。そのレビューです。



使ってみるとあら便利…自分好みのいいWMでした。ありがとうfluxbox開発者。

こちらを参考にしてスタイルをつくってみました。

~/.fluxbox/styles/simplegray
! background
background:                          solid
background.color:                    gray40

! global
*.font:                              *-12:bold
bevelWidth:                          1
borderWidth:                         1
handleWidth:                         3

*.color:                             gray60
*.unfocus.color:                     gray30
*.textColor:                         white
*.unfocus.textColor:                 gray70
borderColor:                         black

! window
window.button.focus.color:           gray80
window.button.unfocus.color:         gray50
window.button.focus.picColor:        white
window.button.unfocus.picColor:      gray70
window.grip.focus.color:             gray80
window.grip.unfocus.color:           gray50

! toolbar
toolbar.borderWidth:                 0
toolbar.clock.justify: center

toolbar.color:                       black
toolbar.iconbar.unfocused.color:     gray30
toolbar.iconbar.unfocused.textColor: gray70
toolbar.*.color:                     gray30
toolbar.iconbar.*.color:             gray60
toolbar.button.color:                gray50
toolbar.button.pressed:              flat solid
toolbar.button.pressed.color:        gray80
toolbar.iconbar.empty.color:         gray30

! menu
menu.frame.font:                     *-10
menu.title.justify:                  center
menu.bullet.position:                right
menu.bullet:                         triangle

menu.title.color:                    gray30
menu.frame.color:                    gray80
menu.title.*.textColor:              white
menu.frame.*.textColor:              black
menu.hilite.color:                   white
menu.hilite.textColor:               black


スタイルの他にも細かく設定できる…

~/.fluxbox/init
...
session.screen0.toolbar.onTop:          True
session.screen0.toolbar.widthPercent:   100
session.screen0.toolbar.placement:      TopCenter

session.screen0.opaqueMove:             True

session.screen0.windowScrollAction:     Shade
session.screen0.windowScrollReverse:    True

session.screen0.rowPlacementDirection:  RightToLeft

session.screen0.strftimeFormat:         %m/%d (%a) %k:%M

session.screen0.workspaces:             2
session.screen0.workspaceNames:         a,b
...

~/.fluxbox/keys
...
Mod4 r :Reconfigure
Mod4 q :Exit
Mod4 l       :ExecCommand xscreensaver-command -activate
Mod4 Shift l :ExecCommand xscreensaver-command -lock
Mod4 comma  :ExecCommand amixer set SoftMaster 10%-
Mod4 period :ExecCommand amixer set SoftMaster 10%+
Control Shift k      :Close
Control Mod1 Shift k :KillWindow
Mod4 k :ExecCommand xkill

~/.fluxbox/apps
[app] (xconsole)
  [Hidden] {yes}
  [Deco] {tool}
  [Sticky] {yes}
[end]
[app] (xterm) (title=blender)
  [Layer] {6}
[end]

不満点

かなり細かくかつ簡単に設定でき至れり尽くせり…なのだけど二点不満が残りました。

  • メニューの挙動がもっさりしている

  • アイコンバーで最小化したウインドウと単にアンフォーカスなものとの区別がつかない

メニューについて、表示させるために右クリックして、その上で更にもう一度クリックしないと項目を選べない→動作がもっさり感じる。マウスボタンのプレスでメニューを表示→リリースで選択なら良いのだけど…早い話がよくあるGTK+アプリのメニューと同じ挙動にして欲しい!

アイコンバーについて、最小化したウインドウの名前を例えばイタリック等で表示できれば単にアンフォーカスなウインドウと区別がついて良いのだけど…もしくは、toolbar.iconbar.minimized.fontみたいなスタイルの設定リソースがあれば良いのだけど!とにかく一目で区別できるようにしたい。

解決方法をご存知の方いらっしゃれば、教えて頂けるとありがたいです。あらかたmanとドキュメントに目を通してググってみたけど未解決です。fluxboxのソースを調べつつ何とかできないか検討中…


参考リンク

fluxbox公式
http://fluxbox.org/


Fluxbox Style -- Fluxbox Information
http://www2.odn.ne.jp/add10/fluxbox/styles.html

スタイルについて参考にさせて頂きました。

fluxboxのスタイル(テーマ)を変更する -- Linux初心者の独り言
http://samidarehetima.blog9.fc2.com/blog-entry-38.html


fluxboxのスタイル(テーマ)を変更する その2 -- Linux初心者の独り言
http://samidarehetima.blog9.fc2.com/blog-entry-40.html

ワロタw 参考にさせて頂きました。


環境

OS: Linux
debian-lenny
fluxbox-1.0.0
 

2009年12月31日木曜日

(Code: c) gtrans2

Google Translate を利用して露英翻訳するCのコードです。以前書いたコードを改良。
#include <stdio.h>
#include <curl/curl.h>
#include <stdlib.h>
#include <string.h>

#define FMT_WARN     "Warning: %s\n"
#define FMT_WARN_US  "Warning: unknown state %s\n"
#define FMT_ERR      "Error: %s\n"
#define FMT_ERR_WITH "Error: %s (%d): %s\n"

#define OFFSET 24
static const char *url = "http://translate.google.com/translate_a/t";
static const char *data = "client=t&sl=ru&tl=en&text=";
static const char *useragent = "User-Agent: Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.0)";
static const char *result_null = "{\"src\":\"el\"}";


static char *
urie(const char *text)
{
  char *text_urie;
  char *p;

  text_urie = malloc(strlen(text) * 3 + 1);
  p = text_urie;
  while (*text) {
    snprintf(p, 4, "%%%02X", (unsigned char) *text);
    text++;
    p += 3;
  }
  *p = '\0';

  return text_urie;
}

static char *
unesc(const char *str)
{
  int len;
  char *str_unesc;
  char *p;

  len = strlen(str);
  str_unesc = malloc(len + 1);
  p = str_unesc;
  while (*str) {
    if (*str != '\\') {
      *p = *str;
    } else {
      str++;
      if (*str != 'u') {
*p = *str;
      } else {
str++;
if (*str == '0') {
  str++;
} else {
  fprintf(stderr, FMT_WARN_US, "!(*str == '0') (1)");
  return NULL;
}
if (*str == '0') {
  str++;
} else {
  fprintf(stderr, FMT_WARN_US, "!(*str == '0') (2)");
  return NULL;
}
if (*str == '2') {
  str++;
  if (*str == '6') {
    *p = '&';
  } else {
    fprintf(stderr, FMT_WARN_US, "!(*str == '6')");
    return NULL;
  }   
} else if (*str == '3') {
  str++;
  if (*str == 'c') {
    *p = '<';
  } else if (*str == 'e') {
    *p = '>';
  } else {
    fprintf(stderr, FMT_WARN_US, "!((*str == 'c') || (*str == 'e'))");
    return NULL;
  }      
} else {
  fprintf(stderr, FMT_WARN_US, "!((*str == '2') || (*str == '3'))");
  return NULL;
}
      }
    }
    str++;
    p++;
  }
  *p = '\0';

  return str_unesc;
}

static size_t
write_data(void *buffer, size_t size, size_t nmemb, void *userp)
{
  int len = size * nmemb;
  char result[len + 1];
  char *p, *p_e;
  int len_trans;
  char *trans;
  char *trans_unesc;

  if (len) {
    strncpy(result, buffer, len);
    result[len] = '\0';
    if (strcmp(result, result_null)) {
      if (len < OFFSET) {
fprintf(stderr, FMT_WARN_US, "(len < OFFSET)");
return -1;
      }
      p = result + OFFSET;
      p_e = p;
      while (*p_e != '"' && *p_e) {
if (*p_e == '\\')
  p_e++;
p_e++;
      }
      if (*p_e != '"') {
fprintf(stderr, FMT_WARN_US, "(*p_e != '\"')");
return -1;
      }
      len_trans = p_e - p;
      if (len_trans) {
trans = malloc(len_trans + 1);
strncpy(trans, p, len_trans);
trans[len_trans] = '\0';
if ((trans_unesc = unesc(trans)) != NULL) {
  printf("%s\n", trans_unesc);
} else {
  fprintf(stderr, FMT_WARN, "unesc failed");
  printf("%s\n", trans);
}
free(trans_unesc);
free(trans);
      }
    }
  }

  return len;
}


int
main(int argc, char **argv)
{
  CURL *curl;
  char *text_urie;
  int size_data_all, size_url_all;
  char *data_all, *url_all;
  CURLcode res;
  struct curl_slist *headers = NULL;

  if (argc < 2) {
    fprintf(stderr, FMT_ERR, "need an arg (Russian phrase)");
    return 1;
  } else if (argc > 2) {
    fprintf(stderr, FMT_ERR, "too many args. need just an arg");
    return 1;
  }    

  curl = curl_easy_init();
  if(!curl) {
    fprintf(stderr, FMT_ERR, "curl_easy_init() failed");
    return 1;
  }

  text_urie = urie(argv[1]);

  size_data_all = strlen(data) + strlen(text_urie) + 1;
  data_all = malloc(size_data_all);
  strcpy(data_all, data);
  strcat(data_all, text_urie);
  free(text_urie);

  size_url_all = strlen(url) + 1 + size_data_all;
  url_all = malloc(size_url_all);
  snprintf(url_all, size_url_all, "%s?%s", url, data_all);
  free(data_all);

  curl_easy_setopt(curl, CURLOPT_TIMEOUT, 10);
  curl_easy_setopt(curl, CURLOPT_HTTPGET, 1);
  curl_easy_setopt(curl, CURLOPT_URL, url_all);
  headers = curl_slist_append(headers, useragent);
  curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
  curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_data); 

  res = curl_easy_perform(curl);

  free(url_all);
  curl_slist_free_all(headers);
  curl_easy_cleanup(curl);

  if(res) {
    fprintf(stderr, FMT_ERR_WITH, "curl_easy_perform() failed",
    res, curl_easy_strerror(res));
    return 1;
  }

  return 0;
}

  • urie()で翻訳したいフレーズをURIエンコード

  • libcurlで翻訳したいフレーズをGETで送信

  • エスケープ文字(\)を考慮して24バイトのオフセットで結果をパース

  • unesc()でエスケープ文字と特定の記号(\, &, <, >)をアンエスケープ処理

以前に書いたコードはエスケープや数値文字参照を考慮してませんでした。

「я сказал "да"」のようにダブルクオーテーションマーク(")が含まれるフレーズを翻訳すると下の結果が返ってくる。ダブルクオーテーションマークのエスケープに"\"が使われている模様。
{"sentences":[{"trans":"I said \"yes\"","orig":"я сказал \"да\"","translit":""}],"src":"ky"}
特定の記号を含むフレーズ、例えば「& < >」を翻訳すると下の結果が返ってくる。数値文字参照になっている模様。
{"sentences":[{"trans":"\u0026 \u003c\u003e","orig":"\u0026 \u003c \u003e","translit":""}],"src":"en"}
このような翻訳結果をエスケープ文字を考慮してパースした後、unesc()でアンエスケープ処理して対応しました。


コンパイル

実際にはMakefileを書いてmakeで済ませてます。コンパイル前にlibcurlのdevパッケージをインストールしてます。
$ gcc -Wall -O2 `curl-config --cflags`  `curl-config --libs`  gtrans.c   -o gtrans

テスト翻訳
$ ./gtrans 'я сказал "да"'
I said "yes"

$ ./gtrans 'вы & я'
You & I

$ ./gtrans '<<<<<'
<<<<<

$ ./gtrans '>>>>>'
>>>>>
まずまず動作。ダブルクオーテーションや特定の記号を含んだフレーズも問題なく翻訳できるようになりました。


環境

OS: Linux
debian-lenny
libcurl-7.18.2
 

2009年12月20日日曜日

(Code: c) gtrans

Google Translate を利用して露英翻訳するCのコードです。以前書いたシェルスクリプトをCでリライト。
#include <stdio.h>
#include <curl/curl.h>
#include <stdlib.h>
#include <string.h>

#define OFFSET 24
static const char *url = "http://translate.google.com/translate_a/t";
static const char *data = "client=t&sl=ru&tl=en&text=";
static const char *useragent = "User-Agent: Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.0)";
static const char *result_null = "{\"src\":\"el\"}";


static char *
urie(const char *text)
{
  char *text_urie;
  char *p;

  text_urie = malloc(strlen(text) * 3 + 1);
  p = text_urie;
  while (*text) {
    snprintf(p, 4, "%%%02X", (unsigned char) *text);
    text++;
    p += 3;
  }
  *p = '\0';

  return text_urie;
}

static size_t
write_data(void *buffer, size_t size, size_t nmemb, void *userp)
{
  int len = size * nmemb;
  char result[len + 1];
  char *p, *p_e;
  int len_trans;
  char *trans;

  if (len) {
    strncpy(result, buffer, len);
    result[len] = '\0';
    if (strcmp(result, result_null)) {
      if (len < OFFSET) {
fprintf(stderr, "Warning: unknown state (len < OFFSET)\n");
return -1;
      }
      p = result + OFFSET;
      p_e = p;
      while (*p_e != '"' && *p_e)
p_e++;
      if (*p_e != '"') {
fprintf(stderr, "Warning: unknown state (*p_e != '\"')\n");
return -1;
      }
      len_trans = p_e - p;
      if (len_trans) {
trans = malloc(len_trans + 1);
strncpy(trans, p, len_trans);
trans[len_trans] = '\0';
printf("%s\n", trans);
free(trans);
      }
    }
  }

  return len;
}


int
main(int argc, char **argv)
{
  CURL *curl;
  char *text_urie;
  int size_data_all, size_url_all;
  char *data_all, *url_all;
  CURLcode res;
  struct curl_slist *headers = NULL;

  if (argc < 2) {
    fprintf(stderr, "Error: need an arg (Russian phrase)\n");
    return 1;
  } else if (argc > 2) {
    fprintf(stderr, "Error: too many args. need just an arg (Russian phrase)\n");
    return 1;
  }    

  curl = curl_easy_init();
  if(!curl) {
    fprintf(stderr, "Error: curl_easy_init() failed\n");
    return 1;
  }

  text_urie = urie(argv[1]);

  size_data_all = strlen(data) + strlen(text_urie) + 1;
  data_all = malloc(size_data_all);
  strcpy(data_all, data);
  strcat(data_all, text_urie);
  free(text_urie);

  size_url_all = strlen(url) + 1 + size_data_all;
  url_all = malloc(size_url_all);
  snprintf(url_all, size_url_all, "%s?%s", url, data_all);
  free(data_all);

  curl_easy_setopt(curl, CURLOPT_TIMEOUT, 10);
  curl_easy_setopt(curl, CURLOPT_HTTPGET, 1);
  curl_easy_setopt(curl, CURLOPT_URL, url_all);
  headers = curl_slist_append(headers, useragent);
  curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
  curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_data); 

  res = curl_easy_perform(curl);

  free(url_all);
  curl_slist_free_all(headers);
  curl_easy_cleanup(curl);

  if(res) {
    fprintf(stderr, "Error: curl_easy_perform() failed (%d): %s\n",
    res, curl_easy_strerror(res));
    return 1;
  }

  return 0;
}

  • urie()で翻訳したいフレーズをURIエンコード

  • libcurlで翻訳したいフレーズをGETで送信

  • 24バイトのオフセットで結果をパース

UserAgentがcurlだと拒絶される、空だと翻訳結果がKOI8-Rで返ってきてUTF-8の環境でパースしづらくなるのでIEに偽装しています。UAがIEやFirefoxだとUTF-8で結果が返ってくるみたい。


コンパイル

実際にはMakefileを書いてmakeで済ませてます。コンパイル前にlibcurlのdevパッケージをインストールしてます。
$ gcc -Wall -O2 `curl-config --cflags`  `curl-config --libs`  gtrans.c   -o gtrans


テスト翻訳
$ ./gtrans 'здравств'
hello

$ ./gtrans 'я из Японии'
I'm from Japan

$ ./gtrans 'только хорошие умирают молодыми'
only the good die young

$ ./gtrans 'through ascii phrase'
through ascii phrase

$ ./gtrans ' '
(出力なし)

$ ./gtrans ''
(出力なし)

$ ./gtrans '誤って日本語を入力'
誤っ て 日本語 を 入力

$ ./gtrans `echo "えすじす" | iconv -t SJIS-WIN`
(文字化け)
まずまずシェルスクリプト版と同じ動作。関数化してチャットロガーに仕込む下準備が整った!Cでlibcurlをはじめて使ったのだけどすごく便利でした。


環境

OS: Linux
debian-lenny
libcurl-7.18.2
 

Makefile

小さいコードを書くときによく使うMakefileです。

カレントディレクトリーにある*.cファイルを全部コンパイル。"make print"でファイルの行数を出力。CFLAGSとLDFLAGSは用途により適当に修正します。下のコードはlibcurlを使うコードをmakeするときのものです。
PROGS = $(basename $(wildcard *.c))

CC = gcc
CFLAGS = -Wall -O2 `curl-config --cflags`
LDFLAGS = `curl-config --libs`

all: $(PROGS)

print:
wc -l *.c

clean:
$(RM) $(PROGS)


環境

OS: Linux
debian-lenny
make-3.81
 

2009年12月3日木曜日

(Code: sh) gtrans2

Google Translate を利用して露英翻訳するシェルスクリプトです。以前書いたコードを改良。
#!/bin/sh

PROG=`basename $0`

## check cmd
LIST="curl urie"
for CMD in $LIST ;do
TEST_CMD=`which $CMD`
if [ -z "$TEST_CMD" ] ; then
echo "$PROG: Error: we need command \"$CMD\"" >&2
exit 1
fi
done

## check arg
if [ -z "$1" ] ; then
echo "$PROG: Error: need an arg (Russian phrase)" >&2
exit 1
elif [ $# -gt 1 ] ; then
echo "$PROG: Error: too many args. need just an arg (Russian phrase)" >&2
exit 1
fi
TEXT="$1"


## body
UA='Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.0)'
URL=http://translate.google.com/translate_a/t
TEXT_URIE=`echo "$TEXT" | urie`

RESULT=`curl -Ss -m 10 -G -A "$UA" "$URL" -d client=t -d text="$TEXT_URIE" -d sl=ru -d tl=en`
TEST_CURL=$?
#echo "$RESULT" ##debug
if [ $TEST_CURL -ne 0 ] ; then
echo "$PROG: Error: curl failed" >&2
exit 1
fi

TEST_RESULT=`echo "$RESULT" | grep '"trans"'`
if [ -n "$TEST_RESULT" ] ; then ## for empty translation result {"src":"en"}
echo "$RESULT" | sed 's/.*"trans":"\([^"]*\)".*/\1/'
fi

  • urieで翻訳したいフレーズをURIエンコード

  • curlで翻訳したいフレーズをGETで送信

  • sedで結果をパース

UserAgentがcurlだと拒絶される、空だと翻訳結果がKOI8-Rで返ってきてUTF-8の環境でパースしづらくなるのでIEに偽装しています。UAがIEやFirefoxだとUTF-8で結果が返ってくるみたい。以前書いたコードと異なり"http://translate.google.com/"でなく"http://translate.google.com/translate_a/t"に翻訳したいフレーズを送信しています。
{"sentences":[{"trans":"short","orig":"короткий","translit":""}],"dict":[{"pos":"","terms":["s"]},{"pos":"adjective","terms":["short","brief","little","small","short","skimpy"]}],"src":"ru"}
こんな感じの翻訳結果をGoogleから受信できます。"http://translate.google.com/"のものより短い!パースし易い!!URIエンコーディングにCで書いたコマンド(urie)を使っています。GETで送信(curl -G)するとPOSTするより送信データーが69バイト短くて済むのでそうしてます。


テスト翻訳
$ ./gtrans 'здравств'
hello

$ ./gtrans 'я из Японии'
I'm from Japan

$ ./gtrans 'только хорошие умирают молодыми'
only the good die young

$ ./gtrans 'through ascii phrase'
through ascii phrase

$ ./gtrans ' '
(出力なし)

$ ./gtrans '誤って日本語を入力'
誤っ て 日本語 を 入力

$ ./gtrans `echo "えすじす" | iconv -t SJIS-WIN`
????????
まずまず動作。LANG=ja_JP.UTF-8のシェルでテスト翻訳しました。
文字コードが混在した環境で自動翻訳しようとすると翻訳フレーズごとに文字コードの自動判定も必要になりそう。ロシア版ポトリスではロシア語にCP1251、日本語にSJIS-WINが使われてるみたい。


環境

OS: Linux
debian-lenny