SQLの窓

2012年12月11日


Google Chrome の拡張 / 1クリックで Javascript をオン・オフする



こちらから、ZIP ファイルをダウンロードして適当なフォルダに置き解凍すると README.md が入っているフォルダが出来上がるので、そのフォルダを拡張ページから追加します。

追加するには、『デベロッパーモード』にチェックを入れて、『パッケージ化されていない拡張機能を読み込む』ボタンで上記フォルダを選択すると使えるようになります。



現在、Google Chrome では一般サイトから拡張機能をインストールできないようになっています。その事については、Google の HELP にあります。

また、過去の WEB にある記事中の 『試験運用版の拡張機能 API 』は有効にせずとも利用できます。



posted by lightbox at 2012-12-11 11:47 | Google Chrome | このブログの読者になる | 更新情報をチェックする

2012年12月03日


PHP で mdb(古い形式) の(架空の)ユーザデータを取得する ODBC クラス

通常の DB アクセスはそのまま Windows のあらゆる ODBC で可能ですが、JSON のデータを作成する為に機能を少し追加してあります。

print_r 関数は、そのままでもすでに整形されているので、str_replace で JSON に改造しました。日本語部分を unicode 表現には変換していませんが、このほうがテストには向いていると思います。

この為に mdb のデータは作成しました。ランダムに存在しないような名前を合成しています。

OneDrive よりダウンロード


<?
# **********************************************************
# データベースクラス
# **********************************************************
class DB {
 
	var $connect;
	var $result;
	var $json;
 
# **********************************************************
# コンストラクタ
# **********************************************************
	function DB( $server='127.0.0.1', $db_name='lightbox', $user='', $password='' ) {

		$this->connect = odbc_connect($db_name, $user, $password);
		$this->json = false;
	}
 
# **********************************************************
# 接続解除
# **********************************************************
	function close( ) {
		odbc_close( $this->connect );
	}
 
# **********************************************************
# クエリー
# **********************************************************
	function query( $sql_query ) {

		$ret = odbc_exec( $this->connect, $sql_query );
		return $ret;
	}
 
# **********************************************************
# フェッチ
# **********************************************************
	function fetch( $result ) {

		$ret = odbc_fetch_array( $result );
		$ret2 = $ret;
		$cnt = 0;
		while (list($_key, $_value) = @each($ret)) {
			$ret2[$cnt] = $_value;
			$cnt++;
		}
		return $ret2;
	}
 
# **********************************************************
# クエリーとフェッチ
# **********************************************************
	function query_ex( $sql_query='' ) {
 
		if ( $this->json ) {
			if ( $sql_query != '' ) {
				$sql_query = mb_convert_encoding( $sql_query, "shift_jis", "UTF-8" );
				$this->result = $this->query( $sql_query );
				if ( !$this->result ) {
					return false;
				}
			}
			$ret = odbc_fetch_array( $this->result );
			while (list($_key, $_value) = @each($ret)) {
				$ret[$_key] = mb_convert_encoding( $ret[$_key], "UTF-8", "shift_jis" );
			}

			$ret = print_r($ret,true);

			$ret = str_replace( "Array\n(\n", "{", $ret );
			$ret = str_replace( ")\n", "}", $ret );
			$ret = str_replace( "    [", "    \"", $ret );
			$ret = str_replace( "] => ", "\" : \"", $ret );
			$ret = str_replace( "\n    \"", "\",\n    \"", $ret );
			$ret = str_replace( "\n}", "\"\n}", $ret );
			$ret = str_replace( "{    ", "{\n    ", $ret );

			return $ret;
		}
		else {
			if ( $sql_query != '' ) {
				$this->result = $this->query( $sql_query );
				if ( !$this->result ) {
					return false;
				}
				return $this->fetch( $this->result );
			}
			else {
				return $this->fetch( $this->result );
			}
		}
 
	}
 
# **********************************************************
# 実行
# **********************************************************
	function Execute( $sql_exec ) {
		$ret = odbc_exec( $this->connect, $sql_exec );
		return $ret;
	}
 
 
}
?>
以下は実際のテスト出力ですが、全体の出力はこちらから参照して下さい。
<?
header( "Content-Type: text/html; Charset=utf-8" );
header( "pragma: no-cache" );
header( "Expires: Wed, 31 May 2000 14:59:58 GMT" );
header( "Cache-control: no-cache" );

require_once("db.php");

$db_path = "C:\\httpd142p\\lightbox\\work\\api\\api.mdb";

$connect_string = "Provider=MSDASQL;";
$connect_string .= "Driver={Microsoft Access Driver (*.mdb)};";
$connect_string .= "dbq={$db_path}";

$db = new DB( "", $connect_string );
$db->json = true;

$query = "select * from [user_data] order by [id]";

$column = $db->query_ex( $query );

print "<pre>";
print "{ \"items\" : [\n";
$flg = false;
while ( $column ) {

	if ( !$flg ) {
		$flg = true;
	}
	else {
		print ",\n";
	}
	print( $column );
	$column = $db->query_ex( );
};
print "\n]\n}";
print "</pre>";

$db->close();

?>


以下は5件のみ表示しています
{
    "items": [
        {
            "id": "0001",
            "user_name": "浦岡 孫准",
            "name_f": "ウラオカ ソンジュン",
            "class_code": "0003",
            "h_type": "0",
            "create_date": "2012-12-02 00:00:00",
            "update_date": "2013-02-17 00:00:00"
        },
        {
            "id": "0002",
            "user_name": "蘭村 瑠璃",
            "name_f": "ランムラ ルリ",
            "class_code": "0003",
            "h_type": "1",
            "create_date": "2012-09-06 00:00:00",
            "update_date": "2012-12-08 00:00:00"
        },
        {
            "id": "0003",
            "user_name": "多岡 愛葛",
            "name_f": "タオカ アイカツ",
            "class_code": "0002",
            "h_type": "0",
            "create_date": "2012-11-03 00:00:00",
            "update_date": "2013-02-03 00:00:00"
        },
        {
            "id": "0004",
            "user_name": "高田 愛魅",
            "name_f": "タカタ アイミ",
            "class_code": "0003",
            "h_type": "1",
            "create_date": "2012-09-02 00:00:00",
            "update_date": "2012-12-25 00:00:00"
        },
        {
            "id": "0005",
            "user_name": "内高 孫之",
            "name_f": "ウチタカ ソンユキ",
            "class_code": "0003",
            "h_type": "0",
            "create_date": "2012-12-02 00:00:00",
            "update_date": "2013-01-30 00:00:00"
        }
    ]
}
関連する記事

ログイン画面からリダイレクトしてアクセストークンを取得するまでの簡単な PHP コード

※ JSON のチェックおよび最終整形にはこちらを使っています



タグ:PHP MDB ODBC
posted by lightbox at 2012-12-03 18:50 | PHP + データベース | このブログの読者になる | 更新情報をチェックする

Windows8(C#) で Google にログインしてカレンダーの情報を扱う

Facebook もそうですが、ログイン処理には WebView を使ってユーザにはブラウザでログインするのと同じ処理をしてもらい、その結果で返ってくる URL 情報によって以降のアクセスで利用する『アクセストークン』を取得します。

プログラム作成に先だって、APIs Console で自分の API キー等を取得しておきます。( アプリは Client ID for web applications で取得 )





それぞれの API は API エクスプローラでテストする事ができます。例えばそのユーザが持ってるカレンダーの一覧は簡単に見る事ができます(右上の  OAuth 2.0 をオンにしてログインする必要があります )

アプリに登録する『リダイレクト場所』は、WEB 上の自分が管理する URL にします。このログインでは直接利用しませんが、実際はログイン後にユーザになんらかの情報を受け渡す為に使うといいと思います。

注意する事として、Google のログインページは JavaScript を使用しますので、Android や Windows Phone で同様の処理をする場合は、ブラウザの JavaScript を有効にしておく必要があります

LoginPage.xaml
<Page
	x:Class="Win8_C_Sharp_GoogleLogin.LoginPage"
	xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
	xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
	xmlns:local="using:Win8_C_Sharp_GoogleLogin"
	xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
	xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
	mc:Ignorable="d">

	<Grid Background="{StaticResource ApplicationPageBackgroundThemeBrush}">
		
		<!-- 戻るボタン -->
		<Button 
			x:Name="backButton" 
			Style="{StaticResource BackButtonStyle}"
			Click="backButton_Click"
			VerticalAlignment="Top" 
			Margin="101,52,0,0"/>

		<!-- 処理表示 -->
		<TextBlock 
			HorizontalAlignment="left" 
			Margin="208,52,0,0" 
			TextWrapping="Wrap" 
			Text="ログイン処理" 
			VerticalAlignment="Top" 
			Height="60" 
			Width="260" FontSize="48"/>
		
		<!-- ログイン認証WebView -->
		<WebView
		   x:Name="webView" 
			HorizontalAlignment="left" 
			Height="689" 
			Margin="101,136,0,-57" 
			VerticalAlignment="Top" 
			Width="1039" 
			LoadCompleted="webView_LoadComplete"/>

	</Grid>
</Page>

LoginPage.xaml
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using Windows.Foundation;
using Windows.Foundation.Collections;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Controls.Primitives;
using Windows.UI.Xaml.Data;
using Windows.UI.Xaml.Input;
using Windows.UI.Xaml.Media;
using Windows.UI.Xaml.Navigation;

using Windows.Storage;
using System.Diagnostics;
using System.Net.Http;
using Newtonsoft.Json.Linq;


namespace Win8_C_Sharp_GoogleLogin
{

	public sealed partial class LoginPage : Page
	{

		// ***************************************************
		// コンストラクタ
		// ***************************************************
		public LoginPage()
		{
			this.InitializeComponent();

			FacebookLogin();
		}

		// ***************************************************
		// WebView の表示
		// ***************************************************
		private void FacebookLogin()
		{
			// 対象となる URL を取得
			String url = App.gc.getLoginUrl();

			// 
			webView.Navigate(new Uri(url));

		}

		// ***************************************************
		// WebView がページを表示し終わった時の処理
		// ***************************************************
		private async void webView_LoadComplete(object sender, NavigationEventArgs e)
		{

			// URL を取得
			String token = e.Uri.ToString();

			if (token.IndexOf("code=") == 0)
			{
				// URL に含まれる仮のアクセストークンを取得する
				int cur = token.IndexOf("=");
				String code = token.Substring(cur+1);

				// アクセストークンを取得
				await App.gc.getAccessToken(code);

				// ユーザ情報を取得
				String info = await App.gc.getUserInfo();

				// このページを呼び出したメインページのフィールドにセット
				// 但し、メインページに戻る時は、GoBack を使ってはいけない
				((TextBox)App.mainPage.FindName("PostBody")).Text = info;
				
			}

		}


		// ***************************************************
		// メインページに戻る処理
		// ***************************************************
		private void backButton_Click(object sender, RoutedEventArgs e)
		{

			// 前のページに戻る「this.Frame.GoBack()」を実行するとMainPageの結果が消えてしまうため、
			// 一時変数を用意し、ページ遷移後に一時変数の中身をMainPageにセットする
			MainPage mp = App.mainPage;

			Frame rootFrame = Window.Current.Content as Frame;
			rootFrame.Content = App.mainPage;

		}

		protected override void OnNavigatedTo(NavigationEventArgs e)
		{
		}

	}
}

ここでは、前のページに戻る処理が重要です。サンプル等で使われている GoBack() では、元のページのインスタンスが新たに作成されるようなので、『ログイン』のようなダイアログ的な処理で使うととても都合が悪くなります。また、それに伴って、FindName で元のページのフィールドを参照する方法は重要です。

メインページのインスタンスは、起動時に App.xaml.cs で static の プロパティとして設定しておいて、アプリ全体からいつでもアクセスできるようにしておきます。

ログインや API の処理をするクラス
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Text;
using System.Threading.Tasks;
using Windows.Data.Json;

namespace Win8_C_Sharp_GoogleLogin
{
	public class NGCalendar
	{

		// API Console 情報
		private String API_KEY = "";
		private String client_id = "";
		private String client_secret = "";

		// ログイン処理
		private String loginUrl = "https://accounts.google.com/o/oauth2/auth";
		private String type = "code";
		// redirect_uri は、API に登録した URL( ここでは Google Plus の プロフィールページでテスト )
		private String redirect_uri = "";
		// スコープ(権限)を設定 / 後で自分の情報を取得するのに、Gooogle Plus のスコープも設定
		private String scope = "https://www.googleapis.com/auth/calendar+https://www.googleapis.com/auth/calendar.readonly+https://www.googleapis.com/auth/plus.me";

		// 最終データ
		private String code = "";
		private String access_token = "";
		private String token_type = "";

		// Google API 取得先
		private String oauth2_url = "https://accounts.google.com/o/oauth2/token";
		private String g_calendar_list_url = "https://www.googleapis.com/calendar/v3/users/me/calendarList";
		private String g_galendar_event_url = "https://www.googleapis.com/calendar/v3/calendars/[id]/events";

		// ***************************************************
		// GoogleログインURLを取得する
		// ***************************************************
		public String getLoginUrl()
		{
			String access_url = "";

			access_url = loginUrl;
			access_url += "?response_type=" + type;
			access_url += "&client_id=" + client_id;
			access_url += "&redirect_uri=" + redirect_uri;
			access_url += "&scope=" + scope;

			return access_url;

		}

		// ***************************************************
		// アクセストークンを取得する (POST)
		// ***************************************************
		public async Task<Boolean> getAccessToken(String code)
		{

			Boolean result = true;

			try
			{

				// Webにアクセスする
				HttpClient httpClient = new HttpClient();
				HttpRequestMessage requestMsg = new HttpRequestMessage();
				requestMsg.Method = new HttpMethod("POST");


				String body = "";
				body = "code=" + code;
				body += "&grant_type=authorization_code";
				body += "&redirect_uri=" + redirect_uri;
				body += "&client_id=" + client_id;
				body += "&client_secret=" + client_secret;

				// 指定したURIを非同期で通信
				requestMsg.Content = new StringContent(body);
				requestMsg.Method = new HttpMethod("POST");
				requestMsg.RequestUri = new Uri(oauth2_url, UriKind.Absolute);
				requestMsg.Content.Headers.ContentType = new MediaTypeHeaderValue("application/x-www-form-urlencoded");

				// 呼び出し( 非同期 )
				var response = await httpClient.SendAsync(requestMsg);

				// 情報取得( 非同期 )
				String res = await response.Content.ReadAsStringAsync();

				// Json文字列を整形( Freamwork の JSON 処理 )
				JsonValue jv = JsonValue.Parse(res);

				// JSON よりアクセストークンとトークンのタイプを取得する
				this.access_token = jv.GetObject().GetNamedString("access_token");
				this.token_type = jv.GetObject().GetNamedString("token_type");

			}
			catch (Exception Err)
			{
				result = false;
			}

			return result;

		}


		// ***************************************************
		// カレンダー一覧を取得する (GET)
		// ▼ API エクスプローラでテストできます
		// https://developers.google.com/apis-explorer/#p/calendar/v3/calendar.calendarList.list
		// ***************************************************
		public async Task<String> getCalendarList()
		{
			try
			{
				String api_url = g_calendar_list_url + "?key=" + API_KEY;

				HttpClient httpClient = new HttpClient();
				HttpRequestMessage requestMsg = new HttpRequestMessage();

				requestMsg.RequestUri = new Uri(api_url, UriKind.Absolute);
				requestMsg.Method = new HttpMethod("GET");

				// ヘッダにアクセスする為の情報(アクセストークン)をセット
				// API エクスプローラで実際の内容を見る事ができます
				httpClient.DefaultRequestHeaders.Add("Authorization", token_type + " " + access_token);

				// 呼び出し( 非同期 )
				var response = await httpClient.SendAsync(requestMsg);

				// 情報取得( 非同期 ) / 直接呼び出し元へ返しています( String )
				return await response.Content.ReadAsStringAsync();

			}
			catch (Exception Err)
			{
				throw;
			}
		}

		// ***************************************************
		// カレンダーに登録されたイベントを取得する ( GET )
		// ***************************************************
		public async Task<String> getCalendarEvent(String cid)
		{
			try
			{

				String api_url = g_galendar_event_url.Replace("[id]", Uri.EscapeDataString(cid)) + "?key=" + API_KEY;

				HttpClient httpClient = new HttpClient();
				HttpRequestMessage requestMsg = new HttpRequestMessage();

				requestMsg.RequestUri = new Uri(api_url, UriKind.Absolute);
				requestMsg.Method = new HttpMethod("GET");

				// ヘッダにアクセスする為の情報(アクセストークン)をセット
				httpClient.DefaultRequestHeaders.Add("Authorization", token_type + " " + access_token);

				// 呼び出し( 非同期 )
				var response = await httpClient.SendAsync(requestMsg);

				// 情報取得( 非同期 ) / 直接呼び出し元へ返しています( String )
				return await response.Content.ReadAsStringAsync();
			}
			catch (Exception Err)
			{
				throw;
			}
		}

		// ***************************************************
		// Google Plus よりユーザー情報を取得する ( GET )
		// ***************************************************
		public async Task<String> getUserInfo()
		{
			try
			{

				String api_url = "https://www.googleapis.com/plus/v1/people/me?key=" + API_KEY;

				HttpClient httpClient = new HttpClient();
				HttpRequestMessage requestMsg = new HttpRequestMessage();

				requestMsg.RequestUri = new Uri(api_url, UriKind.Absolute);
				requestMsg.Method = new HttpMethod("GET");

				// ヘッダにアクセスする為の情報(アクセストークン)をセット
				httpClient.DefaultRequestHeaders.Add("Authorization", token_type + " " + access_token);

				// 呼び出し( 非同期 )
				var response = await httpClient.SendAsync(requestMsg);

				// 情報取得( 非同期 ) / 直接呼び出し元へ返しています( String )
				return await response.Content.ReadAsStringAsync();
			}
			catch (Exception Err)
			{
				throw;
			}
		}
	}
}

ここでは、JSON の処理を Framework で行っていますが、実際は Json.NET で行うととても便利です。Json.NET を使うと、ListBox 等の一覧処理が JSON 文字列からバインドまでを一気にできるようになります。

また、Windows8 では非同期処理でイベントを定義する必要がありません。async と await を駆使してコードを書くことができます。

関連する記事

Windows Phone(C#) のデータバインドを Json.NET を使って一行で実装する( しかも XML を JSON 変換して使う )

Windows8 の非同期処理(C#)
Windows8(C#) の WebView の LoadComplete で取得した URL 内のアクセストークンを Split で取得


posted by lightbox at 2012-12-03 12:34 | Win8 ストアアプリ | このブログの読者になる | 更新情報をチェックする
Seesaa の各ページの表示について
Seesaa の 記事がたまに全く表示されない場合があります。その場合は、設定> 詳細設定> ブログ設定 で 最新の情報に更新の『実行ボタン』で記事やアーカイブが最新にビルドされます。

Seesaa のページで、アーカイブとタグページは要注意です。タグページはコンテンツが全く無い状態になりますし、アーカイブページも歯抜けページはコンテンツが存在しないのにページが表示されてしまいます。

また、カテゴリページもそういう意味では完全ではありません。『カテゴリID-番号』というフォーマットで表示されるページですが、実際存在するより大きな番号でも表示されてしまいます。

※ インデックスページのみ、実際の記事数を超えたページを指定しても最後のページが表示されるようです

対処としては、このようなヘルプ的な情報を固定でページの最後に表示するようにするといいでしょう。具体的には、メインの記事コンテンツの下に『自由形式』を追加し、アーカイブとカテゴリページでのみ表示するように設定し、コンテンツを用意するといいと思います。


※ エキスパートモードで表示しています

アーカイブとカテゴリページはこのように簡単に設定できますが、タグページは HTML 設定を直接変更して、以下の『タグページでのみ表示される内容』の記述方法で設定する必要があります

<% if:page_name eq 'archive' -%>
アーカイブページでのみ表示される内容
<% /if %>

<% if:page_name eq 'category' -%>
カテゴリページでのみ表示される内容
<% /if %>

<% if:page_name eq 'tag' -%>
タグページでのみ表示される内容
<% /if %>
この記述は、以下の場所で使用します
container 終わり



フリーフォントで簡単ロゴ作成
フリーフォントでボタン素材作成
フリーフォントで吹き出し画像作成
フリーフォントではんこ画像作成
ほぼ自由に利用できるフリーフォント
フリーフォントの書体見本とサンプル
画像を大きく見る為のウインドウを開くボタンの作成

CSS ドロップシャドウの参考デモ
イラストAC
ぱくたそ
写真素材 足成
フリーフォント一覧
utf8 文字ツール
右サイド 終わり
base 終わり