CentOS6.2でsambaをインストールしてファイル共有サーバを構築する。
1.sambaをインストール
yum install samba.x64_86
2.sambaがインストールされたことを確認する。
yum list installed samba
->samba.x64_86 3.6.9-151.el6_4.1
4./etc/samba/smb.confに以下の設定を追加
[global]
dos charset = CP932
display charset = UTF-8
workgroup = VMLAN
netbios name = VMSAMBA
[public] <-フォルダ名がpublicとして公開される。
path = /var/samba/shared <-後で実体のフォルダを作る
writable = Yes
write list = smbguest <-後でアカウントを作る。
5.sharedフォルダの作成
mkdir /var/samba
mkdir /var/samba/shared
6.sharedフォルダを読み書きOKにする。
chmod 777 /var/samba/shared
7.アクセス用アカウントを作成する
/usr/sbin/useradd -m smbguest
8.アクセス用アカウントにパスワードを設定する
pdbedit -a smbguest
9.サービスを起動する
rc.d/init.d/smb start
rc.d/init.d/nmb start
できればOS起動時に自動自動するようにしたほうがよい。
10.FWでSMB関連ポートを開く
vi /etc/sysconfig/iptables で以下の設定を追加する。
-A INPUT -p tcp --dport 139 -j ACCEPT
-A INPUT -p udp --dport 137 -j ACCEPT
-A INPUT -p udp --dport 138 -j ACCEPT
-A INPUT -p tcp --dport 445 -j ACCEPT
参考:http://futurismo.biz/archives/1390
11.しかしpublicフォルダにアクセスできない。
selinuxによるセキュリティがかかっている。
semanageコマンドでアクセスできるようにする。
semanageコマンドが無い場合があるのでその場合は追加インストールする。
/usr/bin/yum provides /usr/sbin/semanage
ここは結構はまるところ。
12.以下のコマンドを実行
semanage fcontext -a -t samba_share_t "/var/samba/shared"
restorecon -RF "/var/samba/shared"
13.Windowsマシンからアクセスする。
¥¥サーバ名(またはIPアドレス)¥shared
14.ログイン要求されるのでsmbguestで認証する。
15.アクセスでき晴れて書き込みできる状態に。
2013年10月30日水曜日
2013年10月10日木曜日
GoogleSpreadSheetでToDoタスクを作り、期限が近づいたらメールで通知する。
GoogleSpreadSheetは非常に便利だ。
Excelと同じように表計算やマクロ機能(Google Apps Script)を持っているが
何と言っても一番はスケジューラ機能だ。
スプレッドシートの内容を、指定した時間にメールで通知するなんてことも可能。
これはExcelだけではなかなかできないと思う。
という訳で自分の仕事を円滑に進められるようにするためにということで、
GoogleSpreadSheetを多様しているのだが、中でもToDoリストとしての活用は
いろいろな方でも使えるものだと思うのでサンプルコードを書いてみた。
コードはGitHubにアップしているのでそれを参考にしていただければ思う。
https://github.com/maar4569/notifyToDoWithGAS
そのサンプルを元にToDoアプリを作ってみようと思う。
このToDoアプリができること。
・利用者はスプレッドシートにToDoを書く。
・ToDoの締め切り日が近づいてくるとメールで通知してくれる。
N日前ですよとか、締め切り当日ですよとか、過ぎてますよとか。
作成手順
1.GitHubからコードをダウンロードしておく。
2.まずはGoogleドライブ上に新規のスプレッドシート「ToDoList」を作成する。
2-1.シート名を「ToDo」に変更する。
2-2.ToDoListに1行目のカラムに「task」「deadline」「notes」「deleted」と記述する。
task やるべきことを書いておく。
deadline 期日を書く。(yyyy/mm/dd形式で)
notes 補足事項があれば書いておく。
deleted メールで通知する必要が無くなった場合「1」と書いておくと通知しなくなる。
つまりもう済んだタスクは1と書いておく。書かないとずっとメールで通知して
くることになる。
2-3.2行名以降にはやるべきtaskを書く。
3.ダウンロードしたコードを挿入する。
3-1.空のプロジェクトを選択。
3-2.[ファイル]-[新規作成]-[スクリプトファイル]を選択。
3-3.main.gsというファイル名に変更し、ダウンロードしたコードをコピペする。
4.関数 notifyDoDoを探し、変数に設定する。(赤い字のところを変更する)
function notifyToDo(){
//Spread Sheet Config
var sheetName = "ToDo"; <-シート名を設定する。手順2.1でToDoにしたのでここは編集しなくてもよい。
var spreadSheetKey = "your spread sheet Key"; <-スプレッドシートのキーを設定する
スプレッドシートを開いたときのURLで下のアドレスバーの黒塗りの箇所に該当する文字列を登録する。
//mail config
var subject = "[MyToDoリストからの通知]ステータスのお知らせ"; <-メールのタイトルを設定する
var recipients = new Array("mailaddress"); <-メールアドレスを設定する。複数ある場合は、カンマ区切りで設定する。ex)aaa@x.com,bbb@x.com
//notification config
var threshold = 4; <-期限の4日間になったら通知する
5.関数notifyToDoを実行する。
6.SpreadSheet、Gmailの利用承認を求められる。
6-1.「続行」をクリックする。
6-2.「承認する」をクリックする。
これによってこのアプリがSpreadSheetへのアクセスとメール送信が許可される。
7.トリガーを設定する。
これは定期的にToDoの状況をメールで通知するようにするためである。
7-1.「リソース」から「現在のプロジェクトのトリガー」を選択。
7-2.「トリガーが設定されていません。・・・」をクリックする。
7-3.トリガーを設定する。
実行は、notifyTodo関数
イベントは、時間主導型、日タイマー、午後4時から5時。
これで毎日午後4〜5時の間にタスクのステータスがメールで通知される。
8.トリガーで設定した時間になるとメールで通知される。(めでたしめでたし)
Excelと同じように表計算やマクロ機能(Google Apps Script)を持っているが
何と言っても一番はスケジューラ機能だ。
スプレッドシートの内容を、指定した時間にメールで通知するなんてことも可能。
これはExcelだけではなかなかできないと思う。
という訳で自分の仕事を円滑に進められるようにするためにということで、
GoogleSpreadSheetを多様しているのだが、中でもToDoリストとしての活用は
いろいろな方でも使えるものだと思うのでサンプルコードを書いてみた。
コードはGitHubにアップしているのでそれを参考にしていただければ思う。
https://github.com/maar4569/notifyToDoWithGAS
そのサンプルを元にToDoアプリを作ってみようと思う。
このToDoアプリができること。
・利用者はスプレッドシートにToDoを書く。
・ToDoの締め切り日が近づいてくるとメールで通知してくれる。
N日前ですよとか、締め切り当日ですよとか、過ぎてますよとか。
作成手順
1.GitHubからコードをダウンロードしておく。
2.まずはGoogleドライブ上に新規のスプレッドシート「ToDoList」を作成する。
2-1.シート名を「ToDo」に変更する。
2-2.ToDoListに1行目のカラムに「task」「deadline」「notes」「deleted」と記述する。
task やるべきことを書いておく。
deadline 期日を書く。(yyyy/mm/dd形式で)
notes 補足事項があれば書いておく。
deleted メールで通知する必要が無くなった場合「1」と書いておくと通知しなくなる。
つまりもう済んだタスクは1と書いておく。書かないとずっとメールで通知して
くることになる。
2-3.2行名以降にはやるべきtaskを書く。
3.ダウンロードしたコードを挿入する。
3-1.空のプロジェクトを選択。
3-2.[ファイル]-[新規作成]-[スクリプトファイル]を選択。
3-3.main.gsというファイル名に変更し、ダウンロードしたコードをコピペする。
4.関数 notifyDoDoを探し、変数に設定する。(赤い字のところを変更する)
function notifyToDo(){
//Spread Sheet Config
var sheetName = "ToDo"; <-シート名を設定する。手順2.1でToDoにしたのでここは編集しなくてもよい。
var spreadSheetKey = "your spread sheet Key"; <-スプレッドシートのキーを設定する
スプレッドシートを開いたときのURLで下のアドレスバーの黒塗りの箇所に該当する文字列を登録する。
//mail config
var subject = "[MyToDoリストからの通知]ステータスのお知らせ"; <-メールのタイトルを設定する
var recipients = new Array("mailaddress"); <-メールアドレスを設定する。複数ある場合は、カンマ区切りで設定する。ex)aaa@x.com,bbb@x.com
//notification config
var threshold = 4; <-期限の4日間になったら通知する
5.関数notifyToDoを実行する。
6.SpreadSheet、Gmailの利用承認を求められる。
6-1.「続行」をクリックする。
6-2.「承認する」をクリックする。
これによってこのアプリがSpreadSheetへのアクセスとメール送信が許可される。
7.トリガーを設定する。
これは定期的にToDoの状況をメールで通知するようにするためである。
7-1.「リソース」から「現在のプロジェクトのトリガー」を選択。
7-2.「トリガーが設定されていません。・・・」をクリックする。
7-3.トリガーを設定する。
実行は、notifyTodo関数
イベントは、時間主導型、日タイマー、午後4時から5時。
これで毎日午後4〜5時の間にタスクのステータスがメールで通知される。
8.トリガーで設定した時間になるとメールで通知される。(めでたしめでたし)
2013年10月8日火曜日
コマ大数学科 特別集中講座
ビートたけしがやっていたTV番組「たけしのコマ大数学科」からスピンアウトした書籍。
Eテレの「サイエンスZERO」でおなじみの竹内薫さんとの対談本である。
竹内薫さんはというと、「99・9%は仮説 思いこみで判断しないための考え方」 で
有名な方だ(と私は勝手に思っている)が、
日常にあふれている様々な事が、実は科学では厳密に解明できておらず仮説に基づいて成立しているということを、いくつかの事例に基づいて書いていて、トリビア的な要素が知的好奇心をそそる。
そんなお二人が数学を通して、仕事や人生など(おおげさな言い方だが)の価値観に
影響を与えてきた事をつれづれなるままに語っている。
実際読んでみるとビートたけしって本当に数学が好きなんだなぁというのがひしひしと
伝わってくる。余暇のあるときに数学の本を買ってきて問題を解いてみたり、孫と一緒に算数の勉強をしたり、小学生向けの英語の算数の教科書で問題を解きつつ英語の勉強をしてみたりと、いくら理系の人たちといえど趣味で数学の問題を解くなんて相当なマニアでないかぎりやらないだろう。しかしそこに楽しさ・美しさを見い出しているビートたけし
を知りさらに人間的な魅力を感じた次第だ。
「問題を作るっていうのは、自分用の教科書を作るのと同じなんですよ。だから次に同じような問題が出ても解けちゃう。数学の問題集1冊に対して5冊くだい自分用のノートを作り、それを眺めたりしてるうちにどんどんキレイに問題が解けるようになってくるんですね。」
「問題があって答えを出すなんていう形式の問題はよくないね。逆に「答えから問題を考える」なんて方法があったっていい。どんな計算をしても答えが5というだけなら、カンニングしてもいいし、鉛筆転がしだって答えさえ合ってたら合格だ。それより、どうやって5という解答を導きだしたかという家庭が大切でおもしろいのにね」
これってビジネスの世界でも同じ「課題設定をどうするか」っていうことと同じじゃないか!と思った。ある程度の年齢になってくると与えられる立場から自分が仕事を与えたり、作る立場になる。
例えば売り上げを2倍にするという答え(結果)を作る(達成する)場合、それにたどり着くまでには結果に至るにあたっての問題(課題)とそれを解き明かす方法(プロセス)を正しく設定できなければならない。
まぁできれば売り上げも上がって会社の評価もあがるんだけど難しいんだよね。
でもこれもたけしが自分のノートを作るといっていたように思考の訓練が必要なのだ。
与えられているコト(問題)をこなす(解答する)だけで満足していないか?
自らが作り出すこと、すなわち課題を設定する事し問題を解決していくことを
怠っていないか?
I'll give it a shot.
今からでもやってみよう、と思う。
それにしても平成教育委員会は本当に面白い番組だったなぁ。
あんな知的なクイズ番組後にも先にもないと思う。
あの番組が自分が小学生の頃から存在していたらもっと勉強が好きになったのになぁ。
Eテレの「サイエンスZERO」でおなじみの竹内薫さんとの対談本である。
竹内薫さんはというと、「99・9%は仮説 思いこみで判断しないための考え方」 で
有名な方だ(と私は勝手に思っている)が、
日常にあふれている様々な事が、実は科学では厳密に解明できておらず仮説に基づいて成立しているということを、いくつかの事例に基づいて書いていて、トリビア的な要素が知的好奇心をそそる。
そんなお二人が数学を通して、仕事や人生など(おおげさな言い方だが)の価値観に
影響を与えてきた事をつれづれなるままに語っている。
実際読んでみるとビートたけしって本当に数学が好きなんだなぁというのがひしひしと
伝わってくる。余暇のあるときに数学の本を買ってきて問題を解いてみたり、孫と一緒に算数の勉強をしたり、小学生向けの英語の算数の教科書で問題を解きつつ英語の勉強をしてみたりと、いくら理系の人たちといえど趣味で数学の問題を解くなんて相当なマニアでないかぎりやらないだろう。しかしそこに楽しさ・美しさを見い出しているビートたけし
を知りさらに人間的な魅力を感じた次第だ。
「問題を作るっていうのは、自分用の教科書を作るのと同じなんですよ。だから次に同じような問題が出ても解けちゃう。数学の問題集1冊に対して5冊くだい自分用のノートを作り、それを眺めたりしてるうちにどんどんキレイに問題が解けるようになってくるんですね。」
「問題があって答えを出すなんていう形式の問題はよくないね。逆に「答えから問題を考える」なんて方法があったっていい。どんな計算をしても答えが5というだけなら、カンニングしてもいいし、鉛筆転がしだって答えさえ合ってたら合格だ。それより、どうやって5という解答を導きだしたかという家庭が大切でおもしろいのにね」
これってビジネスの世界でも同じ「課題設定をどうするか」っていうことと同じじゃないか!と思った。ある程度の年齢になってくると与えられる立場から自分が仕事を与えたり、作る立場になる。
例えば売り上げを2倍にするという答え(結果)を作る(達成する)場合、それにたどり着くまでには結果に至るにあたっての問題(課題)とそれを解き明かす方法(プロセス)を正しく設定できなければならない。
まぁできれば売り上げも上がって会社の評価もあがるんだけど難しいんだよね。
でもこれもたけしが自分のノートを作るといっていたように思考の訓練が必要なのだ。
与えられているコト(問題)をこなす(解答する)だけで満足していないか?
自らが作り出すこと、すなわち課題を設定する事し問題を解決していくことを
怠っていないか?
I'll give it a shot.
今からでもやってみよう、と思う。
それにしても平成教育委員会は本当に面白い番組だったなぁ。
あんな知的なクイズ番組後にも先にもないと思う。
あの番組が自分が小学生の頃から存在していたらもっと勉強が好きになったのになぁ。
ZaimとGoogleSpreadSheetが連携できない。
Zaimでは外部のサービスと連携するためにAPIを公開している。
認証はoAuth1.0aに対応しているのだが、GoogleAppsScriptと相性が悪いのか、
oAuthエラーというエラーが発生し認証に失敗する。
丸1日費やしたが失敗の原因がわからないのでひとまず撤収。
もし「できる!知ってるよ!」という方がいたら教えてください。
私が書いたコードを一応のせておきます。
var oAuthConfig = function(serviceName,accessTokenURL,requestTokenUrl,authorizationUrl){
var m_methods = {};
var m_oAuthConfig = UrlFetchApp.addOAuthService(serviceName);
m_oAuthConfig.setAccessTokenUrl( accessTokenURL );
m_oAuthConfig.setRequestTokenUrl( requestTokenUrl );
m_oAuthConfig.setAuthorizationUrl( authorizationUrl );
var setConsumerKeyAndSecret = function(key,secret){
ScriptProperties.setProperty('consumerKey', key);
ScriptProperties.setProperty('consumerSecret', secret);
m_oAuthConfig.setConsumerKey(ScriptProperties.getProperty('consumerKey'));
m_oAuthConfig.setConsumerSecret(ScriptProperties.getProperty('consumerSecret'));
}
m_methods.setConsumerKeyAndSecret = setConsumerKeyAndSecret;
var getConfig = function(){ return m_oAuthConfig; }
m_methods.getConfig = getConfig;
var authConfigDump = function(){
Logger.log('AccessTokenURL->' + m_oAuthConfig.getAccessTokenUrl());
Logger.log('AuthorizationUrl->'+ m_oAuthConfig.getAuthorizationUrl());
Logger.log('Method->' + m_oAuthConfig.getMethod());
Logger.log('ParameterLocation->' + m_oAuthConfig.getParamLocation());
Logger.log('RequestTokenURL->' + m_oAuthConfig.getRequestTokenUrl());
Logger.log('ServiceName->' + m_oAuthConfig.getServiceName());
}
m_methods.authConfigDump = authConfigDump;
//create nonce from SHA-1 Digest
var getNonce = function(){
var now = new Date();
var nonce = Utilities.computeDigest(Utilities.DigestAlgorithm.SHA_1,now.getTime(),Utilities.Charset.US_ASCII);
var strNonce = bytes2StringDigest(nonce);
Logger.log('nonce(bytes2StringDigest)->' + strNonce);
return strNonce;
}
m_methods.getNonce = getNonce;
return m_methods;
}
var urlString = function(url){
var m_methods = {};
var m_response = UrlFetchApp.getRequest(url);
var m_methodName = m_response.method;
var m_url = m_response.url;
var getMethod = function(){return m_methodName;}
m_methods.getMethod = getMethod;
var getUrl = function(){ return encodeURIComponent( m_url.split('?')[0] );}
m_methods.getUrl = getUrl;
var getQueryStrings = function(){ return encodeURIComponent( m_url.split('?')[1] ); }
m_methods.getQueryStrings = getQueryStrings;
var dump = function(){
for(var i in m_response) {
Logger.log(i + ": " + m_response[i]);
}
}
m_methods.dump = dump;
return m_methods;
}
var getOAuthSignature = function(url,common_param_oauth){
//HASHMAC Signature
var urlStr = urlString(url);
var sign_url = encodeURIComponent(urlStr.getUrl());
var sign_param = encodeURIComponent(urlStr.getQueryStrings());
var sign_source = 'GET' + '&'+ sign_url + '&' +
// 'oauth_body_hash' + encodeURIComponent('=') + common_param_oauth.oauth_body_hash + '&' +
'oauth_consumer_key' + encodeURIComponent('=') + common_param_oauth.oauth_consumer_key + '&' +
'oauth_nonce' + encodeURIComponent('=') + common_param_oauth.oauth_nonce +'&' +
'oauth_signature_method' + encodeURIComponent('=') + common_param_oauth.oauth_signature_method +'&' +
'oauth_timestamp' + encodeURIComponent('=') + common_param_oauth.oauth_timestamp + '&' +
'oauth_version' + encodeURIComponent('=') + '1.0';
//if (sign_param != undefined){ sign_source = sign_source + '&' + sign_param }
Logger.log('SIGN_SOURCE->' + sign_source);
//create Signature(HMAC SHA-1) and encode BASE64.
var tmpSignature = Utilities.computeHmacSignature(Utilities.MacAlgorithm.HMAC_SHA_1,sign_source,common_param_oauth.oauth_consumer_key);
common_param_oauth.oauth_signature = Utilities.base64Encode(tmpSignature);
Logger.log('Signature(bytecode)->' + tmpSignature );
Logger.log('Signature(base64)->' + common_param_oauth.oauth_signature );
return common_param_oauth.oauth_signature;
}
/////////////////////
//MAIN
/////////////////////
function main(){
var serviceName = 'Zaim';
var accessTokenUrl = "https://api.zaim.net/v2/auth/access";
var requestTokenUrl = "https://api.zaim.net/v2/auth/request";
var authorizationUrl = "https://www.zaim.net/users/auth";
var key = 'Your consumerKey';
var secret = 'Your consumerSecret';
var methodName = 'get'; //default get
var paramLocation = 'auth-header'; //Allowed values are 'post-body', 'uri-query' and 'auth-header'.
var tergetUrl = 'https://api.zaim.net/v2/home/user/verify';
var response='';
try{
var oAuthConf = oAuthConfig(serviceName,accessTokenUrl,requestTokenUrl,authorizationUrl);
oAuthConf.setConsumerKeyAndSecret(key,secret);
oAuthConf.authConfigDump();
oAuthConf.getConfig().setMethod( methodName );
oAuthConf.getConfig().setParamLocation( paramLocation );
oAuthConf.authConfigDump();
Logger.log('key->' + ScriptProperties.getProperty('consumerKey'));
Logger.log('secret->' + ScriptProperties.getProperty('consumerSecret'));
var now = new Date();
var common_param_oauth =
{
'oauth_consumer_key' : ScriptProperties.getProperty('consumerKey'),
'oauth_signature' : '', //see after code.
'oauth_signature_method' : 'HMAC-SHA1',
'oauth_token' : '',
//'oauth_timestamp' : now.getTime(),
//'oauth_nonce' : oAuthConf.getNonce(),
'oauth_timestamp' : '',
'oauth_nonce' : '',
'oauth_version' : '1.0'
//'oauth_body_hash' : ''
};
getOAuthSignature(tergetUrl,common_param_oauth );
Logger.log('COMMON_PARAM_OAUTH->' + Utilities.jsonStringify(common_param_oauth));
var options =
{
"oAuthServiceName" : serviceName,
"oAuthUseToken" : "always",
"method" : methodName,
//"headers" : '',
//"payload" : common_param_oauth,
"muteHttpExceptions" : true
};
Logger.log('options->' + Utilities.jsonStringify(options));
//var response = UrlFetchApp.fetch( tergetUrl );
response = UrlFetchApp.fetch( tergetUrl , options );
}catch(e){
Logger.log('main failure.' + e.message);
}
}
2013/11/27
再チャレンジしたが認証エラーでやはりNG。
上のソースコードはかなり間違いがあるのだが、再度oauth_signatureの作成方法(アルゴリズム、パラメータのソート、URIエンコード・・・)などを
oauth1.0の仕様書に基づきトライしてもダメ。
ということでGoogle Apps Scriptとの連携は一旦あきらめる。
認証はoAuth1.0aに対応しているのだが、GoogleAppsScriptと相性が悪いのか、
oAuthエラーというエラーが発生し認証に失敗する。
丸1日費やしたが失敗の原因がわからないのでひとまず撤収。
もし「できる!知ってるよ!」という方がいたら教えてください。
私が書いたコードを一応のせておきます。
var oAuthConfig = function(serviceName,accessTokenURL,requestTokenUrl,authorizationUrl){
var m_methods = {};
var m_oAuthConfig = UrlFetchApp.addOAuthService(serviceName);
m_oAuthConfig.setAccessTokenUrl( accessTokenURL );
m_oAuthConfig.setRequestTokenUrl( requestTokenUrl );
m_oAuthConfig.setAuthorizationUrl( authorizationUrl );
var setConsumerKeyAndSecret = function(key,secret){
ScriptProperties.setProperty('consumerKey', key);
ScriptProperties.setProperty('consumerSecret', secret);
m_oAuthConfig.setConsumerKey(ScriptProperties.getProperty('consumerKey'));
m_oAuthConfig.setConsumerSecret(ScriptProperties.getProperty('consumerSecret'));
}
m_methods.setConsumerKeyAndSecret = setConsumerKeyAndSecret;
var getConfig = function(){ return m_oAuthConfig; }
m_methods.getConfig = getConfig;
var authConfigDump = function(){
Logger.log('AccessTokenURL->' + m_oAuthConfig.getAccessTokenUrl());
Logger.log('AuthorizationUrl->'+ m_oAuthConfig.getAuthorizationUrl());
Logger.log('Method->' + m_oAuthConfig.getMethod());
Logger.log('ParameterLocation->' + m_oAuthConfig.getParamLocation());
Logger.log('RequestTokenURL->' + m_oAuthConfig.getRequestTokenUrl());
Logger.log('ServiceName->' + m_oAuthConfig.getServiceName());
}
m_methods.authConfigDump = authConfigDump;
//create nonce from SHA-1 Digest
var getNonce = function(){
var now = new Date();
var nonce = Utilities.computeDigest(Utilities.DigestAlgorithm.SHA_1,now.getTime(),Utilities.Charset.US_ASCII);
var strNonce = bytes2StringDigest(nonce);
Logger.log('nonce(bytes2StringDigest)->' + strNonce);
return strNonce;
}
m_methods.getNonce = getNonce;
return m_methods;
}
var urlString = function(url){
var m_methods = {};
var m_response = UrlFetchApp.getRequest(url);
var m_methodName = m_response.method;
var m_url = m_response.url;
var getMethod = function(){return m_methodName;}
m_methods.getMethod = getMethod;
var getUrl = function(){ return encodeURIComponent( m_url.split('?')[0] );}
m_methods.getUrl = getUrl;
var getQueryStrings = function(){ return encodeURIComponent( m_url.split('?')[1] ); }
m_methods.getQueryStrings = getQueryStrings;
var dump = function(){
for(var i in m_response) {
Logger.log(i + ": " + m_response[i]);
}
}
m_methods.dump = dump;
return m_methods;
}
var getOAuthSignature = function(url,common_param_oauth){
//HASHMAC Signature
var urlStr = urlString(url);
var sign_url = encodeURIComponent(urlStr.getUrl());
var sign_param = encodeURIComponent(urlStr.getQueryStrings());
var sign_source = 'GET' + '&'+ sign_url + '&' +
// 'oauth_body_hash' + encodeURIComponent('=') + common_param_oauth.oauth_body_hash + '&' +
'oauth_consumer_key' + encodeURIComponent('=') + common_param_oauth.oauth_consumer_key + '&' +
'oauth_nonce' + encodeURIComponent('=') + common_param_oauth.oauth_nonce +'&' +
'oauth_signature_method' + encodeURIComponent('=') + common_param_oauth.oauth_signature_method +'&' +
'oauth_timestamp' + encodeURIComponent('=') + common_param_oauth.oauth_timestamp + '&' +
'oauth_version' + encodeURIComponent('=') + '1.0';
//if (sign_param != undefined){ sign_source = sign_source + '&' + sign_param }
Logger.log('SIGN_SOURCE->' + sign_source);
//create Signature(HMAC SHA-1) and encode BASE64.
var tmpSignature = Utilities.computeHmacSignature(Utilities.MacAlgorithm.HMAC_SHA_1,sign_source,common_param_oauth.oauth_consumer_key);
common_param_oauth.oauth_signature = Utilities.base64Encode(tmpSignature);
Logger.log('Signature(bytecode)->' + tmpSignature );
Logger.log('Signature(base64)->' + common_param_oauth.oauth_signature );
return common_param_oauth.oauth_signature;
}
/////////////////////
//MAIN
/////////////////////
function main(){
var serviceName = 'Zaim';
var accessTokenUrl = "https://api.zaim.net/v2/auth/access";
var requestTokenUrl = "https://api.zaim.net/v2/auth/request";
var authorizationUrl = "https://www.zaim.net/users/auth";
var key = 'Your consumerKey';
var secret = 'Your consumerSecret';
var methodName = 'get'; //default get
var paramLocation = 'auth-header'; //Allowed values are 'post-body', 'uri-query' and 'auth-header'.
var tergetUrl = 'https://api.zaim.net/v2/home/user/verify';
var response='';
try{
var oAuthConf = oAuthConfig(serviceName,accessTokenUrl,requestTokenUrl,authorizationUrl);
oAuthConf.setConsumerKeyAndSecret(key,secret);
oAuthConf.authConfigDump();
oAuthConf.getConfig().setMethod( methodName );
oAuthConf.getConfig().setParamLocation( paramLocation );
oAuthConf.authConfigDump();
Logger.log('key->' + ScriptProperties.getProperty('consumerKey'));
Logger.log('secret->' + ScriptProperties.getProperty('consumerSecret'));
var now = new Date();
var common_param_oauth =
{
'oauth_consumer_key' : ScriptProperties.getProperty('consumerKey'),
'oauth_signature' : '', //see after code.
'oauth_signature_method' : 'HMAC-SHA1',
'oauth_token' : '',
//'oauth_timestamp' : now.getTime(),
//'oauth_nonce' : oAuthConf.getNonce(),
'oauth_timestamp' : '',
'oauth_nonce' : '',
'oauth_version' : '1.0'
//'oauth_body_hash' : ''
};
getOAuthSignature(tergetUrl,common_param_oauth );
Logger.log('COMMON_PARAM_OAUTH->' + Utilities.jsonStringify(common_param_oauth));
var options =
{
"oAuthServiceName" : serviceName,
"oAuthUseToken" : "always",
"method" : methodName,
//"headers" : '',
//"payload" : common_param_oauth,
"muteHttpExceptions" : true
};
Logger.log('options->' + Utilities.jsonStringify(options));
//var response = UrlFetchApp.fetch( tergetUrl );
response = UrlFetchApp.fetch( tergetUrl , options );
}catch(e){
Logger.log('main failure.' + e.message);
}
}
2013/11/27
再チャレンジしたが認証エラーでやはりNG。
上のソースコードはかなり間違いがあるのだが、再度oauth_signatureの作成方法(アルゴリズム、パラメータのソート、URIエンコード・・・)などを
oauth1.0の仕様書に基づきトライしてもダメ。
ということでGoogle Apps Scriptとの連携は一旦あきらめる。
2013年10月4日金曜日
JavaScriptに連想配列(ハッシュテーブル)は存在しない
最近JavaScriptの勉強を兼ねて、仕事(Windowsサーバのシステム)で
JScriptを利用するようにしている。(残念ながらLinux環境にない。。。)
Webで調べながら「JavaScriptでハッシュを実現するにはこうすればいいのね」と
得意げに 以下のようなコードを書いていた。
var hash = {};
hash[ 'apple' ] = 100;
hash[ 'lemon' ] = 200;
for(key in hash){
var ret = hash[key];
}
retにはそれぞれ100,200が返る。
しかし実はJavaScriptにハッシュなど存在しなかった。
それを知ったのはつい最近のことである。
JavaScriptで配列を実現できるのはArray()だけだ。
Array()による配列の実現は以下のとおりである。
var list = []; //空の配列を生成。 var list = new Array()と同義。
list[0] = 100;
list[1] = 200;
for(var i=0 ; i<list.length ; i++){
var ret = list[i];
}
じゃあどうして前者のコードはあたかもハッシュテーブルのように
見えるのだろうか?そしてハッシュテーブルとは別物なのか?
var hash = {}; は
var hash = new Object();と同義である。
つまりhashは空の新しいObject型のオブジェクトを生成していることを表す。
では以下のコードは何を意味するか?
hash[ 'apple' ] = 100;
これはhashオブジェクトにappleプロパティを設定し、値を100とする
ことを意味する。
hash.apple = 100と同じ事である。
hash['lemon'] = 200も同じだ。
見た目はhash配列にappleをキーとして値に100を設定しているように見えるが、
全く違うのだ。
それでは以下の部分はどうだろう。
for(key in hash){
var ret = hash[key];
} in演算子は対象のオブジェクトが指定された名前のプロパティを
保持しているかどうかを確認する。(true/falseが返る。)
forと組み合わせる事によって、指定オブジェクトの各プロパティ名を
取得していくことができる。
だから
hash[key]は、hashオブジェクトのkeyプロパティに設定された値を
取得することを意味する。
上記の例でいうとプロパティにapple、lemonを追加したから、
hash['apple']、hash['lemon']の値を取得することになる。
hash.apple、hash.lemonでもかまわない。
補足だがプロパティが数値の場合は、ドットを利用したアクセスはできない。
hash['1000'] -> OK
hash.1000 -> NG エラーになる。
つまり、JavaScriptにおけるハッシュテーブルに似た仕組みの裏側は、
オブジェクトにプロパティを設定するという行為である。
考察
コードを書いて少しでも動いてしまうと、
同じようなケースに遭遇したときに、
動作原理について知らないまま
経験に基づいてコードを書いてしまうことが少なくない。
理論ではなく経験則に基づいてということだ。
これは非常に危うい。
プログラムの複雑さが増し問題にぶちあたった時に、
原理を知らないからそれに基づいて問題解決に取り組む事ができないからだ。
当然経験も無いので何から手をつけたらいいかわからなくなる。
しかし原理を知らないまま書く事が悪いといっている訳ではない。
どのような動作をするかを知るためには、
体で理解すること、反復練習をすること
つまり何度も同じようなコードを自分の手で書くことで、
体にしみ込ませる事が必要だと思うからだ。
重要なのは、体がわかるようになり余裕が出てきた時に
なぜそのような動作になるかを知ることだと思う。
経験と原理両面から知る事で深い理解につながる。
算数・数学などの公式なども一緒だと思う。
公式の意味するところは最初はわからないが、
問題を数多くこなす事につれ体と頭が理解するようになる。
人間何かを学ぶためには、理論と経験の両輪で考えなければならない。
JScriptを利用するようにしている。(残念ながらLinux環境にない。。。)
Webで調べながら「JavaScriptでハッシュを実現するにはこうすればいいのね」と
得意げに 以下のようなコードを書いていた。
var hash = {};
hash[ 'apple' ] = 100;
hash[ 'lemon' ] = 200;
for(key in hash){
var ret = hash[key];
}
retにはそれぞれ100,200が返る。
しかし実はJavaScriptにハッシュなど存在しなかった。
それを知ったのはつい最近のことである。
JavaScriptで配列を実現できるのはArray()だけだ。
Array()による配列の実現は以下のとおりである。
var list = []; //空の配列を生成。 var list = new Array()と同義。
list[0] = 100;
list[1] = 200;
for(var i=0 ; i<list.length ; i++){
var ret = list[i];
}
じゃあどうして前者のコードはあたかもハッシュテーブルのように
見えるのだろうか?そしてハッシュテーブルとは別物なのか?
var hash = {}; は
var hash = new Object();と同義である。
つまりhashは空の新しいObject型のオブジェクトを生成していることを表す。
では以下のコードは何を意味するか?
hash[ 'apple' ] = 100;
これはhashオブジェクトにappleプロパティを設定し、値を100とする
ことを意味する。
hash.apple = 100と同じ事である。
hash['lemon'] = 200も同じだ。
見た目はhash配列にappleをキーとして値に100を設定しているように見えるが、
全く違うのだ。
それでは以下の部分はどうだろう。
for(key in hash){
var ret = hash[key];
} in演算子は対象のオブジェクトが指定された名前のプロパティを
保持しているかどうかを確認する。(true/falseが返る。)
forと組み合わせる事によって、指定オブジェクトの各プロパティ名を
取得していくことができる。
だから
hash[key]は、hashオブジェクトのkeyプロパティに設定された値を
取得することを意味する。
上記の例でいうとプロパティにapple、lemonを追加したから、
hash['apple']、hash['lemon']の値を取得することになる。
hash.apple、hash.lemonでもかまわない。
補足だがプロパティが数値の場合は、ドットを利用したアクセスはできない。
hash['1000'] -> OK
hash.1000 -> NG エラーになる。
つまり、JavaScriptにおけるハッシュテーブルに似た仕組みの裏側は、
オブジェクトにプロパティを設定するという行為である。
考察
コードを書いて少しでも動いてしまうと、
同じようなケースに遭遇したときに、
動作原理について知らないまま
経験に基づいてコードを書いてしまうことが少なくない。
理論ではなく経験則に基づいてということだ。
これは非常に危うい。
プログラムの複雑さが増し問題にぶちあたった時に、
原理を知らないからそれに基づいて問題解決に取り組む事ができないからだ。
当然経験も無いので何から手をつけたらいいかわからなくなる。
しかし原理を知らないまま書く事が悪いといっている訳ではない。
どのような動作をするかを知るためには、
体で理解すること、反復練習をすること
つまり何度も同じようなコードを自分の手で書くことで、
体にしみ込ませる事が必要だと思うからだ。
重要なのは、体がわかるようになり余裕が出てきた時に
なぜそのような動作になるかを知ることだと思う。
経験と原理両面から知る事で深い理解につながる。
算数・数学などの公式なども一緒だと思う。
公式の意味するところは最初はわからないが、
問題を数多くこなす事につれ体と頭が理解するようになる。
人間何かを学ぶためには、理論と経験の両輪で考えなければならない。
2013年10月3日木曜日
ziprubyを使ったzip圧縮ライブラリ
ziprubyを利用したライブラリを作成。
使い方は以下のとおり。
require relative '******/ziparchiver.rb'
objZip = ZipArchiver.new( 'zipファイルのフルパス' )
objZip.createZip( '対象のフォルダまたはファイルのパス' )
*フォルダを指定するとサブディレクトリも含めて圧縮する。
objZip.encrypt( 'zipファイルのパスワード' ) <-任意で設定
https://github.com/maar4569/Ziparchiver
使い方は以下のとおり。
require relative '******/ziparchiver.rb'
objZip = ZipArchiver.new( 'zipファイルのフルパス' )
objZip.createZip( '対象のフォルダまたはファイルのパス' )
*フォルダを指定するとサブディレクトリも含めて圧縮する。
objZip.encrypt( 'zipファイルのパスワード' ) <-任意で設定
https://github.com/maar4569/Ziparchiver
植物はすごい 生き残りをかけた仕組みと工夫
植物は動くことがなければ、コミュニケーションを取る事もできない。
そのような特徴を持っているとしても、
いかにして自分を守りながら子孫を増やせばよいかを遺伝子の中に
組み込んできた。そのやり方も様々。
例えば、栗と柿を例に取ると一見全く違う戦略だが目的は一緒というところが面白い。
栗は過剰なほどに防衛する。あのトゲトゲの中に、固い皮の鎧をまとっている。
仮に皮を剝く事ができたとしても、渋皮という下着をつけ、これでも食うの?
といった様子。超ディフェンシブ。
一方、柿といえば種が成熟するまでは渋柿で「食べちゃいやよ」オーラを振りまくが、
ほどよく成長すると、食べても渋みを感じ無いようにし、甘みで誘惑してを出して
「私を食べて、そして遠くへ連れてって」と言わんばかりの様子。
(渋柿をかじると渋く感じるのはタンニンが溶けだしてくるからだそうな。果実が成熟するとアルコールでおなじみアセトアルデヒドが生成されタンニンを不溶性にするとのこと)
こちらは反対に超オフェンシブ。
守る戦略と、攻めてリスク分散をはかる戦略。
育ってきた環境によってそれぞれが選択した戦略なのだろう。
ビジネスでも一緒だと思う。
自分たちが置かれている環境をよく見極め戦略を考えなければならない。
植物は気の遠くなるような時間をかけていまの戦略を選択したが、
ビジネスではそうはいかないのがまた難しい。
そのような特徴を持っているとしても、
いかにして自分を守りながら子孫を増やせばよいかを遺伝子の中に
組み込んできた。そのやり方も様々。
例えば、栗と柿を例に取ると一見全く違う戦略だが目的は一緒というところが面白い。
栗は過剰なほどに防衛する。あのトゲトゲの中に、固い皮の鎧をまとっている。
仮に皮を剝く事ができたとしても、渋皮という下着をつけ、これでも食うの?
といった様子。超ディフェンシブ。
一方、柿といえば種が成熟するまでは渋柿で「食べちゃいやよ」オーラを振りまくが、
ほどよく成長すると、食べても渋みを感じ無いようにし、甘みで誘惑してを出して
「私を食べて、そして遠くへ連れてって」と言わんばかりの様子。
(渋柿をかじると渋く感じるのはタンニンが溶けだしてくるからだそうな。果実が成熟するとアルコールでおなじみアセトアルデヒドが生成されタンニンを不溶性にするとのこと)
こちらは反対に超オフェンシブ。
守る戦略と、攻めてリスク分散をはかる戦略。
育ってきた環境によってそれぞれが選択した戦略なのだろう。
ビジネスでも一緒だと思う。
自分たちが置かれている環境をよく見極め戦略を考えなければならない。
植物は気の遠くなるような時間をかけていまの戦略を選択したが、
ビジネスではそうはいかないのがまた難しい。
2013年10月1日火曜日
理系による支配
今月のクーリエジャポンの特集。
文系優遇の時代が終わり、「理系」による支配の時代になったとのこと。
GAFA(Google,Amazon,Facebook,Apple)に代表されるIT企業もFounderを見ると、
大抵が理系出身だ。
またIT業界だけでなくThe Quantsにあるように、金融業界などにおいてもその影響力は
凄まじいものがある。
ただ「理系」支配の裏側には、理系で培った深い専門性に加え、文系人間と同等かそれ以上のコミュニケーションスキルやリーダシップなど基本的な人としてのスキルセットや、
専門以外の分野、つまり理系学問で学んだことを応用できる可能性のある他の分野に関する深い造詣を持つ、多能工的な人材が出てきたということだろうと思う。
いずれにせよ凡人の私からすると、到底このような境地に達する事はできないが、
少なくとも学ぶ事はできるだろうと思う。
文系優遇の時代が終わり、「理系」による支配の時代になったとのこと。
GAFA(Google,Amazon,Facebook,Apple)に代表されるIT企業もFounderを見ると、
大抵が理系出身だ。
またIT業界だけでなくThe Quantsにあるように、金融業界などにおいてもその影響力は
凄まじいものがある。
ただ「理系」支配の裏側には、理系で培った深い専門性に加え、文系人間と同等かそれ以上のコミュニケーションスキルやリーダシップなど基本的な人としてのスキルセットや、
専門以外の分野、つまり理系学問で学んだことを応用できる可能性のある他の分野に関する深い造詣を持つ、多能工的な人材が出てきたということだろうと思う。
いずれにせよ凡人の私からすると、到底このような境地に達する事はできないが、
少なくとも学ぶ事はできるだろうと思う。
JScript UTF-8のファイル読み込み
WSHでは通常ファイルを読み込むときに、
FileSystemObjectをnewしてEOFまでファイルを読むというスタイルを取る。
サンプルコードは以下のサイトへ。
https://github.com/maar4569/Tips/blob/master/fileReader.js
FileSystemObjectをnewしてEOFまでファイルを読むというスタイルを取る。
しかしこれはファイルのエンコード形式がShift-JISに限定されている。
var fso = new ActiveXObject('Scripting.FileSystemObject');
while(textStream.AtEndOfLine == false){
//your code
}
UTF-8など他のエンコード形式の場合は、ADOを利用する。
var fso = new ActiveXObject('ADODB.Stream');
fso.type = 2;
fso.charset = 'utf-8';
fso.open();fso.loadFromFile( filePath );
while(!fso.EOS){
//your code }fso.close();
サンプルコードは以下のサイトへ。
https://github.com/maar4569/Tips/blob/master/fileReader.js
登録:
投稿 (Atom)