2009/01/07


im.kayac.comに送信するperlスクリプト。
コードだけ。
#!/usr/bin/perl
use strict;
use warnings;

use Encode;
use LWP::UserAgent;
use HTTP::Request::Common qw(POST);
use Config::Pit;
use Digest::SHA1 qw(sha1_hex);
use JSON;

if ($^O eq 'MSWin32') {
    eval {
        require Win32::API;
        Win32::API->Import('kernel32', 'UINT GetACP()');
        Encode::from_to($ARGV[0], 'cp'.GetACP(), 'utf-8');
    };
}

my $config = pit_get("im.kayac.com", require => {
        "username" => "your username on im.kayac.com",
        "password" => "your password(or secretkey) on im.kayac.com",
        "authtype" => "auth type on im.kayac.com: none/password/secretkey",
    });

my %data = ( message => shift );
die "should be specify message" unless $data{message};
$data{password} = $config->{password} if $config->{authtype} eq "password";
$data{sig} = sha1_hex($data{message} . $config->{password}) if $config->{authtype} eq "secretkey";

my $ua = LWP::UserAgent->new;
my $res = from_json($ua->post(
    "http://im.kayac.com/api/post/$config->{username}", \%data,
    "Content-Type" => "application/x-www-form-urlencoded"
)->decoded_content);

print $res->{result}.$res->{error};
Posted at by



2009/01/06


WindowsでGitを使う場合、msysGitというMSYS(Minimal SYStem)ポーティングされたGitを使うのですが、これにはssh-askpassが付いてきません。以前書いた「Big Sky :: Windowsでもssh-agentとssh-addを使ってパスフレーズ入力を省略する。」でご紹介した方法は、開いたコマンドプロンプト内でしか有効になりません。これは新しく起動したコマンドプロンプトに、ssh-agentから引き渡されるSSH_AGENT_PID/SSH_AUTH_SOCKといった環境変数が引き継がれていないのが原因です。これを解決する方法のひとつとして、win-ssh-askpassという物があります。
win-ssh-askpass 1.05 (GANAware)

GUI ssh-agent for cygwin.

http://www.ganaware.jp/archives/2006/04/winsshaskpass_1.html
win-ssh-askpass バージョンアップについてあれこれ (GANAware)

ずいぶん久しぶりに win-ssh-askpass をバージョンアップしました。

http://www.ganaware.jp/archives/2006/04/winsshaskpass_2.html
このwin-ssh-askpassは、ssh-agent起動時に得た環境変数情報をWindowsのユーザ環境変数に登録してくれ、次回起動するコマンドプロンプトでもパスフレーズを聞かれなくするという物です。UNIXだとx11-ssh-askpassとか、ssh-askpass-gnomeというGUIバージョンも存在しますが、これのWindows版という所ですね。
但し、win-ssh-agentはcygwinを使っており、cygwin配下でunix domain socketを使った通信を行っています。unix domain socketを使わず実装されているmsysGitでは動かないのです。他に、puttyのpagent/plinkを使った方法もありますが私が使いたい条件
  • OpenSSH for windows
  • msysGit付属のbashではなく、コマンドプロンプト
  • cygwinは使いたくない
には適応出来なかったりします。
という事で、win-ssh-askpass-1.05のcygwin依存を無くすパッチを書いてみました。
気を付ける所は
  • setenv/putenvの置き換え
  • fork/execからsystemへ
だけです。
以下パッチ diff -u win-ssh-askpass-1.05.orig/agent.cpp win-ssh-askpass-1.05/agent.cpp
--- win-ssh-askpass-1.05.orig/agent.cpp 2006-04-02 10:42:24.000000000 +0900
+++ win-ssh-askpass-1.05/agent.cpp  2009-01-06 17:21:35.953125000 +0900
@@ -2,8 +2,10 @@
 #include <stdlib.h>
 #include <string.h>
 #include <string>
+#ifdef __CYGWIN__
 #include <sys/cygwin.h>
 #include <sys/wait.h>
+#endif
 #include <unistd.h>
 #include <list>
 #include <stdarg.h>
@@ -56,6 +58,7 @@
 // run ssh-add
 int run_ssh_add(const char *i_identityFile)
 {
+#ifdef __CYGWIN__
   pid_t childPID = fork();
   setenv("SSH_ASKPASS", getAskpassPath().c_str(), 1);
   verbose("export SSH_ASKPASS=%s\n", getAskpassPath().c_str());
@@ -95,6 +98,25 @@
       else
    return -1;
   }
+#else
+  std::string str;
+
+  str = "SSH_ASKPASS=";
+  str += getAskpassPath().c_str();
+  putenv(str.c_str());
+  verbose("export SSH_ASKPASS=%s\n", getAskpassPath().c_str());
+
+  str = "DISPLAY=localhost:0";
+  putenv(str.c_str());
+  verbose("exec ssh-add %s\n", i_identityFile ? i_identityFile : "");
+  if (i_identityFile && !i_identityFile[0])
+    i_identityFile = NULL;
+  str = "ssh-add ";
+  if (i_identityFile) str += i_identityFile;
+  str += " < NUL 2> NUL";
+  verbose(str.c_str());
+  system(str.c_str());
+#endif
 }
 
 // http://sourceware.org/ml/cygwin/2006-02/msg00289.html
@@ -118,6 +140,7 @@
       /* Convert POSIX to Win32 where necessary */
       if (!strcmp(var, "PATH") ||
      !strcmp(var, "LD_LIBRARY_PATH")) {
+#ifdef __CYGWIN__
    winpathlist = (char *)
      malloc(cygwin_posix_to_win32_path_list_buf_size(val) + 1);
    if (winpathlist) {
@@ -125,12 +148,19 @@
      SetEnvironmentVariable(var, winpathlist);
      free(winpathlist);
    }
+#else
+   SetEnvironmentVariable(var, val);
+#endif
       } else if (!strcmp(var, "HOME") ||
         !strcmp(var, "TMPDIR") ||
         !strcmp(var, "TMP") ||
         !strcmp(var, "TEMP")) {
+#ifdef __CYGWIN__
    cygwin_conv_to_win32_path(val, winpath);
    SetEnvironmentVariable(var, winpath);
+#else
+   SetEnvironmentVariable(val, winpath);
+#endif
       } else {
    SetEnvironmentVariable(var, val);
       }
@@ -144,7 +174,11 @@
 void run_program(char **i_argv)
 {
   char win32_pathname[1024];
+#ifdef __CYGWIN__
   cygwin_conv_to_win32_path(i_argv[0], win32_pathname);
+#else
+  strcpy(win32_pathname, i_argv[0]);
+#endif
   setup_win_environ();
  
   if (i_argv[1])
@@ -386,7 +420,7 @@
           NULL, NULL, g_hInst, this);
    
     // show tasktray icon
-    std::memset(&m_ni, 0, sizeof(m_ni));
+    memset(&m_ni, 0, sizeof(m_ni));
     m_ni.cbSize = sizeof(m_ni);
     m_ni.uID    = ID_TaskTrayIcon;
     m_ni.hWnd   = m_hwndTaskTray;
@@ -513,7 +547,13 @@
       verbose("DISPLAY=%s\n", getenv("DISPLAY"));
    
     std::string askpassPath(getAskpassPath());
+#ifdef __CYGWIN__
     setenv("SSH_ASKPASS", askpassPath.c_str(), 1);
+#else
+    std::string str("SSH_ASKPASS=");
+    str += askpassPath;
+    putenv(str.c_str());
+#endif
     writeRegistry(HKEY_CURRENT_USER, "Environment", "SSH_AGENT_PID",
          getenv("SSH_AGENT_PID"));
     verbose("export SSH_AGENT_PID=%s\n", getenv("SSH_AGENT_PID"));
diff -u win-ssh-askpass-1.05.orig/misc.cpp win-ssh-askpass-1.05/misc.cpp
--- win-ssh-askpass-1.05.orig/misc.cpp  2002-09-23 03:32:39.000000000 +0900
+++ win-ssh-askpass-1.05/misc.cpp   2009-01-06 17:18:43.656250000 +0900
@@ -1,5 +1,7 @@
 #include "misc.h"
+#ifdef __CYGWIN__
 #include <sys/cygwin.h>
+#endif
 
 // instance
 HINSTANCE g_hInst = NULL;
@@ -74,9 +76,16 @@
 // get the path of win-ssh-askpass.exe
 std::string getSelfPath()
 {
+#ifdef __CYGWIN__
   char win32_pathname[1024];
   GetModuleFileName(NULL, win32_pathname, NUMBER_OF(win32_pathname));
   char posix_pathname[1024];
   cygwin_conv_to_posix_path(win32_pathname, posix_pathname);
   return posix_pathname;
+#else
+  char win32_pathname[1024], *ptr = win32_pathname;
+  GetModuleFileName(NULL, win32_pathname, NUMBER_OF(win32_pathname));
+  while (*ptr++) if (*ptr == '\\') *ptr = '/';
+  return win32_pathname;
+#endif
 }
これを適応すると、mingw32だけでビルド出来る様になります(mingw32-make)。なお、cygwinでビルドすればこれまで通りのモジュールが出来上がります。
ビルド出来たら、win-ssh-agentを起動します。すると
win-ssh-askpass
の様に入力ダイアログが表示されます。ここにパスフレーズを入力すれば、後は次回から起動するコマンドプロンプトで
win-ssh-askpass-console
と環境変数が引き継がれる事になります。
Big Sky :: Windowsでもssh-agentとssh-addを使ってパスフレーズ入力を省略する。」で書いた、setxがあればwin-ssh-agentを使わなくても美味く行くのですが、コマンドプロンプトが出ないので少しカッコよくなりました。
これをWindowsのスタートアップに入れておけば初回にパスフレーズを入力した後は、sshパスフレーズを聞かれる事無くsshが行える様になります。

win-ssh-agent++

よろしければどうぞ。
というか私くらいしか、必要ないか...
Posted at by



2008/12/22


scaffoldで客寄せするのも悪くない...私はそうは思うんです。
scaffoldがあるから何秒でwebアプリケーションができました風の自慢はやめた方がいいと思う - val it : α → α = fun

この観点からいうと、scaffoldというのはつまりHQ9+である。

http://www.jmuk.org/diary/2008/12/20/1
確かに釣りな記事を書いた事には間違いないです。が、私が思うscaffoldの認識と少し違うかなと思ったので...

scaffoldはそもそも足場という意味の単語で、アプリケーションフレームワーク上では何かのベースとなる部品を提供する機能を一般的に指しているのだと思う。確かに「××分で出来る」ってのはbuzzword的に広まっており、「rails 分で出来る」なんてググると、わんさか出てきたりします。それだけインパクトがあり、需要があってこそなんだと思います。
mukaiさんの仰っておられるのは、「scaffoldで出来上がったデモがその後のユーザにとって本当に意味のある物になるのか...無駄じゃないのか」という事だと私は読み取ったのですが、巷のIDEの様に幾らか雛を作ってくれる物は初級者にとって敷居を下げてくれ、マニュアルやフレームワーク自身のコード解析からフレームワークの使い方を学ぶ手間と比べると、改造ベースからコーディングを始められる良さってのはあると信じています。
これは使い手側の意識と、先人が思う考察の違いの問題であって、例えばブログを書くのにWYSIWYGなツールを使う事は、HTMLを学べないから良くないとか、HTMLを知らなくてもHTMLを書けるWYSIWYGエディタの自慢をする事は良くないとか、そんな事はユーザにとってどうでもいい事の様な気がするんです。HTMLなんて知りたくないけどWYSIWYGは便利だよって人もいるだろうし、Google App Engineのマスタになりたいなんて思わないけどGoogle App Engineを使ってみたいって人はいると思う。
ユーザが開発者で、Google App Engineを学びたい人であって、Google App Engine Oilを知らなくて、何から手っ取り早くGoogle App Engine Oilで何が出来るかを知るには、多少特化したエッセンスを用いて表すのもアリなんじゃないかと。

例えば「10分で出来る、かんたん餃子レシピ」なんて物があって「その後本当に餃子の皮から作りたい人が、果たしてこのレシピを有用と見るだろうか」なんて考えるのはナンセンスな気がするんです。
調べる人は自分で調べるだろうし、「かんたん餃子レシピ」の役目は「餃子を自分で作ってみたいけど、皮から作るなんて難しい」と思ってる人への道しるべになれたのならそれで十分だと思う。そして本当に10分で美味しい餃子が出来たのなら、私はそのレシピを評価してあげて良いと思う。
Google App Engine Oilは、素のGoogle App Engineでは痒い所に手が届かない部分に色々と機能を追加していってくれていますし、良い意味でも悪い意味でもキャッチーです。
WSGIってどう書けば良いの?モデルを作ってそのモデルを編集する画面ってどう作ればいいの?って人は、まずサンプル触るのが良いと思うんですよね。
「そのフレームワークを学ぶ」が目的じゃなくて、「○○みたいなの作るにはどうしたら良いの?」が目的な人多いと思うんですよね。

これはあくまで私の持論であって、「自慢がいけない」のか「scaffoldがいけない」のかの違いも本筋でもない気がしています。

私は餃子を作りたいと思った時に「餃子のプロが見せる超絶技巧100」よりは「10分で出来る、かんたん餃子レシピ」を見たい人もいると思うんですよね。

ちなみに、お店で出すメニューに「10分で出来る、かんたん餃子レシピ」で作った餃子を出して自慢する...なんて事はもちろん、私も(その店にとって)良くない事だと思っていますよ。:-)
Posted at by