ブラウザを使ってPC間のファイル転送中に一時停止する。

ファイル転送中に一時停止できたら良いな。 と思ったことがある人は意外と多いんじゃないかと思います。

転送中に、他の小さなデータがほしい時は、大きなファイルが転送されるまで待っていました。

自分はSMB接続で比較的大きなファイル転送する事が多いです。 ファイル転送ツールを専用に入れたこともありました。

が、ブラウザの万能性に気が付いた! ブラウザでダウンロードすれば一時停止できる!しかも専用にツールも必要ない!

本当は標準装備のIEでできたら良かったんですが、残念ながらIE8とIE9では出来ませんでした。。 chrome8とFirefox4で確認しました。

ディレクトリをブラウザにドラッグアンドドロップすれば、ファイルブラウジングが簡単にできます。

他にも、音楽ファイルも投げるだけで、ミュージックプレイヤーを立ち上げる暇もなく確認できます
chromeならPDFだって一瞬で表示してくれますよね

AmazonS3の使い方 APIとか

①バケツの一覧確認
②バケツ作成
③最後にバケツの一覧を確認
するプログラムです。凄く雑です。

それにしてもサンプルコードが少ない。。ツールも少ない。。
LiteLanguageにはAmazonS3のライブラリが有るんですが、Cには無いのかな@@

clxのライブラリを使えば簡単にhttpsに出来るはずです。でも移植性が!

サンプルプログラム

#include <iostream>
#include <string>
#include <clx/https.h>
#include <clx/uri.h>
#include <clx/base64.h>
#include <clx/format.h>
#include <clx/time.h>
#include <boost/asio.hpp>
#include <openssl/sha.h>
#include <openssl/hmac.h>
#include <openssl/evp.h>
#include <openssl/bio.h>
#include <openssl/buffer.h>

// 参考サイトから
char *base64(const unsigned char *input, int length)
{
  BIO *bmem, *b64;
  BUF_MEM *bptr;

  b64 = BIO_new(BIO_f_base64());
  bmem = BIO_new(BIO_s_mem());
  b64 = BIO_push(b64, bmem);
  BIO_write(b64, input, length);
  BIO_flush(b64);
  BIO_get_mem_ptr(b64, &bptr);

  char *buff = (char *)malloc(bptr->length);
  memcpy(buff, bptr->data, bptr->length-1);
  buff[bptr->length-1] = 0;

  BIO_free_all(b64);

  return buff;
}

// バケットリストの一覧用シグネチャ
std::string cresig_Bucket_list(std::string date, std::string SecretAccessKey)
{
	std::string StringToSign = "GET\n\n\n" + date + "\n/";
	std::string sigunetya;

	unsigned int reslen;
    unsigned char res[SHA_DIGEST_LENGTH + 1];

	HMAC(EVP_sha1(), SecretAccessKey.c_str(), SecretAccessKey.size(), (unsigned const char*)StringToSign.c_str(), StringToSign.size(), res, &reslen);

	char* output = base64(res, reslen);

	return std::string(output);
}

// 新しいバケット作成用シグネチャ
std::string cresig_PUT_Bucket(std::string date, std::string SecretAccessKey)
{
    // ※helloidea埋め込み (雑)
	std::string StringToSign = "PUT\n\n\n" + date + "\n/helloidea/";
	std::string sigunetya;

	unsigned int reslen;
    unsigned char res[SHA_DIGEST_LENGTH + 1];

	HMAC(EVP_sha1(), SecretAccessKey.c_str(), SecretAccessKey.size(), (unsigned const char*)StringToSign.c_str(), StringToSign.size(), res, &reslen);

	char* output = base64(res, reslen);

	return std::string(output);
}

int main() {
    
	std::string AWSAccessKeyId = "■■■■あなたのAWSAccessKeyId ■■■■";
	std::string SecretAccessKey = "■■■■■■■あなたのSecretAccessKey ■■■■■■■■";
	
	std::string fmt = "%a, %d %b %Y %H:%M:%S GMT";
	std::string time;
	clx::date_time now;
	std::cout << now.to_string<char>(fmt) << std::endl;
	time = (now + clx::hours(-9)).to_string<char>(fmt);

	boost::asio::ip::tcp::iostream s("s3.amazonaws.com", "http");

	std::string line;

    /********************************************************************************
         バケツリスト表示
    ********************************************************************************/
	time = (now + clx::hours(-9)).to_string<char>(fmt);
	s << "GET / HTTP/1.1\r\n";
	s << "Host: s3.amazonaws.com\r\n";
	s << "Date: " + time + "\r\n";
	s << "Authorization: AWS " +  AWSAccessKeyId + ":" + cresig_Bucket_list(time, SecretAccessKey)  + "\r\n";
	s << "\r\n";
	s << std::flush;

	// 受信
	while( getline(s, line) )
	{
		if(line == "0\r") break;
		std::cout << line << std::endl;
	}

    /********************************************************************************
        新しいバケツ作成
    ********************************************************************************/
	time = (now + clx::hours(-9)).to_string<char>(fmt);
	s << "PUT / HTTP/1.1\r\n";
	s << "Host: helloidea.s3.amazonaws.com\r\n";
	s << "Content-Length: 0\r\n";
	s << "Date: " + time + "\r\n";
	s << "Authorization: AWS " +  AWSAccessKeyId + ":" + cresig_PUT_Bucket(time, SecretAccessKey)  + "\r\n";
	s << "\r\n";
	s << std::flush;

	// 受信
	while( getline(s, line) )
	{
		if(line == "\r") break;
		std::cout << line << std::endl;
	}
	

    /********************************************************************************
         バケツリスト表示
    ********************************************************************************/
	time = (now + clx::hours(-9)).to_string<char>(fmt);
	s << "GET / HTTP/1.1\r\n";
	s << "Host: s3.amazonaws.com\r\n";
	s << "Date: " + time + "\r\n";
	s << "Authorization: AWS " +  AWSAccessKeyId + ":" + cresig_Bucket_list(time, SecretAccessKey)  + "\r\n";
	s << "\r\n";
	s << std::flush;

	// 受信
	while( getline(s, line) )
	{
		if(line == "0\r") break;
		std::cout << line << std::endl;
	}
    
    return 0;
}

実行結果

Wed, 29 Dec 2010 02:10:45 GMT
HTTP/1.1 200 OK
x-amz-id-2: aC+IMQJqhaar2Ge7xPExs/89HxVa3uX0XkHh5UjyJg6r3q1eXE8i8amVJqkn+wEJ
x-amz-request-id: B938635CD29FA243
Date: Tue, 28 Dec 2010 17:10:47 GMT
Content-Type: application/xml
Transfer-Encoding: chunked
Server: AmazonS3

171
<?xml version="1.0" encoding="UTF-8"?>
<ListAllMyBucketsResult xmlns="http://s3.amazonaws.com/doc/2006-03-01/"><Owner><ID>48cf8016ac58fbcb1eac1d3494f2aa32a1c962e693e2cdcf07260dd32ad20c1b</ID><DisplayName>monyuonyu</DisplayName></Owner><Buckets><Bucket><Name>mk-pino</Name><CreationDate>2010-12-27T13:09:37.000Z</CreationDate></Bucket></Buckets></ListAllMyBucketsResult>
HTTP/1.1 200 OK
x-amz-id-2: RxRWtFXn+tC87ssZPN0ETtoJ9LRQb8Y+o6O/h8ROoUTWYejJE0mi7aL0OSc9E40I
x-amz-request-id: 394C83DC35E55C94
Date: Tue, 28 Dec 2010 17:10:47 GMT
Location: /helloidea
Content-Length: 0
Server: AmazonS3

HTTP/1.1 200 OK
x-amz-id-2: ND24MyAfKEysFZadhha3uGgKruXPaOUVqBNezeimYof8CFiTMIunxmtSQYp6Ytol
x-amz-request-id: F062E71478508082
Date: Tue, 28 Dec 2010 17:10:47 GMT
Content-Type: application/xml
Transfer-Encoding: chunked
Server: AmazonS3

1cd
<?xml version="1.0" encoding="UTF-8"?>
<ListAllMyBucketsResult xmlns="http://s3.amazonaws.com/doc/2006-03-01/"><Owner><ID>48cf8016ac58fbcb1eac1d3494f2aa32a1c962e693e2cdcf07260dd32ad20c1b</ID><DisplayName>monyuonyu</DisplayName></Owner><Buckets><Bucket><Name>helloidea</Name><CreationDate>2010-12-28T17:10:47.000Z</CreationDate></Bucket><Bucket><Name>mk-pino</Name><CreationDate>2010-12-27T13:09:37.000Z</CreationDate></Bucket></Buckets></ListAllMyBucketsResult>

パケットキャプチャ

GET / HTTP/1.1
Host: s3.amazonaws.com
Date: Tue, 28 Dec 2010 17:12:02 GMT
Authorization: AWS AKIAJEB3RUBMODUOMC2A:9MewU/ovOLenn16jxpJWDo/BFDA=

HTTP/1.1 200 OK
x-amz-id-2: qWXRbV7oveOX7lwgcgZHI1Qr3wGnrRfT5P/AcFKFLe2wpUCEi4HPqusWBDJDUhiB
x-amz-request-id: 38F96C42725BF3E0
Date: Tue, 28 Dec 2010 17:12:05 GMT
Content-Type: application/xml
Transfer-Encoding: chunked
Server: AmazonS3

171
<?xml version="1.0" encoding="UTF-8"?>
<ListAllMyBucketsResult xmlns="http://s3.amazonaws.com/doc/2006-03-01/"><Owner><ID>48cf8016ac58fbcb1eac1d3494f2aa32a1c962e693e2cdcf07260dd32ad20c1b</ID><DisplayName>monyuonyu</DisplayName></Owner><Buckets><Bucket><Name>mk-pino</Name><CreationDate>2010-12-27T13:09:37.000Z</CreationDate></Bucket></Buckets></ListAllMyBucketsResult>
0

PUT / HTTP/1.1
Host: helloidea.s3.amazonaws.com
Content-Length: 0
Date: Tue, 28 Dec 2010 17:12:02 GMT
Authorization: AWS AKIAJEB3RUBMODUOMC2A:o/kGf8J/7QGDL40p/J01VhOUMRQ=

GET / HTTP/1.1
Host: s3.amazonaws.com
Date: Tue, 28 Dec 2010 17:12:02 GMT
Authorization: AWS AKIAJEB3RUBMODUOMC2A:9MewU/ovOLenn16jxpJWDo/BFDA=
HTTP/1.1 200 OK
x-amz-id-2: 19v/z0GcSOurF1NVtKikSSvQJT5Ohq642c1weziUroWv99NBWmKOos17qwvjBvoF
x-amz-request-id: 5E30C041AB2E8523
Date: Tue, 28 Dec 2010 17:12:06 GMT
Location: /helloidea
Content-Length: 0
Server: AmazonS3

HTTP/1.1 200 OK
x-amz-id-2: 5sSB/Dr9tlFFjv8mFQxloozANn0ZEtL9/ZzMKLQkiR+HIglhiledhCwO/vMxNBU8
x-amz-request-id: 81FA9B5EB1BFD1A5
Date: Tue, 28 Dec 2010 17:12:06 GMT
Content-Type: application/xml
Transfer-Encoding: chunked
Server: AmazonS3

1cd
<?xml version="1.0" encoding="UTF-8"?>
<ListAllMyBucketsResult xmlns="http://s3.amazonaws.com/doc/2006-03-01/"><Owner><ID>48cf8016ac58fbcb1eac1d3494f2aa32a1c962e693e2cdcf07260dd32ad20c1b</ID><DisplayName>monyuonyu</DisplayName></Owner><Buckets><Bucket><Name>helloidea</Name><CreationDate>2010-12-28T17:12:06.000Z</CreationDate></Bucket><Bucket><Name>mk-pino</Name><CreationDate>2010-12-27T13:09:37.000Z</CreationDate></Bucket></Buckets></ListAllMyBucketsResult>
0

基本的にパケットキャプチャをしながら作業すると楽だと思います。
FirefixのプラグインのS3Foxをパケットキャプチャすると動作がよくわかります。
それとS3Foxはデータが暗号化されてない事もわかりました・・・気をつけてください。

sigunetyaの作成に関しては、Amazon Simple Storage Service Developer Guide(下参照)に詳しく書いてあります。
載っていないAPIのsigunetya生成に関しては、周りのAPIを見て判断します。

AWSAccessKeyId が丸見えですがなにか^^;
参考サイト

Amazon Simple Storage Service Developer Guide
Amazon Simple Storage Service API Reference
Howto base64 encode with C/C++ and OpenSSL
openssl HMAC を試す
CLX C++ Libraries
HTTP クライアントを作ってみよう(5) – Basic 認証編 –
REST APIでS3からオブジェクトを取得する
boost::asio
Web 2.0時代のWebServices ~SOAP/REST使い分けの指針

実機へアプリ転送 -Androidアプリ-

少し手こずったので走り書きメモ。

① USBドライバをダウンロード

マネージャーの、UpdataAllからUSBドライバを探してきます。

そのままでは、パッケージ になにも表示されないようなので、

Available packagesでツリーを展開(開くだけ)してから UpdataAllをすると、

無事、下から2番目にUSBドライバを見つけることが出来ます。

② ドライバのインストール
infファイルの [Google.NTx86] と [Google.NTamd64] セクションに

; HTC Desire
%CompositeAdbInterface% = USB_Install, USB\VID_0BB4&amp;PID_0C87&amp;MI_01
;
; Xperia X10
%SingleAdbInterface% = USB_Install, USB\VID_0FCE&amp;PID_D12E
%CompositeAdbInterface% = USB_Install, USB\VID_0FCE&amp;PID_D12E&amp;MI_01
;
; HTC Dream
%SingleAdbInterface%        = USB_Install, USB\VID_0BB4&amp;PID_0C01
%CompositeAdbInterface%     = USB_Install, USB\VID_0BB4&amp;PID_0C02&amp;MI_01
%SingleBootLoaderInterface% = USB_Install, USB\VID_0BB4&amp;PID_0FFF
; HTC Magic
%CompositeAdbInterface%     = USB_Install, USB\VID_0BB4&amp;PID_0C03&amp;MI_01
;
;Moto Sholes
%SingleAdbInterface%        = USB_Install, USB\VID_22B8&amp;PID_41DB
%CompositeAdbInterface%     = USB_Install, USB\VID_22B8&amp;PID_41DB&amp;MI_01
;
;Google NexusOne
%SingleAdbInterface%        = USB_Install, USB\VID_18D1&amp;PID_0D02
%CompositeAdbInterface%     = USB_Install, USB\VID_18D1&amp;PID_0D02&amp;MI_01
%SingleAdbInterface%        = USB_Install, USB\VID_18D1&amp;PID_4E11
%CompositeAdbInterface%     = USB_Install, USB\VID_18D1&amp;PID_4E12&amp;MI_01

を追記。

そして、デバイスマネージャからドライバインストール。
USB Driver4 はインストール出来ませんでしたが、USB Driver1.6で上手くいきました。

③ adb devices コマンドで実機接続確認
接続が上手くいってれば、List of devices attached の下にデバイス名が表示されます。

④ 転送
eclipseの 実行(R) – 実行(R) を押すと次のような画面が現れます。
OKで転送されます。コンソールタブで状況が確認できます。
※現れない場合は、実行(R) – 実行構成(N) – Androidアプリケーション – (プロジェクト名) – ターゲット で 手操作に設定します。

基本的な動作 -android開発-

基本的な動きの流れが分かったのでメモメモ。

SDKに付いてくるサンプルプログラムを見てみると、必ずインポートしてるライブラリがあります。
import android.app.Activity;

そして、どのアプリケーションも必ず同じ始まり方をしているようです。

@Override
public void onCreate(Bundle savedInstanceState) {…}

なんじゃらホイって調べると、Androidアプリケーションの基本的な流れが詳しく解説してあるページが見つかります。↓
androidパッケージが一覧になっているサイト(AndroidDevelopers)で捜すと、
android.app.Activity Class Overviewが見つかります。
XMLタグの種類も書かれています。

@ITでは流れが分かりやすく解説してあるサイトが見つかりました。
Androidアプリ作成の基本“Activity”とは何か?

非常に分かりやすいサンプルが置いてあるので貼らせていただきますm。(コピペじゃないよ!)

package com.example.android.lifecycle;

import android.app.Activity;
import android.os.Bundle;
import android.widget.Toast;

public class ActivityLifecycle extends Activity {
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        Toast.makeText(this, "onCreate()", Toast.LENGTH_SHORT).show();
    }
  
    @Override
    protected void onStart() {
        super.onStart();
        Toast.makeText(this, "onStart()", Toast.LENGTH_SHORT).show();
    }

    @Override
    protected void onRestart() {
        super.onRestart();
        Toast.makeText(this, "onRestart()", Toast.LENGTH_SHORT).show();
    }

    @Override
    protected void onResume() {
        super.onResume();
        Toast.makeText(this, "onResume()", Toast.LENGTH_SHORT).show();
    }

    @Override
    protected void onPause() {
        super.onPause();
        Toast.makeText(this, "onPause()", Toast.LENGTH_SHORT).show();
    }

    @Override
    protected void onStop() {
        super.onStop();
        Toast.makeText(this, "onStop()", Toast.LENGTH_SHORT).show();
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        Toast.makeText(this, "onDestroy()", Toast.LENGTH_SHORT).show();
    }
}

他のClassを見てみると、ほとんどの動作がオーバーライドされていて、基本動作は全てイベントドリブンな事も分かりました。

①基本的なフローをオーバーライド
②中でオブジェクトを作成・設定
③オブジェクトの中でさらにオーバーライド
みたいな感じで出来そう。

onCreate自体どうやって呼ばれてるのとか凄く気になる。。。